[英]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.