我正在尝试使用FFT从麦克风获取频率。这里给出了 - http://www.wikijava.org/wiki/The_Fast_Fourier_Transform_in_Java_%28part_1%29
FFT函数接受三个参数,实数,虚数和布尔值。 从记录的缓冲区中获得实部和虚部。
FFT函数返回一个数组,从中计算出最大幅度的索引。 这用于获取频率。
但是当我运行应用程序时,我没有得到所需的频率值。 我的采样率/ buffersize / blocksize有问题吗? 或者计算本身是否有问题。
公共类MainActivity扩展了Activity {
int audioSource = MediaRecorder.AudioSource.MIC; // Audio source is the device MIC
int channelConfig = AudioFormat.CHANNEL_IN_MONO; // Recording in mono
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; // Records in 16bit
int blockSize = 1024; // deal with this many samples at a time
int sampleRate = 8000; // Sample rate in Hz
public double frequency = 0.0; // the frequency given
RecordAudio recordTask; // Creates a Record Audio command
TextView tv; // Creates a text view for the frequency
boolean started = false;
Button startStopButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView1);
startStopButton = (Button) findViewById(R.id.button1);
startStopButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick (View v){
if (started) {
started = false;
startStopButton.setText("Start");
recordTask.cancel(true);
}
else{
started = true;
startStopButton.setText("Stop");
recordTask = new RecordAudio();
recordTask.execute();
}
}
});
}
private class RecordAudio extends AsyncTask<Void, Double, Void> {
@Override
protected Void doInBackground(Void... params) {
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding); // Gets the minimum buffer needed
AudioRecord audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); // The RAW PCM sample recording
short[] buffer = new short[blockSize]; // Save the raw PCM samples as short bytes
double[] re = new double[blockSize];
double[] im = new double[blockSize];
double[] magnitude = new double[blockSize];
try {
audioRecord.startRecording(); //Start
} catch (Throwable t) {
}
while (started) {
int bufferReadResult = audioRecord.read(buffer, 0, blockSize);
for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
re[i] =((double) buffer[i] / 32768.0); // signed 16 bit
im[i]=0;
}
double[] newArray = new double[blockSize*2];
newArray = FFTbase.fft(re, im,true);
double real;
double imag;
for(int i=0;i<(newArray.length/2)-1;i++)
{
real=newArray[2*i];
imag=newArray[2*i+1];
magnitude[i]=Math.sqrt(real*real+imag*imag);
}
double MaxMagn=-1.0;
int index=0;
for (int i = 0; i < (magnitude.length); i++) {
if (magnitude[i]>MaxMagn)
{
MaxMagn = magnitude[i];
index=i;
}
}
publishProgress((double)(index * sampleRate)/blockSize);
}
return null;
}
@Override
protected void onProgressUpdate(Double... values) {
TextView display = (TextView) findViewById(R.id.textView1);
display.setText(String.valueOf(values[0]));
}
}
这是我试过的过零法。但这也没有给我所需的频率。
公共类MainActivity扩展了Activity {
int audioSource = MediaRecorder.AudioSource.MIC; // Audio source is the device MIC
int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO; // Recording in mono
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; // Records in 16bit
int blockSize = 256; // deal with this many samples at a time
int sampleRate = 8000; // Sample rate in Hz
public double frequency = 0.0; // the frequency given
RecordAudio recordTask; // Creates a Record Audio command
TextView tv; // Creates a text view for the frequency
boolean started = false;
Button startStopButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView1);
startStopButton = (Button) findViewById(R.id.button1);
startStopButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick (View v){
if (started) {
started = false;
startStopButton.setText("Start");
recordTask.cancel(true);
}
else{
started = true;
startStopButton.setText("Stop");
recordTask = new RecordAudio();
recordTask.execute();
}
}
});
}
private class RecordAudio extends AsyncTask<Void, Double, Void> {
@Override
protected Void doInBackground(Void... params) {
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding); // Gets the minimum buffer needed
AudioRecord audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); // The RAW PCM sample recording
short[] buffer = new short[blockSize]; // Save the raw PCM samples as short bytes
double[] re = new double[blockSize];
double[] im = new double[blockSize];
double[] magnitude = new double[blockSize];
try {
audioRecord.startRecording(); //Start
} catch (Throwable t) {
}
int sampling=0;
while (started) {
sampling++;
int bufferReadResult = audioRecord.read(buffer, 0, blockSize);
int numCrossing=0; //initialize your number of zero crossings to 0
int p=0;
for (p=0;p<bufferSize/4;p+=4) {
if (buffer[p]>0 && buffer[p+1]<=0) numCrossing++;
if (buffer[p]<0 && buffer[p+1]>=0) numCrossing++;
if (buffer[p+1]>0 && buffer[p+2]<=0) numCrossing++;
if (buffer[p+1]<0 && buffer[p+2]>=0) numCrossing++;
if (buffer[p+2]>0 && buffer[p+3]<=0) numCrossing++;
if (buffer[p+2]<0 && buffer[p+3]>=0) numCrossing++;
if (buffer[p+3]>0 && buffer[p+4]<=0) numCrossing++;
if (buffer[p+3]<0 && buffer[p+4]>=0) numCrossing++;
}//for p
for (p=(bufferSize/4)*4;p<bufferSize-1;p++) {
if (buffer[p]>0 && buffer[p+1]<=0) numCrossing++;
if (buffer[p]<0 && buffer[p+1]>=0) numCrossing++;
}
frequency=(sampleRate/bufferSize)*(numCrossing/2);
if(sampling>20){
//publishProgress((double)(index * sampleRate)/bufferSize);
publishProgress((double)frequency);
sampling=0;
}}
return null;
}