基于傅里叶变换的音频重采样算法 (附完整c代码)
前面有提到音頻采樣算法:
WebRTC 音頻采樣算法 附完整C++示例代碼
簡潔明了的插值音頻重采樣算法例子 (附完整C代碼)
近段時間有不少朋友給我寫過郵件,說了一些他們使用的情況和問題。
坦白講,我精力有限,但一般都會抽空回復一下。
大多數情況,閱讀一下代碼就能解決的問題,
也是要嘗試一下的。
沒準,你就解決了呢?
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
轉載于:https://www.cnblogs.com/cpuimage/p/9270739.html
總結
以上是生活随笔為你收集整理的基于傅里叶变换的音频重采样算法 (附完整c代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++primer plus 第13章
- 下一篇: 提高Python运行效率的6大技巧!