Ich habe einen Tonhöhenerkennungsalgorithmus mit HPS erstellt und stehe vor einem Problem. Ich bin ein Anfänger in der Signalverarbeitung und diese Seite hat mir schon früher geholfen, also sollte ich fragen.
Für höhere Tonhöhen ( eg. >C6:1046.50hz
) fange ich an, Mülldaten vom HPS zu erhalten. Je höher die Tonhöhe, desto mehr Müll bekomme ich (mit Müll meine ich Frequenzen, die weder Oktavfehler noch Harmonische sind und zwischen 1 Hz und 20 Hz liegen).
Was ich empirisch beobachtet habe:
Die Ergebnisse sind für höhere Tonhöhen am schlechtesten. Wenn die Grundwelle über A6 oder so liegt, erhalte ich nur Mülldaten.
Die FFT funktioniert auch für eine sehr hohe Tonhöhe einwandfrei (mit gut meine ich, dass ihre Spitze entweder die Grundwelle oder eine ihrer Harmonischen zeigt, aber keinen Müll).
Wenn ich die Anzahl der Harmonischen reduziere, die ich für das HPS berücksichtige, verringert sich der Müll, aber das macht es schwieriger, zwischen der Grundwelle und der Harmonischen zu unterscheiden.
Hier ist mein Algorithmus:
->raw buffer -> hann window, 16384 samples, 50% overlap -> zero padding -> FFT -> HPS
Jede Hilfe wird geschätzt!
UPDATE 1: Also, es gibt noch ein paar Dinge, die ich hinzufügen möchte:
- Die Abtastrate, mit der ich aufnehme, beträgt 44100 Hz
- Ich habe beobachtet, dass dieses Verhalten auf einer Gitarre kaum sichtbar ist, auf einem Digitalpiano jedoch sehr gut sichtbar (für dieselbe gespielte Note).
Hier ist mein HP-Algorithmus. Vielleicht kann jemand mit größerer Erfahrung ein Problem erkennen.
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; }