ローパスフィルターはプログラムでどのように機能しますか?


9

私のアプリケーションでは、100 Hz未満の測定用のシンプルなローパスフィルターに取り組んでいます。しかし、これまでのところ、私はその背後にある理論に苦労しています。うまく動いたのはかっこいいですが、どのように/なぜ動いているのか知っていれば本当に楽しめます

私は次のコードを見つけました:

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

係数を計算します。次に、オーディオサンプルで、次のように「ローパス」します。

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

ローパス設計を取得します。

私はいくつかのことを考えています:

  1. オーディオサンプルを単純なfloat *配列で受け取ります。その浮動小数点数は何ですか?私が目にするのは数字だけですが、その音はどうですか?
  2. コードは、サンプルごとの新しい計算で過去の計算(そのうちの3つ)を使用しています。それは、最初の2つのデータサンプルが正しくフィルタリングされないことを意味しますか?(2つのサンプルしかないので問題になるわけではありませんが、疑問に思っています)
  3. すべてを学ぼうとしたところ、バターワース(第2極)フィルターの式がいくつか見つかりました。これらの数式はこのコードにどのように反映されますか?私が見つけた式には、「getLPCoefficientsButterworth2Pole()」関数で確認できるこれらの計算はありません。

1
私はここで失礼なことをしようとしているわけではありませんが、あなたの声明は「その音はどうですか?」時間離散処理の基本原理を理解していないようです。サンプリング定理、量子化、LTIシステムなどの基本を理解せずにDSPの問題に取り組むことは非常に困難です。良いテキストブックを使ってしばらくお勧めします。これは無料ですdspguide.com/pdfbook.htm
Hilmar

回答:


6
  1. 数値float *配列は、配列へのポインターです。これは、float値の配列の最初の要素のアドレスを含む単一の数値です。

  2. 通常、初期条件(つまり、xとyの最初の「過去」の要素)は0ですが、それらの値が0でない場合も、しばらくすると初期条件が出力に影響しないため、大きな問題にはなりません。安定したフィルタの信号。そして、あなたのフィルターは明らかに安定しています。

  3. バタワース特性とカットオフ周波数を備えた2次ローパス伝達関数 ωa=2πfa (と fa ヘルツ)は

(1)H(s)=ωa2s2+2ωas+ωa2
これは、Webで簡単に見つけることができる標準的な結果です。離散時間フィルターを取得するには、いわゆる双一次変換を適用できます。

(2)s=2fsz1z+1

どこ fsサンプリング周波数です。これは、アナログ信号の周波数軸(0f)離散時間信号の許容周波数範囲にマッピングする必要があります(0ffs/2)。この変換は周波数をゆがめるため、所定のカットオフ周波数から目的のアナログカットオフ周波数を計算する必要がありますfd 離散時間領域で:

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

(2)を(1)に挿入すると、

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

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

私が使用した場所 α=tan(ωd2)。伝達関数(3)は時間領域方程式に対応します

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

ご覧のとおり、コードにはかなりの類似点があります。ただし、いくつかの違いもあり、フィルターの周波数応答を確認する必要があります。上記の方程式は正しいと思いますが、それらをチェックして、正しいバージョンを決定するのはあなた次第です。


ありがとう。1つ目は理解しました。しかし、それはまだフロートの配列です。つまり、単一の浮動小数点値は何を表していますか?
Niek van der Steen 2013

2
単一のfloat値は、入力サンプルの1つです。
Matt L.

3
つまり、音は空気圧の変化であり、トランスデューサー(マイク)によって電気信号に変換され、その変化は空気圧と同じパターンに従います。電気信号の振幅は毎秒N回(=サンプルレート)計測され、float *配列に表示される一連の数値を生成します。このプロセスをより詳細に説明する(オーディオ)デジタル処理に関する数十のオンラインプレゼンテーションがあります。
ピシェネット2013

質問の最後の部分に対処するために、回答を編集しました。
Matt L.

あなたはx(n-何か)を使っています、xとは何ですか?「n」は入力サンプルだと思いますか?いい答えだ!
Niek van der Steen 2013

11

あなたはローパスフィルターがどのように機能するか尋ねて、フィルターがあなたのデータの過去の値を使用すると述べました。これはローパスフィルターで何が起こるかについての非技術的な議論です。

ローパスフィルターは、信号のさまざまなビュー(時間的にシフト)を取得し、それらをスケーリングして加算します。信号を3回描画することを想像できます。1つは電流、2つ目は1サンプル時間シフト、3つ目は2サンプル時間シフトします。

低周波数では、すべてのビューが非常によく似ています(単一のサンプルによるシフトは、信号のどこにいてもほとんど変化しません)。この場合、3つのバージョンが建設的(または少なくとも非破壊的)に加算されるため、信号はフィルターを通過します。

より高い周波数に移行すると、信号のシフトされた各バージョンは、任意の瞬間(サンプルポイント)でより明確になり、実際には符号が逆になることさえあります。これらの高い周波数では、信号の3つのバージョンが相殺(破壊的に追加)される傾向があるため、信号が減衰します。

異なるタイプのフィルターは、この種の建設的/破壊的な干渉が適切な周波数帯域で発生するように調整して、ローパス、バンドパス、またはハイパスフィルターを作成します。


1

それはあなたがそれをどのようにしたいかに依存します。私のために私はで実装しましたC。それで、私がしたことは、を使用してフィルター係数を生成したmatlabことfirlsです。次に、そのフィルター係数を配列に格納し、これらのフィルター係数をのフィルター関数に渡しましたC。ではmatlab、フィルター係数を生成し、畳み込み演算を使用するか、特定のフィルターを使用するのは非常に簡単です。しかし、Cあなたもフィルターを実装する必要があります。私の部分では、DSPでそれを行う必要があるため、mex関数を使用して実装しC、結果を得ましたmatlab。係数を計算するには、次のコマンドを使用します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 )
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.