Göra lampor reagera på ljud (3 / 5 steg)
Steg 3: programvara
Du hittar programvaran som Atmel Studio projekt på github
Det finns 2 projekt i denna git. Grundläggande projektet omfattar alla grundläggande funktioner för att mäta och beräkna data. Den innehåller också en klass för WS2812 LED. Matrixproject innehåller alla data för mitt projekt baserade en en 7 x 6 LED-matris med WS2812 LED. Eftersom detta är mycket specifika, är denna kod mer av en inspiration och exempel för vad du kan göra.
Denna del är den mest komplexa av detta projekt som programmet behöver för att göra en massa saker.
Provtagning Data
Först måste du hämta data till kontrollern. Detta görs genom provtagning ljudsignalen med en ADC. Provtagningsfrekvensen beror på frekvensen spänner du vill arbeta med. Om du prova signalen med en skattesats på 32kHz kan du återskapa signalerar upp till 16kHz med Fourier omvandling (FT). Detta är frekvensen spänner vi vill arbeta med.
För att göra detta arbete timern en att utlösa med en frekvens av 32kHz och läsa ett värde från ADC varje gång detta händer. Eftersom atxmega handkontrollen har en DMA-styrenheten, används för att automatisera processen. DMA (Direct Memory Access) kan du flytta data från en punkt i minnet till en annan helt i hårdvara. DMA är inställd på ett sätt, att den rör sig resultatet från ADC till en specifik plats i RAM-minnet när den utlöses av timern. Vi prova 128 värden per kanal.
Fast Fourier omvandling (FFT)
Vi använder elmchan FFT biblioteket för detta projekt.
Vanligtvis en FT använder en massa tid för beräkning, men gör att du kan återskapa varje frekvens inom given signal spektrumet. FFTEN förenklar den här processen och snabbar det upp. Nackdelen är, att det inte ger dig särskilda frekvenser men frekvensband. För detta projekt är informationen tillräckligt bra.
Eftersom vi prova 128 värden, ger FFTEN oss 64 resultat. På grund av samplingsfrekvens (32 kHz) kan vi återskapa frekvenser upp till 16 kHz, som är indelade i 64 band av FFTEN. 16000 / 64 = 250. Detta innebär att varje FFT band beskriver nivån av 250 Hz. FFT band 1 ger ett värde för 1Hz till 250Hz, band 2 för 251Hz till 500Hz, band 3 för 501Hz till 750Hz och så vidare. Genom att öka antalet ingående prover kan du öka denna resolution, men också öka behövs beräkning tiden.
De 64 band konsolideras i 7 band, som används för matrisen, som har en bredd på 7 LED. Vissa effekter är fortfarande baserade på de ursprungliga 64 band.
Algoritm för att beräkna FFT är kodad på ett sätt, att det inte gör alla beräkningssteg på en gång, men delar upp dem i mindre bitar. Detta görs för att ge controller tid att beräkna annan sak mellan dessa steg. Om du inte gör detta, animationer kommer ibland stammar, som inte ser bra ut.
Det mänskliga örat reagerar olika på vissa frekvenser. Det är mycket förnuftigt att frekvenser runt 4kHz och inte förnuftigt att mycket låga och höga frekvenser. I en audio signal de låga frekvenserna kommer att ha en hög amplitud, som leder till höga FFT resultat, och låga amplituder i mitten frekvenserna, vilket leder till låga FFT resultat. Detta gör det svårt att göra beräkningar med. För att motverka detta en mycket enkel omvänd a-viktningssystemet används. Koefficienterna som pre beräknas för varje band och multiplicerade med var och en av de 64 FFT band.
Fick upptäcka
Den grundläggande tanken bakom detta är enkel: den genomsnittliga ljudnivån makt. Om den nuvarande makten är långt högre än genomsnittet har du ett beat. Du skulle behöva prova ljudsignalen kontinuerligt, vilket vi inte gör det gör ordentligt. Men vi fortfarande använder denna idé.
FFT resultaten delas upp i 3 band: låg, medium och hög. Dessa värden är medelvärde över tiden som ett glidande medelvärde. Om den nuvarande nivån är högre än 50% till 100% (beroende på bandet) av detta genomsnitt bedöms det som beat. Detta fungerar mycket bra med en metronom som producerar en enkel ljud, men fungerar också bra med komplexa signaler som låtar. Slå upptäckt i det lägre bandet fungerar bäst och mitten bandet värst när det finns sång i låten.
Vad göra med dessa data?
Jag ska förklara hur mono spektrum displayen fungerar som ett exempel. Du kan hitta koden i den kompletta projektet i animations.cpp i funktionen void anim_monospektrum_step(). Denna animation används i introvideon.
Värdena på de 7 konsoliderade band ställs som målvärden för höjden av kolumnerna. Det skalas på ett sätt, att detta värde varierar mellan 0 och 9000. Målet färg offset anges av amplituden. De faktiska värden som används för att beräkna produktionen, ändra sakta deras värde för att matcha målvärdet. Detta gör att animeringen ser mycket vätska och hindrar plötsliga hopp.
Matrisen har en höjd av 6 LED. Detta innebär att varje LED täcker 9000 / 6 = 1500 räknas av det faktiska värdet. Om det faktiska värdet av ett band är 1500, skulle endast LED i botten tändas. Om värdet var 3000 de två mest botten LED skulle lysa upp. Så länge det faktiska värdet är större än 1500 vi lyser upp en mer ledde och subtrahera 1500 från värdet. Om det efter denna process, värdet inte är 0, lysdioden ovanför den senaste full-lit LED belyst också, men ljusstyrkan skalas med värdet. Ju lägre den återstående värde, desto lägre ljusstyrka.
Som en extra detalj blinkar band när ett beat inom detta band har upptäckts.