Java 基于互相关的声音文件时延估计

Java 基于互相关的声音文件时延估计,java,signal-processing,audio-processing,cross-correlation,Java,Signal Processing,Audio Processing,Cross Correlation,我正试图加速我的算法,在Java中估计两个声音文件之间的时间延迟。我的想法是使用互相关并搜索最大值,该值给出了延迟的样本量 我已经做了,它的工作很好。我创建了一些示例文件,然后计算了时间延迟。结果很好。问题是,由于运算量大,该算法需要花费大量时间 有没有办法加快速度 /** * Input vector for signal x1 (reference). */ private double[] x1; /** * Input vector for signal x2 (test).

我正试图加速我的算法,在Java中估计两个声音文件之间的时间延迟。我的想法是使用互相关并搜索最大值,该值给出了延迟的样本量

我已经做了,它的工作很好。我创建了一些示例文件,然后计算了时间延迟。结果很好。问题是,由于运算量大,该算法需要花费大量时间

有没有办法加快速度

/**
 * Input vector for signal x1 (reference).
 */
private double[] x1;

/**
 * Input vector for signal x2 (test).
 */
private double[] x2;


/**
 * Execute the cross correlation between signal x1 and x2 and calculate the time delay.
 */
public void execCorrelation()
{
    // define the size of the resulting correlation field
    int corrSize = 2*x1.length;
    // create correlation vector
    out = new double[corrSize];
    // shift variable
    int shift = x1.length;
    double val;
    int maxIndex = 0;
    double maxVal = 0;

    // we have push the signal from the left to the right
    for(int i=0;i<corrSize;i++)
    {
        val = 0;
        // multiply sample by sample and sum up
        for(int k=0;k<x1.length;k++)
        {
            // x2 has reached his end - abort
            if((k+shift) > (x2.length -1))
            {
                break;
            }

            // x2 has not started yet - continue
            if((k+shift) < 0)
            {
                continue;
            }

            // multiply sample with sample and sum up
            val += x1[k] * x2[k+shift];
            //System.out.print("x1["+k+"] * x2["+(k+tmp_tau)+"] + ");
        }
        //System.out.println();
        // save the sample
        out[i] = val;
        shift--;
        // save highest correlation index
        if(out[i] > maxVal)
        {
            maxVal = out[i];
            maxIndex = i;
        }
    }

    // set the delay
    this.delay = maxIndex - x1.length;
}
/**
*信号x1的输入矢量(参考)。
*/
私有双[]x1;
/**
*信号x2的输入向量(测试)。
*/
私人双[]x2;
/**
*执行信号x1和x2之间的互相关,并计算延时。
*/
公共关系
{
//定义结果相关字段的大小
int corrSize=2*x1.1长度;
//创建相关向量
out=新的双精度[corrSize];
//移位变量
int-shift=x1.5长度;
双val;
int maxIndex=0;
双maxVal=0;
//我们已将信号从左向右推
对于(int i=0;i maxVal)
{
maxVal=out[i];
maxIndex=i;
}
}
//设置延迟
this.delay=maxIndex-x1.length;
}

如果我没记错的话,互相关与其中一个信号时间反转的卷积是一样的。通过将两个信号的频谱相乘,依次高效地计算卷积;i、 例如,将每个信号的FFT至少填充到两个信号的大小之和,乘以FFT变换后的频谱,进行逆IFFT,然后搜索峰值

对于Java,可以使用来执行FFT/IFFT


如果您想在实际实现之前使用此方法,可以尝试我的应用程序;它有一个卷积模块,可以接收两个声音文件(您将问题标记为“音频处理”,因此我假设您可以生成声音文件)。

它假设信号是循环的。@SimonRichter-您的意思是什么?进行填充以防止时间混叠;请参阅维基百科。是的,如果信号被填充,这是有效的(加上峰值的相位角,你可以获得更高的分辨率)。@SimonRichter-thx供你回复。我已经实现了FFT,但我不确定如何将其用于相关性。我使用apachemath的FFT,FFT的输出很复杂。所以我乘以FFT{x1}和FFT{x2*}的复向量。所以我有一个复杂的[]数组。IFFT输入需要双[]值。所以现在我不确定IFFT使用什么。复数数组的实数还是绝对值?对不起,我不熟悉FFT/IFFT。对FFT结果进行复数乘法,然后使用复数->复数IFFT函数,搜索最大的绝对值(
re*re+im*im
,无需计算平方根)。您有一个for-if模式,用于检查样本的边界。你可以通过计算一次内循环的开始和结束来加快计算速度。此外,你的结果是加权的,因为小的移位将有更有效的组合,所以相关性的总和在绝对值中上升。你说的“加权”是什么意思?