【QT】采用FFTW计算FFT的频谱图和MATLAB计算不一致的情况

项目场景:在QT中对某段信号计算FFT,并采用QcustomPlot画出频谱图


问题描述:QT中画出的频谱图一直显示在-744Hz至744Hz的频段内,而MATLAB中FFT的结果在0-10KHz都有频率分量,出现不一致情况。

1、QT输出FFT频谱图

2、MATLAB输出FFT频谱图


原因分析:第一反应是QT中引用FFTW函数计算FFT出现错误,开始详细排查。


解决方案:通过参考一些网上的demo,发现代码本身没有问题。

1、排除FFTW计算的问题。与MATLAB计算的结果进行了比较,发现二者输出的结果是一致的。

//FFTW计算FFT
void FFT(double *y,int N,double *FFT){

    fftw_complex *in = NULL;
    fftw_complex *out = NULL;
    fftw_plan p;
    //分配内存空间
    in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * N);
    out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * N);
    // 创建句柄
    p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
    // 输入
    for (int i=0; i<N; i++)
    {
        in[i][0] = y[i];
        in[i][1] = 0;
    }
    //执行
    fftw_execute(p);
    fftw_destroy_plan(p);
    // 输出
    for (int i=0; i<N; i++)
    {
     FFT[i]= sqrt((out[i][0])*(out[i][0])+(out[i][1])*(out[i][1]));
    }


    fftw_free(in);
    fftw_free(out);
}

2、进一步判断是否为QT绘制频谱图的问题。需要将下列横轴的计算公式做一定的调整,结果输出才是正常的,不知道为啥会有这么一个bug的出现,终归是解决了。

//修改前的代码
   QVector<double> x(N/2), y(N/2);
   for (int i=0; i< N/2; i++)
   {
     x[i]=i*handlex2.fs/N;
     y[i]=FFT[i];  //y
   }
 //修改后的代码
  QVector<double> x(N/2), y(N/2);
   for (int i=0; i< N/2; i++)
   {
     x[i]=i;
     x[i]=x[i]*handlex2.fs/N;
     y[i]=FFT[i];  //y
   }

3、正常输出,且与MATLAB结果一致,问题得到解决。

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Qt中使用FFTW库实现音频频谱图的方法如下: 1. 首先,您需要在Qt项目中添加FFTW库的引用。您可以从官方网站(http://www.fftw.org/download.html)下载并安装FFTW库。 2. 在您的Qt代码中,包含FFTW库的头文件。例如,添加以下代码行到您的文件中: ``` #include <fftw3.h> ``` 3. 创建一个QHSpectrumAnalyser类,用于分析音频频谱。在该类中,您需要定义一个成员变量来存储频谱幅度。 ``` QVector<double> m_spectrum; ``` 4. 在QHSpectrumAnalyser类中,实现一个槽函数slotAnalyseSpectrum,用于进行频谱分析。您可以使用以下代码作为参考: ``` void QHSpectrumAnalyser::slotAnalyseSpectrum(const QVector<double>& data) { memcpy(m_inputBuffer, data.data(), data.size() * sizeof(double)); for(int i = 0; i < m_inputLength; i++) { m_inputBuffer[i = m_inputBuffer[i * m_window[i]; } fftw_execute(m_plan); int spectrumLen = m_spectrum.length(); for(int i = 0; i < spectrumLen; i++) { double realVal = m_outputBuffer[i][REAL]; double imagVal = m_outputBuffer[i][IMAG]; // 计算频谱幅度 m_spectrum[i = qSqrt(realVal * realVal + imagVal * imagVal) / static_cast<double>(m_inputLength); } emit signalSpectrumAnalysed(m_spectrum); } ``` 在该函数中,将音频数据存储到m_inputBuffer数组中,并将其与汉宁窗(m_window)相乘。然后,执行FFT变换并计算频谱幅度。最后,通过信号signalSpectrumAnalysed发送频谱数据。 5. 在您的Qt代码中,使用QHSpectrumAnalyser类的实例进行音频频谱分析。您可以连接音频输入信号到槽函数slotAnalyseSpectrum,并在槽函数中处理分析后的频谱数据。 ``` QHSpectrumAnalyser spectrumAnalyser; connect(audioInput, SIGNAL(dataReady(QVector<double>)), &spectrumAnalyser, SLOT(slotAnalyseSpectrum(QVector<double>))); ``` 这里的audioInput是您的音频输入设备,它会发送音频数据到槽函数。 6. 最后,在您的界面上显示频谱图。您可以使用Qt提供的绘图功能来绘制频谱图,或使用第三方库(如QCustomPlot)来简化绘图过程。 ``` // 在绘图区域绘制频谱图 void MyWidget::paintEvent(QPaintEvent*) { QPainter painter(this); painter.setPen(Qt::blue); for(int i = 0; i < spectrum.size(); i++) { int x = i; int y = height() - spectrum[i * height(); // 根据频谱幅度计算绘制高度 painter.drawPoint(x, y); } } ``` 这里的spectrum是频谱幅度数据。 希望这些信息对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旺旺碎冰冰!!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值