Съдържание:

Детектор за музикални бележки на Arduino: 3 стъпки
Детектор за музикални бележки на Arduino: 3 стъпки

Видео: Детектор за музикални бележки на Arduino: 3 стъпки

Видео: Детектор за музикални бележки на Arduino: 3 стъпки
Видео: The Wagner PMC fighters after the defense of Bakhmut #shorts 2024, Ноември
Anonim
Image
Image

Откриването на музикални ноти от аудио сигнала е трудно да се направи, особено на Arduino поради ограничената памет и процесорната мощност. Като цяло бележката не е чиста синусоида, която затруднява откриването. Ако вземем честотната трансформация на различни музикални инструменти, тя може да съдържа множество хармоници въз основа на свирената нота. Всеки инструмент има своя собствена комбинация от различни хармоници. В този код се опитах да направя програма, която да обхване възможно най -много инструменти. Можете да се обърнете към приложен видеоклип, в който се опитах да тествам различните видове инструменти, проверяват се различни видове тонове, генерирани от клавиатурата, и дори звук на вокал. Точността на откриването варира от инструмент към инструмент. За някои инструменти (т.е. пиано) в ограничен диапазон (200-500Hz) той е точен, докато за някой инструмент има ниска точност (т.е. хармоника).

Този код използва предварително разработен FFT код, наречен EasyFFT.

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

Консумативи

- Arduino Nano/Uno или по -горе

- Модул за микрофон за Arduino

Стъпка 1: Алгоритъм за откриване на бележки

Както бе споменато в предишната стъпка, откриването е трудно поради наличието на множество честоти в аудио пробите.

Програмата работи в следния поток:

1. Събиране на данни:

- този раздел взема 128 проби от аудио данни, разделянето между две проби (честота на вземане на проби) в зависимост от честотата, която представлява интерес. В този случай използваме разстоянието между две проби, което се използва за прилагане на прозоречната функция на Hann, както и за изчисляване на амплитуда/RMS. Този код също прави грубо нулиране, като изважда 500 от стойността на аналоговото четене. Тази стойност може да бъде променена, ако е необходимо. За типичен случай тези стойности работят добре. Освен това трябва да се добави известно забавяне, за да има честота на дискретизация около 1200Hz. в случай на 1200Hz честота на дискретизация може да бъде открита максимум 600 HZ честота.

for (int i = 0; i <128; i ++) {a = analogRead (Mic_pin) -500; // груба нулева промяна sum1 = sum1+a; // към средна стойност sum2 = sum2+a*a; // към RMS стойност a = a*(sin (i*3.14/128)*sin (i*3.14/128)); // прозорец на Hann в = 4*a; // мащабиране за забавяне на преобразуване с плаващо към intMicroseconds (195); // въз основа на честотния диапазон на работа}

2. FFT:

След като данните са готови, FFT се извършва с помощта на EasyFFT. Тази функция EasyFFT е модифицирана, за да фиксира FFT за 128 проби. Кодът също е променен, за да се намали консумацията на памет. Оригиналната функция EasyFFT, проектирана да има до 1028 проби (със съвместимата платка), докато имаме нужда само от 128 проби. този код намалява консумацията на памет с около 20% в сравнение с оригиналната функция EasyFFT.

След като FFT бъде направен, кодът връща топ 5 на най -доминиращите честотни пикове за по -нататъшен анализ. Тази честота е подредена в низходящ ред по амплитуда.

3. За всеки пик кодът открива възможни бележки, свързани с него. този код сканира само до 1200 Hz. Не е необходимо да имате бележка същата като честотата с максимална амплитуда.

Всички честоти са картографирани между 0 до 255, тук се открива първата октава, например 65,4 Hz до 130,8 представлява една октава, 130,8 Hz до 261,6 Hz представлява друга. За всяка октава честотите са картографирани от 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. Амплитуден праг:

Този код се активира само ако амплитудата на сигнала е достатъчно висока. тази настройка трябва да бъде зададена ръчно от потребителя. тази стойност зависи от чувствителността на микрофона, както и от приложението.

ако (sum2-sum1> 5) {

..

в горния код sum2 дава RMS стойност, докато sum 1 дава средна стойност. така че разликата между тези две стойности дава амплитудата на звуковия сигнал. в моя случай работи правилно със стойност на амплитуда около 5.

4. По подразбиране този код ще отпечата откритата бележка. обаче, ако планирате да използвате бележката за някаква друга цел, трябва да използвате директно зададения номер. например C = 0; C#= 1, D = 2, D#= 3 и нататък.

5. Ако инструментът има по -висока честота, кодът може да даде фалшив изход. максималната честота е ограничена от честотата на вземане на проби. така че можете да играете под стойностите на забавяне, за да получите оптимален изход. при по -долу кодово забавяне от 195 микросекунди. които могат да бъдат променени, за да се постигне оптимален резултат. Това ще повлияе на общото време за изпълнение.

{a = analogRead (Mic_pin) -500; // грубо изместване на нулата

sum1 = sum1+a; // към средна стойност sum2 = sum2+a*a; // към RMS стойност a = a*(sin (i*3.14/128)*sin (i*3.14/128)); // прозорец на Hann в = 4*a; // мащабиране за забавяне на преобразуване с плаващо към intMicroseconds (195); // въз основа на честотния диапазон на работа}

6. този код ще работи само до 2000Hz честота. чрез елиминиране на закъснението между вземане на проби около 3-4 kHz на честотите на дискретизация могат да бъдат получени.

Предпазни мерки:

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

Стъпка 3: Лято

Откриването на бележки е изчислително интензивна работа, получаването на изход в реално време е много трудно, особено на Arduino. Този код може да даде около 6,6 проби /секунди (за добавено закъснение от 195 микросекунди). този код работи добре с пианото и някои други инструменти.

Надявам се този код и урок да бъдат полезни във вашия проект, свързан с музиката. в случай на съмнение или предложение не се колебайте да коментирате или изпратите съобщение.

В предстоящия урок ще променя този код за откриване на музикални акорди. така че следете.

Препоръчано: