Как я могу рассчитать пик, используя kissFFT?

я хочу применить БПФ к реальному аудиоустройству и рассчитать пик

вот мой код ..

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

1

Решение

Я подозреваю, что вы (а) не можете подать оконная функция до БПФ и / или (б) у вас есть большой компонент постоянного тока. Это приведет к большому, возможно, размазанному (из-за спектральная утечка) пик при 0 Гц. Вы можете убедиться в этом, распечатав / нанеся на график свой спектр.

Чтобы исправить это:

  • применить подходящую оконную функцию (например, Hann) до БПФ

  • измените цикл поиска пиков так, чтобы он начинался где-то выше уровня 0, например

    const int PEAK_MIN = BUFFER_SIZE / 1024;

    for (int i = PEAK_MIN; i < BUFFER_SIZE / 2 + 1; i++) {
    ...

2

Другие решения

Существует довольно простой, но интенсивный в вычислительном отношении способ определения высоты звука голоса с использованием автокорреляция метод. Я не понимаю, почему это не относится и к гитаре! Это будет, однако, бороться, когда есть более чем одна фундаментальная частота. Я не знаю об алгоритме, который обрабатывает это, как бы то ни было.

Вам нужно взять достаточно образцов, чтобы покрыть как минимум 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.

Надеюсь, это поможет!

2

По вопросам рекламы [email protected]