首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实FFT输出

实FFT输出
EN

Stack Overflow用户
提问于 2015-06-03 04:09:18
回答 1查看 658关注 0票数 2

我已经将fft实现到at32ucb系列控制器中,使用了kiss库,目前还在挣扎于fft的输出。我的目的是分析来自压电扬声器的声音。目前,测深仪的频率是420赫兹,这是我成功地从fft输出(交叉检查与示波器)。然而,如果将功能发生器的波形放入系统中,则输出频率仅为预期的一半。我怀疑这是我错了的频率仓计算公式;目前使用的是fft_peak_magnitude_index*sampling频率/ fft_size。我的输入是真实的,做真正的fft。(输出样本= N/2),并在fft前进行iir滤波和加窗。任何建议都会有很大的帮助!

代码语言:javascript
复制
            // IIR filter calculation, n = 256 fft points       
        for (ctr=0; ctr<n; ctr++)
        {       
            // filter calculation
            y[ctr] = num_coef[0]*x[ctr];
            y[ctr] += (num_coef[1]*x[ctr-1]) - (den_coef[1]*y[ctr-1]);
            y[ctr] += (num_coef[2]*x[ctr-2]) - (den_coef[2]*y[ctr-2]);
            y1[ctr] = y[ctr] - 510; //eliminate dc offset

            // hamming window
            hamming[ctr] = (0.54-((0.46) * cos(2*M_PI*ctr/n)));
            window[ctr] = hamming[ctr]*y1[ctr];

            fft_input[ctr].r = window[ctr];
            fft_input[ctr].i = 0;
            fft_output[ctr].r = 0;
            fft_output[ctr].i = 0;
        }


        kiss_fftr_cfg fftConfig = kiss_fftr_alloc(n,0,NULL,NULL);
        kiss_fftr(fftConfig, (kiss_fft_scalar * )fft_input, fft_output);

        peak = 0;
        freq_bin = 0;       
        for (ctr=0; ctr<n1; ctr++)
            {   
                fft_mag[ctr] = 10*(sqrt((fft_output[ctr].r * fft_output[ctr].r) + (fft_output[ctr].i * fft_output[ctr].i)))/(0.5*n);

                if(fft_mag[ctr] > peak)
                {
                    peak = fft_mag[ctr];
                    freq_bin = ctr;
                }

            frequency = (freq_bin*(10989/n)); // 10989 is the sampling freq
                //************************************
                //Usart write
                char filtResult[10];
                //sprintf(filtResult, "%04d %04d %04d\n", (int)peak, (int)freq_bin, (int)frequency);
                sprintf(filtResult, "%04d  %04d  %04d\n", (int)x[ctr], (int)fft_mag[ctr], (int)frequency);
                char c;
                char *ptr = &filtResult[0];
                do
                {
                    c = *ptr;
                    ptr++;
                    usart_bw_write_char(&AVR32_USART2, (int)c);
                    // sendByte(c);

                } while (c != '\n');
            }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-03 12:49:54

主要问题可能是您如何声明fft_input。基于your previous question,您将fft_input分配为kiss_fft_cpx数组。另一方面,函数kiss_fftr需要一个标量数组。通过将输入数组转换为具有:

代码语言:javascript
复制
kiss_fftr(fftConfig, (kiss_fft_scalar * )fft_input, fft_output);

KissFFT本质上是看到一个实值数据数组,其中包含每秒钟的零样本(作为假想部分填入的内容)。这实际上是原始信号的上采样版本(尽管没有内插),即一个采样率为采样率的两倍的信号(在您的freq_binfrequency转换中没有考虑到这一点)。为了解决这个问题,我建议您将数据打包到一个kiss_fft_scalar数组中:

代码语言:javascript
复制
kiss_fft_scalar fft_input[n];
...
for (ctr=0; ctr<n; ctr++)
{       
    ...
    fft_input[ctr] = window[ctr];
    ...
}
kiss_fftr_cfg fftConfig = kiss_fftr_alloc(n,0,NULL,NULL);
kiss_fftr(fftConfig, fft_input, fft_output);

还请注意,在寻找峰值时,您可能只对最终的最大峰值感兴趣,而不是对运行的最大值感兴趣。因此,您可以将循环限制为只计算峰值(如果需要,可以在以下freq_bin语句中使用ctr而不是ctr作为数组索引):

代码语言:javascript
复制
for (ctr=0; ctr<n1; ctr++)
{   
  fft_mag[ctr] = 10*(sqrt((fft_output[ctr].r * fft_output[ctr].r) + (fft_output[ctr].i * fft_output[ctr].i)))/(0.5*n);

  if(fft_mag[ctr] > peak)
  {
    peak = fft_mag[ctr];
    freq_bin = ctr;
  }
} // close the loop here before computing "frequency"

最后,在计算与最大幅度的桶相关联的频率时,需要确保使用浮点算法进行计算。如果我怀疑n是一个整数,那么您的公式将使用整数算法执行10989/n因子,从而导致截断。这可以简单地通过以下方法加以补救:

代码语言:javascript
复制
frequency = (freq_bin*(10989.0/n)); // 10989 is the sampling freq
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30610682

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档