Wie funktioniert ein Tiefpassfilter programmgesteuert?

9

Ich habe in meiner Anwendung an einem einfachen Tiefpassfilter für die Messung <100 Hz gearbeitet. Aber bis jetzt kämpfe ich mit der Theorie dahinter. Es ist cool, dass ich es zum Laufen gebracht habe, aber ich würde es wirklich genießen, wenn ich wüsste, wie / warum es funktioniert.

Ich habe folgenden Code gefunden:

void getLPCoefficientsButterworth2Pole(const int samplerate, const double cutoff, double* const ax, double* const by)
{
    double PI = M_PI;
    double sqrt2 = sqrt(2);

    double QcRaw  = (2 * PI * cutoff) / samplerate; // Find cutoff frequency in [0..PI]
    double QcWarp = tan(QcRaw); // Warp cutoff frequency

    double gain = 1 / ( 1 + sqrt2 / QcWarp + 2 / ( QcWarp * QcWarp ) );

    by[2] = ( 1 - sqrt2 / QcWarp + 2 / ( QcWarp * QcWarp ) ) * gain;
    by[1] = ( 2 - 2 * 2 / ( QcWarp * QcWarp ) ) * gain;
    by[0] = 1;

    ax[0] = 1 * gain;
    ax[1] = 2 * gain;
    ax[2] = 1 * gain;
}

Berechnung der Koeffizienten. Dann 'passiere' ich sie in den Audio-Samples folgendermaßen:

        xv[2] = xv[1];
        xv[1] = xv[0];

        xv[0] = pData[j];
        yv[2] = yv[1];
        yv[1] = yv[0];

        yv[0] = (ax[0] * xv[0] + ax[1] * xv[1] + ax[2] * xv[2]
                   - by[1] * yv[0]
                   - by[2] * yv[1]);

        pData[j] = yv[0];

Um ein Tiefpass-Design zu erhalten.

Ich frage mich ein paar Dinge:

  1. Ich empfange die Audio-Samples in einem einfachen float * -Array. Was ist diese Float-Nummer? Das einzige was ich sehe ist eine Zahl, wie ist das ein Stück Klang?
  2. Der Code verwendet frühere Berechnungen (drei davon) in der neuen Berechnung pro Stichprobe. Bedeutet das, dass die ersten beiden Datenproben nicht richtig gefiltert werden? (nicht, dass es wichtig wäre, weil es nur 2 Proben sind, aber ich frage mich nur)
  3. Beim Versuch, alles zu lernen, fand ich einige Formeln für den Butterworth-Filter (2. Pol). Wie spiegeln sich diese Formeln in diesem Code wider? Keine der gefundenen Formeln enthält diese Berechnungen, die Sie in der Funktion 'getLPCoefficientsButterworth2Pole ()' sehen können.
Niek van der Steen
quelle
1
Ich versuche hier nicht respektlos zu sein, aber Ihre Aussage "Wie ist das ein Stück Klang?" scheint darauf hinzudeuten, dass Sie die Grundprinzipien der zeitdiskreten Verarbeitung nicht verstehen. Es wird sehr schwierig sein, ein DSP-Problem anzugehen, ohne die Grundlagen wie Abtasttheorem, Quantisierung, LTI-System usw. zu verstehen. Ich würde einige Zeit mit einem guten Lehrbuch empfehlen. Dieser ist kostenlos dspguide.com/pdfbook.htm
Hilmar

Antworten:

6
  1. Das Array number * ist ein Zeiger auf das Array. Es ist eine einzelne Zahl, die die Adresse des ersten Elements des Arrays von Gleitkommawerten enthält.

  2. Normalerweise ist die Anfangsbedingung (dh die anfänglichen 'vergangenen' Elemente von x und y) 0, aber wenn ihre Werte nicht gleich 0 sind, ist dies auch kein großes Problem, da die Anfangsbedingungen nach einer Weile keine Auswirkung auf die Ausgabe haben Signal für jeden stabilen Filter. Und Ihr Filter ist offensichtlich stabil.

  3. Eine Tiefpassübertragungsfunktion zweiter Ordnung mit Butterworth-Charakteristik und Grenzfrequenz (mit in Hertz) ist gegeben durchωein=2πfeinfein

(1)H.(s)=ωein2s2+2ωeins+ωein2
Dies ist ein Standardergebnis, das Sie leicht im Web finden können . Um einen zeitdiskreten Filter zu erhalten, können Sie eine sogenannte bilineare Transformation anwenden:

(2)s=2fsz- -1z+1

Dabei ist die Abtastfrequenz. Dies ist erforderlich, da die Frequenzachse der analogen Signale ( ) für zeitdiskrete Signale ( ) auf den zulässigen Frequenzbereich abgebildet werden muss . Da diese Transformation die Frequenzen , müssen wir die gewünschte analoge Grenzfrequenz aus der gegebenen Grenzfrequenz im zeitdiskreten Bereich :fs0f0ffs/.2fd

ωein=2fsbräunen(ωd2) mit ωd=2πfd/.fs

Wenn Sie (2) in (1) einfügen, erhalten Sie

(3)H.(z)=kz2+b1z+b2z2+ein1z+ein2

mit

k=α21+2α+α2 (dazugewinnen)
ein1=2(α2- -1)1+2α+α2,ein2=1- -2α+α21+2α+α2,b1=2,b2=1

wo ich . Die Übertragungsfunktion (3) entspricht der Zeitbereichsgleichungα=bräunen(ωd2)

y(n)=kx(n)+kb1x(n- -1)+kb2x(n- -2)- -ein1y(n- -1)- -ein2y(n- -2)

Wie Sie sehen können, gibt es eine gewisse Ähnlichkeit mit Ihrem Code. Es gibt jedoch auch einige Unterschiede, und Sie sollten den Frequenzgang Ihres Filters überprüfen. Ich denke, dass die obigen Gleichungen korrekt sind, aber es liegt an Ihnen, sie zu überprüfen und zu entscheiden, welche Version die richtige ist.

Matt L.
quelle
Vielen Dank. Den ersten verstehe ich. Aber es ist immer noch eine Reihe von Schwimmern. Ich meine: Was bedeutet ein einzelner Float-Wert?
Niek van der Steen
2
Ein einzelner Float-Wert ist eines Ihrer Eingabebeispiele.
Matt L.
3
Kurz gesagt: Schall ist eine Änderung des Luftdrucks, die von einem Wandler (Mikrofon) in ein elektrisches Signal umgewandelt wird, dessen Änderungen dem gleichen Muster wie der Luftdruck folgen. Die Amplitude des elektrischen Signals wird N-mal (= Abtastung) pro Sekunde gemessen, um die Zahlenfolge zu erhalten, die Sie in Ihrem float * -Array sehen. Es gibt Dutzende von Online-Präsentationen zur (Audio-) Digitalverarbeitung, in denen dieser Prozess ausführlicher erläutert wird.
Pichenettes
Ich habe meine Antwort bearbeitet, um den letzten Teil Ihrer Frage zu beantworten.
Matt L.
Sie verwenden x (n - etwas), was ist x? Ich nehme an, dass 'n' das Eingabebeispiel ist? Gute Antwort!
Niek van der Steen
11

Sie haben gefragt, wie ein Tiefpassfilter funktioniert, und erwähnt, dass der Filter frühere Werte Ihrer Daten verwendet. Dies ist eine nicht technische Diskussion darüber, was in einem Tiefpassfilter passiert.

Der Tiefpassfilter nimmt unterschiedliche (zeitlich verschobene) Ansichten Ihres Signals auf, skaliert sie und addiert sie. Sie können sich vorstellen, Ihr Signal dreimal zu zeichnen, wobei eines aktuell ist, das zweite um eine Abtastzeit und das dritte um zwei Abtastzeiten verschoben ist.

Bei niedrigen Frequenzen sehen alle Ansichten sehr ähnlich aus (die Verschiebung um ein einzelnes Sample ändert sich kaum, wenn Sie sich zu einem bestimmten Zeitpunkt auf dem Signal befinden). In diesem Fall addieren sich die drei Versionen auf konstruktive (oder zumindest zerstörungsfreie) Weise, sodass das Signal den Filter durchläuft.

Wenn Sie sich nun zu höheren Frequenzen bewegen, wird jede verschobene Version des Signals zu jedem Zeitpunkt (Abtastpunkt) deutlicher und kann sogar das Vorzeichen umkehren. Bei diesen höheren Frequenzen heben sich die drei Versionen Ihres Signals auf (werden destruktiv hinzugefügt), sodass das Signal gedämpft wird.

Verschiedene Arten von Filtern sorgen dafür, dass diese Art von konstruktiver / destruktiver Interferenz über geeignete Frequenzbänder stattfindet, um Tiefpass-, Bandpass- oder Hochpassfilter zu erzeugen.

user2718
quelle
1

Es hängt davon ab, wie Sie es wollen. Für mich habe ich in implementiert C. Also habe ich Filterkoeffizienten bei der matlabVerwendung generiert firls. Dann habe ich diese Filterkoeffizienten in einem Array gespeichert und diese Filterkoeffizienten dann an die Filterfunktion in übergeben C. In matlabes ist ganz einfach , um die Filterkoeffizienten erzeugt wird , und dann die Faltungsoperation verwenden oder einen bestimmten Filter verwenden. Aber in muss Cman auch den Filter implementieren. Ich für meinen Teil muss es für DSPs tun, also implementiert in Cund habe die Ergebnisse bei der matlabVerwendung der mex-Funktion erhalten. Verwenden Sie diesen Befehl, um die Koeffizienten zu berechnen matlab:

n=17                  %filter order
f=[0 0.167 0.333 1]   %Frequency band edges
a=[1 1 0 0]           %Desired amplitudes
fir= firls (n, f,a )
DX
quelle