Ho creato un algoritmo di rilevamento del passo usando HPS e sto affrontando un problema. Sono un principiante con l'elaborazione del segnale e questo sito mi ha aiutato prima, quindi ho pensato di chiedere.
Per i toni più alti ( eg. >C6:1046.50hz
) sto iniziando a ottenere dati spazzatura dall'HPS. Maggiore è il tono, più immondizia ottengo (per immondizia intendo frequenze che non sono errori di ottava né armoniche e sono circa 1Hz-20Hz)
Quello che ho osservato empirico:
i risultati sono peggiori per i toni più alti, se il fondamentale è sopra A6 o giù di lì, ottengo solo dati spazzatura.
la FFT funziona bene anche per un tono molto alto, (intendo che il suo picco mostra sia la fondamentale o una delle sue armoniche, ma non la spazzatura)
se abbasso il numero di armoniche che prendo in considerazione per l'HPS, la spazzatura diminuisce, ma ciò rende più difficile discriminare tra le fondamentali e le armoniche.
Ecco il mio algoritmo:
->raw buffer -> hann window, 16384 samples, 50% overlap -> zero padding -> FFT -> HPS
Qualsiasi aiuto è apprezzato!
AGGIORNAMENTO 1: Quindi, ci sono alcune altre cose che voglio aggiungere:
- La frequenza di campionamento su cui sto registrando è 44100 Hz
- Ho osservato che questo comportamento è appena visibile su una chitarra, ma molto visibile su un piano digitale (per la stessa nota suonata)
Ecco il mio algoritmo hps, forse qualcuno con una maggiore esperienza può individuare un problema.
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; }