Оглавление:

Детектор музыкальных нот Arduino: 3 шага
Детектор музыкальных нот Arduino: 3 шага

Видео: Детектор музыкальных нот Arduino: 3 шага

Видео: Детектор музыкальных нот Arduino: 3 шага
Видео: 🤖 Ардуино робот играет музыку на бокалах 🎼 2024, Декабрь
Anonim
Image
Image

Обнаружение музыкальных нот по аудиосигналу затруднено, особенно на Arduino, из-за ограниченной памяти и вычислительной мощности. Как правило, нота не является чистой синусоидой, что затрудняет обнаружение. Если мы возьмем частотное преобразование различных музыкальных инструментов, оно может содержать несколько гармоник в зависимости от проигрываемой ноты. У каждого инструмента есть своя фирменная комбинация различных гармоник. В этом коде я попытался создать программу, которая может охватывать как можно больше инструментов. Вы можете сослаться на прикрепленное видео, в котором я пытался протестировать различные типы инструментов, различные типы тонов, генерируемых клавиатурой, и даже проверяются звуки вокала. Точность обнаружения зависит от прибора. Для некоторых инструментов (например, фортепиано) в ограниченном диапазоне (200-500 Гц) он является точным, в то время как для некоторых инструментов он имеет низкую точность (например, гармоника).

Этот код использует ранее разработанный код БПФ под названием EasyFFT.

Демонстрация кода показана в приведенном выше видео с различными типами инструментального звука, а также вокала.

Запасы

- Arduino Nano / Uno или выше

- Микрофонный модуль для Arduino

Шаг 1. Алгоритм обнаружения нот

Как упоминалось в предыдущем шаге, обнаружение затруднено из-за наличия нескольких частот в аудиосэмплах.

Программа работает в следующем потоке:

1. Сбор данных:

- этот раздел берет 128 отсчетов из аудиоданных, разделение между двумя отсчетами (частота дискретизации) зависит от интересующей частоты. В этом случае мы используем интервал между двумя выборками, который используется для применения оконной функции Ханна, а также для расчета амплитуды / среднеквадратичного значения. Этот код также выполняет грубое обнуление путем вычитания 500 из аналогового считываемого значения. При необходимости это значение можно изменить. Для типичного случая эти значения работают хорошо. Кроме того, необходимо добавить некоторую задержку, чтобы получить частоту дискретизации около 1200 Гц. в случае частоты дискретизации 1200 Гц может быть обнаружена максимальная частота 600 Гц.

для (int i = 0; i <128; i ++) {a = analogRead (Mic_pin) -500; // приблизительный сдвиг нуля sum1 = sum1 + a; // к среднему значению sum2 = sum2 + a * a; // к среднеквадратичному значению a = a * (sin (i * 3.14 / 128) * sin (i * 3.14 / 128)); // Окно Ханна in = 4 * a; // масштабирование для преобразования типа float в int delayMicroseconds (195); // в зависимости от диапазона рабочих частот}

2. БПФ:

Когда данные готовы, выполняется БПФ с использованием EasyFFT. Эта функция EasyFFT модифицирована для исправления БПФ для 128 выборок. Код также изменен, чтобы уменьшить потребление памяти. Оригинальная функция EasyFFT рассчитана на 1028 отсчетов (с совместимой платой), в то время как нам нужно всего 128 отсчетов. этот код снижает потребление памяти примерно на 20% по сравнению с исходной функцией EasyFFT.

После выполнения БПФ код возвращает 5 самых доминирующих частотных пиков для дальнейшего анализа. Эти частоты расположены в порядке убывания амплитуды.

3. Для каждого пика код определяет возможные ноты, связанные с ним. этот код сканирует только до 1200 Гц. Необязательно иметь такую же ноту, что и частота с максимальной амплитудой.

Все частоты отображаются в диапазоне от 0 до 255, здесь определяется первая октава, например, от 65,4 Гц до 130,8 Гц соответствует одна октава, от 130,8 Гц до 261,6 Гц - другая. Для каждой октавы частоты отображаются от 0 до 255. здесь отображение начинается от C до C '.

if (f_peaks > 1040) {f_peaks = 0;} if (f_peaks > = 65,4 && f_peaks = 130,8 && f_peaks = 261,6 && f_peaks = 523,25 && f_peaks = 1046 && f_peaks <= 2093) {f_peaks = 255 * ((f_peaks / 1046) -1);}

Значения массива NoteV используются для присвоения ноты обнаруженным частотам.

байт NoteV [13] = {8, 23, 40, 57, 76, 96, 116, 138, 162, 187, 213, 241, 255};

4. После расчета ноты для каждой частоты может случиться так, что существует несколько частот, которые предполагают одну и ту же ноту. Чтобы получить точный выходной код, также учитываются повторения. Код суммирует все значения частоты в зависимости от порядка амплитуды и повторений и увеличивает ноту с максимальной амплитудой.

Шаг 2: Заявление

Использование кода простое, однако есть также несколько ограничений, которые необходимо учитывать при его использовании. Код можно скопировать, так как он используется для обнаружения заметок. При его использовании необходимо учитывать следующие моменты.

1. Назначение контактов:

На основании прикрепленного PIN-кода необходимо изменить назначение. Для своего эксперимента я оставил аналоговый вывод 7, void setup () {Serial.begin (250000); Mic_pin = A7; }

2. Чувствительность микрофона:

Необходимо изменить чувствительность микрофона, чтобы сигнал мог генерироваться с хорошей амплитудой. В основном модуль микрофона имеет настройку чувствительности. необходимо выбрать соответствующую чувствительность, чтобы сигнал не был слишком слабым и не прерывался из-за более высокой амплитуды.

3. Порог амплитуды:

Этот код активируется только в том случае, если амплитуда сигнала достаточно высока. этот параметр должен быть установлен пользователем вручную. это значение зависит от чувствительности микрофона, а также от приложения.

if (sum2-sum1> 5) {

..

в приведенном выше коде сумма 2 дает среднеквадратичное значение, а сумма 1 дает среднее значение. поэтому разница между этими двумя значениями дает амплитуду звукового сигнала. в моем случае он работает правильно со значением амплитуды около 5.

4. По умолчанию этот код распечатывает обнаруженную заметку. однако, если вы планируете использовать примечание для других целей, следует использовать непосредственно присвоенный номер. например C = 0; C # = 1, D = 2, D # = 3 и далее.

5. Если прибор имеет более высокую частоту, код может дать ложный результат. максимальная частота ограничена частотой дискретизации. так что вы можете поэкспериментировать с указанными ниже значениями задержки, чтобы получить оптимальный выход. в приведенном ниже коде задержка 195 микросекунд. который можно настроить для получения оптимального результата. Это повлияет на общее время выполнения.

{a = analogRead (Mic_pin) -500; // грубый сдвиг нуля

сумма1 = сумма1 + а; // к среднему значению sum2 = sum2 + a * a; // к среднеквадратичному значению a = a * (sin (i * 3.14 / 128) * sin (i * 3.14 / 128)); // Окно Ханна in = 4 * a; // масштабирование для преобразования типа float в int delayMicroseconds (195); // в зависимости от диапазона рабочих частот}

6. этот код будет работать только до частоты 2000 Гц. за счет устранения задержки между дискретизацией можно получить около 3-4 кГц частот дискретизации.

Меры предосторожности:

  • Как упоминалось в учебнике EasyFFT, БПФ съедает огромный объем памяти Arduino. Поэтому, если у вас есть программа, которая должна сохранять некоторые значения, рекомендуется использовать плату с большим объемом памяти.
  • Этот код может хорошо работать для одного инструмента / вокалиста и плохо работать для другого. Точное обнаружение в реальном времени невозможно из-за вычислительных ограничений.

Шаг 3: Лето

Обнаружение нот - это трудоемкая вычислительная работа, получение вывода в реальном времени очень сложно, особенно на Arduino. Этот код может дать около 6,6 выборок в секунду (добавлена задержка в 195 микросекунд). этот код хорошо работает с фортепиано и некоторыми другими инструментами.

Я надеюсь, что этот код и руководство будут полезны в вашем проекте, связанном с музыкой. в случае каких-либо сомнений или предложений не стесняйтесь оставлять комментарии или сообщения.

В следующем уроке я изменю этот код для определения музыкальных аккордов. так что следите за обновлениями.

Рекомендуемые: