tiefpass koeffizienten berechnen
-
hallo zusammen,
ich schreibe ein programm, welches ein xy signal auf dem bildschirm darstellt. dieses signal möchte ich in echtzeit glätten, wofür ein tiefpass filter sinn macht. zu diesem zweck habe ich mit von dem simplen programm winFilter folgenden c code generieren lassen:
/************************************************************** WinFilter version 0.8 http://www.winfilter.20m.com akundert@hotmail.com Filter type: Low Pass Filter model: Butterworth Filter order: 5 Sampling Frequency: 1000 Hz Cut Frequency: 300.000000 Hz Coefficents Quantization: float Z domain Zeros z = -1.000000 + j 0.000000 z = -1.000000 + j 0.000000 z = -1.000000 + j 0.000000 z = -1.000000 + j 0.000000 z = -1.000000 + j 0.000000 Z domain Poles z = -0.238827 + j -0.699060 z = -0.238827 + j 0.699060 z = -0.174643 + j -0.315932 z = -0.174643 + j 0.315932 z = -0.158384 + j -0.000000 ***************************************************************/ #define NCoef 5 float iir(float NewSample) { float ACoef[NCoef+1] = { 0.10837789384895716000, 0.54188946924478576000, 1.08377893848957150000, 1.08377893848957150000, 0.54188946924478576000, 0.10837789384895716000 }; float BCoef[NCoef+1] = { 1.00000000000000000000, 0.98532523927923832000, 0.97384933183676425000, 0.38635655864844887000, 0.11116384057834201000, 0.01126351245656587500 }; static float y[NCoef+1]; //output samples static float x[NCoef+1]; //input samples int n; //shift the old samples for(n=NCoef; n>0; n--) { x[n] = x[n-1]; y[n] = y[n-1]; } //Calculate the new output x[0] = NewSample; y[0] = ACoef[0] * x[0]; for(n=1; n<=NCoef; n++) y[0] += ACoef[n] * x[n] - BCoef[n] * y[n]; return y[0]; }
der programmcode wird generiert, nachdem man in winFilter die grenzfrequenz eingegeben hat. ich möchte aber in meinem programm über einen regler die grenzfrequenz einstellbar machen. danach müsste ich dann die koeffizienten selber neu berechnen. wie mache ich das?
ich habe schon sehr ausgiebig hier im forum gesucht und gegoogelt, finde aber leider nur für mein verständnis viel zu mathematische erklärungen gefunden oder beiträge, in denen matlab benutzt wird und der filter nicht zur laufzeit änderbar ist oder anwendungen auf audiosignale.
z.b. gibt es hier einen guten beitrag http://www.c-plusplus.net/forum/p140825 mit fertigem c++ code (!) http://www.musicdsp.org/showArchiveComment.php?ArchiveID=243, aber das liefert mir keine guten ergebnisse, vermutlich wegenThere are some minima and maxima defined, to make ist sound nice in all situations.
Mein signal ist eben kein audio signal.
mein filter soll optimalerweise stark abregeln, also nach http://en.wikipedia.org/wiki/Butterworth_filter#Transfer_function z.b. 5. ordnung sein, falls das zu kompliziert wäre ginge auch einer 2. ordnung.
nur eben wie berechne ich die koeffizienten?danke!
EDIT: es geht mir nicht um exakt diese koeffizienten im quellcode, sondern allgemein funktionierende.
-
Ein paar Kommentare:
- Die Speicherung des Filter-Zustandes als static-Variablen innerhalb einer Funktion ist extrem unschön. Stattdessen könntest Du das als struct machen. Siehe Folie 19
- Wenn du die Filterparameter zur Laufzeit anpassen willst, dann müssen diese Parameter natürlich auch Teil des Zustandes sein (wie auch in dem verlinkten Codebeispiel). Es ist auch sehr empfehlenswert, den Filter in mehrere "kleine" (niedriger Ordnung) zu faktorisieren, die man dann hintereinander schaltet, wenn du die Parameter dynamisch ändern willst. Denn es besteht die Gefahr, dass ein Filter höherer Ordnung kurzzeitig instabil beim Umschalten auf andere Parameter wird. Da du ja schon die Pole und Zeros kennst, teilst du sie einfach auf in mehrere Biquad-Filter, wobei ein Biquad dann bis zu zwei Zeros und Pole haben kann. Damit du reellwertige Filterkoeffizienten bekommst, musst du bei komplexwertigen Zeros oder Polen die komplex konjugierten paaren.
- Die Grenzfrequenz des Butterworth-Filters könntest du per "Frequenzwarping" erhöhen oder erniedrigen. Das ist äquivalent zum Butterworth-Design mit einer anderen Grenzfrequenz. Ich müsste irgendwo Matlab Code haben, der dieses Frequenz-Warping auf den Filterkoeffizienten durchführt. So kompliziert ist das eigentlich gar nicht, habe nur gerade keine Zeit, das nachzugucken. Aber vielleicht findest du ja unter dem Stichwort "frequency warping" etwas im Netz. Man kann es jedenfalls direkt auf den Filterkoeffizienten machen, oder die Pole und Zeros verschieben und die dann in Filterkoeffizienten umrechnen.
-
Hast du Matlab?
Muss es Butterworth sein, oder ist das zufällige gewählt?
-
danke für eure antworten!
@KasF:
ich habe leider kein matlab. wäre es denn damit möglich, die veränderung der koeffizienten beim verstellen der grenzfrequenz abzubilden?
es muss nicht butterworth sein, ich hätte nur gerne einen tiefpass mit recht starker dämpfung. im moment habe ich 24dB, weniger sollten es nicht sein.
im moment habe ich mir http://www.musicdsp.org/showone.php?id=243 angepasst, funktioniert auch, finde ich aber nicht so ideal.@krümelkacker:
die speicherung des filterzustandes würde ich tatsächlich nicht static machen. der code war nur ein ansatz, wie er mir von winFilter erzeugt wurde.
für das aufteilen in mehrere biquad filter wie von dir beschrieben fehlt mir leider das mathematische verständnis. am besten wäre ein algorithmus, der die koeffizienten berechnet. um instabilität zu vermeiden würde ich während der berechnung die darstellung des signals aussetzen. da es kein audiosignal ist würden auch kurze extremwerte nicht stören.
ich befürchte, auch das frequency warping übersteigt meine mathematischen fähigkeiten
-
Und was willst du dann mit den Koeffizienten machen? Dich interessiert doch nur das Ergebniss für verschiedene Grenzfrequenzen, oder? Das Codestück von musicdsp gibt dir doch auch die Koeffizienten. Die Codeecken mit min/max kannst du ja abschneiden :), wenn du glaubst, dass sie dein Ergebnis negativ beeinflussen.
Ja, mit Matlab kannst du dir dann auch die Koeffizienten anzeigen lassen. Aber wie gesat, willst du überhaupt die Koeffizienten, oder doch nur das gefilterte Ausgangssignal?
-
Was ich für solche Fälle (variable Grenzfrequenz) ganz geschickt finde ist: http://www.earlevel.com/main/2003/03/02/the-digital-state-variable-filter/
Bei sehr hohen Grenzfrequenzen ist das Filter nicht zu empfehlen (kann instabil werden). Aber die "Koeffizienten" berechnen sich sehr einfach. Für kleine Grenzfrequenzen kann man sich den sin() auch noch sparen.
-
Tim schrieb:
Bei sehr hohen Grenzfrequenzen ist das Filter nicht zu empfehlen (kann instabil werden).
Interessanter Artikel, danke! Die stabilitätsgrenze 1/6 der samplerate ist dann aber leider zu niedrig.
KasF schrieb:
Dich interessiert doch nur das Ergebniss für verschiedene Grenzfrequenzen, oder?
Ja, das ist richtig. Mein erster Post kam noch vor der jetzigen Lösung mit dem angepassten musicdsp code. ich dachte nur, es würde irgendwie einfacher gehen. aber denn belasse ich es einfach dabei.
danke für eure ideen!
-
mael15 schrieb:
Tim schrieb:
Bei sehr hohen Grenzfrequenzen ist das Filter nicht zu empfehlen (kann instabil werden).
Interessanter Artikel, danke! Die stabilitätsgrenze 1/6 der samplerate ist dann aber leider zu niedrig.
Wie im Artikel steht: Oversampling. Rechentechnisch bist du wahrscheinlich trotzdem besser als wenn du dir klassisch die Koeffizienten für deine Biquads ständig neu berechnest.
Edit: Auch wenn es für dich wahrscheinlich nicht relevant ist, aber das Ding hat sehr gute Fixkomma-Eigenschaften.
-
oversampling wird zu aufwändig, weil der tiefpass in echtzeit auf maximal 4 kanäle mit jeweils maximal 10k sample rate angewendet wird.
aber trotzdem danke für die anregung.
-
Wie gesagt, ich bezweifle, dass Oversampling hier mehr kostet als die Koeffizienten für die Biquads zu berechnen. Aber kein Problem, nimm was du willst
btw, Koeffizientenberechnung:
T = Abtastzeit
aus:
Digitale Audiosignalverarbeitung | ISBN: 3519261804
3. AusgabePS: Aufpassen: Die Benennung der Koeffizienten ai und bi ist nicht immer identisch. Im oberen Fall sind die ai die Vorwärtskoeffizienten.
-
danke!