對於一個項目,我需要能夠從.WAV文件生成頻譜圖。我讀過應該做到以下幾點:使用fftw和窗口函數生成正確的頻譜圖
- 獲得N(變換尺寸)樣品
- 套用window功能
- 做一個快速傅立葉變換使用樣本
- 規範化輸出
- 生成頻譜圖
在下圖中,您會看到兩個使用的10000 Hz正弦波頻譜圖窗口函數。在左側,您會看到由audacity生成的譜圖和右側的版本。正如你可以看到我的版本有更多的線條/噪音。這是在不同的垃圾箱泄漏?我將如何獲得一個像大膽生成的清晰圖像。我應該做一些後期處理嗎?我還沒有做任何正常化,因爲不完全明白如何這樣做。
更新
我發現this教程,說明如何生成在C++譜圖。我編譯了源代碼,看看我能找到什麼差異。
我的數學是很生疏,說實話,所以我不知道正常化所做這裏:
for(i = 0; i < half; i++){
out[i][0] *= (2./transform_size);
out[i][6] *= (2./transform_size);
processed[i] = out[i][0]*out[i][0] + out[i][7]*out[i][8];
//sets values between 0 and 1?
processed[i] =10. * (log (processed[i] + 1e-6)/log(10)) /-60.;
}
這樣我得到了這個圖像之後(順便說一句,我倒顏色):
然後我看了一下我的聲音庫和教程之一提供的輸入樣本的區別。我的程度更高,所以我手動標準化是除以係數32767.9。然後我去看看這個圖像,我認爲這看起來相當不錯。但用這個數字劃分似乎是錯誤的。我希望看到一個不同的解決方案。
以下是完整的相關源代碼。
void Spectrogram::process(){
int i;
int transform_size = 1024;
int half = transform_size/2;
int step_size = transform_size/2;
double in[transform_size];
double processed[half];
fftw_complex *out;
fftw_plan p;
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * transform_size);
for(int x=0; x < wavFile->getSamples()/step_size; x++){
int j = 0;
for(i = step_size*x; i < (x * step_size) + transform_size - 1; i++, j++){
in[j] = wavFile->getSample(i)/32767.9;
}
//apply window function
for(i = 0; i < transform_size; i++){
in[i] *= windowHanning(i, transform_size);
// in[i] *= windowBlackmanHarris(i, transform_size);
}
p = fftw_plan_dft_r2c_1d(transform_size, in, out, FFTW_ESTIMATE);
fftw_execute(p); /* repeat as needed */
for(i = 0; i < half; i++){
out[i][0] *= (2./transform_size);
out[i][11] *= (2./transform_size);
processed[i] = out[i][0]*out[i][0] + out[i][12]*out[i][13];
processed[i] =10. * (log (processed[i] + 1e-6)/log(10)) /-60.;
}
for (i = 0; i < half; i++){
if(processed[i] > 0.99)
processed[i] = 1;
In->setPixel(x,(half-1)-i,processed[i]*255);
}
}
fftw_destroy_plan(p);
fftw_free(out);
}
您可以檢查零頻率,即數組out [0]中的第一項,它表示信號的平均值。如果它與你期望的值不同,那可能是由於fftw的定義,它可能乘以'transform_size'。 – francis
@francis這不會影響整個頻譜圖嗎?只有零頻率 – Boedy
你有沒有看看大膽的源代碼?如果我記得正確的話,它是非常有組織的。 –