Das Kuhschwanzfilter für Tiefenanpassung (engl. Low shelving filter) verstärkt oder dämpft einen Frequenzbereich unter gleichmäßig, während es die die höheren Frequenzen des Spektrums unverändert durchlässt.
Die Übertragungsfunktion eines digitalen Low-Shelving Filters 2. Ordnung kann als
(1)
beschrieben werden.
Ermittlung der Koeffizienten für das Biquad-filter
Nach der bilinearen Transformation erhält man
(2)
wobei
(3)
Implementierung
Somit erhält man alle Koeffizienten, die man für die Implementierung braucht. Die Implementierung der Koeffizientenberechnung würde folgendermaßen aussehen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//Deklaration double A,w0,cosw0,sinw0,alpha,a0; //Hilfsvariablen A=pow(10,gain/40); w0=2*PI*(f0/FS); cosw0=cos(w0); sinw0=sin(w0); alpha=sinw0/(2*Q); //Normalisierungsparameter a0_inv=1/((A+1)+(A-1)*cosw0+2*sqrt(A)*alpha); //Koeffizientenberechnung bn0=(float)((A*((A+1)-(A-1)*cosw0+2*sqrt(A)*alpha))*a0_inv); bn1=(float)((2*A*((A-1)-(A+1)*cosw0))*a0_inv); bn2=(float)((A*((A+1)-(A-1)*cosw0-2*sqrt(A)*alpha))*a0_inv); an1= (float)((-2*((A-1)+(A+1)*cosw0))*a0_inv); an2=(float)(((A+1)+(A-1)*cosw0-2*sqrt(A)*alpha)*a0_inv); |
Am Code lassen sich manche Optimierungen erkennen.
- Mehrmals vorkommende Variablen sind vorberechnet (z.B. trigonometrische Funktionen)
- Anstatt jedes mal durch zu teilen, wird mit inversem (ein mal vorberechneten) Wert multipliziert, da Multiplikation günstiger ist als Division für viele CPUs.
- Die Berechnungen erfolgen mit Gleitkommezahlen doppelter Präzision (double) und wird am Ende auf Float gecastet. Der Grund: Trigonometrischen Funktionen mit Single-Präzision (float) kann zu erheblichen numerischen Fehlern und dadurch zu unerwünschten Ergebnissen bzw. Instabilität führen.
- Der Code ist optimiert für die Hardware-FPU von Cortex-M7 Mikroprozessor.