0

I am using fftw to analyse the frequency spectrum of audio input to a computer from the mic input. I am using portaudio c++ libraries to capture the windows of time-domain audio data and then fftw to do a real to complex r2c transformation of this data to the frequency domain. Below is my function which I call everytime I receive the block of data.

The sample rate is 44100 samples per second , the sample type is short (signed 16 bit integer)and I am taking 250ms blocks of data in each window. The fft resolution is therefore 4Hz.

The problem is , i'm not sure how to interpret the data which I am receiving after the transformation. When no audio is played , I am getting amplitudes of around 1000 to 4000 for every frequency component, as soon as audio is played from an instrument for example, all of the amplitudes go negative.

I have tried doing a normalisation before the fft, by dividing by the average power and then the data makes more sense. All amplitudes are from 200 to 500 when nothing is played, then for example if I play a tone of 76Hz, the amplitude for this component increases to around 2000. So that is something along the lines of what I expect, but still not sure if this process can be implemented better.

My question is, am I doing the right thing here? Must the data be normalised and am I doing it right? Why am I still receiving high amplitudes on the frequencies that are not being played. Has anyone any experience of doing something similar and maybe give some tips. Many thanks in advance.

void AudioProcessor::GetFFT(void* inputData, void* freqSpectrum)
{
    double* input = (double*)inputData;
    short* freq_spectrum = (short*)freqSpectrum;

    fftPlan = fftw_plan_dft_r2c_1d(FRAMES_PER_BUFFER, input, complexOut, FFTW_ESTIMATE);

    fftw_execute(fftPlan);

    ////

    for (int k = 0; k < (FRAMES_PER_BUFFER + 1) / 2; ++k)
    {
        freq_spectrum[k] = (short)(sqrt(complexOut[k][0] * complexOut[k][0] + complexOut[k][1] * complexOut[k][1]));
    }

    if (FRAMES_PER_BUFFER % 2 == 0) /* frames per buffer is even number */
    {
        freq_spectrum[FRAMES_PER_BUFFER / 2] = (short)(sqrt(complexOut[FRAMES_PER_BUFFER / 2][0] * complexOut[FRAMES_PER_BUFFER / 2][0] + complexOut[FRAMES_PER_BUFFER / 2][1] * complexOut[FRAMES_PER_BUFFER / 2][1]));  /* Nyquist freq. */
    }
}
Engineer999
  • 3,683
  • 6
  • 33
  • 71
  • Why are you using `short` for your magnitudes ? It can't possibly represent the range of values that you might get - and it should never be negative, which suggests that you are just getting UB when you cast the double result of `sqrt`. – Paul R Apr 24 '17 at 07:52
  • Thanks for your reply. Why would it not represent the range of values that I get? Using the portaudio library, there are of course options to use different data types in the configuration settings, but someone recommended that I use shorts at 44,100 samples per second to capture the audio. This array of shorts are then converted to an array of doubles before calling my above function. By converting back to shorts , I wouldn't expect any loss, or should I? What would you recommend? Thanks – Engineer999 Apr 24 '17 at 09:23
  • `short` is fine for the input (time domain) data, but you need to use floating point for the output, at least up until the point that you have scaled it for display purposes (or whatever else you might want to do with it). Magnitude values can be very small (< 1, but not necessarily 0) and can also be quite large, due to the fact the FFT output data typically has a scaling factor of N. Work with float or double until you at least have the magnitude in a form that you want to use (note that typically you want to work with log magnitude it it's for display purposes). – Paul R Apr 24 '17 at 09:29
  • Ok , I understand. I will try that. Regarding working with log magnitude, how do I do this? Sorry, I'm a bit of a noob with this stuff – Engineer999 Apr 24 '17 at 09:38
  • Re log magnitude: see [this answer](http://stackoverflow.com/a/4678313/253056), which I previously referred you to in [your earlier question](http://stackoverflow.com/a/39845450/253056). – Paul R Apr 24 '17 at 09:49

0 Answers0