I'm trying to do the HPS algorithm on my FFT output, but I'm stuck here. My signal is from a bass (cable), 16bits, 48.000Hz.
I split in time domain the array of the whole record into multiple arrays of 24.000 frames (miniBuffer[24000]).
I'm applying a Hamming window once it's split, like this:
miniBuffer [m] = miniBuffer [m] * 0.5 * (1.0 - Math.cos(2.0*Math.PI*m/24000));
Then, I compute FFT on each array.
Finally I try the HPS:
double mag[] = new double[miniBuffer.length]; //Saves magnitude of the fft values
double m_max0 = miniBuffer[0];
for (int i=0; i < miniBuffer.length / 2 - 1; i++) {
double real = miniBuffer[2*i];
double imag = miniBuffer[2*i+1];
//Gets magnitude
mag[i] = (float)Math.sqrt(real*real + imag * imag);
if (miniBuffer[i] > m_max0 && i>0) {
m_max0 = miniBuffer[i];
}
}
int i_max = 0;
double m_max = miniBuffer[0]; //max
m_max = m_max0;
double sum [] = new double[miniBuffer.length];
int fund_freq = 0;
//HPS
for(int k = 0; k < 24000/48 ; k++)
{
sum[k] = miniBuffer[k] * miniBuffer[2*k] * miniBuffer[3*k];
// find fundamental frequency (maximum value in plot)
if( sum[k] > m_max && k > 0 )
{
m_max = sum[k];
i_max = k;
}
}
fund_freq = i_max * 48000 / 24000;
System.out.println(fund_freq);
The values of the max magnitude are the frequency that is recording the program, but when i apply the HPS, for example, to a 220Hz sound, the HPS returns me 26 or 30.
I think that this values come from the frequencies limiter that doesn't works (I want to cap before 37Hz and after 440):
double hz = ((double)( miniBuffer.length * 2)) /48000;
for(int z = 0; z<(37*hz); z++) {
miniBuffer[z] = Double.NEGATIVE_INFINITY;
}
for(int z = 0; z>(440*hz); z++) {
miniBuffer[z] = Double.NEGATIVE_INFINITY;
}
If I delete this, HPS returns me 0 in every output.
So:
- Is the window correctly applied?
- Is the HPS a good algorithm for bass pitch detection? (Low Frequency)
- What could i use for limit my values in a right way?
- How to fix my HPS algorithm?
- Some other advice?
Thank you!