Domanda

in la mia domanda precedente Dopo aver trovato un campione audio di riferimento in un campione audio più grande, è stato proposto, che dovrei usare la convoluzione.
Usando Dsputil, Sono stato in grado di farlo. Ho giocato un po 'con esso e ho provato diverse combinazioni di campioni audio, per vedere quale fosse il risultato. Per visualizzare i dati, ho appena scaricato l'audio grezzo come numeri per eccellere e ho creato un grafico usando questi numeri. Un picco è visibile, ma non so davvero come questo mi aiuti. Ho questi problemi:

  • Non so, come dedurre la posizione di partenza della partita nel campione audio originale dalla posizione del picco.
  • Non so come dovrei applicarlo con un flusso continuo di audio, quindi posso reagire, non appena si verifica il campione audio di riferimento.
  • Non capisco, perché l'immagine 2 e la foto 4 (vedi sotto) differiscono così tanto, anche se entrambi rappresentano un campione audio contorto con se stesso ...

Qualsiasi aiuto è molto apprezzato.

Le seguenti immagini sono il risultato dell'analisi usando Excel:

  1. Un campione audio più lungo con l'audio di riferimento (un segnale acustico) vicino alla fine:
  2. Il segnale acustico si convocava con se stesso:
  3. Un campione audio più lungo senza il segnale acustico convocato con il segnale acustico:
  4. Il campione audio più lungo di Point 3 è stato contorto con se stesso:

Aggiornamento e soluzione:
Grazie all'ampio aiuto di Han, sono stato in grado di raggiungere il mio obiettivo.
Dopo aver lanciato la mia lenta implementazione senza FFT, ho trovato Alglib che fornisce un'implementazione rapida. C'è un presupposto di base al mio problema: uno dei campioni audio è completamente contenuto all'interno dell'altro.
Pertanto, il seguente codice restituisce l'offset in campioni nel più grande dei due campioni audio e il valore di correlazione incrociata normalizzato a quell'offset. 1 significa una correlazione completa, 0 non significa alcuna correlazione e -1 significa correlazione negativa completa:

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:
Non sono richieste nuove risposte! Ho iniziato la generosità per assegnarlo a Han per il suo continuo sforzo con questa domanda!

È stato utile?

Soluzione

Qui andiamo per la taglia :)

Per trovare un particolare segnale di riferimento in un frammento audio più ampio, è necessario utilizzare un algoritmo di correlazione incrociata. Le formule di base si trovano in questo Articolo di Wikipedia.

La correlazione incrociata è un processo mediante il quale vengono confrontati 2 segnali. Questo viene fatto moltiplicando entrambi i segnali e sommando i risultati per tutti i campioni. Quindi uno dei segnali viene spostato (di solito di 1 campione) e il calcolo viene ripetuto. Se si tenta di visualizzarlo per segnali molto semplici come un singolo impulso (ad es. 1 campione ha un certo valore mentre i campioni rimanenti sono zero) o un'onda sinusoidale pura, vedrai che il risultato della correlazione incrociata è davvero Una misura per quanto entrambi i segnali siano uguali e il ritardo tra loro. Un altro articolo che può fornire ulteriori informazioni possono essere trovate qui.

Questo Articolo di Paul Bourke Contiene anche il codice sorgente per un'implementazione semplice del dominio del tempo. Si noti che l'articolo è scritto per un segnale generale. L'audio ha la proprietà speciale che la media di lunga data è di solito 0. Ciò significa che le medie utilizzate nella formula di Paul Bourkes (MX e MY) possono essere escluse. Esistono anche rapide implementazioni della correlazione incrociata in base all'FFT (vedi Alglib).

Il valore (massimo) della correlazione dipende dai valori del campione nei segnali audio. Nell'algoritmo di Paul Bourke tuttavia il massimo viene ridimensionato a 1.0. Nei casi in cui uno dei segnali è contenuto interamente all'interno di un altro segnale, il valore massimo raggiungerà 1. Nel caso più generale il massimo sarà inferiore e un valore di soglia dovrà essere determinato per decidere se i segnali sono sufficientemente simili.

Altri suggerimenti

Invece di una convoluzione dovresti usare una correlazione. La dimensione del picco di correlazione indica quanto siano uguali entrambi i segnali, la posizione del picco della loro posizione relativa in tempo o il ritardo tra i due segnali.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top