在Android中使用FFT
我无法理解如何将 PCM 数据从麦克风传递到我正在使用的由 Piotr Wendykier 制作的 FFT 类(它是 JTransforms 中的 DoubleFFT_1D 类)。
我想我必须返回一个实数和虚数,然后将实数加倍才能最终获得Frequency = 8000 * i / 1024,其中i是最高幅度的索引。
有人可以帮我找到演奏音符的频率吗?
我的录音课如下:
import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D;
...other various imports...
class recorderThread {
...public variables...
public static void getFFtresult(){
AudioRecord recorder;
short[] audioData;
int bufferSize;
int samplerate = 8000;//or 8192?
bufferSize= AudioRecord.getMinBufferSize(samplerate,AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT)*2; //get the buffer size to use with this audio record
recorder = new AudioRecord (AudioSource.MIC,samplerate,AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,bufferSize); //instantiate the AudioRecorder
recording=true; //variable to use start or stop recording
audioData = new short [bufferSize]; //short array that pcm data is put into.
int recordingLoops = 0;
while (recordingLoops < 4) { //loop while recording is needed
if (recorder.getState()==android.media.AudioRecord.STATE_INITIALIZED) // check to see if the recorder has initialized yet.
if (recorder.getRecordingState()==android.media.AudioRecord.RECORDSTATE_STOPPED)
recorder.startRecording(); //check to see if the Recorder has stopped or is not recording, and make it record.
else {
recorder.read(audioData,0,bufferSize); //read the PCM audio data into the audioData array
DoubleFFT_1D fft = new DoubleFFT_1D(1023); //instance of DoubleFFT_1D class
double[] audioDataDoubles = new double[1024];
for (int j=0; j <= 1023; j++) { // get audio data in double[] format
audioDataDoubles[j] = (double)audioData[j];
}
fft.complexForward(audioDataDoubles); //this is where it falls
for (int i = 0; i < 1023; i++) {
Log.v(TAG, "audiodata=" + audioDataDoubles[i] + " no= " + i);
}
recordingLoops++;
}//else recorder started
} //while recording
if (recorder.getState()==android.media.AudioRecord.RECORDSTATE_RECORDING) recorder.stop(); //stop the recorder before ending the thread
recorder.release(); //release the recorders resources
recorder=null; //set the recorder to be garbage collected
}//run
}//recorderThread
非常感谢!
本
I am having trouble understanding how I should pass PCM data from the mic to this FFT class I am using made by Piotr Wendykier (it's the DoubleFFT_1D class in JTransforms).
I think I have to return a real and imaginary number and then double the real number to eventually obtain Frequency = 8000 * i / 1024 where i is the index of the highest magnitude.
Can someone help me in finding the frequency of a note played in?
I have a recording class as follows:
import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D;
...other various imports...
class recorderThread {
...public variables...
public static void getFFtresult(){
AudioRecord recorder;
short[] audioData;
int bufferSize;
int samplerate = 8000;//or 8192?
bufferSize= AudioRecord.getMinBufferSize(samplerate,AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT)*2; //get the buffer size to use with this audio record
recorder = new AudioRecord (AudioSource.MIC,samplerate,AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,bufferSize); //instantiate the AudioRecorder
recording=true; //variable to use start or stop recording
audioData = new short [bufferSize]; //short array that pcm data is put into.
int recordingLoops = 0;
while (recordingLoops < 4) { //loop while recording is needed
if (recorder.getState()==android.media.AudioRecord.STATE_INITIALIZED) // check to see if the recorder has initialized yet.
if (recorder.getRecordingState()==android.media.AudioRecord.RECORDSTATE_STOPPED)
recorder.startRecording(); //check to see if the Recorder has stopped or is not recording, and make it record.
else {
recorder.read(audioData,0,bufferSize); //read the PCM audio data into the audioData array
DoubleFFT_1D fft = new DoubleFFT_1D(1023); //instance of DoubleFFT_1D class
double[] audioDataDoubles = new double[1024];
for (int j=0; j <= 1023; j++) { // get audio data in double[] format
audioDataDoubles[j] = (double)audioData[j];
}
fft.complexForward(audioDataDoubles); //this is where it falls
for (int i = 0; i < 1023; i++) {
Log.v(TAG, "audiodata=" + audioDataDoubles[i] + " no= " + i);
}
recordingLoops++;
}//else recorder started
} //while recording
if (recorder.getState()==android.media.AudioRecord.RECORDSTATE_RECORDING) recorder.stop(); //stop the recorder before ending the thread
recorder.release(); //release the recorders resources
recorder=null; //set the recorder to be garbage collected
}//run
}//recorderThread
Thanks so much!
Ben
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您正在寻找音符的音高,您会发现音高通常与 FFT 产生的频谱频率峰值不同,特别是对于低音音符。
要从复数 FFT 中找到频率峰值,您需要计算实部和虚部结果的矢量幅度。
If you are looking for the pitch of a musical note, you will find that pitch is often different from the spectral frequency peak produced by an FFT, especially for lower notes.
To find the frequency peak from a complex FFT, you need to calculate the vector magnitude of both the real and imaginary results.
由于您使用真实的音频数据作为输入,因此您应该使用
realForward
函数:然后您可以通过计算实部和虚部的幅度来计算频率上的能量:
Since you're using real audio data as the input you should use
realForward
function:Then you can compute the energy on a frequency by computing the magnitude of real and imaginary parts: