Pregunta

en Mi pregunta anterior Al encontrar una muestra de audio de referencia en una muestra de audio más grande, se propuso que debo usar la convolución.
Usando Dsputil, Pude hacer esto. Jugué un poco con él y probé diferentes combinaciones de muestras de audio, para ver cuál fue el resultado. Para visualizar los datos, acabo de arrojar el audio sin procesar como números para sobresalir y creé un gráfico usando estos números. Un pico es Visible, pero realmente no sé cómo me ayuda esto. Tengo estos problemas:

  • No sé, cómo inferir la posición inicial del partido en la muestra de audio original desde la ubicación del pico.
  • No sé, cómo debería aplicar esto con un flujo continuo de audio, para que pueda reaccionar, tan pronto como ocurra la muestra de audio de referencia.
  • No entiendo, por qué la imagen 2 y la imagen 4 (ver más abajo) difieren tanto, aunque, ambos representan una muestra de audio convolucida de sí misma ...

Cualquier ayuda es muy apreciada.

Las siguientes imágenes son el resultado del análisis utilizando Excel:

  1. Una muestra de audio más larga con el audio de referencia (un pitido) cerca del final:
  2. El pitido se convoluciona de sí mismo:
  3. Una muestra de audio más larga sin el pitido convolucionado con el pitido:
  4. La muestra de audio más larga de Point 3 convolucionado de sí misma:

Actualización y solución:
Gracias a la amplia ayuda de Han, pude lograr mi objetivo.
Después de rodar mi propia implementación lenta sin FFT, encontré alglib que proporciona una implementación rápida. Hay una suposición básica en mi problema: una de las muestras de audio está completamente contenida dentro de la otra.
Por lo tanto, el siguiente código devuelve el desplazamiento en muestras en la mayor de las dos muestras de audio y el valor de correlación cruzada normalizada en ese desplazamiento. 1 significa correlación completa, 0 significa que no hay correlación en absoluto y -1 significa correlación 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);
}

GENEROSIDAD:
¡No se requieren nuevas respuestas! ¡Comencé la recompensa para otorgarlo a Han por su continuo esfuerzo con esta pregunta!

¿Fue útil?

Solución

Aquí vamos por la recompensa :)

Para encontrar una señal de referencia particular en un fragmento de audio más grande, debe usar un algoritmo de correlación cruzada. Las fórmulas básicas se pueden encontrar en esto Artículo de Wikipedia.

La correlación cruzada es un proceso mediante el cual se comparan 2 señales. Esto se hace multiplicando ambas señales y sumando los resultados para todas las muestras. Luego, una de las señales se desplaza (generalmente por 1 muestra), y el cálculo se repite. Si intenta visualizar esto para señales muy simples, como un solo impulso (por ejemplo, la muestra de la muestra tiene un cierto valor, mientras que las muestras restantes son cero), o una onda sinusoidal pura, verá que el resultado de la correlación cruzada es de hecho Una medida de cuánto son ambas señales iguales y el retraso entre ellas. Se puede encontrar otro artículo que pueda proporcionar más información. aquí.

Este Artículo de Paul Bourke También contiene código fuente para una implementación directa del dominio de tiempo. Tenga en cuenta que el artículo está escrito para una señal general. El audio tiene la propiedad especial de que el promedio de mucho tiempo es habitual 0. Esto significa que los promedios utilizados en la fórmula de Paul Bourkes (MX y MI) pueden dejarse fuera. También hay implementaciones rápidas de la correlación cruzada basadas en el FFT (ver Alglib).

El valor (máximo) de la correlación depende de los valores de muestra en las señales de audio. En el algoritmo de Paul Bourke, sin embargo, el máximo se escala a 1.0. En los casos en que una de las señales se contiene completamente dentro de otra señal, el valor máximo alcanzará 1. En el caso más general, el máximo será más bajo y se debe determinar un valor umbral para decidir si las señales son suficientemente parecidas.

Otros consejos

En lugar de una convolución, debe usar una correlación. El tamaño del pico de correlación le dice cuánto son ambas señales iguales, la posición del pico de su posición relativa en el tiempo o el retraso entre ambas señales.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top