より大きなオーディオ サンプルでリファレンス オーディオ サンプルを見つけることに関する私の以前の質問では、畳み込みを使用する必要があると提案されました。DSPUtil
を使用して、これを行うことができました。少し遊んで、オーディオ サンプルのさまざまな組み合わせを試して、結果がどうなるかを確認しました。データを視覚化するために、生の音声を数値として Excel にダンプし、この数値を使用してグラフを作成しました。ピークが見えますが、これがどのように役立つかはよくわかりません。私はこれらの問題を抱えています:
- ピークの位置から元のオーディオ サンプルの一致の開始位置を推測する方法がわかりません。
- これをオーディオの連続ストリームに適用する方法がわからないので、参照オーディオ サンプルが発生するとすぐに反応できます。
- 画像 2 と画像 4 (以下を参照) がなぜそんなに違うのか理解できませんが、どちらもそれ自体で畳み込まれた音声サンプルを表しています...
どんな助けでも大歓迎です。
次の図は、Excel を使用して分析した結果です。
- 末尾近くにリファレンス オーディオ (ビープ音) がある長いオーディオ サンプル:
- ビープ音はそれ自体に畳み込まれました:
- ビープ音と畳み込まれたビープ音のない長いオーディオ サンプル:
- ポイント 3 の長い音声サンプルは、それ自体と畳み込まれています。
更新と解決策:
Han の広範な支援のおかげで、目標を達成することができました。
FFT を使用せずに独自の遅い実装を行った後、高速な実装を提供するalglibを見つけました。私の問題には 1 つの基本的な前提があります。音声サンプルの 1 つが完全に別のサンプルに含まれているということです。
したがって、次のコードは、2 つのオーディオ サンプルのうち大きい方のサンプルのオフセットと、そのオフセットでの正規化された相互相関値を返します。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);
}
報奨金:
新しい回答は必要ありません! ハンのこの質問への継続的な取り組みに対して賞金を授与するために、私はバウンティを開始しました!