Was ist los Leute, hat hier etwa noch Niemand so ein Filter implementiert!?
Naja, also falls mal Jemand sowas brauchen sollte, habe ich hier ein IIR Filter 2. Ordnung:
(wer nicht ganze Arrays, sondern einzelne Werte filtern möchte entfernt einfach die for-Schleife)
Code:
void filter_fr16_biquad_vect(int16_t* coef_a, int16_t* coef_b, int16_t* buf, int16_t* x, int16_t* y, uint16_t len)
{
uint16_t n;
for(n=0; n<len; n++)
{
// y(n) = x(n) * b0 + u0
y[n] = ((int32_t)x[n] * (int32_t)coef_b[0]) >> 15; // 1.15 * 1.15 = 2.30; 2.30 >> 15 = 1.15
y[n] += buf[0];
y[n] <<= 1;
// u0 = x(n) * b1 - y(n) * a1 + u1
buf[0] = (((int32_t)x[n] * (int32_t)coef_b[1]) - ((int32_t)y[n] * (int32_t)coef_a[0])) >> 15;
buf[0] += buf[1];
// u1 = x(n) * b2 - y(n) * a2
buf[1] = (((int32_t)x[n] * (int32_t)coef_b[2]) - ((int32_t)y[n] * (int32_t)coef_a[1])) >> 15;
}
}
Dabei müssen alle Werte zwischen -1 und 1 liegen, d.h. sowohl Eingangssignal als auch die Koeffizienten müssen entsprechend skaliert werden, wobei der Faktor für die Koeffizienten bei dieser Implementierung fest mit 0,5 vorgegeben ist.
So weit so gut, aber ein Problem habe ich doch noch...
betrachten wir mal ein in Matlab erzeugtes butterworth-Filter 2. Ordnung, dann fällt auf, daß die b-Koeffizienten bei niedrigen Grenzfrequenzen sehr klein werden können. Das ist natürlich schlecht, denn es verringert die Präzision erheblich, da mir massenhaft Nachkommastellen verloren gehen.
Erzeuge ich beispielsweise ein Filter mit dem Befehl butter(2, 0.00, dann sind die b-Koeffizienten (umgerechnt in das 16-Bit Festkomma-Format) gerademal 3, 5 und 3. Rechnet man diese wieder in floats um liegt der Fehler für b0 und b2 bei satten 15%, entsprechend beschissen sieht das gefilterte Signal dann auch aus.
Jemand eine Idee, was ich da tun kann?
Lesezeichen