5

For some reason the frequencies as displaced

 391 hz => 1162
 440 hz => 2196
 493 hz => 2454

I am using this values

 final int audioFrames= 1024;
 final float sampleRate= 44100.0f;
 final int bitsPerRecord= 16;
 final int channels= 1;
 final boolean bigEndian = true;
 final boolean signed= true;

 byteData= new byte[audioFrames * 2];  //two bytes per audio frame, 16 bits
 dData= new double[audioFrames * 2];  // real & imaginary

This is how I ready the data and transform it to doubles:

format = new AudioFormat(sampleRate, bitsPerRecord, channels, signed, bigEndian);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); 
microphone = (TargetDataLine) AudioSystem.getLine(info);
microphone.open(format);
microphone.start();
int numBytesRead =  microphone.read(byteData, 0, byteData.length);

Once the data is read, cast from 16 bit, big endian, signed to double

 public void byteToDouble(){
    ByteBuffer buf= ByteBuffer.wrap(byteData);
    buf.order(ByteOrder.BIG_ENDIAN);
    int i=0;
    while(buf.remaining()>1){
        short s = buf.getShort();
        dData[ 2 * i ] = (double) s / 32768.0; //real 
        dData[ 2 * i + 1] = 0.0;    // imag
        ++i;
    }
}

And at last, run the FFT and find the frequency:

 public void findFrequency(){

    double frequency;

            DoubleFFT_1D fft= new DoubleFFT_1D(audioFrames); 
/* edu/emory/mathcs/jtransforms/fft/DoubleFFT_1D.java */

    fft.complexForward(dData); // do the magic so we can find peak      
    for(int i = 0; i < audioFrames; i++){
        re[i] = dData[i*2];
        im[i] = dData[(i*2)+1];
        mag[i] = Math.sqrt((re[i] * re[i]) + (im[i]*im[i]));
    }

    double peak = -1.0;
    int peakIn=-1;
    for(int i = 0; i < audioFrames; i++){
        if(peak < mag[i]){
            peakIn=i;
            peak= mag[i];
        }
    }
    frequency = (sampleRate * (double)peakIn) / (double)audioFrames;
    System.out.print("Peak: "+peakIn+", Frequency: "+frequency+"\n");
}
Jose Hidalgo
  • 362
  • 3
  • 8
  • It looks OK apart from the fact that you are not using a window function, so your spectrum will be smeared. Try plotting `mag[]` and see if the spectrum looks sensible, i.e. a single large peak somewhere the lower order bins. – Paul R Aug 22 '13 at 11:01
  • Hi Paul, seems like my problem is that the frequency bins are not accurate enough, so, for example if the sound is 440 Hz, but my frequency bin closer to that is 445 Hz it won't use it, instead it will use a harmonic like 1320 which may be in the frequency bin. Is there a way to increase the accuracy of those bins without having to read a lot of samples ? – Jose Hidalgo Aug 25 '13 at 15:30
  • For some musical instruments the harmonics are actually louder than the fundamental - you probably want to look at the various different methods for pitch detection rather than just looking for the single largest peak in an FFT, which as you have found, will not be very reliable. Also note that your bin resolution is very coarse 44100/1024 = around 40 Hz per bin. – Paul R Aug 25 '13 at 18:34
  • did you find the answer, please let me know i also having same issue – Ranjithkumar Feb 26 '14 at 02:44

2 Answers2

0

You can interpolate between FFT result bins (parabolic or Sinc interpolation) to get a more accurate estimate of frequency. But you may have a bigger problem: your frequency source may be producing (or be being clipped to produce) some very strong odd harmonics or overtones that mask any fundamental sinusoid in the FFT result magnitudes. Thus you should try using a pitch detection/estimation algorithm instead of just trying to look for a (possibly missing) FFT peak.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153
0

Firstly, if the audio you're recording is long, you'll need to do FFT in chunks, preferably with windowing each chunk before performing FFT. FFT only computes one fundamental frequency, so you need to take FFT at many places if the frequency changes many times.

Accuracy can also be improved from sliding windows. This means that you would take a chunk, then slide over slightly and take another chunk, so that the chunks overlap. How much you slide over is variable, and the size of each chunk is also variable.

Then, FFT alone might produce false results. You can do more analysis like Cepstrum analysis or Harmonic Product Spectrum analysis on the power spectrum produces by the FFT to try and estimate the pitch more accurately.

ritmatter
  • 3,448
  • 4
  • 24
  • 43