1
votes

I'm currently trying to display an audio spectrum using FFTW3 and SFML. I've followed the directions found here and looked at numerous references on FFT and spectrums and FFTW yet somehow my bars are almost all aligned to the left like below. Another issue I'm having is I can't find information on what the scale of the FFT output is. Currently I'm dividing it by 64 yet it still reaches beyond that occasionally. And further still I have found no information on why the output of the from FFTW has to be the same size as the input. So my questions are:

  1. Why is the majority of my spectrum aligned to the left unlike the image below mine?
  2. Why isn't the output between 0.0 and 1.0?
  3. Why is the input sample count related to the fft output count?

What I get:

enter image description here

What I'm looking for:

enter image description here

const int bufferSize = 256 * 8;

void init() {
    sampleCount = (int)buffer.getSampleCount();
    channelCount = (int)buffer.getChannelCount();
    for (int i = 0; i < bufferSize; i++) {
        window.push_back(0.54f - 0.46f * cos(2.0f * GMath::PI * (float)i / (float)bufferSize));
    }
    plan = fftwf_plan_dft_1d(bufferSize, signal, results, FFTW_FORWARD, FFTW_ESTIMATE);
}
void update() {
    int mark = (int)(sound.getPlayingOffset().asSeconds() * sampleRate);
    for (int i = 0; i < bufferSize; i++) {
        float s = 0.0f;

        if (i + mark < sampleCount) {
            s = (float)buffer.getSamples()[(i + mark) * channelCount] / (float)SHRT_MAX * window[i];
        }

        signal[i][0] = s;
        signal[i][1] = 0.0f;
    }
}
void draw() {
    int inc = bufferSize / 2 / size.x;
    int y = size.y - 1;
    int max = size.y;
    for (int i = 0; i < size.x; i ++) {
        float total = 0.0f;
        for (int j = 0; j < inc; j++) {
            int index = i * inc + j;
            total += std::sqrt(results[index][0] * results[index][0] + results[index][1] * results[index][1]);
        }
        total /= (float)(inc * 64);
        Rectangle2I rect = Rectangle2I(i, y, 1, -(int)(total * max)).absRect();
        g->setPixel(rect, Pixel(254, toColor(BLACK, GREEN)));
    }
}
2

2 Answers

0
votes

All of your questions are related to the FFT theory. Study the properties of FFT from any standard text/reference book and you will be able to answer your questions all by yourself only.

The least you can start from is here: https://en.wikipedia.org/wiki/Fast_Fourier_transform.

0
votes
  1. Many FFT implementations are energy preserving. That means the scale of the output is linearly related to the scale and/or size of the input.

  2. An FFT is a DFT is a square matrix transform. So the number of outputs will always be equal to the number of inputs (or half that by ignoring the redundant complex conjugate half given strictly real input), unless some outputs are thrown away. If not, it's not an FFT. If you want less outputs, there are ways to downsample the FFT output or post process it in other ways.