J'ai créé un algorithme de détection de hauteur en utilisant HPS et je suis confronté à un problème. Je suis un débutant en traitement du signal et ce site m'a aidé avant, donc je pensais que je devrais demander.
Pour les hauteurs ( eg. >C6:1046.50hz
), je commence à obtenir des données d'ordures du HPS. Plus la hauteur est élevée, plus j'obtiens d'ordures (par ordures, je veux dire des fréquences qui ne sont pas des erreurs d'octave ni des harmoniques et sont d'environ 1 Hz à 20 Hz)
Ce que j'ai empiriquement observé:
les résultats sont les pires pour les hauteurs, si le fondamental est au-dessus de A6 ou plus, je n'obtiens que des données de poubelle.
la FFT fonctionne très bien même pour une hauteur très élevée, (je veux dire par là que son pic montre soit la fondamentale soit l'une de ses harmoniques, mais pas les ordures)
si je diminue le nombre d'harmoniques que je prends en considération pour le HPS, les ordures diminuent, mais cela rend plus difficile la discrimination entre le fondamental et les harmoniques.
Voici mon algorithme:
->raw buffer -> hann window, 16384 samples, 50% overlap -> zero padding -> FFT -> HPS
Toute aide est appréciée!
MISE À JOUR 1: Donc, il y a quelques autres choses que je veux ajouter:
- La fréquence d'échantillonnage sur laquelle j'enregistre est de 44100 Hz
- J'ai observé que ce comportement est à peine visible sur une guitare, mais très visible sur un piano numérique (pour la même note jouée)
Voici mon algorithme hps, peut-être qu'une personne ayant une plus grande expérience peut détecter un problème.
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; }