я хочу применить БПФ к реальному аудиоустройству и рассчитать пик
вот мой код ..
N=8192
kiss_fft_cpx out[N/2 +1];
int len = fft->N / 2 + 1;
kiss_fft_scalar* samples = &samples2[0]; //inputs from the mic
kiss_fftr(fft->config, samples, out);
for (int i = 0; i < len; i++) {
float re = scale(out[i].r) * N;
float im = scale(out[i].i) * N;
if (i > 0)
spectrum[i] = sqrtf(re * re + im * im) / (N / 2);
else
spectrum[i] = sqrtf(re * re + im * im) / N;
}
Теперь я рассчитываю выбор, используя код. но каждый раз это возвращает 0
float peak = 0;
float maxEnergy = 0;
for (int i = 0; i < BUFFER_SIZE / 2 + 1; i++) {
float binEnergy = spectrum.at(i);
if (binEnergy > maxEnergy) {
maxEnergy = binEnergy;
peak = i;
}
}
Здесь я всегда получаю пик = 0, пожалуйста, помогите
Вот мой вывод спектра для первых 25 образцов FFT ..
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[0]: 0.036530
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[1]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[2]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[3]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[4]: 0.040397
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[5]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[6]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[7]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[8]: 0.044121
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[9]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[10]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[11]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[12]: 0.040396
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[13]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[14]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[15]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[16]: 0.116464
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[17]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[18]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[19]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[20]: 0.040397
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[21]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[22]: 0.012086
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[23]: 0.011568
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[24]: 0.044121
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(267) > peak 2223.000000
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(270) > FREQUENCY 4342.773438
06-05 17:28:34.512 : INFO / HelloWorld ( 3351 : 3351 ) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(281) > octave 8
Я подозреваю, что вы (а) не можете подать оконная функция до БПФ и / или (б) у вас есть большой компонент постоянного тока. Это приведет к большому, возможно, размазанному (из-за спектральная утечка) пик при 0 Гц. Вы можете убедиться в этом, распечатав / нанеся на график свой спектр.
Чтобы исправить это:
применить подходящую оконную функцию (например, Hann) до БПФ
измените цикл поиска пиков так, чтобы он начинался где-то выше уровня 0, например
const int PEAK_MIN = BUFFER_SIZE / 1024;
for (int i = PEAK_MIN; i < BUFFER_SIZE / 2 + 1; i++) {
...
Существует довольно простой, но интенсивный в вычислительном отношении способ определения высоты звука голоса с использованием автокорреляция метод. Я не понимаю, почему это не относится и к гитаре! Это будет, однако, бороться, когда есть более чем одна фундаментальная частота. Я не знаю об алгоритме, который обрабатывает это, как бы то ни было.
Вам нужно взять достаточно образцов, чтобы покрыть как минимум 3 периода. Затем вы автоматически коррелируете сигнал (автокорреляция может быть эффективно выполняется с БПФ).
Если у вас есть свой автокоррелированный сигнал, вы найдете самый большой пик с задержкой 0. Второй самый высокий пик должен быть вашим шагом.
Вы получите лучшие результаты, оконный входной сигнал, используя что-то вроде окна Хемминга до автокорреляции.
Дальше еще Пол Бурсма Praat слава пришла далеко более точный метод определения высоты тона.
В основном используя свою схему. Вы берете автокорреляцию оконной функции и сохраняете ее для последующего использования. Далее вы окно входного сигнала. Автокоррелируйте этот сигнал. Теперь разделите на автокорреляцию оконной функции. Наконец, выберите самый высокий пик, и смещение от лаг 0 — это количество выборок для определения высоты тона.
Стоит отметить, что вам действительно нужно интерполировать пики автокорреляции, чтобы получить наилучшие результаты. Лично я использовал параболическую интерполяцию, и повышение точности, которое я получил, было огромным. Параболическая интерполяция очень проста:
void ParabolicInterpolation( const float kA, const float kB, const float kC, float& p, float& m )
{
p = 0.5f * ((kA - kC) / (kA - (2.0f * kB) + kC));
m = (0.25f * (kA - kC) * p);
}
Где kB — это пик автокорреляции, который вы определили, а kA — образец автокорреляции до него и kC образец после.
Редактировать: Если вам не нужна такая точность, которую обеспечивает вышеуказанный метод, есть еще один ДЕЙСТВИТЕЛЬНО простой метод расчета основной частоты, называемый спектром гармонического продукта (Проверьте начало этой презентации). В основном вы начинаете со своего БПФ. Вы конвертируете его в спектр величин. Наконец вы уменьшаете его в 2, 3 и 4 раза. Затем вы умножаете образцы вместе. Самый большой пик будет по вашей основной частоте. Однако это сильно ограничено вашим разрешением FFT.
Надеюсь, это поможет!