Я створив алгоритм визначення тону за допомогою HPS і зіткнувся з проблемою. Я початківець з обробкою сигналів, і цей сайт мені раніше допомагав, тому я хоч і повинен запитати.
Для більш високих смол ( eg. >C6:1046.50hz
) я починаю отримувати дані сміття з ГЕС. Чим вище крок, тим більше сміття я отримую (під сміттям я маю на увазі частоти, які не є октавними помилками і не гармоніками і становлять приблизно 1 Гц-20 Гц)
Що я емпірично спостерігав:
результати є найгіршими для вищих смол, якщо фундаментальний показник вище A6 або близько того, я отримую лише дані про сміття.
FFT працює чудово навіть для дуже високого кроку (я маю на увазі, що його пік показує або основну, або одну з гармонік, але не сміття)
якщо я знижую кількість гармонік, які я беру до уваги щодо HPS, сміття зменшується, але це ускладнює дискримінацію між основними та гармоніками.
Ось мій алгоритм:
->raw buffer -> hann window, 16384 samples, 50% overlap -> zero padding -> FFT -> HPS
Будь-яка допомога вдячна!
ОНОВЛЕННЯ 1: Отже, я хочу додати ще кілька речей:
- Частота вибірки, яку я записую, становить 44100 Гц
- Я помічав, що така поведінка ледь помітна на гітарі, але дуже помітна на цифровому піаніно (для тієї ж відтвореної ноти)
Ось мій алгоритм hps, можливо, хтось із більшим досвідом може виявити проблему.
int hps(float* spectrum, int spectrumSize, int harmonics) { int i, j, maxSearchIndex, maxBin; maxSearchIndex = spectrumSize/harmonics; maxBin = 1; for (j=1; j<=maxSearchIndex; j++) { for (i=1; i<=harmonics; i++) { spectrum[j] *= spectrum[j*i]; } if (spectrum[j] > spectrum[maxBin]) { maxBin = j; } } // Fixing octave too high errors int correctMaxBin = 1; int maxsearch = maxBin * 3 / 4; for (i=2; i<maxsearch; i++) { if (spectrum[i] > spectrum[correctMaxBin]) { correctMaxBin = i; } } if (abs(correctMaxBin * 2 - maxBin) < 4) { if (spectrum[correctMaxBin]/spectrum[maxBin] > 0.2) { maxBin = correctMaxBin; } } return maxBin; }