Spisu treści:

Wykrywacz nut Arduino: 3 kroki
Wykrywacz nut Arduino: 3 kroki

Wideo: Wykrywacz nut Arduino: 3 kroki

Wideo: Wykrywacz nut Arduino: 3 kroki
Wideo: Arduino wariograf/wykrywacz kłamstw 2024, Listopad
Anonim
Image
Image

Wykrywanie nut z sygnału audio jest trudne, szczególnie na Arduino, ze względu na ograniczoną pamięć i moc obliczeniową. Ogólnie rzecz biorąc, nuta nie jest czystą falą sinusoidalną, co utrudnia wykrycie. Jeśli weźmiemy transformację częstotliwości różnych instrumentów muzycznych, może ona zawierać wiele harmonicznych w zależności od granej nuty. Każdy instrument ma swoją własną charakterystyczną kombinację różnych harmonicznych. W tym kodzie starałem się stworzyć program, który może objąć jak najwięcej instrumentów. Możesz zapoznać się z załączonym filmikiem, w którym próbowałem przetestować różne rodzaje instrumentów, różne rodzaje tonów generowanych przez klawiaturę, a nawet dźwięk wokalu są sprawdzane. Dokładność wykrywania różni się od przyrządu do przyrządu. Dla niektórych instrumentów (np. fortepian) w ograniczonym zakresie (200-500Hz) jest dokładny, podczas gdy dla niektórych ma niską dokładność (np. Harmonijka).

Ten kod wykorzystuje wcześniej opracowany kod FFT o nazwie EasyFFT.

Demonstracja kodu jest pokazana na powyższym filmie z różnymi rodzajami dźwięku instrumentów oraz wokalem.

Kieszonkowe dzieci

- Arduino Nano/Uno lub nowszy

- Moduł mikrofonu dla Arduino

Krok 1: Algorytm wykrywania nut

Jak wspomniano w poprzednim kroku, wykrywanie jest trudne ze względu na obecność wielu częstotliwości w próbkach audio.

Program działa w następującym przepływie:

1. Pozyskiwanie danych:

- ta sekcja pobiera 128 próbek z danych audio, separacja między dwiema próbkami (częstotliwość próbkowania) w zależności od częstotliwości będącej przedmiotem zainteresowania. W tym przypadku używamy odstępów między dwiema próbkami, aby zastosować funkcję okna Hanna, a także obliczenia amplitudy/RMS. Ten kod wykonuje również zerowanie zgrubne, odejmując 500 od wartości odczytu analogowego. W razie potrzeby tę wartość można zmienić. W typowym przypadku te wartości działają dobrze. Ponadto należy dodać pewne opóźnienie, aby uzyskać częstotliwość próbkowania około 1200 Hz. w przypadku częstotliwości próbkowania 1200Hz można wykryć maks. częstotliwość 600 Hz.

for(int i=0;i<128;i++) { a=analogRead(Mic_pin)-500; //zgrubna suma przesunięcia zera1=sum1+a; //do średniej wartości sum2=sum2+a*a; // do wartości skutecznej a=a*(sin(i*3.14/128)*sin(i*3.14/128)); // Okno Hanna w=4*a; // skalowanie konwersji float na int delayMicroseconds(195); // na podstawie zakresu częstotliwości pracy }

2. FFT:

Gdy dane są gotowe, FFT jest wykonywane za pomocą EasyFFT. Ta funkcja EasyFFT została zmodyfikowana, aby naprawić FFT dla 128 próbek. Kod jest również modyfikowany w celu zmniejszenia zużycia pamięci. Oryginalna funkcja EasyFFT zaprojektowana do obsługi do 1028 próbek (z kompatybilną płytą), podczas gdy potrzebujemy tylko 128 próbek. ten kod zmniejsza zużycie pamięci o około 20% w porównaniu z oryginalną funkcją EasyFFT.

Po zakończeniu FFT kod zwraca 5 najbardziej dominujących szczytów częstotliwości do dalszej analizy. Te częstotliwości są uporządkowane w malejącym porządku amplitudy.

3. Dla każdego piku kod wykrywa możliwe nuty z nim związane. ten kod skanuje tylko do 1200 Hz. Nie trzeba mieć nuty takiej samej jak częstotliwość przy maksymalnej amplitudzie.

Wszystkie częstotliwości są mapowane od 0 do 255, tutaj wykrywana jest pierwsza oktawa, na przykład 65,4 Hz do 130,8 reprezentuje jedną oktawę, 130,8 Hz do 261,6 Hz reprezentuje inną. Dla każdej oktawy częstotliwości są mapowane od 0 do 255. tutaj mapowanie zaczynając od C do C'.

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

Wartości tablicy NoteV służą do przypisywania nuty do wykrytych częstotliwości.

bajt UwagaV[13]={8, 23, 40, 57, 76, 96, 116, 138, 162, 187, 213, 241, 255};

4. Po obliczeniu nuty dla każdej częstotliwości może się zdarzyć, że istnieje wiele częstotliwości, co sugeruje tę samą nutę. Aby mieć dokładny kod wyjściowy, należy również wziąć pod uwagę powtórzenia. Kod sumuje wszystkie wartości częstotliwości w oparciu o porządek amplitud i powtórzeń oraz zwiększa nutę z maksymalną amplitudą.

Krok 2: Aplikacja

Korzystanie z kodu jest proste, jednak istnieje również wiele ograniczeń, o których należy pamiętać podczas jego używania. Kod można skopiować, ponieważ jest używany do wykrywania banknotów. Poniższe punkty należy wziąć pod uwagę podczas korzystania z niego.

1. Przypisanie pinów:

Na podstawie załączonego przypisania Pin należy zmodyfikować. W moim eksperymencie trzymałem go na pin analogowy 7, void setup() {Serial.begin(250000); Mic_pin = A7; }

2. Czułość mikrofonu:

Czułość mikrofonu wymaga modyfikacji, tak aby przebieg mógł być generowany z dobrą amplitudą. Przeważnie moduł mikrofonu jest wyposażony w ustawienie czułości. należy dobrać odpowiednią czułość tak, aby sygnał nie był zbyt mały i nie przecinał się z powodu wyższej amplitudy.

3. Próg amplitudy:

Ten kod aktywuje się tylko wtedy, gdy amplituda sygnału jest wystarczająco wysoka. to ustawienie musi być ustawione ręcznie przez użytkownika. wartość ta zależy od czułości mikrofonu oraz aplikacji.

jeśli(suma2-suma1>5){

..

w powyższym kodzie sum2 daje wartość RMS, a suma 1 daje wartość średnią. więc różnica między tymi dwiema wartościami daje amplitudę sygnału dźwiękowego. w moim przypadku działa poprawnie z wartością amplitudy około 5.

4. Domyślnie ten kod wydrukuje wykrytą notatkę. jeśli jednak planujesz wykorzystać notatkę w innym celu, należy użyć bezpośrednio przypisanego numeru. na przykład C=0;C#=1, D=2, D#=3 i dalej.

5. Jeśli instrument ma wyższą częstotliwość, kod może dawać fałszywe dane wyjściowe. maksymalna częstotliwość jest ograniczona częstotliwością próbkowania. więc możesz pobawić się poniżej wartości opóźnienia, aby uzyskać optymalną wydajność. w poniższym opóźnieniu kodu 195 mikrosekund. które można dostosować, aby uzyskać optymalną wydajność. Wpłynie to na całkowity czas wykonania.

{ a=analogowyOdczyt(Mic_pin)-500; //zgrubne przesunięcie zera

suma1=suma1+a; //do średniej wartości sum2=sum2+a*a; // do wartości skutecznej a=a*(sin(i*3.14/128)*sin(i*3.14/128)); // Okno Hanna w=4*a; // skalowanie konwersji float na int delayMicroseconds(195); // na podstawie zakresu częstotliwości pracy }

6. ten kod będzie działał tylko do częstotliwości 2000Hz. eliminując opóźnienie między próbkowaniem można uzyskać około 3-4 kHz częstotliwości próbkowania.

Środki ostrożności:

  • Jak wspomniano w samouczku EasyFFT, FFT pochłania ogromną ilość pamięci Arduino. Więc jeśli masz program, który musi przechowywać jakieś wartości, zaleca się użycie płyty z większą pamięcią.
  • Ten kod może działać dobrze dla jednego instrumentu/wokalisty, a źle dla innego. Dokładne wykrywanie w czasie rzeczywistym nie jest możliwe ze względu na ograniczenia obliczeniowe.

Krok 3: Lato

Wykrywanie nut jest pracochłonną pracą obliczeniową, a uzyskanie danych wyjściowych w czasie rzeczywistym jest bardzo trudne, szczególnie na Arduino. Ten kod może dać około 6,6 próbek na sekundę (dla dodanego opóźnienia 195 mikrosekund). ten kod działa dobrze z fortepianem i niektórymi innymi instrumentami.

Mam nadzieję, że ten kod i samouczek będą pomocne w Twoim projekcie związanym z muzyką. w przypadku jakichkolwiek wątpliwości lub sugestii prosimy o komentarz lub wiadomość.

W nadchodzącym samouczku zmodyfikuję ten kod do wykrywania akordów muzycznych. bądźcie na bieżąco.

Zalecana: