10

より大きなオーディオ サンプルでリファレンス オーディオ サンプルを見つけることに関する私の以前の質問では、畳み込みを使用する必要があると提案されました。DSPUtil
を使用して、これを行うことができました。少し遊んで、オーディオ サンプルのさまざまな組み合わせを試して、結果がどうなるかを確認しました。データを視覚化するために、生の音声を数値として Excel にダンプし、この数値を使用してグラフを作成しました。ピーク見えますが、これがどのように役立つかはよくわかりません。私はこれらの問題を抱えています:

  • ピークの位置から元のオーディオ サンプルの一致の開始位置を推測する方法がわかりません。
  • これをオーディオの連続ストリームに適用する方法がわからないので、参照オーディオ サンプルが発生するとすぐに反応できます。
  • 画像 2 と画像 4 (以下を参照) がなぜそんなに違うのか理解できませんが、どちらもそれ自体で畳み込まれた音声サンプルを表しています...

どんな助けでも大歓迎です。

次の図は、Excel を使用して分析した結果です。

  1. 末尾近くにリファレンス オーディオ (ビープ音) がある長いオーディオ サンプル:
  2. ビープ音はそれ自体に畳み込まれました:
  3. ビープ音と畳み込まれたビープ音のない長いオーディオ サンプル:
  4. ポイント 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);
}

報奨金:
新しい回答は必要ありません! ハンのこの質問への継続的な取り組みに対して賞金を授与するために、私はバウンティを開始しました!

4

2 に答える 2

4

畳み込みの代わりに、相関を使用する必要があります。相関ピークのサイズは、両方の信号がどの程度似ているか、ピークの位置は時間内の相対的な位置、または両方の信号間の遅延を示します。

于 2011-05-01T10:08:43.330 に答える
3

さあ、賞金に行きましょう :)

大きなオーディオ フラグメントで特定の基準信号を見つけるには、相互相関アルゴリズムを使用する必要があります。基本的な式は、このウィキペディアの記事にあります。

相互相関は、2 つの信号を比較するプロセスです。これは、両方の信号を乗算し、すべてのサンプルの結果を合計することによって行われます。次に、信号の 1 つが (通常は 1 サンプル分) シフトされ、計算が繰り返されます。単一のインパルス (たとえば、1 つのサンプルが特定の値を持ち、残りのサンプルがゼロである)、または純粋な正弦波などの非常に単純な信号についてこれを視覚化しようとすると、相互相関の結果が実際に両方の信号がどの程度似ているか、およびそれらの間の遅延の尺度。詳細については、こちらの記事を参照してください

Paul Bourke によるこの記事には、単純な時間領域実装のソース コードも含まれています。この記事は一般的なシグナル用に書かれていることに注意してください。オーディオには、長時間の平均が通常 0 であるという特別な特性があります。これは、Paul Bourkes の式 (mx と my) で使用される平均を省略できることを意味します。FFT に基づく相互相関の高速実装もあります ( ALGLIBを参照)。

相関の (最大) 値は、オーディオ信号のサンプル値によって異なります。ただし、Paul Bourke のアルゴリズムでは、最大値は 1.0 にスケーリングされます。シグナルの 1 つが別のシグナル内に完全に含まれている場合、最大値は 1 に達します。より一般的な場合、最大値はより低くなり、シグナルが十分に類似しているかどうかを判断するためにしきい値を決定する必要があります。

于 2011-05-05T09:40:45.663 に答える