chebyshev lpf導入ノイズ
-
29-10-2019 - |
質問
このサイトによって生成された係数に基づいて、シンプルなChebyshev Low Passフィルターを作成しました。 http://www-users.cs.york.ac.uk/~fisher/mkfilter/, 、8kHzにダウンサンプリングする前に、16kHzのサンプルレートオーディオ信号で4kHzを超える周波数を除外するために使用しています。これが私のコードです(これはC#ですが、この質問はC#固有ではありません。異なる言語で他の言語を自由に使用してください)。
/// <summary>
/// Chebyshev, lowpass, -0.5dB ripple, order 4, 16kHz sample rte, 4kHz cutoff
/// </summary>
class ChebyshevLpf4Pole
{
const int NZEROS = 4;
const int NPOLES = 4;
const float GAIN = 1.403178626e+01f;
private float[] xv = new float[NZEROS+1];
private float[] yv = new float[NPOLES + 1];
public float Filter(float inValue)
{
xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4];
xv[4] = inValue / GAIN;
yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4];
yv[4] = (xv[0] + xv[4]) + 4 * (xv[1] + xv[3]) + 6 * xv[2]
+ (-0.1641503452f * yv[0]) + (0.4023376691f * yv[1])
+ (-0.9100943707f * yv[2]) + (0.5316388226f * yv[3]);
return yv[4];
}
}
テストするために、Audacityを使用して20Hzから8kHzまでの正弦波「Chirp」を作成しました。テスト信号は次のようになります:
それをフィルタリングした後、私は取得します:
波形は、フィルターが実際に4kHzを超える周波数の振幅を減少させていることを示していますが、信号にノイズが追加されています。これは、私が実装しようとするフィルタータイプのどちらかが当てはまるようです(例:Butterworth、Raised Cosineなど)。
私は何か間違ったことをしているのですか、それともこれらのフィルターは単に他の周波数でアーティファクトを導入しますか?すべてのサンプルを平均化するナイーブなアプローチを使用してダウンサンプリングすると、このノイズはまったくありません(ただし、明らかにエイリアシングははるかに悪いです)。
解決
わかりました、それは本当に愚かでした。私のLPFの作成は、外部ではなく処理ループ内で起こっていました。つまり、512サンプルごとに私が新しいものを作成していたことは、救われた状態を失っていたことを意味します。フィルターがファイル全体で実行されているインスタンスが1つだけで、ノイズは消え、予想通り、フィルターがカットオフ上のすべてを完全に削除できないため、エイリアス周波数を取得します。
他のヒント
Mathematicaのフィルターコードを確認しましたが、ノイズを導入せずにここで正常に動作します。そのため、おそらくノイズはコードの他の部分から発生します。
特に極のいずれかがユニットサークルに近い場合、数値の安定性の問題がある可能性があります。すべての中間用語を2倍の精度にしてから、最後に単一の精度に戻してください。私はC#にあまり精通していませんが、Cではこれは次のとおりです。
yv[4] = (float)(((double)xv[0] + (double)xv[4]) + 4.0 * ((double)xv[1] + (double)xv[3]) + 6.0 * xv[2]
+ (-0.1641503452 * (double)yv[0]) + (0.4023376691 * (double)yv[1])
+ (-0.9100943707 * (double)yv[2]) + (0.5316388226 * (double)yv[3]));
適切に初期化されていません xv
と yv
初めて使用する前の配列。ほとんどの言語では、これは彼らの価値が未定義であり、あなたのような予期しない結果につながる可能性があることを意味します。それらを適切な値に初期化する(0など)が問題を解決する場合があります。