Оглавление:
2025 Автор: John Day | [email protected]. Последнее изменение: 2025-01-23 15:04
Удивите своих друзей и семью этим проектом, который распознает ноты, сыгранные на инструменте. В этом проекте будет отображаться приблизительная частота, а также музыкальная нота, сыгранная на электронной клавиатуре, приложении для фортепиано или любом другом инструменте.
Подробности
В этом проекте аналоговый выход детектора звукового модуля отправляется на аналоговый вход A0 Arduino Uno. Аналоговый сигнал дискретизируется и квантуется (оцифровывается). Код автокорреляции, взвешивания и настройки используется для нахождения основной частоты с использованием первых 3 периодов. Затем приблизительная основная частота сравнивается с частотами в диапазоне октав 3, 4 и 5 для определения ближайшей частоты музыкальной ноты. Наконец, на экране печатается предполагаемое примечание для ближайшей частоты.
Примечание. В этом руководстве рассказывается только о том, как построить проект. Для получения дополнительной информации о деталях и обоснованиях дизайна перейдите по этой ссылке: Подробнее
Запасы
- (1) Arduino Uno (или Genuino Uno)
- (1) Совместимость с модулем обнаружения звука высокой чувствительности датчика микрофона DEVMO
- (1) Макетная плата без пайки
- (1) Кабель USB-A - B
- Провода перемычки
- Музыкальный источник (фортепиано, клавиатура или приложение paino с динамиками)
- (1) Компьютер или ноутбук
Шаг 1. Создайте оборудование для детектора музыкальных нот
Используя Arduino Uno, соединительные провода, макетную плату без пайки и модуль обнаружения звука высокой чувствительности датчика микрофона DEVMO (или аналогичный), создайте схему, показанную на этом изображении.
Шаг 2: запрограммируйте детектор музыкальных нот
В IDE Arduino добавьте следующий код.
gistfile1.txt
| /* |
| Имя файла / эскиза: MusicalNoteDetector |
| Номер версии: v1.0 Создано 7 июня 2020 г. |
| Автор оригинала: Клайд А. Леттсом, PhD, PE, MEM |
| Описание: этот код / эскиз отображает приблизительную частоту, а также музыкальную ноту, сыгранную на электронной клавиатуре или в приложении для фортепиано. Для этого проекта аналоговый выход из |
| Звуковой модуль детектора отправляется на аналоговый вход A0 Arduino Uno. Аналоговый сигнал дискретизируется и квантуется (оцифровывается). Код автокорреляции, взвешивания и настройки используется для |
| найти основную частоту, используя первые 3 периода. Затем приблизительная основная частота сравнивается с частотами в диапазоне 3, 4 и 5 октав для определения ближайшего музыкального |
| обратите внимание на частоту. Наконец, на экране печатается предполагаемое примечание для ближайшей частоты. |
| Лицензия: Эта программа является бесплатным программным обеспечением; вы можете распространять и / или изменять его в соответствии с условиями Стандартной общественной лицензии GNU (GPL) версии 3 или любой более поздней. |
| версия по вашему выбору, опубликованная Free Software Foundation. |
| Примечания: Copyright (c) 2020 by C. A. Lettsome Services, LLC |
| Для получения дополнительной информации посетите |
| */ |
| #define SAMPLES 128 // Макс 128 для Arduino Uno. |
| #define SAMPLING_FREQUENCY 2048 // Fs = на основе Найквиста, должно быть в 2 раза больше максимальной ожидаемой частоты. |
| #define OFFSETSAMPLES 40 // используется для калибровки |
| #define TUNER -3 // Регулируйте, пока C3 не станет 130,50 |
| float samplingPeriod; |
| беззнаковые длинные микросекунды; |
| int X [ОБРАЗЦЫ]; // создаем вектор размера SAMPLES для хранения реальных значений |
| float autoCorr [ОБРАЗЦЫ]; // создаем вектор размера SAMPLES для хранения мнимых значений |
| float storedNoteFreq [12] = {130,81, 138,59, 146,83, 155,56, 164,81, 174,61, 185, 196, 207,65, 220, 233,08, 246,94}; |
| int sumOffSet = 0; |
| int offSet [СМЕЩЕНИЯ]; // создаем вектор смещения |
| int avgOffSet; // создаем вектор смещения |
| int i, k, periodEnd, periodBegin, period, adjuster, noteLocation, octaveRange; |
| float maxValue, minValue; |
| длинная сумма; |
| int thresh = 0; |
| int numOfCycles = 0; |
| float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total; |
| байт state_machine = 0; |
| int samplesPerPeriod = 0; |
| установка void () |
| { |
| Serial.begin (115200); // 115200 бод для последовательного монитора |
| } |
| пустой цикл () |
| { |
| //***************************************************************** |
| // Раздел калибровки |
| //***************************************************************** |
| Serial.println («Калибровка. Пожалуйста, не играйте никаких нот во время калибровки.»); |
| for (i = 0; i <OFFSETSAMPLES; i ++) |
| { |
| offSet = analogRead (0); // Считывает значение с аналогового вывода 0 (A0), квантует его и сохраняет как действительный член. |
| //Serial.println(offSet); // используйте это, чтобы настроить модуль обнаружения звука примерно на половину или 512, когда звук не воспроизводится. |
| sumOffSet = sumOffSet + offSet [я]; |
| } |
| samplesPerPeriod = 0; |
| maxValue = 0; |
| //***************************************************************** |
| // Готовимся принять ввод от A0 |
| //***************************************************************** |
| avgOffSet = round (sumOffSet / OFFSETSAMPLES); |
| Serial.println («Обратный отсчет»); |
| задержка (1000); // пауза на 1 секунду |
| Serial.println («3»); |
| задержка (1000); // пауза на 1 секунду |
| Serial.println («2»); |
| задержка (1000); // пауза на 1 |
| Serial.println («1»); |
| задержка (1000); // пауза на 1 секунду |
| Serial.println («Сыграй свою ноту!»); |
| задержка (250); // пауза на 1/4 секунды на время реакции |
| //***************************************************************** |
| // Собираем SAMPLES выборки из A0 с периодом выборки samplingPeriod |
| //***************************************************************** |
| samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Период в микросекундах |
| для (i = 0; i <ОБРАЗЦЫ; i ++) |
| { |
| микросекунды = микросекунды (); // Возвращает количество микросекунд, прошедших с того момента, как плата Arduino начала запускать текущий скрипт. |
| X = analogRead (0); // Считывает значение с аналогового вывода 0 (A0), квантует его и сохраняет как действительный член. |
| / * оставшееся время ожидания между выборками, если необходимо, в секундах * / |
| а (микросекунды () <(микросекунды + (период выборки * 1000000))) |
| { |
| // ничего не делаем, просто ждем |
| } |
| } |
| //***************************************************************** |
| // Автокорреляционная функция |
| //***************************************************************** |
| for (i = 0; i <SAMPLES; i ++) // i = задержка |
| { |
| сумма = 0; |
| for (k = 0; k <SAMPLES - i; k ++) // Сопоставить сигнал с задержанным сигналом |
| { |
| сумма = сумма + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] - это сигнал, а X [k + i] - это отложенная версия |
| } |
| autoCorr = сумма / ОБРАЗЦЫ; |
| // Конечный автомат первого обнаружения пика |
| если (state_machine == 0 && i == 0) |
| { |
| порог = autoCorr * 0,5; |
| state_machine = 1; |
| } |
| else if (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, найти 1 период для использования первого цикла |
| { |
| maxValue = autoCorr ; |
| } |
| иначе if (state_machine == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0) |
| { |
| periodBegin = i-1; |
| state_machine = 2; |
| numOfCycles = 1; |
| samplesPerPeriod = (periodBegin - 0); |
| период = samplesPerPeriod; |
| регулятор = TUNER + (50.04 * exp (-0.102 * samplesPerPeriod)); |
| signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod)) - регулятор; // f = fs / N |
| } |
| else if (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, найти 2 периода для 1-го и 2-го цикла |
| { |
| maxValue = autoCorr ; |
| } |
| иначе if (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0) |
| { |
| periodEnd = i-1; |
| state_machine = 3; |
| numOfCycles = 2; |
| samplesPerPeriod = (periodEnd - 0); |
| signalFrequency2 = ((numOfCycles * SAMPLING_FREQUENCY) / (samplesPerPeriod)) - регулятор; // f = (2 * fs) / (2 * N) |
| maxValue = 0; |
| } |
| else if (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, найти 3 периода для 1-го, 2-го и 3-го цикла |
| { |
| maxValue = autoCorr ; |
| } |
| иначе if (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0) |
| { |
| periodEnd = i-1; |
| state_machine = 4; |
| numOfCycles = 3; |
| samplesPerPeriod = (periodEnd - 0); |
| signalFrequency3 = ((numOfCycles * SAMPLING_FREQUENCY) / (samplesPerPeriod)) - регулятор; // f = (3 * fs) / (3 * N) |
| } |
| } |
| //***************************************************************** |
| // Анализ результатов |
| //***************************************************************** |
| если (samplesPerPeriod == 0) |
| { |
| Serial.println («Хм….. я не уверен. Вы пытаетесь меня обмануть?»); |
| } |
| еще |
| { |
| // подготавливаем весовую функцию |
| всего = 0; |
| если (частота сигнала! = 0) |
| { |
| всего = 1; |
| } |
| если (signalFrequency2! = 0) |
| { |
| итого = всего + 2; |
| } |
| если (signalFrequency3! = 0) |
| { |
| итого = всего + 3; |
| } |
| // вычисляем частоту с помощью весовой функции |
| signalFrequencyGuess = ((1 / всего) * signalFrequency) + ((2 / total) * signalFrequency2) + ((3 / total) * signalFrequency3); // находим взвешенную частоту |
| Serial.print («Сыгранная вами нота примерно равна»); |
| Serial.print (signalFrequencyGuess); // Распечатываем предположение о частоте. |
| Serial.println («Гц»); |
| // находим диапазон октав на основе предположения |
| octaveRange = 3; |
| while (! (signalFrequencyGuess> = storedNoteFreq [0] -7 && signalFrequencyGuess <= storedNoteFreq [11] +7)) |
| { |
| для (я = 0; я <12; я ++) |
| { |
| storedNoteFreq = 2 * storedNoteFreq ; |
| } |
| octaveRange ++; |
| } |
| // Находим ближайшую заметку |
| minValue = 10000000; |
| noteLocation = 0; |
| для (я = 0; я <12; я ++) |
| { |
| если (minValue> abs (signalFrequencyGuess-storedNoteFreq )) |
| { |
| minValue = abs (signalFrequencyGuess-storedNoteFreq ); |
| noteLocation = i; |
| } |
| } |
| // Распечатываем заметку |
| Serial.print («Думаю, ты играл»); |
| если (noteLocation == 0) |
| { |
| Serial.print ("C"); |
| } |
| иначе, если (noteLocation == 1) |
| { |
| Serial.print («C #»); |
| } |
| иначе, если (noteLocation == 2) |
| { |
| Serial.print ("D"); |
| } |
| иначе, если (noteLocation == 3) |
| { |
| Serial.print ("D #"); |
| } |
| иначе, если (noteLocation == 4) |
| { |
| Serial.print («E»); |
| } |
| иначе, если (noteLocation == 5) |
| { |
| Serial.print («F»); |
| } |
| иначе, если (noteLocation == 6) |
| { |
| Serial.print ("F #"); |
| } |
| иначе, если (noteLocation == 7) |
| { |
| Serial.print ("G"); |
| } |
| иначе, если (noteLocation == 8) |
| { |
| Serial.print ("G #"); |
| } |
| иначе, если (noteLocation == 9) |
| { |
| Serial.print («А»); |
| } |
| иначе, если (noteLocation == 10) |
| { |
| Serial.print ("A #"); |
| } |
| иначе, если (noteLocation == 11) |
| { |
| Serial.print («B»); |
| } |
| Serial.println (octaveRange); |
| } |
| //***************************************************************** |
| //Остановись здесь. Нажмите кнопку сброса на Arduino, чтобы перезапустить |
| //***************************************************************** |
| в то время как (1); |
| } |
просмотреть rawgistfile1.txt, размещенный на ❤ на GitHub
Шаг 3: Настройте Детектор музыкальных нот
Подключите Arduino Uno к ПК с кодом, написанным или загруженным в Arduino IDE. Скомпилируйте и загрузите код в Arduino. Разместите схему рядом с источником музыки. Примечание. Во вводном видео я использую приложение, установленное на планшете, в сочетании с динамиками ПК в качестве источника музыки. Нажмите кнопку сброса на плате Arduino, а затем сыграйте ноту на источнике музыки. Через несколько секунд детектор музыкальных нот отобразит сыгранную ноту и ее частоту.
Рекомендуемые:
Детектор музыкальных нот Arduino: 3 шага
Детектор музыкальных нот Arduino: обнаружение музыкальных нот по аудиосигналу затруднено, особенно на Arduino, из-за ограниченной памяти и вычислительной мощности. Как правило, нота не является чистой синусоидой, что затрудняет обнаружение. Если мы возьмем частотное преобразование va
Колесо музыкальных впечатлений сегодняшнего шоу: 7 шагов
Колесо музыкальных впечатлений сегодняшнего шоу. Эта машина вдохновлена фрагментом вечернего шоу, в котором Джимми Фэллон в главной роли называется «Колесо музыкальных впечатлений». Сначала вы нажимаете кнопку на коробке, и на ЖК-дисплее отображается случайный певец и песня. Тогда вам придется подражать
4 схемы музыкальных реактивных светодиодов -- Кабель MIC / AUX / динамик: 3 шага
4 схемы музыкальных реактивных светодиодов || Кабель MIC / AUX / динамик: это схема, которая реагирует на окружающую музыку и светит светодиодами в такт музыке. Здесь я покажу вам четыре различных способа создания схемы музыкальных реактивных светодиодов, используя: -1. Одиночный транзистор 2. Два транзистора 3. Кабель AUX 4. Оратор
Как закодировать песню с использованием нот в Sonic Pi: 5 шагов
Как кодировать песню с использованием нот в Sonic Pi: в этом руководстве будут описаны некоторые основные шаги и фрагменты кода, которые необходимо использовать при кодировании песни в Sonic Pi с использованием нот! Есть миллион других фрагментов кода, чтобы попытаться добавить изюминку к вашей готовой части, так что не забудьте также поиграть с y
Портативная музыкальная шкатулка / инструмент на 6 нот (легко сделать и улучшить!): 5 шагов (с изображениями)
Портативная музыкальная шкатулка / инструмент на 6 нот (легко сделать и улучшить!) Привет! Вдохновленный Мартином Молином, участником шведской группы Wintergatan, я недавно влюбился в музыкальные шкатулки и все, что с ними связано. Люди, пишущие песни для музыкальных шкатулок, все еще используют старомодный способ пробивать песню, а не
