java从记录的声音中查找最高频率包括FFT
我正在做一个项目,我必须创建一个音调监听器,这样我就可以使用Android的AudioRecord类录制音调。这个音调监听器会听这个音调,然后给出音调的频率。我正在使用FFT来获得频率,但由于它没有给出确切的频率,我被卡住了。有什么办法可以奏效吗? 我在搜索安卓的FFT和音频记录类。 代码片段如下:
while (isListening) {
for (int t = 0; t <= 5; t++) {
// System.out.println("Inside for loop");
int numberOfShortsRead = audioRecord
.read(audioData,
audioSize,
(kRecorderNumberOfSamples - audioSize));
// System.out.println("Read"+numberOfShortsRead);
if (numberOfShortsRead > 0) {
System.out.println("inside read>0");
System.out.println("Number of read"
+ numberOfShortsRead);
audioSize += numberOfShortsRead;
System.out
.println("Final audio data size"
+ audioSize);
System.out.println("Number Of Samples"
+ kRecorderNumberOfSamples);
if (kRecorderNumberOfSamples == audioSize) {
for (int i = 0; i < audioSize; i++) {
x[i] = audioData[i]; // real
y[i] = 0; // imaginary
}
System.out.println("Inside FFT"
+ "x" + x + "y" + y);
int i, j, k, n1, n2, a;
double c, s, t1, t2;
// Bit-reverse
j = 0;
n2 = n / 2;
for (i = 1; i < n - 1; i++) {
n1 = n2;
while (j >= n1) {
j = j - n1;
n1 = n1 / 2;
}
j = j + n1;
if (i < j) {
t1 = x[i];
x[i] = x[j];
x[j] = t1;
t1 = y[i];
y[i] = y[j];
y[j] = t1;
}
}
// FFT
n1 = 0;
n2 = 1;
for (i = 0; i < m; i++) {
n1 = n2;
n2 = n2 + n2;
a = 0;
for (j = 0; j < n1; j++) {
c = cos[a];
s = sin[a];
a += 1 << (m - i - 1);
for (k = j; k < n; k = k
+ n2) {
t1 = c * x[k + n1] - s
* y[k + n1];
t2 = s * x[k + n1] + c
* y[k + n1];
x[k + n1] = x[k] - t1;
y[k + n1] = y[k] - t2;
x[k] = x[k] + t1;
y[k] = y[k] + t2;
}
}
}
# 1 楼答案
假设FFT算法有效,要获得音频数据中最显著的频率,必须找到幅度最大的频率。换句话说,找到具有最高幅值的FFT数据点。如果你想要更精确的频率值,你需要使用更高的N来获得更高的分辨率
希望有帮助
# 2 楼答案
频率估计方法,例如加窗FFT幅度峰值的抛物线插值(或复FFT结果的Sinc插值)可能会提供更精确的频率估计,使用更长FFT的更多数据也会提供更紧密的FFT频率结果箱。你可能需要缓冲更多记录的样本,直到你有足够的时间使用更长的FFT。在更长的FFT之前进行零填充也是用于频率估计的另一种插值方法,但其结果将比使用更多数据更具噪声,因此精度较低