Saya telah membuat algoritma deteksi pitch menggunakan HPS dan saya menghadapi masalah. Saya seorang pemula dengan pemrosesan sinyal dan situs ini membantu saya sebelumnya, jadi saya pikir saya harus bertanya.
Untuk nada tinggi ( eg. >C6:1046.50hz
) saya mulai mendapatkan data sampah dari HPS. Semakin tinggi pitch semakin banyak sampah yang saya dapatkan (oleh sampah saya maksud frekuensi yang bukan kesalahan oktaf atau harmonik dan sekitar 1Hz-20Hz)
Apa yang saya amati secara empiris:
hasilnya terburuk untuk nada tinggi, jika fundamentalnya di atas A6 atau lebih, saya hanya mendapatkan data sampah.
FFT bekerja dengan baik bahkan untuk nada yang sangat tinggi, (maksud saya maksudnya puncaknya menunjukkan fundamental atau salah satu harmoniknya, tetapi bukan sampah)
jika saya menurunkan jumlah harmonik yang saya pertimbangkan untuk HPS, sampahnya berkurang, tetapi itu membuat lebih sulit untuk membedakan antara fundamental dan harmonik.
Ini algoritma saya:
->raw buffer -> hann window, 16384 samples, 50% overlap -> zero padding -> FFT -> HPS
Bantuan apa pun dihargai!
UPDATE 1: Jadi, ada beberapa hal lagi yang ingin saya tambahkan:
- Tingkat sampel yang saya rekam adalah 44100 Hz
- Saya telah mengamati bahwa perilaku ini hampir tidak terlihat pada gitar, tetapi sangat terlihat pada piano digital (untuk nada yang sama dimainkan)
Berikut ini adalah algoritma hps saya, mungkin seseorang dengan pengalaman lebih besar dapat menemukan masalah.
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; }