Использование алгоритма Герцеля для определения частоты

Я пытаюсь написать программу для Android для определения частоты с использованием алгоритма Герцеля. Однако, когда я применяю алгоритм к данным, которые я получаю из метода AudioRecord read(), амплитуда не достигает пика на целевой частоте (т. Е. Обычно она достигает пика на низкой частоте). Я что-то неправильно понимаю?

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);
 }

}


person Jay    schedule 15.10.2016    source источник
comment
Для уточнения, какой размер буфера и какую целевую частоту вы ожидаете?   -  person paisanco    schedule 15.10.2016
comment
Там будет передатчик (ноутбук, использующий Matlab для генерации тона), и эта программа должна определить частоту от передатчика. а для размера буфера я использую getMinBufferSize(44100,AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);   -  person Jay    schedule 16.10.2016
comment
Если я правильно понимаю ваш код, вы просматриваете частоты от 0 до 20 кГц с шагом 50 Гц и вычисляете отклик фильтра, а пиковый отклик не там, где вы ожидали. Это скорее анализатор спектра, чем определение тона. Можете ли вы построить отклик фильтра и показать, где должна была быть целевая частота?   -  person paisanco    schedule 16.10.2016
comment
Извините, я всего лишь студент, и это было мое задание, поэтому я не очень разбираюсь в программировании Android, а также это было для меня совершенно новым. Если вы не возражаете, не могли бы вы объяснить, как я могу определить тон с помощью goertzel? Я написал этот код, потому что из того, что я нашел в Интернете, целевая частота обычно возвращает пиковую величину с Goertzel (embedded.com/design/configurable-systems/4024443/). Я что-то неправильно понял, потому что этот код, кажется, не работает, и его ответ действительно непоследовательный.   -  person Jay    schedule 16.10.2016
comment
Для обнаружения тона вы пытаетесь определить наличие или отсутствие одной определенной частоты в сигнале. Для анализа спектра вы пытаетесь определить отклик сигнала на различных частотах. Какую проблему вы пытаетесь решить?   -  person paisanco    schedule 16.10.2016
comment
Я пытаюсь обнаружить одну конкретную частоту. Кстати, я думаю, что нашел проблему с моим кодом, я забыл стереть свой образец перед записью, поэтому результат был очень противоречивым. Теперь, после того, как я это сделал, величина достигает пика, когда я играю на целевой частоте. Из того, что я прочитал в Интернете, мне нужен порог для определения частоты, есть ли хороший способ получить пороговое значение? Я думаю, что нужно провести много выборочных тестов на целевой частоте и найти минимальное значение амплитуды?   -  person Jay    schedule 16.10.2016