Dan*_*rth 9 .net c# signal-processing convolution cross-correlation
在我之前关于在更大的音频样本中找到参考音频样本的问题中,有人建议我应该使用卷积.
使用DSPUtil,我能够做到这一点.我玩了一下,尝试了不同的音频样本组合,看看结果是什么.为了可视化数据,我只是将原始音频作为数字转储到Excel并使用这些数字创建了一个图表.一个高峰是可见的,但我真的不知道这对我有什么帮助.我有这些问题:
任何帮助都非常感谢.
以下图片是使用Excel进行分析的结果:
更新和解决方案:
感谢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);
}
Run Code Online (Sandbox Code Playgroud)
BOUNTY:
无需新答案!我开始赏金给Han,因为他继续努力解决这个问题!
我们来领取赏金:)
要在较大的音频片段中找到特定的参考信号,您需要使用互相关算法。基本公式可以在这篇维基百科文章中找到。
互相关是比较两个信号的过程。这是通过将两个信号相乘并对所有样本的结果求和来完成的。然后将其中一个信号移动(通常移动 1 个样本),并重复计算。如果您尝试将其可视化为非常简单的信号,例如单个脉冲(例如,1 个样本具有特定值,而其余样本为零)或纯正弦波,您将看到互相关的结果确实是衡量两个信号的相似程度以及它们之间的延迟的指标。可以在此处找到另一篇可能提供更多见解的文章。
Paul Bourke 的这篇文章还包含简单时域实现的源代码。请注意,本文是针对一般信号而写的。音频具有特殊的属性,即长期平均值通常为 0。这意味着 Paul Bourkes 公式(mx 和 my)中使用的平均值可以省略。还有基于 FFT 的互相关的快速实现(请参阅ALGLIB)。
相关性的(最大)值取决于音频信号中的样本值。然而,在 Paul Bourke 的算法中,最大值缩放为 1.0。在其中一个信号完全包含在另一个信号内的情况下,最大值将达到 1。在更一般的情况下,最大值将更低,并且必须确定阈值来决定信号是否足够相似。