Forum: Digitale Signalverarbeitung / DSP / Machine Learning FIR Low-, High-, Bandpass und Bandstop Filtern


von Vili V. (villamosvili)


Lesenswert?

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.

von Carl (Gast)


Lesenswert?

>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.

von Vili V. (villamosvili)


Lesenswert?

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
}

von Achim S. (Gast)


Lesenswert?

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.

von Dergute W. (derguteweka)


Lesenswert?

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

von Robert K. (Firma: Medizintechnik) (robident)


Lesenswert?

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.

von Robert K. (Firma: Medizintechnik) (robident)


Lesenswert?

Dergute W. schrieb:
> eine reine Frage der
> Koeffizienten;

Warum verwendest du nur jeden zweiten Wert? Sind die Koeffs dazwischen 
Null?

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Robert K. schrieb:
> Sind die Koeffs dazwischen
> Null?

Jepp. Multiplikationen mit Null wirken angenehm performancesteigernd.

Gruss
WK

von W.S. (Gast)


Lesenswert?

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.

von J. S. (engineer) Benutzerseite


Lesenswert?

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.

von Bernd (Gast)


Angehängte Dateien:

Lesenswert?

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

von Dergute W. (derguteweka)


Lesenswert?

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
Noch kein Account? Hier anmelden.