I generate a sine wave
for(quint32 i = 0; i < ALen; ++i) ABuffer[i] = AAmplitude * qSin(i * M_2_PI * ASigFreq/ADiscrFreg); With the help of the FFTW library I get its spectrum in a complex form
// подготовка плана преобразования fftw_plan myPlan = fftw_plan_dft_r2c_1d(static_cast<int>(SampleCount), z, y, FFTW_ESTIMATE); // расчет ДПФ fftw_execute(myPlan); where SampleCount is the number of samples
z is an array describing a sine wave
y is an array of results
I get an array of amplitudes in real form
for (int i = 0; i < fftSampleCount; ++i) fftSamples[i] = sqrt(y[i][0] * y[i][0] + y[i][1] * y[i][1]); I calculate the "peak" and its position in the spectrum
auto GarmAmplMax = std::max_element(fftSamples,(fftSamples+ADataLen)); auto GarmNum = std::distance(fftSamples,GarmAmplMax); GarmAmplMax - peak amplitude
GarmNum - position in the spectrum fftSamples
Attention! Question: how to calculate the frequency for the received peak?
Function code entirely
void MainWindow::on_actGetData_triggered() { ui->pbRecord->setEnabled(false); // производим запись, а не генерацию звука qint64 SampleCount; double * x = nullptr; double * z = nullptr; QString WindowName; auto getCoeff = [&](int i ) -> double { switch (FWindowIndex) { case 0 : // без окна WindowName = "Без окна"; return 1; case 1 : // Hann WindowName = "Окно Ханна"; return 0.5*(1 - qCos((2 * M_PI * i)/(SampleCount-1))); case 2 : // Gausse { WindowName = "Окно Гауса"; double a = (SampleCount-1)/2; double t = (i - a)/(0.5 * a); return qExp(-(t*t)/2); }; case 3 : // Hamming WindowName = "Окно Хэммнга"; return 0.54 - 0.46 * qCos((M_2_PI * i)/(SampleCount - 1)); } return 0; }; int devIndex = ui->cbDevice->currentIndex(); if(ui->cbDevice->currentIndex()) { QAudioFormat format; format.setSampleRate(ui->spbDescrFreq->value()); format.setChannelCount(1); format.setSampleSize(16); format.setCodec("audio/pcm"); format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleType(QAudioFormat::SignedInt); QList<QAudioDeviceInfo> list = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); QAudioDeviceInfo info = list.at(devIndex - 1); if(!info.isFormatSupported(format)) { addMessage("Заданный формат записи не поддерживается"); ui->pbRecord->setEnabled(true); return; }; FRecorder = new QAudioInput(info,format, this); FBuffer->open(QIODevice::ReadWrite); FRecorder->start(FBuffer); addMessage("Запись запущена."); QTest::qWait(ui->spbDuration->value()); addMessage("Запись окончена. Начата обработка данных."); SampleCount = (*FBuffer).size()/2; qint16 * SamplesList = reinterpret_cast<qint16 *>((*FBuffer).buffer().data()); addMessage(QString("Сделано %1 отсчетов").arg(SampleCount)); x = new double [SampleCount]; z = new double [SampleCount]; // накладываем окно for (int i = 0; i < SampleCount; ++i) { x[i] = SamplesList[i]; z[i] = getCoeff(i) * x[i]; } FBuffer->buffer().clear(); delete FRecorder; FRecorder = nullptr; } else // генерация звука { // секунды частота SampleCount = (ui->spbDuration->value()/1000) * ui->spbDescrFreq->value(); addMessage("Начата генерация данных."); x = new double [SampleCount]; z = new double [SampleCount]; generateSinWav(x, // приемник данных SampleCount, // количество отсчетов ui->spbDescrFreq->value(), // частота дискретизации ui->spdSignalFreq->value(), // частота синусоиды 20000); // амплитуда сигнала for (int i = 0; i < SampleCount; ++i) { z[i] = getCoeff(i) * x[i]; //addMessage(QString("x[%1] = %2").arg(i).arg(x[i])); } addMessage("Данные сгенерированы. Начата их обработка"); } qint64 fftSampleCount = SampleCount / 2 + 1; fftw_complex * y = new fftw_complex[fftSampleCount]; // подготовка плана преобразования fftw_plan myPlan = fftw_plan_dft_r2c_1d(static_cast<int>(SampleCount), z, y, FFTW_ESTIMATE); // расчет ДПФ fftw_execute(myPlan); fftw_destroy_plan(myPlan); double * fftSamples = new double[fftSampleCount]; for (int i = 0; i < fftSampleCount; ++i) fftSamples[i] = sqrt(y[i][0] * y[i][0] + y[i][1] * y[i][1]); //получаем модуль комплексного числа - амплитуду сигнала addMessage("обработка закончена"); ChartForm * Form = new ChartForm; Form->setAttribute(Qt::WA_DeleteOnClose, true); Form->showSourceSignalChart(x,SampleCount,ui->spdSignalFreq->value()); Form->showSignalChart(z,SampleCount,WindowName); Form->showSpectrChart(fftSamples,fftSampleCount,ui->spbDescrFreq->value()); Form->show(); if(fftSamples) delete [] fftSamples; if(z) delete [] z; if(y) delete [] y; if(x) delete [] x; ui->pbRecord->setEnabled(true); }