使用卷积在连续的声音流中找到参考音频样本

| 在我以前的有关在较大的音频样本中查找参考音频样本的问题中,有人建议我应该使用卷积。 使用DSPUtil,我能够做到这一点。我试了一下,尝试了不同的音频样本组合,以查看结果。为了可视化数据,我只是将原始音频作为数字转储到Excel中,并使用该数字创建了图表。可以看到一个高峰,但是我真的不知道这对我有什么帮助。我有这些问题: 我不知道如何从峰值的位置推断出匹配在原始音频样本中的开始位置。 我不知道如何在连续音频流中应用此方法,以便在出现参考音频样本后立即做出反应。 我不明白,为什么图片2和图片4(见下文)相差如此之大,尽管它们都代表了一个与自身卷积在一起的音频样本... 非常感谢您的帮助。 以下图片是使用Excel分析的结果: 较长的音频样本,结尾处带有参考音频(蜂鸣声): 蜂鸣声与其自身有关: 没有蜂鸣声的较长音频样本会与蜂鸣声卷积: 点3的较长音频样本与其自身发生了卷积: 更新和解决方案: 得益于Han的广泛帮助,我得以实现自己的目标。 在没有FFT的情况下滚动自己的慢速实现后,我发现alglib提供了一种快速实现。 我的问题有一个基本假设:一个音频样本完全包含在另一个音频样本中。 因此,以下代码返回两个音频样本中较大者的样本中的偏移以及该偏移处的归一化互相关值。 1表示完全相关,0表示完全不相关,-1表示完全负相关:
private void CalcCrossCorrelation(IEnumerable<double> data1, 
                                  IEnumerable<double> data2, 
                                  out int offset, 
                                  out double maximumNormalizedCrossCorrelation)
{
    var data1Array = data1.ToArray();
    var data2Array = data2.ToArray();
    double[] result;
    alglib.corrr1d(data1Array, data1Array.Length, 
                   data2Array, data2Array.Length, out result);

    var max = double.MinValue;
    var index = 0;
    var i = 0;
    // Find the maximum cross correlation value and its index
    foreach (var d in result)
    {
        if (d > max)
        {
            index = i;
            max = d;
        }
        ++i;
    }
    // if the index is bigger than the length of the first array, it has to be
    // interpreted as a negative index
    if (index >= data1Array.Length)
    {
        index *= -1;
    }

    var matchingData1 = data1;
    var matchingData2 = data2;
    var biggerSequenceCount = Math.Max(data1Array.Length, data2Array.Length);
    var smallerSequenceCount = Math.Min(data1Array.Length, data2Array.Length);
    offset = index;
    if (index > 0)
        matchingData1 = data1.Skip(offset).Take(smallerSequenceCount).ToList();
    else if (index < 0)
    {
        offset = biggerSequenceCount + smallerSequenceCount + index;
        matchingData2 = data2.Skip(offset).Take(smallerSequenceCount).ToList();
        matchingData1 = data1.Take(smallerSequenceCount).ToList();
    }
    var mx = matchingData1.Average();
    var my = matchingData2.Average();
    var denom1 = Math.Sqrt(matchingData1.Sum(x => (x - mx) * (x - mx)));
    var denom2 = Math.Sqrt(matchingData2.Sum(y => (y - my) * (y - my)));
    maximumNormalizedCrossCorrelation = max / (denom1 * denom2);
}
赏金: 无需新答案!我开始赏金,将其奖励给Han,以感谢他在这个问题上的不懈努力!     
已邀请:
在这里,我们去赏金:) 要在较大的音频片段中找到特定的参考信号,您需要使用互相关算法。基本公式可以在此Wikipedia文章中找到。 互相关是比较两个信号的过程。这是通过将两个信号相乘并求和所有样本的结果来完成的。然后,其中一个信号被移位(通常为1个样本),然后重复计算。如果您尝试将其可视化为非常简单的信号,例如单个脉冲(例如1个采样具有某个值,而其余采样为零)或纯正弦波,则将看到互相关的结果确实是两种信号的相似程度以及它们之间的延迟的量度。在这里可以找到另一篇可能提供更多见解的文章。 Paul Bourke的这篇文章还包含用于直接时域实现的源代码。请注意,本文是为一般性信号而写的。音频的特殊属性是长期平均值通常为0。这意味着可以忽略Paul Bourkes公式(mx和my)中使用的平均值。 也有基于FFT的互相关的快速实现(请参阅ALGLIB)。 相关的(最大值)值取决于音频信号中的样本值。但是,在Paul Bourke的算法中,最大值被缩放为1.0。在其中一个信号完全包含在另一个信号中的情况下,最大值将达到1。在更一般的情况下,最大值将更低,并且必须确定阈值以决定信号是否足够相似。     
而不是卷积,您应该使用相关。相关峰的大小告诉您两个信号的相似程度,峰的位置及其相对位置的时间,或两个信号之间的延迟。     

要回复问题请先登录注册