Stworzyłem algorytm wykrywania wysokości dźwięku za pomocą HPS i mam problem. Jestem początkującym w przetwarzaniu sygnałów i ta strona pomogła mi wcześniej, więc pomyślałem, że powinienem zapytać.
Dla wyższych tonów ( eg. >C6:1046.50hz
) zaczynam pobierać śmieciowe dane z HPS. Im wyższy ton, tym więcej śmieci otrzymuję (przez śmieci rozumiem częstotliwości, które nie są błędami oktawowymi ani harmonicznymi i wynoszą około 1 Hz-20 Hz)
Co zaobserwowałem empirycznie:
wyniki są najgorsze dla wyższych tonów, jeśli podstawa jest wyższa od A6 lub mniej więcej, dostaję tylko śmieciowe dane.
FFT działa dobrze nawet przy bardzo wysokim skoku (przez grzywnę mam na myśli, że jego szczyt pokazuje albo podstawową albo jedną z jej harmonicznych, ale nie śmieci)
jeśli obniżę liczbę harmonicznych, które biorę pod uwagę dla HPS, śmieci zmniejszają się, ale utrudnia to rozróżnienie między składową podstawową a harmoniczną.
Oto mój algorytm:
->raw buffer -> hann window, 16384 samples, 50% overlap -> zero padding -> FFT -> HPS
Każda pomoc jest mile widziana!
AKTUALIZACJA 1: Jest jeszcze kilka rzeczy, które chcę dodać:
- Częstotliwość próbkowania, z którą nagrywam, wynosi 44100 Hz
- Zauważyłem, że takie zachowanie jest ledwo widoczne na gitarze, ale bardzo widoczne na pianinie cyfrowym (dla tej samej granej nuty)
Oto mój algorytm hps, może ktoś z większym doświadczeniem zauważy problem.
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; }