Sida 1 av 2

Implementera IIR coupled form BiQuads

Postat: 17 december 2012, 01:12:24
av Korken
Godagens!

Jag har precis gjort en kurs i DSPer och allt kul man kan göra med dom.
Som slutprojekt gjorde jag en digital förförstärkare (EQ, vol och balanace).

Nu har jag funderat på att implementera detta i STM32F4 för att testa lite men funderar på hur dessa ska implementeras.
Då de inte stödjer SIMD instruktionerna för att hämta 2 koefficienter från minne, köra en MAC och skriva tillbaka på en klockcykel så kan det bli lite trångt (min nuvarande implementation behövde ca 2000 klockcykler per sample när jag hade dessa SIMD instruktioner).

Jag körde med ett gäng (12 st) 150 ordningens FIR filter för att skapa alla effekter, men detta kommer inte gå så ska gå över till 6-8 ordningens IIR filter var tanken.
Som många säkert vet så är det svårt med högre ordningens IIR filter så tänkte implementera det som BiQuads (kaskad-kopplade 2nd order filters) implementerade i "Coupled Form" för att få diskritiseringen av polpositioner att vara ett rutnät och inte halvmånarna som uppstår med dålig precision nära realaxeln om man kör med A och B polynom.

Men till frågan.
Har någon exempel hur man implementerar detta som effektivast? Fiffiga sätt att göra beräkningar för att få så lite operationer mot minnet tex.
För att få filter att fungera i lågfrekvensområden (under 1kHz) så tänkte jag down-sampla signalen 16ggr, planen är att ha en 8-10 bands EQ helst.
Banden kommer vara 2^n logaritmiskt uppdelade med en bas på 25-50 Hz tänkte jag, dvs tex: 50, 100, 200, 400, 800 Hz ... osv

Jag har märkt lite konstiga effekter mellan bandpass filtren, kan någon förklara detta (se bild)?
Detta uppstår inte med FIR filters. Och det spelar ingen roll om jag flyttar gränsfrekvenserna, fenomenet blir mindre men försvinner inte. Har som bäst fått +/- 3dB.
Har det att göra med den olinjära fasen hos IIR filter? Eller vilken ordning filtren har?
eq.png

Re: Implementera IIR coupled form BiQuads

Postat: 17 december 2012, 12:18:05
av anders_w
Hur har du gjort? Skapat ett antal bandpassfilter och summerar utsignalerna från dessa? I så fall kommer du att få problem vid övergångarna om inte grupplöptiden är lika för angränsande filter. Vilket antagligen är fallet för dina IIR-filter. Gör du FIR-filter av olika längd eller med olika samplingsfrekvens blir det också problem om du inte håller tungan rätt i munnen.

Re: Implementera IIR coupled form BiQuads

Postat: 17 december 2012, 22:30:34
av superx
Som anders_w påpekar, så ser det nästan ut som om du kör filtren parallellt och summerar utsignalerna. Det kan man göra, men det är inte så lätt att förutse vad som händer. En kaskad av bi-quads är väl det normala.

Vad är "Coupled Form"? Är det någon av dessa under ett annat namn:
http://www.earlevel.com/main/2003/02/28/biquads/

Att nedsampla signalen låter vanskligt. Har du några nedsamplingsfilter? Jag antar att du gör detta i en parallell-gren, för annars blir det väl inte mycket diskant kvar i signalen, och då uppstår risken för utsläckning på grund av olika grupplöptid när du summerar med resten av signalen.

Vad är det du vill åstadkomma -- är det något som liknar en grafisk EQ du är ute efter?

Re: Implementera IIR coupled form BiQuads

Postat: 18 december 2012, 13:09:52
av Korken
Så, nu har jag rest klart och har tillgång till internet igen :)

Såhär fungerar filtret:
eq2.png
Som ni har gissat så är det ett gäng filter som körs parallellt och sedan summeras signalerna från varje. Varje filter har samma ordning för att kunna använda samma kodsnuttar och öka effektiviteten.
Detta fungerade utan problem med FIR filters så har svårt att se varför detta inte fungerar med IIR.

Tanken om att ner-sampla för att få bättre precision i lägre frekvenser tycks vara den ända lösningen för att få det bra, självklart får man upp-sampla signalen och interpolera när man har filtrerat klart.
Jag gillar Butterworth filter, men har man väldigt liten bandbredd så blir de väldigt konstiga tyvärr (tex ett gain på 10^-16).

Grupptiden, vad är detta?
Det har vi inte gått igenom i någon av signalanayskurserna. Förklara gärna mer!

Detta ska bli en grafisk equalizer, ja. Vi byggde en riktigt fin analog förstärkare i en annan kurs och skulle vilja ha en liten skärm med grafisk EQ till den för att göra den komplett. :)

Coupled form är ett sätt att beräkna en BiQuad så att alla polpositioner kan placeras ut som ett rutnät.
Se figur 2 i bifogat dokument för info. :)
coupled_form.pdf

EDIT:
Här är en jämförelse mellan Coupled form implementation och Direct form implementaion.
Varje prick motsvarar en möjlig polposition med 6 bitars koefficienter:
coupled_vs_biquad.png

Re: Implementera IIR coupled form BiQuads

Postat: 18 december 2012, 17:35:36
av superx
FIR och IIR är olika. Detta kommer inte funka med IIR-filter, just eftersom att de alltid kommer att introducera en frekvensberoende fördröjning (grupplöptid är ett mått på detta). Om du summerar signaler som fördröjts olika mycket kommer det ge upphov till ett kamfilter, vilket är vad du ser i din plot av frekvenssvaret.

Jag gissar att dina FIR-filter var symmetriska och därmed hade en konstant fördröjning, oberoende av frekvens. Då går det att addera utsignalerna utan sidoeffekter. Men med den strukturen du skissat på kan du enbart åstadkomma förstärkning av frekvenser, men ingen dämpning. Dämpar du signalen i ett band kommer den gå rakt igenom i alla de parallella grenarna!

Observera dock att analoga filter fungerar precis som IIR-filter i det här avseendet, och det är därför inte helt trivialt att konstruera en grafisk EQ analogt heller. Rane har lite artiklar om detta på nätet tror jag.

Att sampla ned en parallell-gren och filtrera och sampla upp kommer inte att fungera. Nedsamplings- och interpellations-filtren kommer även dessa att fördröja signalen, och därmed skapa kamfilter-effekter när du summerar. Det går att få bra precision ändå, utan ned-sampling, men det kan vara lite klurigt. Kolla på noise-shaping t.ex.

Vad har STM-processorn för sorts ackumulator. Kan den göra 32x32 bitars multiplikation med 64-bitars resultat?

Hur stor bufferstorlek kör du? Det brukar göra stor skillnad på effektiviteten att köra 100-samples åt gången jämfört med en i taget.

Och sedan skulle jag nog föredra en bra parametrisk EQ framför en grafisk, men smaken är väl olika här.

Re: Implementera IIR coupled form BiQuads

Postat: 18 december 2012, 18:09:16
av Korken
>> FIR och IIR är olika. Detta kommer inte funka med IIR-filter, just eftersom att de alltid
>> kommer att introducera en frekvensberoende fördröjning (grupplöptid är ett mått på detta).
>> Om du summerar signaler som fördröjts olika mycket kommer det ge upphov till ett kamfilter,
>> vilket är vad du ser i din plot av frekvenssvaret.
Ajdå, jag satt och trodde att detta kanske var problemet (fast jag tänkte det som ett problem med olinjär fasförskjutning över frekvens).
Men avfärdade det då jag stirrade mig blind på magnitudplotten.

>> Jag gissar att dina FIR-filter var symmetriska ...
Precis, alla var 150e ordningens FIR filter.

Men precis som du säger så kommer inte ner och uppsampling att fungera som det ska heller.
Hur brukar detta problem lösas? Lite googling ger inga direkta bra svar.

>> Vad har STM-processorn för sorts ackumulator. Kan den göra 32x32 bitars multiplikation med 64-bitars resultat?
Japp de kan den! Allt i en instruktion (och en klockcykel). Hade du något i åtanke? :)
Jag hade nästan som plan att göra allt med floating point för att slippa behandla overflows i beräkningarna.

>> Hur stor bufferstorlek kör du? Det brukar göra stor skillnad på effektiviteten att köra 100-samples åt gången jämfört med en i taget.
Jag kör med ett sample åt gången. Hur kan det vara effektivare att ta flera på en gång? Man måste göra samma antal beräkningar per sample iaf.

>> Och sedan skulle jag nog föredra en bra parametrisk EQ framför en grafisk, men smaken är väl olika här.
Vad är en parametisk EQ? Hur skiljer sig denna från en grafisk?

Re: Implementera IIR coupled form BiQuads

Postat: 18 december 2012, 18:37:06
av superx
Ajdå, jag satt och trodde att detta kanske var problemet (fast jag tänkte det som ett problem med olinjär fasförskjutning över frekvens).
Men avfärdade det då jag stirrade mig blind på magnitudplotten.
Du kan ju lägga filtren i serie istället. Då kan du dessutom dämpa frekvenser, vilket du inte kan nu (förutom de som råkar dämpas av kamfiltret då).
Hur brukar detta problem lösas? Lite googling ger inga direkta bra svar.
Kolla på delen om noise-shaping här:
http://www.earlevel.com/main/2003/02/28/biquads/
Kräver dock att du kan få alla delresultat att ligga kvar i ackumulatorn med 64-bitar och enbart trunkerar när du sparar till minnet. Signalprocessorer brukar kunna detta. Vet ej hur det är i ditt fall.

32-bit floating point löser problemet åt dig och då slipper du dessutom skala om signalen om du förstärker några frekvenser. Som lite övning kan du ju försöka lista ut hur stor insignalen max får vara för att garanterat undvika klippning i ditt parallella fall med fixed-point-filter. Inte ett superlätt problem.

En parametrisk EQ har ett fåtal band där du kan välja frekvens, bandbredd och dämpning/förstärkning fritt. Här kommer ett klassiskt exempel:
http://www.solid-state-logic.com/music/ ... ies_eq.asp
Jag kör med ett sample åt gången. Hur kan det vara effektivare att ta flera på en gång? Man måste göra samma antal beräkningar per sample iaf.
Nja, om filterkoden för en bi-quad t.ex. kräver ett funktionsanrop så blir det ett funktionsanrop per sample jämfört med ett funktionsanrop per 100 sampels. Ganska stor skillnad!
Dessutom brukar man kunna ladda in koefficienter och tillstånd till register en gång per buffer och sedan bara multiplicera och addera i innerloopen. Om du kör en sample i taget behöver du ladda allt för varje filter för varje sample!

Re: Implementera IIR coupled form BiQuads

Postat: 19 december 2012, 13:41:17
av anders_w
Olinjär fasförskjutning över frekvens är samma sak som variation i grupplöptiden. Linjär fas = konstant grupplöptid. Så du tänkte rätt m a o (grupplöptid är derivatan av fasen och mäts i sekunder eller ibland samples, om man vill vara oberoende av samplingsfrekvensen).

Filter i serie är mycket enklare. Vill du köra parallelt är FIR bäst. Det går naturligtvis att sampla ner vissa grenar, filtrera och sampla upp igen. Men alla grenar måste fördröjas exakt lika lång tid innan de summeras. Vilket innebär en del svårigheter och det kostar operationer och minne.

Re: Implementera IIR coupled form BiQuads

Postat: 19 december 2012, 13:55:05
av Korken
Ah, jag förstår! Tackar! :)

Finns det något enkelt sätt att få bra precision vid lägre frekvenser utan att nedsampla?
Med floating point kan jag få ned det ganska rejält, men det är fortfarande problem under 400Hz vif 48kHz samplingshastighet.

Re: Implementera IIR coupled form BiQuads

Postat: 19 december 2012, 13:59:48
av superx
Vad får du för problem med 400Hz och 48kHz samplingshastighet? Det borde inte ge några problem tycker jag?
Hur ser filtret ut?

Re: Implementera IIR coupled form BiQuads

Postat: 19 december 2012, 14:13:37
av Korken
Problemet som uppstår är att om jag designar med butterworth så faller filtret för sakta så alla filter vid låg frekvens överlappar för mycket.

Och vill helst inte öka ordningen för mycket.

Re: Implementera IIR coupled form BiQuads

Postat: 19 december 2012, 14:22:48
av superx
Visa koefficienterna!

Re: Implementera IIR coupled form BiQuads

Postat: 19 december 2012, 15:16:33
av Korken
Koefficienter för 8de ordningens Butterworth LP-filter med brytfrekvens på 400Hz:

Kod: Markera allt

sos =

    1.0000    2.0000    1.0000    1.0000   -1.8997    0.9024
    1.0000    2.0000    1.0000    1.0000   -1.9140    0.9166
    1.0000    2.0000    1.0000    1.0000   -1.9408    0.9435
    1.0000    2.0000    1.0000    1.0000   -1.9771    0.9798


g =

  1.9331e-013

Re: Implementera IIR coupled form BiQuads

Postat: 19 december 2012, 15:23:00
av superx
Hm... kan du förtydliga lite. Vilken koefficient är vilken?

Re: Implementera IIR coupled form BiQuads

Postat: 19 december 2012, 15:26:34
av Korken
Ah, det är på SOS form. Det är såhär då:

BiQuad 1:
B = 1.0000 2.0000 1.0000
A = 1.0000 -1.8997 0.9024

BiQuad 2:
B = 1.0000 2.0000 1.0000
A = 1.0000 -1.9140 0.9166

BiQuad 3:
B = 1.0000 2.0000 1.0000
A = 1.0000 -1.9408 0.9435

BiQuad 4:
B = 1.0000 2.0000 1.0000
A = 1.0000 -1.9771 0.9798

Gain som läggs på efter filtret för att få unity gain:
g = 1.9331e-013