使用 FFTW 執行 R2C 正向轉換、頻域濾波、C2R 逆向轉換後,輸出波形與原始資料極其相似,而非預期的頻帶濾波結果。MATLAB 實作同邏輯則正確。
// 正向 FFT
fftw_plan p = fftw_plan_dft_r2c_1d(N, in, out1, FFTW_ESTIMATE);
fftw_execute(p);
// 頻域濾波
for (int m = 0; m < Nout-1; m++) {
float K = m / (Nout / nSamples); // 問題行
if (K < f1 || K > f2) { out2[m][0] = out2[m][1] = 0; }
else { out2[m][0] = out1[m][0]; out2[m][1] = out1[m][1]; }
}
// 逆向 FFT
fftw_plan c2cP = fftw_plan_dft_c2r_1d(N, out2, out3, FFTW_ESTIMATE);
fftw_execute(c2cP);
// FFTW 逆變換不自動除以 N,需手動縮放
for (int i = 0; i < N; i++) out3[i] /= N;
關鍵錯誤在於頻率索引計算:
float K = m / (Nout / nSamples); // 整數除法導致 K 恆為 0 或 1
C/C++ 中整數除法會捨去小數部分,導致 `K` 無法正確映射至實際頻率,濾波條件失效,幾乎所有頻率分量被保留,逆變換後自然接近原始波形。
float K = 1.0f * m / (Nout / nSamples); // 強制浮點除法
// 或
float K = (float)m / (Nout / nSamples);
float fs = nSamples; // 假設採樣率 = 樣本數/秒
for (int m = 0; m < Nout; m++) {
float freq = m * fs / N; // 真實頻率 Hz
if (freq < fmin || freq > fmax) { /* 零化 */ }
}
修正後,輸出波形應明顯不同於原始波形,僅保留目標頻帶成分。可對比 MATLAB `fft` -> 零化 -> `ifft` 結果確認一致性。