音频处理中频域转时域的恢复

本文中使用的语言为c++,使用的三方库为fftw,libsndfile

音频的时域转频域

这一部分主要使用傅里叶变换,将时域转成频域。这一块的帖子已经很多,这里不再赘述了。主要注意点如下:

  • fftw库的使用,请参考 fftw官网
  • libsndfile库的使用,请参考 libsndfile官网
  • 窗体采用汉宁窗,宽度为512ms,处理音频采样率为8k,16bit,单声道,窗体移动为1/2窗体宽度
    汉宁窗函数
    汉宁窗函数如上所示

实现逻辑如下:

  1. 使用libsndfile读取wav文件,获取到double数组
  2. 制定窗宽度为512ms,sample长度为N=512*8
  3. 每个窗载入N个sample的数组,然后做傅里叶变换,调用fftw_plan_dft_r2c_1d函数,获取到复数数组。
    // HERE IS pseudocode
    double *in = (double *) fftw_malloc(N* sizeof(double));
    fftw_complex  *out = (fftw_complex *) fftw_malloc(N* sizeof(fftw_complex));
    ... ...

	for (int i = 0; i < N; ++i) {
        double multiplier = 0.5 * (1 - cos(2*M_PI*i/(N-1)));//Hanning Window
        in[i] =  wav[i]*multiplier;
    }
    ... ...
    plan = fftw_plan_dft_r2c_1d(N, in, out, FFTW_ESTIMATE);
	fftw_execute(plan);
  1. 窗体移动1/2窗体宽度,载入N个sample,再做一次步骤3
  2. 重复步骤4,直到窗体移动到文件末尾
    窗体移动示例

从频域恢复到时域

一般来说,在频域中我们会做一些处理,比如说滤波,将50HZ以下的频率去掉。可以在频域中轻松处理。处理后再使用傅里叶逆变换将频域数据恢复成时域数据。

如下将低频部分频率滤掉

	// HERE IS pseudocode
    for (int i = 0; i < N; ++i) {
        if (i<=50) {
            out[i][0] = 0;
            out[i][1] = 0;
        }
    }

再转回时域

    double *out2 = (double *) fftw_malloc(N* sizeof(double));
    fftw_plan backword_plan  = fftw_plan_dft_c2r_1d(N, out, out2, FFTW_ESTIMATE);
    fftw_execute(backword_plan);
    for (int i=0; i<N; ++i) {
        out2[i] = out2[i]/N; // normalization
    }

最后将数据写入wav文件。
写的时候注意。因为是有重复数据的(窗体是有一半重复的),所以重复的部分是要相乘处理的。

一些常见问题

为什么窗体宽度为512ms?

这个主要看主要分析的频谱范围,因为本人只关心2kHZ以下部分,为了达到这个频率,窗里的sample数必须达到4k以上。512*8=4096,达到要求即可。如果需要更高频率,需要按此计算。

频域转时域是否需要加窗?

上面的例子是没有的,但是实际上是需要的。

窗其实分为两种, 分析窗和合成窗
只是巧合的是位移1/2的汉宁窗(分析窗)+ 矩形窗(合成窗)正好可以还原信号。

还有一种组合是 1/2的正弦窗+ 正弦窗(合成窗)也是可以还原信号的。

为什么窗体位移为1/2?

原始信号乘以窗函数后,无论是哪一种,都会存在前后部分的信号衰减。这主要是因为窗函数的意义——它就是为了将窗体部分的信号趋近于周期的。
1/2的汉宁窗移动有个好处是,前一个窗体的后半部分乘以下一个窗体的前半部分,正好可以还原衰减信号。利用这个特性,所以选取位移为1/2.
汉宁窗位移

为何还原出来的音频听上去一段一段的?

这个问题的根因正如上一个问题的解答。那么为什么会出现这个现象?
周期性衰减
一般来说,原始信号没有使用窗函数,在还原的时候会出现这个现象。

因为在做傅里叶变换时,对变换的信号是由周期性要求的。但是真实环境中的声音是不可能的。所以我们需要加窗处理,将窗中的信号趋近于周期性。

如果非周期行函数做处理会发生什么?能量的泄露。主频率的能量会被分散到其他频率上。这种泄露的频谱再逆变换回来的时候,原信号必然发生失真。而傅里叶变换是一段一段处理的,所以最终的音频也会出现一段一段的失真。


如果您觉得有所帮助,请给与一定的支持和鼓励。感谢。
在这里插入图片描述

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值