使用gdx库和FFT计算频率(Java)
我目前正在使用gdx库com.badlogic.gdx.audio.analysis.FFT和以下方法:使用gdx库和FFT计算频率(Java),java,android,signal-processing,fft,frequency,Java,Android,Signal Processing,Fft,Frequency,我目前正在使用gdx库com.badlogic.gdx.audio.analysis.FFT和以下方法: private float[] fft(int N, int fs, float[] array) { float[] fft_cpx, tmpr, tmpi; float[] res = new float[N / 2]; // float[] mod_spec =new float[array.length/2]; float[] real_mod = n
private float[] fft(int N, int fs, float[] array) {
float[] fft_cpx, tmpr, tmpi;
float[] res = new float[N / 2];
// float[] mod_spec =new float[array.length/2];
float[] real_mod = new float[N];
float[] imag_mod = new float[N];
double[] real = new double[N];
double[] imag = new double[N];
double[] mag = new double[N];
double[] phase = new double[N];
float[] new_array = new float[N];
// Zero Pad signal
for (int i = 0; i < N; i++) {
if (i < array.length) {
new_array[i] = array[i];
}
else {
new_array[i] = 0;
}
}
FFT fft = new FFT(N, 8000);
fft.forward(new_array);
fft_cpx = fft.getSpectrum();
tmpi = fft.getImaginaryPart();
tmpr = fft.getRealPart();
for (int i = 0; i < new_array.length; i++) {
real[i] = (double) tmpr[i];
imag[i] = (double) tmpi[i];
mag[i] = Math.sqrt((real[i] * real[i]) + (imag[i] * imag[i]));
phase[i] = Math.atan2(imag[i], real[i]);
/**** Reconstruction ****/
real_mod[i] = (float) (mag[i] * Math.cos(phase[i]));
imag_mod[i] = (float) (mag[i] * Math.sin(phase[i]));
}
fft.inverse(real_mod, imag_mod, res);
return res;
}
private float[]fft(int N,int fs,float[]array){
浮点[]fftu cpx、tmpr、tmpi;
浮动[]res=新浮动[N/2];
//float[]mod_spec=新的float[array.length/2];
浮点[]实模=新浮点[N];
浮动[]imag_mod=新浮动[N];
double[]实=新的双精度[N];
double[]imag=新的double[N];
double[]mag=新的double[N];
双[]相位=新双[N];
float[]新数组=新浮点[N];
//零位信号
对于(int i=0;i
那么,我如何使用此方法来查找从麦克风录制的声音的频率(然后是音符)?您的目标是获取mag[I]中各个频率的所有大小,并找到最大的一个。首先,您可以在它们上面循环,找到最大磁感应强度[i]。然后你必须从
i
索引中重新计算它对应的频率
频率由以下等式确定:
freq = i * Fs / N;
其中,Fs
是时域数据(输入波数据)的采样频率,N
是计算FFT的采样数i
是频域数据的索引(计算的震级和相位)
在您的情况下,您可以在for循环中添加类似的行来调试它:
double freq = (double)i*(double)fs/(double)N;
System.out.println("Frequency: "+ Double.toString(freq) + "Magnitude: "+ Double.toString(mag[i]));
有关详细信息,请查看此链接:
。。。声明只有当你有两倍的样本时,你才能完美地重建频率。。。。对于重建1000Hz,每秒必须至少有2000个样本。(但这波会非常扭曲。)
如果你有22000Hz的采样器,你将能够以某种方式测量高达11000Hz的频率。mag
和phase
中的数据将对数组的前半部分0..N/2
有意义,然后,您将只看到以前数据的镜像(有关图片,请参阅链接)
如果你想确定你的N或谷歌更多。试着从任意数字开始,比如十分之一的取样器fs。N越大,你的算法就越慢
最简单的方法是把你们要检测到的所有频率做成一个表格,然后把你们的频率和最大值和表格中的所有频率值进行比较。公差较小,例如表中数值的+-2%。确保这些公差不会在两个连续注释中重叠
麦克风输入
用谷歌搜索像java麦克风输入库教程这样的关键字,或者检查。对于麦克风输入,我遇到了一些麻烦。我原以为我发现了如何使用javax.sound实现它,但我使用的是Android SDK,它没有这个软件包。我想我需要使用android.media.audiorecord,但我不知道如何使用,也没有多少信息可以找到。你有什么建议/信息可以给我吗?其他一切看起来都不错。你应该为android重新标记你的问题,如果你在麦克风输入方面遇到困难,你可以先用sin函数生成测试输入,然后用麦克风输入搜索android示例项目