1

このサイトで生成された係数に基づいて、単純なチェビシェフローパスフィルターを作成しました:http : //www-users.cs.york.ac.uk/~fisher/mkfilter/、4kHzを超える周波数をフィルターで除去するために使用しています8kHzにダウンサンプリングする前の16kHzサンプルレートオーディオ信号。これが私のコードです(これは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までの正弦波「チャープ」を作成しました。テスト信号は次のようになります。

テスト信号

それをフィルタリングした後、私は得ます:

フィルタリングされたスペクトル

波形は、フィルターが実際に4kHzを超える周波数の振幅を低減していることを示していますが、信号に大量のノイズが追加されています。これは、私が実装しようとしているフィルタータイプ(バターワース、レイズドコサインなど)のいずれにも当てはまるようです。

フィルタリングされた波形

私は何か間違ったことをしていますか、それともこれらのフィルターは単に他の周波数でアーティファクトを導入しますか?サンプルのすべてのペアを平均化するという単純なアプローチを使用してダウンサンプリングした場合、このノイズはまったく発生しません(ただし、エイリアシングは明らかにはるかに悪いです)。

4

4 に答える 4

2

OK、それは私が本当に愚かだった。LPFの作成は、外部ではなく処理ループの内部で行われていました。つまり、512サンプルごとに新しいサンプルを作成していたため、保存された状態が失われていました。ファイル全体でフィルターのインスタンスを1つだけ実行すると、ノイズがなくなり、フィルターがカットオフより上のすべてを完全に削除できないため、予想どおりエイリアシング周波数が発生します。

フィルタを正しく使用する

于 2011-05-05T11:43:20.223 に答える
2

Mathematica でフィルタコードを確認しましたが、ここではノイズを発生させることなく正常に動作するため、おそらくコードの他の部分からノイズが発生していると思われます。

フィルタリング後のチャープ

于 2011-05-05T11:39:58.023 に答える
1

特に極のいずれかが単位円に近い場合、数値安定性の問題が発生する可能性があります。すべての中間項を倍精度にして、最後に単精度に戻してみてください。私は 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]));
于 2011-05-05T11:41:02.377 に答える
0

初めて使用する前にxv、アレイを適切に初期化していない。yvほとんどの言語では、これはそれらの値が未定義であることを意味し、あなたのような予期しない結果につながる可能性があります。それらを適切な値(0など)に初期化すると、問題が解決する場合があります。

于 2011-05-05T10:55:23.677 に答える