6

I'm getting wrong frequency, I don't understand why i'm getting wrong values.since i have calculating as per instructions followed by stackoverflow. I've used FFT from http://introcs.cs.princeton.edu/java/97data/FFT.java.html and complex from http://introcs.cs.princeton.edu/java/97data/Complex.java.html

audioRec.startRecording();
audioRec.read(bufferByte, 0,bufferSize);
for(int i=0;i<bufferSize;i++){
    bufferDouble[i]=(double)bufferByte[i];    
    }
Complex[] fftArray = new Complex[bufferSize];
    for(int i=0;i<bufferSize;i++){
    fftArray[i]=new Complex(bufferDouble[i],0);
    }
    FFT.fft(fftArray);
double[] magnitude=new double[bufferSize];
for(int i=0;i<bufferSize;i++){
      magnitude[i] = Math.sqrt((fftArray[i].re()*fftArray[i].re()) + (fftArray[i].im()*fftArray[i].im()));
    }
double max = 0.0;
int index = -1;
for(int j=0;j<bufferSize;j++){
    if(max < magnitude[j]){
            max = magnitude[j];
        index = j;
        }
    }
    final int peak=index * sampleRate/bufferSize;
    Log.v(TAG2, "Peak Frequency = " + index * sampleRate/bufferSize);
    handler.post(new Runnable() {
            public void run() {
                textView.append("---"+peak+"---");
            }
        });

i'm getting values like 21000,18976,40222,30283 etc... Please help me..... Thank you..

Corley Brigman
  • 11,633
  • 5
  • 33
  • 40
Pandian
  • 474
  • 1
  • 4
  • 14
  • 2
    You should try running on clean data with known synthesized sinusoids. You don't seem to be looking at magnitude so your results may simply be noise. And it is not obvious if you are using a window function. – Chris Stratton Feb 18 '14 at 14:17
  • What is your sample rate and buffer size? What does your input signal look like? – hotpaw2 Feb 18 '14 at 16:50
  • @chris since I'm new to dsp, please explain in programming... – Pandian Feb 18 '14 at 17:02
  • @hotpaw2 sample rate is 44100, buffer size is 4096, and input signal is mic buffer date from android phone – Pandian Feb 18 '14 at 17:04
  • 2
    Drop the microphone and substitute a calculated sine wave of configurable frequency to experiment with until you get correct results. When you can recover that, then display the magnitude and note how the detected magnitude varies with frequency even when the input is constant... to fix that, go read up on window functions. – Chris Stratton Feb 18 '14 at 17:07
  • @ChrisStratton Pardon me,please explain in coding, i not getting what your'e trying to explain. – Pandian Feb 19 '14 at 06:16
  • Replace the microphone with a program that calculates a sine wave and experiment with that to understand how this all works. If you do not understand what that means, you need to do some substantial reading and research before you start playing with FFTs. – Chris Stratton Feb 19 '14 at 15:43
  • @ChrisStratton and hotpaw2 Please refer this[link](http://stackoverflow.com/questions/21882835/incorrect-peak-frequency-in-jtransform). I've changed algorithm fft to jtransform, still i'm stuck with this....Please help me. – Pandian Feb 21 '14 at 04:52
  • 1
    @ChrisStratton is this way to calculate sine wave.. 'buffer size=4096; sampleSize=44100; for(int i=0;i"); }' – Pandian Feb 21 '14 at 13:26
  • Now try multiplying i by various factors to change the generated frequency. – Chris Stratton Feb 21 '14 at 14:56

1 Answers1

2

Your source code is almost fine. The only problem is that you search for the peaks through the full spectrum, i.e. from 0 via Fs/2 to Fs.

For any real-valued input signal (which you have) the spectrum between Fs/2 and Fs (=sample frequency) is an exact mirror of the spectrum between 0 and Fs/2 (I found this nice background explanation). Thus, for each frequency there exist two peaks with almost identical amplitude. I'm writing 'almost' because due to limited machine precision they are not necessarily exactly identical. So, you randomly find the peak in the first half of the spectrum which contains the frequencies below the Nyquist frequency (=Fs/2) or in the second half of the spectrum with the frequencies above the Nyquist frequency.

If you want to correct the mistake yourself, stop reading here. Otherwise continue:

Just replace

for(int j=0;j<bufferSize;j++){

with

for(int j=0;j<=bufferSize/2;j++){

in the source code you presented.

P.S.: Typically, it is better to apply a window function to the analysis buffer (e.g. a Hamming window) but for your application of peak picking it won't change results very much.

Community
  • 1
  • 1
Hartmut Pfitzinger
  • 2,304
  • 3
  • 28
  • 48
  • sorry for the delay.... I've dropped FFT nd stick with Zero Crossing. Refer this [link](https://github.com/gast-lib/gast-lib/blob/master/library/src/root/gast/audio/processing/ZeroCrossing.java). It doesn't seems major difference in frequency detection.If you have any suggestions, please share with me.Thank you – Pandian Apr 03 '14 at 10:20
  • I will have a look at the link. Meanwhile, you could accept my answer as it is very likely that the wrong values of your alg resulted from searching also through the mirror spectrum. Might be interesting for other readers. – Hartmut Pfitzinger Apr 03 '14 at 10:29
  • Actually, this kind of rough zero-crossing analysis only works if the harmonics are very low compared with the fundamental and only with a good S/N-radio and only if you analyse a monophonic signal. In all other cases the estimate gets more or less worse. – Hartmut Pfitzinger Apr 03 '14 at 10:35
  • Thank you very much.I've tried that,but still i'm getting lot's of noise.pls explain it clearly. – Pandian Apr 15 '14 at 13:17
  • With the FFT-based extraction described here, or the Zero-Crossing from these comments? – Hartmut Pfitzinger Apr 16 '14 at 04:43
  • Did you apply the correction from my answer? Did you also add a window function? – Hartmut Pfitzinger Apr 16 '14 at 10:15
  • yeah, i've applied your correction.Sorry to say i don't know how to apply window function. Please give some codes for window function, Thank you. – Pandian Apr 17 '14 at 04:12
  • If you have any other working example for detecting peak frequency,.. Please share with me. Thanks – Pandian Apr 17 '14 at 10:09
  • See e.g. here: http://stackoverflow.com/a/21497888/1986583 Code for a window function is 2nd question, and we should not discuss it in the comments. You say, your window size is 4096 and sample rate is 44100kHz. This means that you use a window size of almost 93ms. Which frequencies do you intend to detect? Do the signals you record by the mic contain perfectly steady frequencies? – Hartmut Pfitzinger Apr 17 '14 at 17:27