zoukankan      html  css  js  c++  java
  • 基于傅里叶变换的音频重采样算法 (附完整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

  • 相关阅读:
    Linux内核中的红黑树
    研究UEVENT相关东西,看到2篇优秀的博文,转载与此
    Nor Nand OneNand
    Linux设备模型(总线、设备、驱动程序和类)
    linux驱动的入口函数module_init的加载和释放(转)
    hwclock(Linux)
    Linux块设备驱动
    pdflush内核线程池及其中隐含的竞争
    Nand Flash与Nor Flash
    linux内核I2C体系结构(注意结构体原型)
  • 原文地址:https://www.cnblogs.com/cpuimage/p/9270739.html
Copyright © 2011-2022 走看看