我需要对一个简单的wav文件进行频谱分析。 我已经做过的事情:
将文件读入字节数组:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = audioStream.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
fileByteArray = baos.toByteArray();
然后我将它转换为真实值(双打)。 我的样本值存储在double []数组中。
如何对这些样本进行FFT估算+估计基频?
使用JTranforms库我试过这样的事情:
DoubleFFT_1D fft = new DoubleFFT_1D(reader.getSpectrum().getYvalues().length);
double[] x = reader.getSpectrum().getYvalues();
double[] frequencyArray = new double[x.lenght/2];
double[] amplitudeArray = new double[x.lenght/2];
fft.realForward(x);
int i=0;
for (int j = 0; j < x.length-2; j += 2) {
i++;
this.frequencyArray[i] = i;
this.amplitudeArray[i] = Math.sqrt(Math.pow(doub[j],2) + Math.pow(doub[j + 1],2));
}
这是对的吗?
赞赏所有建议;)
答案 0 :(得分:2)
你应该使用 autocorrelation ,这可以通过FFT有效地计算:
DoubleFFT_1D fft = new DoubleFFT_1D(reader.getSpectrum().getYvalues().length);
DoubleFFT_1D ifft = new DoubleFFT_1D(reader.getSpectrum().getYvalues().length);
fft.realForward(x);
for (int i = 0; i < x.length/2; i++) {
x[2*i] = Math.sqrt(Math.pow(x[2*i],2) + Math.pow(x[2*i+1],2));
x[2*i+1] = 0;
}
ifft.realInverse(x);
for (int i = 1; i < x.length; i++)
x[i] /= x[0];
x[0] = 1.0;
此代码为您提供了以下值的列表:
x[i]
:与i轮换的核心化
因此,例如,如果x[n]
的值很高(接近1),则意味着您有一个基本信号周期:n*(1000/sampleRateHz)
msecs。这相当于频率:sampleRateHz/(1000*n)
答案 1 :(得分:0)
频率数组中的值需要与采样率和FFT的长度相关。
您仍然需要解决确定基频与峰值频率的问题。为此,您可能需要使用音高检测/估算算法,其中有很多(查找有关该主题的研究论文)。