基于傅里叶变换的音频重采样算法 (附完整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

相关文章
相关标签/搜索