Come funziona un filtro passa-basso a livello di codice?


9

Ho lavorato su un semplice filtro passa basso per una misurazione <100 Hz nella mia applicazione. Ma finora, sto lottando con la teoria alla base di tutto. È bello che l'ho fatto funzionare, ma mi piacerebbe davvero se sapessi come / perché funziona.

Ho trovato il seguente codice:

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;
}

Per calcolare i coefficienti. Quindi, nei campioni audio, li passo in basso in questo modo:

        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];

Per ottenere un design passa-basso.

Mi chiedo alcune cose:

  1. Ricevo i campioni audio in un semplice array float *. Cos'è quel numero float? L'unica cosa che vedo è un numero, come è un suono?
  2. Il codice utilizza i calcoli precedenti (tre di essi) nel nuovo calcolo per campione. Ciò significa che i primi 2 campioni di dati non sono stati filtrati correttamente? (non che importerebbe perché sono solo 2 campioni, ma solo chiedersi)
  3. Cercando di imparare tutto, ho trovato un paio di formule per il filtro Butterworth (2nd Pole). Come si riflettono quelle formule in questo codice? Nessuna delle formule che ho trovato ha questi calcoli che puoi vedere nella funzione 'getLPCoefficientsButterworth2Pole ()'.

1
Non sto cercando di essere irrispettoso qui, ma la tua affermazione "come può essere un suono?" sembra indicare che non capisci i principi di base dell'elaborazione discreta del tempo. Sarà molto difficile affrontare qualsiasi problema DSP senza comprendere le basi come teorema del campionamento, quantizzazione, sistema LTI, ecc. Consiglierei un po 'di tempo con un buon libro di testo. Questo è gratuito dspguide.com/pdfbook.htm
Hilmar,

Risposte:


6
  1. Il numero float * array è un puntatore all'array. È un singolo numero che contiene l'indirizzo del primo elemento dell'array di valori float.

  2. Di solito, le condizioni iniziali (cioè gli elementi "passati" iniziali di x e y) sono 0, ma se i loro valori non sono uguali a 0 non è nemmeno un grosso problema, perché dopo un po 'le condizioni iniziali non hanno alcun effetto sull'output segnale per qualsiasi filtro stabile. E il tuo filtro è ovviamente stabile.

  3. Una funzione di trasferimento passa basso di secondo ordine con caratteristica Butterworth e frequenza di taglio (con in Hertz) è data daωa=2πfafa

(1)H(s)=ωa2s2+2ωas+ωa2
Questo è un risultato standard che puoi facilmente trovare sul web . Per ottenere un filtro a tempo discreto è possibile applicare una cosiddetta trasformazione bilineare:

(2)s=2fsz1z+1

dove è la frequenza di campionamento. Ciò è necessario perché l'asse di frequenza dei segnali analogici ( ) deve essere mappato alla gamma di frequenza consentita per i segnali a tempo discreto ( ). Poiché questa trasformazione deforma le frequenze, dobbiamo calcolare la frequenza di taglio analogica desiderata dalla data frequenza di taglio nel dominio del tempo discreto:fs0f0ffs/2fd

ωa=2fstan(ωd2) with ωd=2πfd/fs

Se si inserisce (2) in (1) si ottiene

(3)H(z)=kz2+b1z+b2z2+a1z+a2

con

k=α21+2α+α2 (gain)
a1=2(α21)1+2α+α2,a2=12α+α21+2α+α2,b1=2,b2=1

dove ho usato . La funzione di trasferimento (3) corrisponde all'equazione del dominio del tempoα=tan(ωd2)

y(n)=kx(n)+kb1x(n1)+kb2x(n2)a1y(n1)a2y(n2)

Come puoi vedere, c'è una certa somiglianza con il tuo codice. Tuttavia, ci sono anche alcune differenze e dovresti controllare la risposta in frequenza del tuo filtro. Penso che le equazioni di cui sopra siano corrette, ma spetta a te controllarle e decidere quale versione è quella corretta.


Grazie. Il primo, ho capito. Ma è ancora una serie di galleggianti. Voglio dire: cosa rappresenta un singolo valore float?
Niek van der Steen,

2
Un singolo valore float è uno dei tuoi campioni di input.
Matt L.

3
In breve: il suono è una variazione della pressione dell'aria, convertita da un trasduttore (microfono) in un segnale elettrico le cui variazioni seguono lo stesso schema della pressione dell'aria. L'ampiezza del segnale elettrico viene misurata N volte (= campionamento) ogni secondo per produrre la sequenza di numeri che vedi nell'array float *. Esistono dozzine di presentazioni online sull'elaborazione digitale (audio) che spiegano questo processo in modo più dettagliato.
Pichenettes,

Ho modificato la mia risposta per affrontare l'ultima parte della tua domanda.
Matt L.

Stai usando x (n - qualcosa), che cos'è x? Presumo che 'n' sia l'esempio di input? Bella risposta!
Niek van der Steen,

11

Hai chiesto come funziona un filtro passa-basso e hai affermato che il filtro utilizza i valori passati dei tuoi dati. Questa è una discussione non tecnica di ciò che accade in un filtro passa basso.

Il filtro passa-basso acquisisce viste diverse (spostate nel tempo) del segnale, le ridimensiona e le somma insieme. Puoi immaginare di disegnare il tuo segnale 3 volte, uno è corrente, il secondo viene spostato di un tempo di campionamento, il terzo viene spostato di 2 volte di campionamento.

Alle basse frequenze, tutte le viste sembrano molto simili (lo spostamento di un singolo campione cambia a malapena la posizione del segnale in qualsiasi istante nel tempo). In questo caso, le tre versioni si sommeranno in modo costruttivo (o almeno non distruttivo), quindi il segnale passa attraverso il filtro.

Ora spostandosi su frequenze più alte, ogni versione spostata del segnale diventa più distinta in un dato istante (punto di campionamento) e in effetti può persino invertire il segno. A queste frequenze più alte, le tre versioni del segnale tendono ad annullarsi (aggiunte in modo distruttivo) in modo che il segnale venga attenuato.

Diversi tipi di filtri prevedono che questo tipo di interferenza costruttiva / distruttiva avvenga su bande di frequenza appropriate per creare filtri passa-basso, passa-banda o passa-alto.


1

Dipende da come lo vuoi. Per me ho implementato in C. Quindi, quello che ho fatto è stato generare coefficienti di filtro durante l' matlabutilizzo firls. Quindi ho memorizzato i coefficienti di filtro in un array e quindi ho passato questi coefficienti di filtro alla funzione di filtro in C. In matlabè abbastanza facile generare i coefficienti di filtro e quindi utilizzare l'operazione di convoluzione o utilizzare un filtro specifico. Ma Cdevi implementare anche il filtro. Da parte mia devo farlo per i DSP, quindi implementato Ce ottenuto i risultati matlabnell'uso della funzione mex. Per calcolare i coefficienti utilizzare questo comando in 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 )
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.