Innehållsförteckning:

Arduino Music Notes Detector: 3 steg
Arduino Music Notes Detector: 3 steg

Video: Arduino Music Notes Detector: 3 steg

Video: Arduino Music Notes Detector: 3 steg
Video: Arduino MIDI Controller: Part 3 - Multiplexers 2024, November
Anonim
Image
Image

Det är svårt att upptäcka musiknoter från ljudsignalen, särskilt på Arduino på grund av begränsat minne och processorkraft. I allmänhet är noten inte en ren sinusvåg som gör detekteringen svår. Om vi tar frekvensomformningen för olika musikinstrument kan den innehålla flera övertoner baserade på noten som spelas. Varje instrument har sin egen signaturkombination av olika övertoner. I den här koden försökte jag göra ett program som kan täcka så många instrument som möjligt. Du kan hänvisa till bifogad video där jag försökte testa de olika typerna av instrument, olika typer av toner som genereras av tangentbordet och till och med ljud av röst kontrolleras. Detektionens noggrannhet varierar från instrument till instrument. För vissa instrument (dvs piano) inom ett begränsat område (200-500Hz) är det korrekt, medan vissa instrument har låg precision (dvs Harmonica).

Denna kod använder en tidigare utvecklad FFT -kod som kallas EasyFFT.

Demonstrationen av koden visas i videon ovan med olika typer av instrumentljud och sång.

Tillbehör

- Arduino Nano/Uno eller högre

- Mikrofonmodul för Arduino

Steg 1: Algoritm för anteckningsdetektering

Som nämnts i föregående steg är detekteringen svår på grund av förekomsten av flera frekvenser i ljudproverna.

Programmet fungerar i följande flöde:

1. Datainsamling:

- detta avsnitt tar 128 samplingar från ljuddata, separationen mellan två samplingar (samplingsfrekvens) beroende på frekvensen av intresse. I det här fallet använder vi avstånd mellan två samplingar används för att tillämpa Hann -fönsterfunktion samt amplitud/RMS -beräkning. Denna kod gör också grov nollning genom att subtrahera 500 från analogläst värde. Detta värde kan ändras om det behövs. För ett typiskt fall fungerar dessa värden bra. Vidare måste en viss fördröjning läggas till för att ha en samplingsfrekvens på cirka 1200 Hz. vid 1200Hz samplingsfrekvens kan max 600 Hz frekvens detekteras.

för (int i = 0; i <128; i ++) {a = analogRead (Mic_pin) -500; // grov noll skift sum1 = sum1+a; // till genomsnittligt värde sum2 = sum2+a*a; // till RMS -värde a = a*(sin (i*3.14/128)*sin (i*3.14/128)); // Hann -fönster i = 4*a; // skalning för float till int -konverteringsfördröjningMicroseconds (195); // baserat på driftfrekvensintervall}

2. FFT:

När data är klar utförs FFT med EasyFFT. Denna EasyFFT -funktion är modifierad för att fixa FFT för 128 prover. Koden ändras också för att minska minnesförbrukningen. Den ursprungliga EasyFFT -funktionen är utformad för att ha upp till 1028 prover (med det kompatibla kortet), medan vi bara behöver 128 prover. denna kod minskar minnesförbrukningen med cirka 20% jämfört med original EasyFFT -funktionen.

När FFT är klar returnerar koden de fem mest dominerande frekvenstopparna för ytterligare analys. Denna frekvens är arrangerad i fallande amplitudordning.

3. För varje topp upptäcker koden eventuella anteckningar som är associerade med den. denna kod skannar bara upp till 1200 Hz. Det är inte nödvändigt att notera samma som frekvensen med maximal amplitud.

Alla frekvenser kartläggs mellan 0 och 255, här detekteras den första oktaven, till exempel 65,4 Hz till 130,8 representerar en oktav, 130,8 Hz till 261,6 Hz representerar en annan. För varje oktav mappas frekvenser från 0 till 255. här mappning från C till C '.

om (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 -arrayvärden används för att tilldela noten till de detekterade frekvenserna.

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

4. Efter beräkning av ton för varje frekvens kan det vara så att det finns flera frekvenser som föreslår samma ton. Att ha en korrekt utdatakod överväger också upprepningar. Koden lägger till alla frekvensvärden baserade på amplitudordning och repetitioner och toppar noten med maximal amplitud.

Steg 2: Ansökan

Att använda koden är rakt fram, men det finns också flera begränsningar som måste hållas i åtanke medan den. Koden kan kopieras när den används för att upptäcka anteckningar. Nedanstående punkter måste beaktas när du använder det.

1. Stifttilldelning:

Baserat på den bifogade Pin -tilldelningen måste ändras. För mitt experiment höll jag det till analog stift 7, void setup () {Serial.begin (250000); Mic_pin = A7; }

2. Mikrofonkänslighet:

Mikrofonkänsligheten måste modifieras, sådan vågform kan genereras med bra amplitud. Oftast har mikrofonmodulen en känslighetsinställning. lämplig känslighet för att väljas så att signalen inte är för liten och inte klipps av på grund av högre amplitud.

3. Amplitudtröskel:

Denna kod aktiveras endast om signalamplituden är tillräckligt hög. denna inställning måste ställas in manuellt av användaren. detta värde beror på mikrofonkänslighet och applikation.

if (sum2-sum1> 5) {

..

i ovanstående kod ger sum2 RMS -värde medan summa 1 ger medelvärde. så skillnaden mellan dessa två värden ger ljudsignalens amplitud. i mitt fall fungerar det korrekt med ett amplitudvärde på cirka 5.

4. Som standard kommer den här koden att skriva ut den upptäckta anteckningen. men om du planerar att använda lappen för något annat ändamål bör det direkt tilldelade numret användas. till exempel C = 0; C#= 1, D = 2, D#= 3 och framåt.

5. Om instrumentet har högre frekvens kan koden ge falsk utmatning. maxfrekvensen begränsas av samplingsfrekvensen. så du kan spela runt fördröjningsvärdena för att få optimal utgång. i nedanstående kodfördröjning på 195 mikrosekunder. som kan justeras för att få optimal effekt. Detta påverkar den totala körtiden.

{a = analogRead (Mic_pin) -500; // grov nollskiftning

sum1 = sum1+a; // till genomsnittligt värde sum2 = sum2+a*a; // till RMS -värde a = a*(sin (i*3.14/128)*sin (i*3.14/128)); // Hann -fönster i = 4*a; // skalning för float till int -konverteringsfördröjningMicroseconds (195); // baserat på driftfrekvensintervall}

6. den här koden fungerar bara till 2000Hz frekvens. genom att eliminera fördröjningen mellan samplingen runt 3-4 kHz av samplingsfrekvenser kan erhållas.

Försiktighetsåtgärder:

  • Som nämnts i EasyFFT -handledningen äter FFT upp en enorm mängd minne av Arduino. Så om du har ett program som behöver lagra vissa värden rekommenderas att du använder ett kort med högre minne.
  • Denna kod kan fungera bra för ett instrument/sångare och dåligt för ett annat. Realtid Noggrann detektion är inte möjlig på grund av beräkningsbegränsningar.

Steg 3: Sommar

Notupptäckt är beräkningskrävande arbete, det är mycket svårt att få realtidsoutput, särskilt på Arduino. Denna kod kan ge cirka 6,6 prover /sekunder (för 195 mikrosekunder fördröjning tillagd). denna kod fungerar bra med piano och några andra instrument.

Jag hoppas att denna kod och handledning kan vara till hjälp i ditt projekt relaterat till musik. vid tvivel eller förslag, kommentera eller meddela gärna.

I den kommande handledningen kommer jag att ändra den här koden för upptäckt av ackord. så håll utkik.

Rekommenderad: