我尝试使用 Java 中的互相关来查找两个音频文件之间的延迟。到目前为止,我已经完成了这个算法,我知道有多少样本是延迟。
- FFT x1 -> 零填充长度:x1.length() + x2.length()
- FFT x2 -> 零填充长度:x1.length() + x2.length()
- X3 = FFT{x1} 乘以 FFT{2}*
- x3 = IFFT{X3}
为了验证我的结果,我使用八度。所以我可以看到我的结果通常是正确的,但是我的图表的位置不正确。
对于测试,我使用相同的文件,因此这代表自动相关功能。在八度图中,最大相关性位于输出向量的中心,这似乎是正确的。-> 所以延迟为 0,因为相同的文件
在我的版本中,图表位于开头和结尾。
因此,如果我使用两个不同的信号,则在八度音程中,最大相关性从中心向左/向右移动。在我的算法中,它从开始到中间或结束到中间。
所以看来我的图表计算正确,因为峰值移动了文件之间差异的样本量。但是位置不对。
看起来我必须修改我的输出向量:left half <-> right half
有什么想法是我的问题吗?
编辑:
public void execFastCrossCorrelation() throws FFTException
{
// the used block size is N(x1) + N(x2)
int blockSize = (x1.length+x2.length-1);
// create & calc FFT with zero padding & get result
// FFT x1
FFT f1 = new FFT(x1, blockSize, 44100);
f1.execFFT();
Complex[] c1 = f1.getOutputData();
// FFT x2
FFT f2 = new FFT(x2, blockSize, 44100);
f2.execFFT();
Complex[] c2 = f2.getOutputData();
// create output for cross correlation by using fast convolution : c3 = c1 multiply c2*
Complex[] c3 = new Complex[c1.length];
for(int i=0; i<c1.length;i++)
{
c3[i] = c1[i].multiply(c2[i].conjugate());
}
// create & calc IFFT & get result
IFFT f3 = new IFFT(c3, c3.length, 44100);
f3.execIFFT();
Complex[] corrResult = f3.getOutputData();
// search the maximum corrleation coefficient and his index
double maxVal = 0;
int maxIndex = 0;
for(int i=0; i<corrResult.length;i++)
{
if(corrResult[i].abs() > maxVal)
{
maxVal = corrResult[i].abs();
maxIndex = i;
}
}
所以 FFT 类是通过使用 apache-commons-math3 完成的。只需使用输入 vecotr 并为给定的 blockSize 创建一个 FFT(向上/向下舍入到 2 的幂并在必要时填充零)。
编辑:
所以现在我试图翻转输出(意味着左半边 -> 右半边和右半边 -> 左半边)
结果与八度的版本相匹配。
如果我用不同的文件尝试这个,它也像八度一样工作,意味着最大值从中心向左/右移动。这意味着我认为必须“镜像”输出向量的想法似乎是正确的。你知道为什么吗?