2
$\begingroup$

I'm working with the Aquila C++ DSP library. I'm computing the FFT of a wave file (16 bit depth, single channel, 44100 sample rate). I am using a window size of 16384 to calculate the FFT spectrum.

I'm having an issue converting the the digital frequency (0/N, 1/N, ... N/N) to the corresponding analog frequency. When I apply the sample rate multiplier S,

f = S*i/N; // Convert from digital frequency to analog frequency

I get analog frequencies that are 4 times greater than what I expect.

For example, I read in a pianos A1 note. I expect this to be ~55 Hz. Instead I'm getting ~220 Hz. Refer to the photo below.

FFT with analog frequncies 4x larger than expected

Now I'm first wondering if I'm scaling my the wrong number. However, I'm pretty sure it's correct. So now I'm curious if somehow the time domain data I'm reading is compressed by a factor of 4, such that the frequencies appear to be 4 times greater. Does anyone know if there is a common .wav file 'gotch-ya' when reading from them?

I've posted the relevant part of my code if anyone is interested.

/* sample window */
int window_size = 16384;

/* Calculate the FFT */
std::shared_ptr<Aquila::Fft> p_fft_interface = Aquila::FftFactory::getFft(window_size);  // This returns a shared pointer to an FFT calculation object.
auto spectrum = p_fft_interface->fft(wave_object.toArray());

QVector<double> x(window_size);
QVector<double> y(window_size);

/* Prepare to plot & convert to analog frequency */
double max_value = 0;
for(int i = 0; i < window_size; i++)
{
    x[i] = i*(sample_freq/window_size);
    y[i] = abs(spectrum[i]);

    if(abs(spectrum[i]) > max_value)
    {
        max_value = abs(spectrum[i]);
    }
}
$\endgroup$
0
$\begingroup$

Not familiar with Aquila in particular, and I don't see how you're mapping the output spectrum samples to an X-axis that ends at 800 Hz, but remember that a real-only FFT mirrors its output data in the second half of the buffer. You may need to run your loop from 0 to window_size/2 if Aquila's FFT is implemented the usual way.

That could account for a factor of 2x.

$\endgroup$
0
$\begingroup$

Further to @user572's answer, the other 2x could be coming from the fact you are passing a real array to a complex FFT: p_fft_interface->fft(...). Check the documentation for p_fft_interface->fft to make sure it's not treating your samples as pairs of real/imaginary components rather than just real.

$\endgroup$
0
$\begingroup$

An alternative to other answers (that sugguest you're passing real-values to complex-fft).

One common mistake that results in exactly this error is an incorrect sampling rate parameter. It would sound like slow-motion if this is the case.

If the .wav file was actually sampled at 1/4 of the rate entered, your frequency spectrum would reflect this as well. It's possible your file was sampled at 11025 Hz. Try and verify the sampling rate both on your OS and within Aquila.

You didn't say how to obtained the signal, but another possibility is your mic filters out low frequencies, try putting another wav file in the function and see if you find any power below the 100 Hz range. This will confirm it's not just the signal.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.