Frage

in meine vorherige Frage Bei der Suche nach einer Referenz -Audio -Probe in einer größeren Audio -Stichprobe wurde vorgeschlagen, dass ich Faltungen verwenden sollte.
Verwendung DSputil, Ich konnte das tun. Ich habe ein wenig damit gespielt und verschiedene Kombinationen von Audio -Samples ausprobiert, um zu sehen, was das Ergebnis war. Um die Daten zu visualisieren, habe ich gerade das RAW -Audio als Zahlen für Excel abgeladen und ein Diagramm mit diesen Zahlen erstellt. Ein Gipfel ist sichtbar, aber ich weiß nicht wirklich, wie das mir hilft. Ich habe diese Probleme:

  • Ich weiß nicht, wie ich die Ausgangsposition des Spiels in der ursprünglichen Audio -Probe vom Ort des Peaks schließen kann.
  • Ich weiß nicht, wie ich dies mit einem kontinuierlichen Audiostrom anwenden sollte, damit ich reagieren kann, sobald die Referenz -Audio -Probe auftritt.
  • Ich verstehe nicht, warum Bild 2 und Bild 4 (siehe unten) so sehr unterschiedlich, obwohl beide eine mit sich selbst zusammengestellte Audio -Probe darstellen ...

Jede Hilfe wird sehr geschätzt.

Die folgenden Bilder sind das Ergebnis der Analyse mit Excel:

  1. Eine längere Audio -Probe mit dem Referenz -Audio (ein Piepton) gegen Ende:
  2. Der mit sich selbst gepolsterte Piepton:
  3. Eine längere Audio -Probe ohne mit dem Piepton gepolsterten Piepton:
  4. Die längere Audio -Probe von Punkt 3 wurde mit sich selbst gebunden:

Update und Lösung:
Dank der umfangreichen Hilfe von Han konnte ich mein Ziel erreichen.
Nachdem ich meine eigene langsame Implementierung ohne FFT gerollt hatte, fand ich Alglib Dies liefert eine schnelle Implementierung. Mein Problem ist eine grundlegende Annahme: Eine der Audio -Stichproben ist vollständig innerhalb der anderen enthalten.
Daher gibt der folgende Code den Versatz in Proben im größeren der beiden Audioproben und den normalisierten Kreuzkorrelationswert bei diesem Offset zurück. 1 bedeutet eine vollständige Korrelation, 0 bedeutet überhaupt keine Korrelation und -1 vollständig negative Korrelation:

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);
}

KOPFGELD:
Keine neuen Antworten erforderlich! Ich begann das Kopfgeld, um Han für seine fortgesetzte Bemühungen mit dieser Frage zu vergeben!

War es hilfreich?

Lösung

Hier gehen wir für das Kopfgeld :)

Um ein bestimmtes Referenzsignal in einem größeren Audio-Fragment zu finden, müssen Sie einen Kreuzkorrelationsalgorithmus verwenden. Die grundlegenden Formeln finden Sie darin Wikipedia -Artikel.

Kreuzkorrelation ist ein Prozess, durch den 2 Signale verglichen werden. Dies geschieht durch Multiplizieren beider Signale und Summieren der Ergebnisse für alle Stichproben. Dann wird eines der Signale verschoben (normalerweise durch 1 Probe) und die Berechnung wiederholt. Wenn Sie versuchen, dies für sehr einfache Signale wie einen einzelnen Impuls zu visualisieren (z. B. eine Probe hat einen bestimmten Wert, während die verbleibenden Proben Null sind) oder eine reine Sinuswelle, werden Sie feststellen, dass das Ergebnis der Kreuzkorrelation tatsächlich ist Eine Maßnahme für, wie sehr beide Signale gleich sind und die Verzögerung zwischen ihnen. Ein weiterer Artikel, der mehr Einblicke liefern kann hier.

Dies Artikel von Paul Bourke Enthält auch Quellcode für eine unkomplizierte Zeitdomänen-Implementierung. Beachten Sie, dass der Artikel für ein allgemeines Signal geschrieben ist. Audio hat die spezielle Eigenschaft, dass der langjährige Durchschnitt üblich ist. Dies bedeutet, dass die in der Paul Bourkes-Formel (MX und My) verwendeten Durchschnittswerte ausgelassen werden können. Es gibt auch schnelle Implementierungen der Kreuzkorrelation basierend auf der FFT (siehe Alglib).

Der (maximale) Wert der Korrelation hängt von den Stichprobenwerten in den Audiosignalen ab. In Paul Bourkes Algorithmus wird das Maximum jedoch auf 1,0 skaliert. In Fällen, in denen eines der Signale vollständig in einem anderen Signal enthalten ist, erreicht der Maximalwert 1. Im allgemeineren Fall muss das Maximum niedriger sein und ein Schwellenwert bestimmt werden, um zu entscheiden, ob die Signale ausreichend gleich sind.

Andere Tipps

Anstelle einer Faltung sollten Sie eine Korrelation verwenden. Die Größe des Korrelationspeaks zeigt Ihnen, wie sehr beide Signale gleich sind, die Position des Peaks ihrer relativen Position in der Zeit oder der Verzögerung zwischen beiden Signalen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top