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

时间:2011-05-01 09:23:26

标签: c# .net signal-processing convolution cross-correlation

my previous question中找到一个更大的音频样本中的参考音频样本,有人建议我应该使用卷积。
使用DSPUtil,我能够做到这一点。我玩了一下,尝试了不同的音频样本组合,看看结果是什么。为了可视化数据,我只是将原始音频作为数字转储到Excel并使用这些数字创建了一个图表。峰值 可见,但我真的不知道这对我有什么帮助。我有这些问题:

  • 我不知道,如何从峰值位置推断原始音频样本中匹配的起始位置。
  • 我不知道,我应该如何应用连续的音频流,所以一旦参考音频样本出现,我就会做出反应。
  • 我不明白,为什么图片2和图片4(见下文)差别如此之大,尽管两者都代表了与自身融合的音频样本......

非常感谢任何帮助。

以下图片是使用Excel进行分析的结果:

  1. 较长的音频样本,附近有参考音频(哔哔声): http://img801.imageshack.us/img801/976/values1.png
  2. 哔哔声与自己融为一体: http://img96.imageshack.us/img96/6720/values2i.png
  3. 较长的音频样本,没有蜂鸣声与蜂鸣声卷曲: http://img845.imageshack.us/img845/1091/values3.png
  4. 第3点的较长音频样本与自身卷积: http://img38.imageshack.us/img38/1272/values4.png
  5. 更新和解决方案:
    感谢汉的广泛帮助,我实现了目标 我在没有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);
    }
    

    BOUNTY:
    无需新答案!我开始赏金给Han,因为他继续努力解决这个问题!

2 个答案:

答案 0 :(得分:3)

您应该使用相关性而不是卷积。相关峰的大小告诉您两个信号的相似程度,峰的位置及其相对位置,或两个信号之间的延迟。

答案 1 :(得分:3)

我们在这里寻求赏金:)

要在较大的音频片段中查找特定参考信号,您需要使用互相关算法。基本公式可以在Wikipedia article中找到。

互相关是比较2个信号的过程。这是通过将两个信号相乘并对所有样本的结果求和来完成的。然后移动其中一个信号(通常是1个样本),并重复计算。如果您尝试将此信息显示为非常简单的信号(例如单个脉冲(例如,1个样本具有特定值而其余样本为零)或纯正弦波,您将看到互相关的结果确实如此衡量两种信号的相似程度以及它们之间的延迟。可以找到另一篇可能提供更多见解的文章here

article by Paul Bourke还包含简单时域实现的源代码。请注意,该文章是为一般信号而编写的。音频具有特殊属性,即长时间平均值通常为0.这意味着Paul Bourkes公式(mx和my)中使用的平均值可以省略。 还有基于FFT的互相关的快速实现(参见ALGLIB)。

相关的(最大)值取决于音频信号中的采样值。然而,在Paul Bourke的算法中,最大值被缩放到1.0。在其中一个信号完全包含在另一个信号中的情况下,最大值将达到1.在更一般的情况下,最大值将更低并且必须确定阈值以确定信号是否足够相似。