1
$\begingroup$

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!

$\endgroup$
1
$\begingroup$

If you zero out most or all of the harmonics (you set them all to -inf in your cap), then the HPS algorithm can’t find them.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.