我很难理解这个问题的意思。基本上我正在尝试找出通过麦克风播放的频率。据我了解,我需要通过暴力破解高尔泽算法来实现。所以基本上我只需使用高尔泽算法尝试每一个频率,直到找到正确的频率为止。然而,我并不知道如何知道高尔泽算法何时找到正确的算法。可以有人帮帮我吗?
MainActivity.java
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Button recordButton;
private TextView result;
private AudioRecord recording;
private static final int RECORDER_SAMPLERATE = 10000;
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
int bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);
double[] dbSample = new double[bufferSize];
short[] sample = new short[bufferSize];
private int frequency = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recordButton = findViewById(R.id.recordButton);
result = findViewById(R.id.resultTextView);
recordButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
recording = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, RECORDER_SAMPLERATE,
RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING, bufferSize);
recording.startRecording();
int bufferReadResult = recording.read(sample, 0, bufferSize);
for (int j = 0; j < bufferSize && j < bufferReadResult; j++) {
dbSample[j] = (double) sample[j];
goertzel.processSample(dbSample[j]);
}
// Is this correct?
magnitude = Math.sqrt(goertzel.getMagnitudeSquared());
if(magnitude > maxMagnitude){
maxMagnitude = magnitude;
System.out.println("Freq is: " + Integer.toString(frequency));
}
goertzel.resetGoertzel();
frequency += 1;
}
});
}
}
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;
}
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);
}
}
detectFrequencies()
感到困惑,当真实声音被记录时,我该如何使用它。 - Zoey MalkovdetectFrequencies
的数组长度为 256,因为我写的方式是迭代audio
中的所有样本。所以你需要每次从sample
中复制 256 个元素到一个新的short
数组中。 - greeble31recording.read(sample, 0, bufferSize);
这个操作256次吗?然后才能检测频率?我觉得我更加困惑了。 - Zoey Malkovrecording.read(...)
可以返回不同的值,这取决于它实际读取了多少个样本。通常情况下,它会大于256(所以,在这种情况下,你已经完成了)。但如果它返回少于256个样本,你应该处理这种情况:跟踪你已经读取了什么,并发出另一个read
调用,不使用0作为第二个参数,而是使用数组中已有内容的大小。 - greeble31read()
的用法以及音频流的一般知识。 - greeble31