1

I am using FFTW to build a music visualizer. And in my header file, I construct a struct:

struct SpectrumStruct{
    qreal frequency;
    qreal amplitude;
}; 

QVector<SpectrumStruct> m_spectrum;

And in my .cpp file,

void Widget::debug(QAudioBuffer buf)
{
    QAudioBuffer :: S16S * data = buf.data<QAudioBuffer :: S16S>();
    int sampleRate = buf.format().sampleRate();
//    int N = buf.frameCount();
    int N = 1024;
    fftw_complex *in, *out;
    in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * N);
    out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * N);
    for (int i = 0; i < N; ++i) {
        qreal hannwindow = 0.5 * (1 - qCos((2 * M_PI * i) / (N - 1)));
        in[i][0] = data[i].left * hannwindow;
        in[i][1] = 0;
    }
    fftw_plan myPlan = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
    fftw_execute(myPlan);
    for(int i = 0; i < N / 2; ++i) {
        struct SpectrumStruct thisSP;
        thisSP.frequency = double(i * sampleRate / N);
        qreal thisAmpt = qSqrt(out[i][0] * out[i][0] + out[i][1] * out[i][1]);
//        thisAmpt = 2.0 * thisAmpt / N;
        thisAmpt = 0.15 * log10(thisAmpt);
        thisAmpt = qMax(qreal(0.0), thisAmpt);
        thisAmpt = qMin(qreal(1.0), thisAmpt);
        thisSP.amplitude = thisAmpt;
        m_spectrum.push_back(thisSP);
        qDebug() << m_spectrum[i].frequency << "\t" << m_spectrum[i].amplitude << "\t" << thisAmpt;
    }

    fftw_destroy_plan(myPlan);
    fftw_free(in);
    fftw_free(out);

}

I tried to print each sample point's frequency and amplitude . The thisAmpt should be same with the m_spectrum[i].amplitude. But finally in the console thisAmpt is correct but m_spectrum[i].amplitude is always 0. How can it be?

Part of the console result:

20887    0   0.0475125
20930    0   0.0734866
20973    0   0.0784833
21016    0   0.156529
21059    0   0.19284
21102    0   0.168585
21145    0   0.134795
21188    0   0.119863
21231    0   0.122281
21274    0   0.138717
21317    0   0.15457
21360    0   0.139525
21404    0   0.0697819
21447    0   0.0985039
21490    0   0.153734
21533    0   0.147471
21576    0   0.0658756
21619    0   0.13765
21662    0   0.151573
21705    0   0.179327
21748    0   0.184664
21791    0   0.162867
21834    0   0.166042
21877    0   0.128155
21920    0   0.0839292
21963    0   0.0618584
22006    0   0.146992
Liam_1998
  • 1,157
  • 3
  • 12
  • 27
  • 1
    are you sure _m_spectrum_ is empty before the call of _debug_ ? if not `m_spectrum[i]` doesn't access to the value added through the push_back but an old where the frequency is not null but the the amplitude is. – bruno Dec 18 '18 at 13:15
  • to be sure to qDebug the added value use `m_spectrum.back()` rather than `m_spectrum[i]` – bruno Dec 18 '18 at 13:18
  • If buf.frameCount() < N, you will have an UB. Are you sure the frameCount is always >= 1024 ? – tunglt Dec 18 '18 at 13:31
  • I just find what's wrong with my code. I forgot to clear the vector before add value to it. And thank you all:) – Liam_1998 Dec 18 '18 at 13:55

2 Answers2

3
thisSP.frequency = double(i * sampleRate / N);

Expression in brackets has integer type and then it cast to double. So if you get result in range [0;1) you get zero and then cast it to double.

Probably, you want somethink like that:

thisSP.frequency = double(i) * sampleRate / N;
Konstantin T.
  • 994
  • 8
  • 22
0

Just as the @bruno 's comments, I forgot to clear the vector: m_spectrum before adding the value to it. Thank you all to solve my problem :)

Juan Leni
  • 6,982
  • 5
  • 55
  • 87
Liam_1998
  • 1,157
  • 3
  • 12
  • 27