Permalänk
Medlem

Få ut vissa frekvenser ur ljud?

Jag försöker dela upp ett ljud i dess olika frekvenser, eller rättare sagt, konstruera ett bandpassfilter så att jag får ut en kurva för tex ljudet mellan 20 och 100Hz och en annan för ljudet mellan 100Hz och 1000Hz. Efter att ha letat runt ett tag på nätet så har jag kommit fram till att man använder FFT eller Wavelets för att åstakomma detta, dessvärre så förstår jag inte över huvud taget vad det är för data jag får ut :(.
Finns det någon här som kan hjälpa mig med att få ut den datan i ett förståeligt format? Jag har bland annat testat FFTW-biblioteket, och får ut arrayen med komplexa tal, men vad står dom olika talen för? Om ni har andra tips på bibliotek som är lättare att förstå eller andra tillvägagångssätt så är det också välkommet, vilket språk som det implementeras i är ganska oviktigt så länge det inte är några windowsspecifika anrop eller något sånt.

Visa signatur

Micael Ehn
ICQ: 2450221 Mail: micke(at-tecken)ehn.nu

Permalänk

Det du får ut är frekvenserna. Om du tar absolutbeloppet av talen så kan du rita upp frekvensspektrumet. Tyvärr vet jag inte om du får ut värden för den diskreta fft:n, eller den kontinuerliga, så jag kan inte säga vad varje värde i arrayen står för, mer än att de är ordnade i frekvensordning.

Tyvärr kan jag inte tipsa dig om några bra bibliotek eftersom jag bara hållt på i Matlab....

edit: Jag hittade manualen till fftw, jag kanske kan komma med mer info.

edit2: Glömde att fråga en sak. I princip så tar en fft in ett antal värden under ett tidsintervall, sen kan man transformera dessa.
Om du har t.ex. en wav-fil så är det enklaste att ta hela filen och transfomera den. Du kommer då att få en frekvenskurva för hela filen.

Om man vill göra det lite mer komplicerat så kan man dela upp filen i flera smådelar och rita upp en frekvenskurva som ändras med tiden, dock är det lite mer jobb bakom. Hur hade du tänkt göra?

edit 3:
Efter att tagit absolutbeloppet av alla tal du får ut borde du kunna tolka arrayen så här:
element n i arrayen svarar mot frekvens n*fs/N Hz, där fs är samplingsfrekvensen och N är antal sampel du tar in i transformen.
Jag är lite osäker om jag har tolkat utdata rätt. Det kan hända att du får någonting som verkar vara speglad i mitten, då har du frekvenserna från mitten och framåt (alt. från början till mitten).

Permalänk
Medlem

Som jag skrev i första inlägget så skulle jag vilja ha ut en array för varje frekvensområde, där index i arrayen står för tid och innehållet står för amplitud. Jag antar att jag måste göra ytterligare en omvandling för att få tillbaka datan till det formatet.
Att läsa in en wav-fil och skicka in den i fftw är inga problem, det är att tolka utdatan som jag har problem med. Vilka tal är det man ska ta absoultbeloppet på? Den reella eller den imaginära delen?

Visa signatur

Micael Ehn
ICQ: 2450221 Mail: micke(at-tecken)ehn.nu

Permalänk

Jag fixar en liten lathund.

1: Hitta samplingsfrekvensen för din wav-fil (i Hz). Jag kallar den fs och visar med 5 kHz.

2: Bestäm antal sampel som du ska ha med. Om du vill ha 5sekunders ljud så blir sampellängden N = 5*5000 = 25000 sampel.
2: Bestäm dina gränsfrekvenser. Jag visar för ett exempel med ett bandpassfilter mellan 20 (fl) och 100 Hz(fh). I princip går det ut på att hitta det sampel som svarar mot rätt frekvens, men varje frekvens svarar mot 2 frekvenser! (rätt mycket matte till orsakerna, men i princip är frekvensplanet speglat i mitten).
De första är ganska lätta att förstå sig på, helt enkelt:
f = sampelnr *fs/N, dvs sampelnr = f/fs*N
Den andra, spegelvända är
f = (N - sampelnr)*fs/N dvs sampelnr = N - f/fs*N

För mitt exempel kommer du ha följande sampel att hålla reda på:
för 20 Hz:

20/5000*25000 = 100
25000-20/5000*25000 = 24900

för 100 Hz:
100/5000*25000 = 500
25000-100/5000*25000 = 24500.

Första sampelnr är alltså 0.
Om du vill ha med frekvenser på 1000 Hz måste du ha en samplingsfrekvens på minst 2000Hz (alltid det dubbla).

3: Fouriertransformera.

4: Om du vill ha ett bandpassfilter så sätt alla sampel utanför ditt område till 0 och behåll de innanför.
I exemplet, nolla alla sampel i intervallen
0-99, 500-24500, 24900-24999 (högsta sampelnr är ju 24999...)

5: Om du vill kan du nu visa upp vad du har, men spara undan de data du har skapat i punkt 4.
Du kan visa en vettig kurva (på något sätt, du får komma på själv ).
Om du vill slippa knöligheterna med att förklara matematiken bakom så räcker det med att visa hälften av samplena då den andra halvan är spegelvänd.

De sampel det gäller i mitt exempel är 0-12499.
Dessa sampel tar du absolutbeloppen av. De har alla ett utseende som ser ut så här z = a+ib.
absolutbeloppet av det är sqrt (a^2 + b^2). Jag tror att du kan hitta en bra abs(z) i de bibliotek som finns i fftw, så går det snabbt.
Absolutbeloppet är alltid reellt och därför fin att plotta.

6: Gå tillbaka till de data du sparade. Om du vill skapa en ny fil med enbart de frekvenser inom bandpasset så kan du inverstransformera dessa data. Jag har tyvärr inte riktigt hittat hur man gör det i fftw, men det borde rimligtvis gå att göra. sök på inverse transform på siten. När du har inverstransformerat så har du ljudet tillbaka, men bara de frekvenser du ville ha med.

Observera FAQ:en! 3.11 säger att man måste ha float som taltyp.

Hoppas att det räcker!

Permalänk
Medlem

Tack för svaret! Väldigt bra skrivet (och bra med exemplet, annars hade jag nog inte riktigt hängt med). Plotta datan gjorde jag med gnuplot, den kan ta en textfil med värden så det passar väldigt bra. Inversfunktionen hittade jag, den heter samma som den första funktionen, men c2r (complex to real) istället för r2c.
En liten fråga bara, när man har transformerat tillbaka, är det några speglade frekvenser kvar då, eller försvinner dom vid inverstranformeringen?

Visa signatur

Micael Ehn
ICQ: 2450221 Mail: micke(at-tecken)ehn.nu

Permalänk

När du transformerar går du mellan tiddomänen och frekvensdomänen, så när du har transformerat tillbaka så är du i tidsdomänen.
Om du skulle transformera igen så får du dessa speglade frekvenser igen, men dom finns bara till för att matematiken ska funka.

Så svaret är ja, dom finns kvar, men du blir aldrig av med dem.
Alt. Nej dom finns inte, och har aldrig funnits.