4

I am trying to write a program for android to detect frequency using Goertzel algorithm. However when I apply the algorithm on the data that I get from the AudioRecord read() method, the magnitude does not peak on the target frequency (.i.e: it usually peak on low frequency). Am I misunderstanding anything?

protected void detect() {
        double[] dbSample = new double[bufferSize];
        short[] sample = new short[bufferSize];
        max_magnitude = 0;
        while(isRecording){
            int bufferReadResult = recorder.read(sample,0,bufferSize);
            for (int j=0;j<bufferSize&&j<bufferReadResult;j++) {
                dbSample[j] = (double)sample[j];
            }
        }     

        int freq=0;
        while(freq<=20000){
            Goertzel g = new Goertzel(RECORDER_SAMPLE_RATE,freq,bufferSize);
            g.initGoertzel();
            for(int i=0;i<bufferSize;i++){
                g.processSample(dbSample[i]);
            }
            magnitude = Math.sqrt(g.getMagnitudeSquared());
            if(magnitude>max_magnitude){
                max_magnitude = magnitude;
                detect_freq = freq;
            }
            g.resetGoertzel();
            freq+=50;
        }
}

Goertzel.java

public class Goertzel {
 private float samplingRate;
 private float targetFrequency;
 private long n;
 private double coeff, Q1, Q2;
 private double sine, cosine;

 public Goertzel(float samplingRate, float targetFrequency, long inN) {
     this.samplingRate = samplingRate;
     this.targetFrequency = targetFrequency;
     n = inN;
     sine = Math.sin(2 * Math.PI * (targetFrequency / samplingRate));
     cosine = Math.cos(2 * Math.PI * (targetFrequency / samplingRate));
     coeff = 2 * cosine;
     }

     public void resetGoertzel() {
     Q1 = 0;
     Q2 = 0;
 }

 public void initGoertzel() {
     int k;
     float floatN;
     double omega;
     floatN = (float) n;
     k = (int) (0.5 + ((floatN * targetFrequency) / samplingRate));
     omega = (2.0 * Math.PI * k) / floatN;
     sine = Math.sin(omega);
     cosine = Math.cos(omega);
     coeff = 2.0 * cosine;
     resetGoertzel();
 }

 public void processSample(double sample) {
     double Q0;
     Q0 = coeff * Q1 - Q2 + sample;
     Q2 = Q1;
     Q1 = Q0;
 }

 public double[] getRealImag(double[] parts) {
     parts[0] = (Q1 - Q2 * cosine);
     parts[1] = (Q2 * sine);
     return parts;
 }

 public double getMagnitudeSquared() {
     return (Q1 * Q1 + Q2 * Q2 - Q1 * Q2 * coeff);
 }

}

Paul R
  • 208,748
  • 37
  • 389
  • 560
Jay
  • 53
  • 4
  • For clarification,what's the buffer size and what's the target frequency you are expecting? – paisanco Oct 15 '16 at 15:59
  • There will be a transmitter (laptop using matlab to generate tone) and this program has to detect the frequency from the transmitter. and for the buffer size I use getMinBufferSize(44100,AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); – Jay Oct 15 '16 at 23:44
  • If I understand your code correctly you are sweeping through frequencies 0 to 20 kHz in 50 Hz increments and computing the filter response, and the peak response isn't where you expected it to be. That's more a spectrum analyzer than tone detection. Can you plot the filter response and show where the target frequency should have been? – paisanco Oct 15 '16 at 23:48
  • I'm sorry, I'm just a student and this was my assignment so I'm not really an expert in programming android and also this was totally new to me. If you don't mind can you please explain how can I detect tone using goertzel? I wrote this code because from what i found online, the target frequency usually return peak magnitude with goertzel (http://www.embedded.com/design/configurable-systems/4024443/The-Goertzel-Algorithm). Did I misunderstand anything because this code doesn't seem to work and its response is really inconsistent too. – Jay Oct 16 '16 at 10:33
  • For tone detection you are trying to detect the presence or absence of one specific frequency in a signal. For spectrum analysis you are trying to determine the response of the signal at various frequencies. Which problem are you trying to solve? – paisanco Oct 16 '16 at 15:46
  • I'm trying to detect one specific frequency. Btw I think I find the problem with my code, I forgot to wipe my sample before recording, that's why the result was very inconsistent. Now after I did that the magnitude does peak when i play the target frequency. From what i read online, I need a threshold to detect frequency, is there any good way to get the threshold value? What I'm thinking is doing a lot of sample test on the target frequency and find the minimum value of magnitude? – Jay Oct 16 '16 at 19:50

0 Answers0