Reputation: 427
I would like to make real time audio processing with Qt and display the fundamental frequency using FFTW3.
double
arrayMy code always returns 0 as fundamental frequency.
QByteArray *buffer;
QAudioInput *audioInput;
audioInput = new QAudioInput(format, this);
//Check the number of samples in input buffer
qint64 len = audioInput->bytesReady();
//Limit sample size
if(len > 4096)
len = 4096;
//Read sound samples from input device to buffer
qint64 l = input->read(buffer.data(), len);
if(l > 0)
{
int input_size = BufferSize;
// Compute corresponding number of complex output samples
int output_size = (input_size/2 + 1);
double *input_buffer = static_cast<double*>(fftw_malloc(input_size * sizeof(double)));
fftw_complex *out = static_cast<fftw_complex*>(fftw_malloc(output_size * sizeof(fftw_complex)));
//Assign sound samples to double array
input_buffer = (double*)buffer.data();
fftw_plan p3;
//Create plan
p3 = fftw_plan_dft_r2c_1d(input_size, input_buffer, out, FFTW_ESTIMATE);
fftw_execute(p3);
double reout[BufferSize];
double imgout[BufferSize];
double magnitude[BufferSize/2];
long ffond = 0.0; // Position of the frequency
double max = 0; // Maximal amplitude
for (int i = 0; i < BufferSize/2; i++)
{
reout[i] = out[i][0];
imgout[i] = out[i][1];
cout << imgout[i] << endl;
magnitude[i] = sqrt(reout[i]*reout[i] + imgout[i]*imgout[i]); //Calculate magnitude of first
double t = sqrt(reout[i]*reout[i] + imgout[i]*imgout[i]);
if(t > max)
{
max = t;
ffond = i;
}
}
qDebug() << "fundamental frequency is :" << QString::number(ffond*static_cast<double>);
fftw_destroy_plan(p3);
Upvotes: 2
Views: 2517
Reputation: 212929
You have two immediate problems that I can see:
you are not applying a window function, so there will be considerable spectral leakage and associated "smearing" of the spectrum (and probably a large DC (0 Hz) component with associated "skirt")
you are assuming that the largest magnitude in the spectrum is the fundamental frequency, which will most likely be incorrect for two reasons: (a) you may well have a large 0 Hz component which is larger than your fundamental or harmonics and (b) depending on the nature of the sound you are trying to analyse, the fundamental may be smaller in magnitude than the harmonics (it may even be missing completely)
I suggest you do the following:
apply a suitable window function prior to the FFT - this should make your peaks better defined and should reduce the artefacts at 0 Hz and just above
start your search at an appropriate bin rather than 0, e.g. if the minimum fundamental frequency you are interested in is say 50 Hz then start at the corresponding bin for 50 Hz rather than at 0
add a debug option to display the spectrum graphically - this visual debugging aid will help greatly when you are wondering why your results do not make sense
if what you are really trying to measure is pitch rather than fundamental frequency, then read up on pitch detection algorithms, e.g. Harmonic Product Spectrum - this will work a lot better than the naïve approach of trying to identify a fundamental (whose frequency will not be the same as the pitch in the general case)
Upvotes: 1