[英]Using gdx Library and FFT to Calculate Frequency (Java)
我目前正在使用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 = 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;
}
然后如何使用此方法查找从麦克风录制的声音的频率(然后是音符)?
您的目标是获取mag [i]中各个频率的所有幅度,并找到最大的一个。 首先,您可以遍历它们并找到最大mag [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]));
检查此链接以获取更多信息: 如何从fft结果中获取频率?
...指出只有采样数增加一倍,您才能完美地重构频率。...要重构1000Hz,每秒至少必须有2000个采样。 (但此波将非常失真。)。
如果您的采样率为22000Hz,则可以以某种方式测量高达11000Hz的频率。 mag
和phase
数据将对数组0..N/2
的前半部分有意义,然后,您将仅看到先前数据的镜像(有关图片,请参阅Wikipedia页面的链接。)
如果您想确定您的N, 请查看此答案或更多Google。 尝试以任意数字开始,例如采样率fs的十分之一。 N越大,算法就越慢。
最简单的方法是制作一个将要检测到的所有频率的表格,然后将最大幅度的频率与表格中的所有频率值进行比较。 公差较小,例如表中值的+ -2%。 确保两个连续的音符的公差不重叠。
麦克风输入
Google up关键字,例如Java麦克风输入库教程,或查看此答案 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.