2016-09-10 38 views
0

我對信號處理還很陌生,我想創建一個使用FFTW的示例VST插件(因爲我在Rosetta Code上找到的FFT和IFFT似乎也在工作慢慢地),除了(無用地)對每個輸入採樣執行FFT之外什麼也不做,然後對這個結果應用IFFT。目標是獲得原始聲音,但輸出看起來(因爲缺乏用於描述聲音質量的更好術語的知識)「亂碼」。下面是processReplacing函數的代碼:使用FFTW在VST插件中的「亂碼」聲音

void VST_Testing::VST_Testing::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames) { 
    resume(); 
    time = 0; 
    float *in1 = inputs[0]; 
    float *in2 = inputs[1]; 
    float *out1 = outputs[0]; //L 
    float *out2 = outputs[1]; //R 
    float *out3 = outputs[2]; //C 
    float *out4 = outputs[3]; //RL 
    float *out5 = outputs[4]; //RR 
    VstInt32 initialFrames = sampleFrames; 
    fftw_complex* left = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*sampleFrames); 
    fftw_complex* right = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*sampleFrames); 
    int i = 0; 
    while (--sampleFrames >= 0) 
    { 
     left[i][0] = *in1++; 
     left[i][1] = 0; 
     right[i][0] = *in2++; 
     left[i][1] = 0; 
     i++; 
    } 
    sampleFrames = initialFrames; 

    fftw_complex* l_out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*sampleFrames); 
    fftw_complex* r_out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*sampleFrames); 

    fftw_plan p_l = fftw_plan_dft_1d(sampleFrames, left, l_out, FFTW_FORWARD, FFTW_MEASURE); 
    fftw_plan p_r = fftw_plan_dft_1d(sampleFrames, right, r_out, FFTW_FORWARD, FFTW_MEASURE); 

    fftw_execute(p_l); 
    fftw_execute(p_r); 

    fftw_destroy_plan(p_l); 
    fftw_destroy_plan(p_r); 

    p_l = fftw_plan_dft_1d(sampleFrames, l_out, left, FFTW_BACKWARD, FFTW_MEASURE); 
    p_r = fftw_plan_dft_1d(sampleFrames, r_out, right, FFTW_BACKWARD, FFTW_MEASURE); 

    fftw_execute(p_l); 
    fftw_execute(p_r); 
    i = 0; 
    while (--sampleFrames >= 0) 
    { 
     (*out3++) = 0.5*left[i][0] + 0.5*right[i][0]; 
     (*out4++) = left[i][0]; 
     (*out5++) = right[i][0]; 
     i++; 
    } 

    fftw_destroy_plan(p_l); 
    fftw_destroy_plan(p_r); 

    fftw_free(left); 
    fftw_free(right); 
    fftw_free(l_out); 
    fftw_free(r_out); 
    } 
} 

我的期望是,我會得到in1in2信號(左和預期的使用權輸入)輸入回幾乎相同的out4out5(左後和預期用途中的右後輸出)。我在代碼中犯了錯誤,還是我對FFTW的行爲期望不正確?

回答

1

從FFTW參考:

FFTW_MEASURE告訴FFTW發現通過實際計算幾個FFT和測量它們的執行時間的優化方案。根據您的機器,這可能需要一些時間(通常幾秒鐘)。

這表明你可能應該預先運行這個例程,然後使用它生成的計劃,而不是每個週期都重新創建它們。當然,這需要固定的幀大小,但遲早你會面臨這個問題。

1

也許不是你唯一的問題,但你有一個複製粘貼錯誤的位置:

while (--sampleFrames >= 0) 
{ 
    left[i][0] = *in1++; 
    left[i][1] = 0; 
    right[i][0] = *in2++; 
    left[i][1] = 0; // <<< should be right[i][1] = 0; 
    i++; 
} 
2

的問題是很明顯所致,除了複製和粘貼錯誤,事實證明FFTW單位計算一個非標準化的變換。來自「What FFTW really computes」,

FFTW計算非標準化變換,因爲在DFT中求和之前沒有係數。換句話說,應用前向變換和後向變換將使輸入乘以n。

解決這個問題是通過initialFrames爲了正常化來劃分信號:

while (--sampleFrames >= 0) 
{ 
    (*out3++) = 0.5*(left[i][0]/initialFrames) + 0.5*(right[i][0]/initialFrames); 
    (*out4++) = left[i][0]/initialFrames; 
    (*out5++) = right[i][0]/initialFrames; 
    i++; 
}