#java #android #signal-processing #goertzel-algorithm
#java #Android #обработка сигналов #гертцель-алгоритм
Вопрос:
Я пытаюсь написать программу для 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<bufferSizeamp;amp;j<bufferReadResu<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);
}
}
Комментарии:
1. Для пояснения, каков размер буфера и какую целевую частоту вы ожидаете?
2. Там будет передатчик (ноутбук, использующий matlab для генерации сигнала), и эта программа должна определять частоту от передатчика. а для размера буфера я использую getMinBufferSize(44100,АудиоФормат. КАНАЛ_КОНФИГУРАЦИИ_МОНО, АудиоФормат. КОДИРОВКА_PCM_16 БИТ);
3. Если я правильно понимаю ваш код, вы просматриваете частоты от 0 до 20 кГц с шагом 50 Гц и вычисляете отклик фильтра, а пиковый отклик не там, где вы ожидали. Это скорее анализатор спектра, чем определение тона. Можете ли вы построить график отклика фильтра и показать, где должна была находиться целевая частота?
4. Извините, я всего лишь студент, и это было мое задание, так что на самом деле я не специалист в программировании Android, и к тому же это было совершенно ново для меня. Если вы не возражаете, не могли бы вы, пожалуйста, объяснить, как я могу определить тон с помощью goertzel? Я написал этот код, потому что, судя по тому, что я нашел в Интернете, целевая частота обычно возвращает пиковую величину с помощью goertzel ( embedded.com/design/configurable-systems/4024443 /… ). Я что-то неправильно понял, потому что этот код, похоже, не работает, и его ответ тоже действительно непоследователен.
5. Для определения тона вы пытаетесь определить наличие или отсутствие одной определенной частоты в сигнале. Для анализа спектра вы пытаетесь определить отклик сигнала на различных частотах. Какую проблему вы пытаетесь решить?