基於傅里葉變換的音頻重採樣算法 (附完整c代碼)

前面有提到音頻採樣算法:html

WebRTC 音頻採樣算法 附完整C++示例代碼python

簡潔明瞭的插值音頻重採樣算法例子 (附完整C代碼)c++

近段時間有很多朋友給我寫過郵件,說了一些他們使用的狀況和問題。git

坦白講,我精力有限,但通常都會抽空回覆一下。github

大多數狀況,閱讀一下代碼就能解決的問題,算法

也是要嘗試一下的。c#

沒準,你就解決了呢?api

WebRtc的採樣算法自己就考慮到它的自身應用場景,函數

因此它會有一些侷限性,例如不支持任意採樣率等等。工具

而簡潔插值的這個算法,

我我的也一直在使用,由於簡潔明瞭,簡單粗暴。

我天然也就沒有進一步去細究採樣算法,

固然網上還有很多開源的採樣算法也是極其不錯的。

一直也想抽時間再作一個兼顧簡潔和質量的算法出來,不了了之。

最近一直在死磕傅里葉變換,網上的資源看了一籮筐。

徘徊到最後,毫無疑問FFTW3必須是你的首選,

從歲數性能以及使用的機率來講,當之無愧的王者。

固然也順帶整理一下,其餘的一些FFT實現,各有優劣。

用於學習,做爲參考資料也是不二之選。

有興趣的小夥伴,能夠參閱之.

https://github.com/cpuimage/StockhamFFT

https://github.com/cpuimage/uFFT

https://github.com/cpuimage/BluesteinCrz

https://github.com/cpuimage/fftw3

固然最佳的參考資料,仍是fftw3,

個人這個git作了如下工做:

1.梳理調整目錄結構

2.移除一些影響閱讀調試,讓人頭大的宏定義

3.合併代碼至fftw_api.c,移除一些不經常使用的代碼

注意:未通過嚴格測試驗證

也許這個git存在的意義在於方便衆人閱讀學習fftw的算法思路,

以及調試,扣代碼等等諸如此類的行爲。

因此有須要的同窗能夠,參考之。

 

回到本次的主題,

在之前作圖像算法的時候,就一直在想一個問題,

是否能夠利用傅里葉變換的特性進行圖像的重採樣呢?

這個一直是我心中的一個小石頭,一直沒放下。

從理論上來講,可行的,只是估計最終質量並不能保證。

最佳的嘗試莫過於音頻重採樣,在不少時候,

咱們常常須要對一個音頻進行傅里葉變換,而後進行上採樣或下采樣的操做。

那是否是能夠直接就在頻域進行重採樣呢?

這樣的作法是否是質量就能有所保障呢?

事實證實,這是可行的。

通過簡單試驗,基於傅里葉變換的音頻重採樣算法就這樣出爐了。

目前示例採用hsfft 這個開源傅里葉變換進行驗證,

沒有采用fftw3的緣由也很簡單,由於fftw3編譯器來有點麻煩。

而hsfft的函數風格與fftw3相似,只是速度性能上不及fftw3而已。

這樣也符合個人要求,真正應用的時候再使用fftw3替換之便可,

在驗證思路的時候,不必動用fftw3,

這也是我爲何使用簡潔重採樣的緣由之一。

每一個步驟都要有策略和方法,沒必要太過較真。

若是特定狀況下須要,我也能夠上matlab,python,delphi,c#,c++等等。

語言只是工具,關鍵仍是思路和思想。

貼上主要代碼:

#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif 

void FFTResample(float *input, float *output, int sizeIn, int sizeOut) {
    fft_t *fftin = (fft_t *) calloc(sizeof(fft_t), sizeIn);
    fft_t *fftout = (fft_t *) calloc(sizeof(fft_t), sizeOut);
    if (fftin == NULL || fftout == NULL) {
        if (fftout)
            free(fftout);
        if (fftin)
            free(fftin);
return; } fft_real_object fftPlan
= fft_real_init(sizeIn, 1); fft_r2c_exec(fftPlan, input, fftin); free_real_fft(fftPlan); int halfIn = (sizeIn / 2) + 1; int halfOut = (sizeOut / 2) + 1; for (int i = 0; i < MIN(halfIn, halfOut); ++i) { fftout[i].re = fftin[i].re; fftout[i].im = fftin[i].im; } fft_real_object ifftPlan = fft_real_init(sizeOut, -1); fft_c2r_exec(ifftPlan, fftout, output); free_real_fft(ifftPlan); float norm = 1.f / sizeIn; for (int i = 0; i < sizeOut; ++i) { output[i] = (output[i] * norm); } free(fftout); free(fftin); }

算法很是簡單,用一句時髦的語言來描述這個算法,就是「多退少補「。

須要補課FFT的能夠移步:

從多項式乘法到快速傅里葉變換

項目地址:

https://github.com/cpuimage/fftResample

採用Cmake編譯便可,示例代碼也很簡潔。

很少作解釋了~

以上,權當拋磚引玉。

如有其餘相關問題或者需求也能夠郵件聯繫俺探討。

郵箱地址是: gaozhihan@vip.qq.com

相關文章
相關標籤/搜索