2011-05-05 69 views
1

我已經創建了一個簡單的切比雪夫低通濾波器,基於本網站生成的係數:http://www-users.cs.york.ac.uk/~fisher/mkfilter/,我正在使用它來濾除16kHz採樣率音頻信號之前的4kHz以上的頻率,然後下采樣到8kHz。這裏是我的代碼(這是C#,但這個問題不是特定於C#的,可以隨意使用不同語言的其他語言)。Chebyshev LPF引入噪聲

/// <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的正弦波「啁啾聲」。測試信號是這樣的:

test signal

對其進行篩選後,我得到:

filtered spectrum

波形顯示過濾器確實減少4kHz以上頻率的幅度,但我有一個噪音加在我的信號上。這似乎是我嘗試實施的過濾器類型中的任何一種(例如巴特沃斯,凸起的餘弦等)。

filtered waveform

上午我做錯了什麼,或者說這些過濾器只需在其他頻率引入假象?如果我使用平均每對樣本的樸素方法進行下采樣,我根本不會得到這種噪聲(但顯然混疊更糟糕)。

回答

2

好的,這是我真的很愚蠢。我的LPF的創建發生在處理循環內部而不是外部,這意味着每創建一個新樣本512個樣本,這意味着我正在失去保存的狀態。只有一個過濾器運行在整個文件中,噪聲消失,並且正如我們所期望的那樣,由於過濾器無法完全移除截止點以上的所有內容,因此會出現混疊頻率。

correctly using filter

0

在第一次使用它們之前,您尚未正確初始化您的xvyv陣列。在大多數語言中,這意味着它們的值是未定義的,這可能會導致像您一樣的意外結果。將它們初始化爲適當的值(如0)可能會解決您的問題。

+0

它是C#,所以它們將包含零。 – 2011-05-05 11:04:27

+0

好的(標籤會有幫助) – Bart 2011-05-05 11:23:02

+0

將編輯問題。不想標記C#,因爲我會用任何編程語言回答 – 2011-05-05 11:27:32

2

我在Mathematica中檢查了你的過濾代碼,在沒有引入噪聲的情況下它工作正常,所以可能噪聲來自於你的代碼的其他部分。

Chirp after filtering

+0

出於興趣,您是否將中間項的精度限制爲24位(即單精度浮點數)? – 2011-05-05 11:41:49

+0

不,Mathematica默認使用雙機精度,所以我使用它。我會試着看看我是否可以用單一精度重複過濾。 – 2011-05-05 11:47:54

+0

謝謝,你是對的,這是我的代碼的另一部分(請參閱我的答案) – 2011-05-05 12:05:56

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])); 
+0

謝謝,我曾在嘗試雙精度版本的過濾器,而我正在調查,但最終它竟然是一個更簡單問題(請參閱我的回答) – 2011-05-05 12:13:44