Forum: Digitale Signalverarbeitung / DSP / Machine Learning Koeffizientenproblem für IIR-Filter-Implemenation


von Albi G. (deralbi)


Angehängte Dateien:

Lesenswert?

Hallo.
Ich habe, wie man im Anhang sieht eine vorgegebene 
IIR-Filter-Implementation eines DAC-Wandlers.

Die Koeffizienten müssen als FixedPoint (Q15) vorliegen.
Mein Plan ist es 2 Shelf-Filter zu implementieren. Einen für Höhen.. 
einen für Bässe und dafür jeweils ein biquad zu verwenden.


Für einen lowShelf-Filter für die Bässe erhält man z.B. folgende 
koeffizienten:

Berechnung:

float dbGain = 20;
float A = pow(10, dbGain /40);
float omega = 2  pi   f0 / SAMP_FREQ;
float sn = sin(omega);
float cs = cos(omega);
float  beta = sqrt(A + A);
b0 = A*  ((A+1) - (A-1)*cs  + beta*sn);
b1 = 2*A*((A-1) - (A+1)*cs);
b2 = A*  ((A+1) - (A-1)*cs  - beta*sn);
a0 =     ((A+1) + (A-1)*cs) + beta*sn;
a1 = -2* ((A-1) + (A+1)*cs);
a2 =     ((A+1) + (A-1)*cs) - beta*sn;

Koeffizenten: (durch a0 dividiert)
a0 = 1
a1 = -1,98912252587406
a2 = 0,989181317356648
b0 = 1,01182878630458
b1 = -1,98885781422416
b2 = 0,977617242701964


So. Wenn man sich jetzt z.B. a1 oder b1 ansieht, sieht man, dass diese 
nicht in das Q15-Fixkomma-Format passen. (nicht in [1..-1]).
Es läge nun auf der Hand die Koeffizienten einfach durch 2.0 zu teilen.
-> Laut implementation MUSS a0 aber 1.0 (32768) sein. (wäre dann ja 0.5)

Wie geht man hier nun vor, um den gewünschen filtereffekt doch noch zu 
erhalten?
Oder mache ich etwas bei der Berechnung falsch?

Implementiere ich den Filter in Software (mit variablen a0) klingt der 
Filter wie gewünscht. Dividiere ich die Koeffizenten und setze a0 danach 
wieder auf 1.0, kommt wie erwartet humbug raus.

Was tut man in so einem Fall? Eigentlich muss a0 der größe Koeffizient 
sein um einen Filter so implementieren/betreiben zu können.

Oder kann sich der Effekt eines "a0 != 1.0" durch das 2. Biquad wieder 
ausgleichen lassen?  Das sehe ich als einzige Möglichkeit.. funktioniert 
das??

Was tun?

MFG

von die ??? (Gast)


Lesenswert?

a0 auf 1 lassen, anschließend (hier um 2) verstärken (Linksshift).

von Albi G. (deralbi)


Lesenswert?

So funktioniert das im SoftwareFilter zumindest, stimmt - schon 
probiert.
Ich dividiere das Ergebnis im nachhinein einfach mit dem eigentlichen 
a0. (also ~0.5 == *2)

Problem: in der festen implementation geht das nicht. Ich hab ja auch 
den AudoPfad keinen Zugriff mehr sondern nur die Filterkoeffizienten, an 
den ich was drehen kann. Ginge die Multiplikation in den 2. Biquad zu 
verschieben? Oder ist das nur eine Traumvorstellung?

von TheMason (Gast)


Lesenswert?

hallo albi,

ich kenn das von den ti-dsps (tas3103 usw) das die koeffizienten immer 
durch einen festen wert (2'er potenz) geteilt werden.
beim tas3103 wird immer durch 32 geteilt (also 2^5).
dieses "format" wird dann 5.23 genannt (5 vorkomma"stellen", 23 
nachkomma"stellen").
solange du das für ALLE koeffizienten machst, geht das auf jedem system. 
du kannst die koeffizienten auf einem tas3101 (5.23-format) sowie auf 
einem tas3004 (4.16-format) laufen lassen. mußt halt nur anders shiften.

von TheMason (Gast)


Lesenswert?

nachtrag :

bei meinem audio-projekt benutze ich das 8.24 format (also 8 bit 
vorkomma und 24 bit nachkomma). mein audio-signal hat 24 bit + 8 bit 
overhead (intern). so rechne ich durchgängig mit 32 bit zahlen. ich muß 
nur am ende einmal um 8 bit nach rechts schieben wegen dem overhead, der 
im i2s signal ja nicht vorhanden ist. da clippe ich dann einfach.

von Albi G. (deralbi)


Lesenswert?

Ich nutzen als DAC einen "tlv320aic3101"
Hier das Datenblatt: 
http://focus.ti.com/lit/ds/symlink/tlv320aic3101.pdf
Auf Seite 35 gehts los mit dem Thema, das mich [uns hier] beschäftigt.
Ich habe 16bit Koeffizenten und den vorgegeben Filter.

Die gewünschten 6 Koeffizenten sind, wie oben geschrieben:
a0 = 1
a1 = -1,98912252587406
a2 = 0,989181317356648
b0 = 1,01182878630458
b1 = -1,98885781422416
b2 = 0,977617242701964

Die vorhanden eines Fitlers 5 Koeffizenten würde ich wie folgt 
programmieren:
N0..3 = b0..3
D1..2 = a1..2
a0 wird nicht gebraucht, da es auf 1 ist. Ich denke dafür steht die 
32768.
Problem: z.B a1 passt nicht in das Zahlenformat. (< -1.0)
Eure lösung bisher: skalieren. Alles durch 2 oder 4.
geht aber nicht, da a0 ja dann auch skaliert werden müsste. a0 steht 
aber als "1.0" fest. Das Ergebnis des Filters im Nachhinein durch das 
eigentliche a0 zu teilen geht ja nicht, da die Verarbeitungsreihnfolge 
feststeht und ich darauf keinen Zugriff habe.

In einem Softwarefilter wäre das kein Problem. Hier habe ich NUR die 
koeffizienten.


Wie löst man das Problem..?

von die ??? (Gast)


Angehängte Dateien:

Lesenswert?

Nein, a0 muss nicht mitskaliert werden. a0 bleibt 1, alle anderen 
Koeffizienten durch eine passende 2er-Potenz. Hinter dem Filter 
multiplizierst du wieder mit der besagten 2er-Potenz. Warum 2er-Potenz? 
Weil die i.d.R. mit einem Shift realisiert wird. Und warum geht das so? 
Siehe Anhang.  ;^)

von die ??? (Gast)


Angehängte Dateien:

Lesenswert?

Na hoppala, da hat sich der copy-paste-Fehler eingeschlichen. $^)  Aber 
nu....

von Albi G. (deralbi)


Lesenswert?

Versteh doch.. WIE soll ich denn in einer vorgegebenen 
Verarbeitungsreihnfolge, so wie es der DAC implementiert, im Nachhinein 
einen Shift einbauen??? Dafür gibt es weder einen Shift-Koeffizenten 
noch ein Register, wo man sowas ablegen könnte... Bei mir gibt es kein 
"Hinter dem Filter.." da kommt dann der DAC
das genau ist doch mein Problem.. sonst würde ich doch nicht fragen ;-)

von die ??? (Gast)


Lesenswert?

Ähhhh, stop mal eben. Also von dir angegebenen Koeffizienten a0 bis b2 
möchtest du gerne implementieren mit dem fest verwursteten Filter? Daher 
kannst du nicht mehr an a0 ran? (Hatte ich vorher nicht realisiert.) Die 
Filterfunktion wird von ti/BB wie in deinem ersten Anhang angegeben. Und 
dort steht vor a1 und b1 eine 2*...also musst du dein a1 und b1 ohnehin 
durch 2 teilen - und dann passts doch?! Oder sehe ich hier etwas falsch?

von Albi G. (deralbi)


Lesenswert?

aha!
klingt gut. hab ich auch noch nicht bemerkt. Kenne mich mit den Formeln 
niocht so aus.. hab nicht gewusst, dass das unnormal bzw eine 
implementierungshilfe ist ;-)

Mist ist aber immernoch: N0 == b0 == 1.01 ->   :-(

von die ??? (Gast)


Angehängte Dateien:

Lesenswert?

Wo hast du die Koeffizienten her? Einfach auf 1 runden ist nicht ratsam, 
siehe Anhang (rot = gerundet).

von Albi G. (deralbi)


Lesenswert?

Koeffizientenberechnung: Siehe Erster Post.
Der Code entspringt: Beitrag "Zeitvariante Filter"

Auf eins gerundet hab ichs auch schon versucht ;-)
Das Resultat klang ungefähr.. nuja ;-) wie der rote Graph ;-)

Aber das stellt jetzt schon wirklich ein Problem dar, oder?
Mist :-(

von TheMason (Gast)


Lesenswert?

@albi

ganz oben in der formel wird ja 2xN1 und 2xD1 erwähnt.
teilst du dein b1 bzw. a1 durch 2 bleibst du unterhalb von 1.0.
sehe ich das richtig ? somit müsste/könnte es passen.

von die ??? (Gast)


Lesenswert?

Ich habe mir jetzt nicht alles zur Gänze zu Gemüte geführt, aber was mir 
auffällt ist, dass dein Filter eine Verstärkung von +20dB hat. Ich kenne 
das nicht so. Wie klingt es denn mit dem gerundeten Koeffizient? 
Verzerrt oder eigentlich sauber, nur etwas zu "hell"?
Ich kenne das nur so, dass der Frequenzgang maximal 0dB ist (und hiermit 
den Zahlenbereich ausreizt). Nun dann, das musst du selbst wissen ob das 
so gewollt ist oder nicht. Zusätzlich stellt sich mir die Frage, welche 
Aufgabe und Spezifikationen (f_pass, f_stop, f_s, Dämpfung im 
Sperrbereich) dieses Filter haben soll. Davon ausgehend kann ich mir das 
nochmal angucken.

von Der A. (der-albi)


Lesenswert?

Ich kenne mich leider mit digitalen Filtern und deren Eigenschaften 
nicht so recht aus :-(

Angaben wie "f_pass, f_stop, f_s, Dämpfung im Sperrbereich" kann ich dir 
nicht geben. Ich bewerte lieber nach "Klingt <-> klingt nicht" ;-)

Die 20dB Anbhebung funktionieren. Ich muss das Eingangssignal vorher 
skalieren (Faktor 1/6) damit ein Short nicht überläuft.
Das ganze ließe sich sicherlich auch mit 0dB Verstärkung und im 
restlichen Bereich eine Abschwächung um 20dB ohne das Signal zu 
skalieren.
Sollte das Selbe rauskommen. Das wäre quasi ein HighShelf mit 20dB 
Abschwächung ab 100Hz anstatt ein LowShelf bis 100Hz.

Wenn die Senkung des Pegels die Koeffizienten zu meinem Vorteil 
verändert... her mit den Vorschlägen! Ich kenne mich leider nicht genug 
aus... ich weiß nichtmal ob die HighShelf-Variante von der Charakterisik 
einen Skalierten (leidergemachten) LowShelf ersetzen kann...

@Die 3 Fragezeichen: Wenn du andere Formeln hast zur Berechnung solcher 
Filter... mit anderen/mehr parametern... her damit... experimentiere 
gerne :-)

MFG

von die ??? (Gast)


Angehängte Dateien:

Lesenswert?

Du möchtest also die Bässe kräftiger machen, ergo LowShelf. Du hast die 
Frage

> Wie klingt es denn mit dem gerundeten Koeffizient? Verzerrt oder eigentlich
> sauber, nur etwas zu "hell"?

leider nicht beantwortet.

Im Anhang habe ich dir mal ein Schema gelegt welches erklärt, was ich 
mit den Parametern meine. Wie hoch ist deine Abtastfrequenz f_s?

von Der A. (der-albi)


Lesenswert?

Danke für dein Bild :-)

fs ist variabel, aber z.Z. 44100Hz.
Es klingt einfach babarisch nach "WummsWumms" ;-) Und ich muss das 
Eingangssignal mit rund 1/90 skalieren, damit Short nicht überläuft. 
Heller wird dabei nix. bzw es verschwindet im Bass.

Auch die anderen Parameter des Filters sollen variabel gehalten werden. 
Die Berechnung soll später direkt auf dem µC erfolgen..

Wäre schön, wenn du helfen könntest. Am liebsten wären mir Formeln.. 
keine fertigen Koeffizienten ;-)

MFG

von die ??? (Gast)


Lesenswert?

Du solltest Post haben.  :^)

von Albi G. (deralbi)


Lesenswert?

Hab ich. Du aber auch, Justus-Jonas. :-P

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.