前面有提到音頻採樣算法:html
WebRTC 音頻採樣算法 附完整C++示例代碼python
近段時間有很多朋友給我寫過郵件,說了一些他們使用的狀況和問題。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