0

我有一个来自 WAV 文件的采样数据列表。我想将这些值传递到库中,并获取 WAV 文件中播放音乐的频率。现在,我将在 WAV 文件中有 1 个频率,我想找到一个与 Android 兼容的库。我知道我需要使用 FFT 来获取频域。有什么好的图书馆吗?我发现 [KissFFT][1] 很受欢迎,但我不太确定它在 Android 上的兼容性如何。是否有一个更简单、更好的库可以执行我想要的任务?

编辑:我尝试使用 JTransforms 来获取 WAV 文件的 FFT,但始终无法获取文件的正确频率。目前,WAV 文件包含 440Hz 的正弦曲线,音符 A4。然而,我得到的结果是 441。然后我试图得到 G4 的频率,我得到的结果是 882Hz,这是不正确的。G4的频率应该是783Hz。会不会是样本不够?如果是,我应该取多少样本?

//DFT
DoubleFFT_1D fft = new DoubleFFT_1D(numOfFrames);
double max_fftval = -1;
int max_i = -1;
double[] fftData = new double[numOfFrames * 2];
for (int i = 0; i < numOfFrames; i++) {
    // copying audio data to the fft data buffer, imaginary part is 0
    fftData[2 * i] = buffer[i];
    fftData[2 * i + 1] = 0;
}
fft.complexForward(fftData);
for (int i = 0; i < fftData.length; i += 2) {
    // complex numbers -> vectors, so we compute the length of the vector, which is sqrt(realpart^2+imaginarypart^2)
        double vlen = Math.sqrt((fftData[i] * fftData[i]) + (fftData[i + 1] * fftData[i + 1]));
        //fd.append(Double.toString(vlen));
       // fd.append(",");
        if (max_fftval < vlen) {
            // if this length is bigger than our stored biggest length
            max_fftval = vlen;
            max_i = i;
        }
}
//double dominantFreq = ((double)max_i / fftData.length) * sampleRate;
double dominantFreq = (max_i/2.0) * sampleRate / numOfFrames;
fd.append(Double.toString(dominantFreq));

有人可以帮我吗?

EDIT2:我设法通过将样本数量增加到 100000 来解决上述问题,但是,有时我会得到泛音作为频率。知道如何解决吗?我应该使用谐波积频率还是自相关算法?

4

1 回答 1

0

我意识到我的错误。如果我采取更多样本,准确性会提高。但是,这种方法仍然不完整,因为我在获得钢琴/人声的准确结果方面仍然存在一些问题。

于 2012-09-28T09:36:20.610 回答