Hallo Zusammen, kann mir jemand erleuchten, was der Unterschied auf Implementierungsebene in C/C++ zwischen FIR Low-Pass, High-Pass, Bandpass und Bandstop Filtern ist? Ich habe mir paar Beispielimplementierungen bezüglich FIR Filter gesucht, leider die Beispiele, die ich gefunden habe, waren für FIR low-pass Filter. Der Unterschied ist mir zwischen den einzelnen Filtertypen klar. Auf Implementierungsebene blicke ich aber noch nicht.
>kann mir jemand erleuchten, was der Unterschied auf >Implementierungsebene in C/C++ zwischen FIR Low-Pass, High-Pass, >Bandpass und Bandstop Filtern ist? Die Filterkoeffizienten sind unterschiedlich, die Implementierung gleich.
Carl schrieb: >>kann mir jemand erleuchten, was der Unterschied auf >>Implementierungsebene in C/C++ zwischen FIR Low-Pass, High-Pass, >>Bandpass und Bandstop Filtern ist? > > Die Filterkoeffizienten sind unterschiedlich, die Implementierung > gleich. Heißt es, dass die unterschiedlichen Filtertypen mit der unteren Funktion realisierbar sind? Beim Aufruf der Funktion muss man ja aber auf die richtige Parametrisierung achten, sprich Filterkoeffizienten und Delay Elementen.
1 | void fir(input_buffer, *output_buffer, coeff, delay) |
2 | { |
3 | y[n] = x[n] * h[n] |
4 | } |
Vili V. schrieb: > Heißt es, dass die unterschiedlichen Filtertypen mit der unteren > Funktion realisierbar sind? Mit genau dieser Funktion nicht. Denn die multipliziert nur ein Element von Array x mit einem Element von Array h und speichert das Ergebnis in Element y. Dein "coeff" wird dabei z.B. ignoriert. Der Name der Funktion lautet zwar fir, aber sie implementiert keinen FIR-Filter. Hättest du eine funktionierende FIR-Funktion, dann würde gelten, was Carl geschrieben hat.
Moin, Es ist, wie schon die Vorschreiber schruben, eine reine Frage der Koeffizienten; die Berechnung selbst bleibt immer gleich. Man kann z.B. ein Hoch/Tiefpasspaeaerchen basteln, das sich nur in einem einzigen Koeffizienten unterscheidet. Das spart Rechnerei, wenn man beide Filterergebnisse braucht. "s" ist ein Zwischenergebnis, das ist fuer Hochpass und Tiefpass gleich; der Unterschied entsteht erst durch Addition bzw. Subtraktion des gewichteten buf[7]:
1 | s = (f->buf[ 0]+f->buf[14])*(-3) + |
2 | (f->buf[ 2]+f->buf[12])* 9 - |
3 | (f->buf[ 4]+f->buf[10])* 22 + |
4 | (f->buf[ 6]+f->buf[ 8])* 80; |
5 | |
6 | lp=(s+f->buf[7]*128)/256; |
7 | |
8 | hp=(s-f->buf[7]*128)/256; |
Das ganze Ding gibts hier: Beitrag ""LED-Spectrumanalyzer"software ohne Fouriertransformation" Gruss WK
Carl schrieb: > Die Filterkoeffizienten sind unterschiedlich, die Implementierung > gleich. Aber nicht, was C und C++ angeht. Stichwort Koeffizientenidentität und Koheränz. Man kann in C++ Filter mit optimierten Koeffizienten geschickt und auch sehr ungeschickt auf mehrere threads verteilen.
Dergute W. schrieb: > eine reine Frage der > Koeffizienten; Warum verwendest du nur jeden zweiten Wert? Sind die Koeffs dazwischen Null?
Moin, Robert K. schrieb: > Sind die Koeffs dazwischen > Null? Jepp. Multiplikationen mit Null wirken angenehm performancesteigernd. Gruss WK
Vili V. schrieb: > kann mir jemand erleuchten, was der Unterschied auf > Implementierungsebene in C/C++ zwischen FIR Low-Pass, High-Pass, > Bandpass und Bandstop Filtern ist? Was hat ein FIR Filter mit C/C++ zu tun? Ich verstehe deinen Begriff "Implementierungsebene" nicht. Also, was ein FIR-Filter ist, weißt du hoffentlich: es ist ein Filter, das nur die letzten n Samples berücksichtigt und keinerlei Rückführung eines Ergebnisses enthält. Filter, die letzteres tun, heißen IIR. Was ein Lowpaß oder Highpaß oder Bandpass oder Bandsperre ist, weißt du hoffentlich auch. Bleiben also nur noch die zwei Fragen: a. Wie konstruiert man eines der genannten Filter? b. Wie schreibt man das in der Programmiersprache deiner Wahl? Vili V. schrieb: > leider die Beispiele, die ich gefunden habe, waren für FIR > low-pass Filter. Das ist doch OK so. Damit hast du eigentlich alles, was du brauchst, denn: 1. einen Lowpaß kannst du damit schon mal selber berechnen. Vergiß aber das Normieren nicht, also alle Koeffizienten so skalieren, daß die Verstärkung des Filters = 1 ist. 2. aus dem Wissen, daß die Differenz des Eingangssignales zum Ausgangssignal des Lowpasses gleich ein Highpass ist, weißt du nun schon, wie man einen Highpass macht: für alle Koeffizienten Vorzeichen umdrehen, zum in der Mitte befindlichen Koeffizienten 1 addieren. Hinweis dazu: So ein Filter macht man am besten mit einer ungeraden Anzahl von Taps, damit man genau ein Sample exakt in der Mitte hat. Das ist für das Filter (so es denn symmetrisch ist) das aktuelle Sample. Jaja, du speist neue Samples bei n/2 in der Zukunft ein, dann wandern sie durch das Filter, kommen am Zeitpunkt 0 vorbei und verschwinden bei -n/2 auf Nimmerwiedersehen in der Vergangenheit. 3. Durchlaßbereiche, die sich nicht überlappen, kann man zusammenfassen, also einen Tiefpaß für 100 Hz kann man zu einem Hochpaß für 3 kHz addieren, heraus kommt eine Bandsperre von 100 Hz bis 3 kHz. Damit weißt du jetzt auch, wie man eine Bandsperre schreibt. Und wenn du Punkt 2 erinnerst, dann weißt du auch, wie man daraus einen Bandpaß macht. Und was du für eine Fensterfunktion benutzt, ist deine Entscheidung. Kaiser ist - wenn man's recht betrachtet - auch nicht wesentlich aufwendiger als Blackman. Also, wo ist dein Problem? W.S.
Dergute W. schrieb: > Jepp. Multiplikationen mit Null wirken angenehm performancesteigernd. ... führen aber auch zu einer pauschalen Unterdrückung von Frequenzen im Signal und damit Verwurf von Information. Bei bestimmten Anwendungen wie der Mustererkennung führt dies zu einer schlechteren Trennung von gewollten und ungewollten Signalanteilen und verringerten Unterscheidbarkeit. Auch das hier: W.S. schrieb: > 2. aus dem Wissen, daß die Differenz des Eingangssignales zum > Ausgangssignal des Lowpasses gleich ein Highpass ist, weißt du nun > schon, wie man einen Highpass macht: klappt dann nicht so gut.
Dergute W. schrieb: > s = (f->buf[ 0]+f->buf[14])*(-3) + > (f->buf[ 2]+f->buf[12])* 9 - > (f->buf[ 4]+f->buf[10])* 22 + > (f->buf[ 6]+f->buf[ 8])* 80; > > lp=(s+f->buf[7]*128)/256; > > hp=(s-f->buf[7]*128)/256; Sehr schön! Wie kommt man auf diese Koeffizienten? So hier?: https://www.dsprelated.com/showarticle/1113.php
Moin, Jürgen S. schrieb: > Bei bestimmten Anwendungen wie > der Mustererkennung führt dies zu einer schlechteren Trennung von > gewollten und ungewollten Signalanteilen und verringerten > Unterscheidbarkeit. Jepp. Und bei bestimmen Anwendungen wie frequenzabhaengigem LED-Geblinke fuehrt dies dazu, dass man die gesamte digitale Signalverarbeitung locker in Echtzeit auf einem Atmega hinkriegt - mit einer Filtersteilheit, die den Anhaengern von analogen Bandfiltern in Kleinserie das Pipi in die Augen treibt. Also Augen auf bei der Filterauswahl :-) Bernd schrieb: > Wie kommt man auf diese Koeffizienten? Jepp, z.B. so wie in deinem Link oder z.B. so:
1 | round(-256*firls(14,[0 0.38 0.62 1],[1 1 0 0])) |
mit ein bisschen Rumprobieren an den Filtergrenzen, so dass das resultierende Filter trotz Rundungsfehlern auf 8 bit Koeffizienten nicht zu gruselig wird. Gruss WK
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.