我是靠谱客的博主 活力小蝴蝶,这篇文章主要介绍FFT专题:IFFT后信号如何重建,现在分享给大家,希望可以做个参考。

    ifft(outFFTData, g_fft_temp, inFFTData, g_twiddle_ifft, twiddle_stride, F_WLEN);

    //思考ifft输出的复数结果怎么给到硬件输出

之前一直关注FFT后信号奔赴到频域处理,那么频域处理完后,怎么重建信号呢?

给出一段FFT和IFFT函数源码

 
int nFrameRunCount = 0;

#pragma section("ss_fw_code_fast")
void ToneChip_TestFFT_Process(float *Din, float *Dout, int nLen)
{
    float freqResol;                //频点间隔,单位:Hz
    int i = 0;
    int j = 0;
    int k = 0;
    float *pDataIn = (float *)Din;
    float *pDataOut = (float *)Dout;
    int nDataInLen = nLen;
    int twiddle_stride = 1;
    float amp = 0.0f;             //幅值

    float n2r = 2.0 / F_WLEN;     //计算幅值时,相乘
    complex_float *inFFTData = (complex_float *)g_fft_input;
    complex_float *outFFTData = (complex_float *)g_fft_output;
    float *inFrameData = (float * )g_inFrameData;
    float fAmpMax = 0.0;

    freqResol = (SAMPLING_RATE_48K * 1.0) / (F_WLEN * 1.0);    //得到频率分辨率
    memset(inFFTData, 0, sizeof(complex_float) * (F_WLEN) );
    memset(outFFTData, 0, sizeof(complex_float) * (F_WLEN) );

    // NHS处理帧旧数据的移动(最老的数据放在inFrameData[0],最新的数据放在了inFrameData[F_WLEN])
    fft_sp_blk_move((float *)&inFrameData[nDataInLen], (float *)inFrameData, (F_WLEN - nDataInLen));

    // 用新采样的数据更新NHS处理帧的sampleNumber个长度空间
    fft_sp_blk_move((float *)pDataIn, (float *)&inFrameData[F_WLEN - nDataInLen], nDataInLen);
    nFrameRunCount++;

    //前面4帧就不处理
    if(nFrameRunCount < F_WLEN / nDataInLen)
    {
        return;
    }

    //2021年10月29日在加窗前对数据进行一次overlap
    for(i = 0; i < F_WLEN; i++)
    {
        inFFTData[i].re = inFrameData[i] * (g_win[i]);      //数据加窗hanning
        inFFTData[i].im = 0.0f;
    }

    //在ADSP21489中调用FFT库函数
    cfft(inFFTData, g_fft_temp, outFFTData, g_twiddle_fft, twiddle_stride, F_WLEN);
    //如果inFFTData可以数据是临时性可以被重写,那么可以把g_fft_temp省出来
//  cfft(inFFTData, NULL, outFFTData, g_twiddle_fft, twiddle_stride, F_WLEN);

    fAmpMax = -F_FLT_MAX;
    //计算频点的功率

    for(i = 1; i < F_WLEN / 2; i++)
    {
        amp = sqrtf(outFFTData[i].re * outFFTData[i].re  + outFFTData[i].im  * outFFTData[i].im );
        amp = amp * n2r * 2.0;

        if (fAmpMax < amp)
        {
            fAmpMax = amp;      //找出频点中最大的值
            k = i;
        }
    }

    cfft_mag(outFFTData, g_fftSpectrum, F_WLEN);

    memset(inFFTData, 0, sizeof(complex_float) * F_WLEN);
    memset(g_fft_temp, 0, sizeof(complex_float) * F_WLEN);
    twiddle_stride = 1;
    ifft(outFFTData, g_fft_temp, inFFTData, g_twiddle_ifft, twiddle_stride, F_WLEN);

    //思考ifft输出的复数结果怎么给到硬件输出
    for(i = 0; i < nLen; i++)
    {
        pDataOut[i] = inFFTData[i].re;      //重建信号,只取实部
//        pDataOut[i] = pDataIn[i];     //直通测试
    }

}

 原始波形

经过fft和iff处理后上述代码输出的波形

 输出不正常,原因分析:

1.原始信号经过了hanning加窗,信号有衰减,经过加窗后,能量有所衰减。

查阅了相关资料后了解到 

在做FFT计算时,有时候需要用到平顶汉宁窗,如下:
//Tukey window: for 20ms 
/* 
The Tukey window, also known as the cosine-tapered window, 
can be regarded as a cosine lobe of width N*alpha/2 (spanning N*alpha/2 + 1 observations) 
that is convolved with a rectangular window of width N(1 - alpha/2). 
w(n) = 1/2 * (1 - cos(2*pi*n/(alpha*N))); 0 <= n <= alpha*N/2; 
w(n) = 1; alpha*N/2 <= n <= N/2; 
w(N-n) = w(n); 0 <= n <= N/2; 
At α = 0 it becomes rectangular, and at α = 1 it becomes a Hann window. 
*/
平顶汉宁窗的使用场景是:当2帧数据叠在一起时,当前帧大于上一帧,即当前帧所有数据和上一帧的部分数据一起叠帧时,此时就需要使用平顶汉宁窗函数。例如每一帧长320点,当前帧的320点和上一帧的后192点的数据一起叠帧,做512点的FFT,此时就需要使用平顶汉宁窗,其中平顶的数据长度为320-192+1(汉宁窗本身就有1个值为1).

 添加的窗函数还必须满足另外一个条件,即重叠缓冲区的部分的窗口的平方和必须为1, 
即:w(N)^2 + w(M+N)^2 = 1;

虽然加窗能减少频谱泄露,但是加窗也存在一个问题:加窗衰减了每帧信号的能量,特别是边界处。为了解决这一个问题,就引入了合成窗的概念。

在iSTFT中,合成窗是在iFFT之后,对时域信号做的。此次加窗,并不是为了减少频谱泄露,因为之后不再做FFT,不需要满足周期性序列条件。而是为解决分析窗导致能量衰减问题的。

总结就是要对IFFT后的数据进行重建,需要注意

根据完美重建公式,合成窗的选择,不仅跟分析窗有关,还和overlap有关。不同的overlap要采用不同的合成窗。

重点总结

对ifft后的数据要加一个合成窗函数,该函数满足重叠缓冲区的部分的窗口的平方和必须为1,即分析窗和合成窗平方和等于1,(另外测试如果对原始信号不加窗,那么ifft后可以得到正常信号)

参考文档:使用多特征建模分析语音噪声可能性的噪声抑制方法和装置.caj (专利文档:0059,0060)

2022.11.15

补充一下FFT之后取频域信号只取一半,而另一半却往往没注意是怎么分布的

下面截图看一下fft之后数据

 因为我上图是作的1024点变换,那么看一下512点是什么

 1024点FFT时,可以观察到的对称结构为

0点对应512点

511点对应的513点

1点则对应的是1023点

2点则对应的是1022点

最后

以上就是活力小蝴蝶最近收集整理的关于FFT专题:IFFT后信号如何重建的全部内容,更多相关FFT专题内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(143)

评论列表共有 0 条评论

立即
投稿
返回
顶部