La forma más sencilla de detectar dónde comienzan y se detienen los sobres de audio

43

A continuación se muestra una señal que representa una grabación de alguien hablando. Me gustaría crear una serie de señales de audio más pequeñas basadas en esto. La idea es detectar cuándo comienza y termina el sonido 'importante' y usarlos para los marcadores para crear un nuevo fragmento de audio. En otras palabras, me gustaría usar el silencio como indicadores de cuándo un 'fragmento' de audio se ha iniciado o detenido y crear nuevos buffers de audio basados ​​en esto.

Entonces, por ejemplo, si una persona se registra diciendo

Hi [some silence] My name is Bob [some silence] How are you?

entonces me gustaría hacer tres clips de audio de esto. Uno que dice Hi, uno que dice My name is Boby otro que dice How are you?.

Mi idea inicial es pasar por el búfer de audio constantemente comprobando dónde hay áreas de baja amplitud. Tal vez podría hacer esto tomando las primeras diez muestras, promediar los valores y, si el resultado es bajo, etiquetarlo como silencioso. Seguiría bajando el búfer comprobando las siguientes diez muestras. Al aumentar de esta manera pude detectar dónde comienzan y se detienen los sobres.

Si alguien tiene algún consejo sobre una buena pero sencilla forma de hacerlo, sería genial. Para mis propósitos, la solución puede ser bastante rudimentaria.

No soy un profesional en DSP, pero entiendo algunos conceptos básicos. Además, estaría haciendo esto mediante programación, por lo que sería mejor hablar sobre algoritmos y muestras digitales.

¡Gracias por toda la ayuda!

ingrese la descripción de la imagen aquí


EDITAR 1

¡Grandes respuestas hasta ahora! Solo quería aclarar que esto no está en audio en vivo y escribiré los algoritmos yo mismo en C u Objective-C, por lo que cualquier solución que use bibliotecas no es realmente una opción.

Eric Brotto
fuente
1
Parece que está tratando de dividirlo utilizando períodos de silencio como puntos de ruptura. ¿Por qué no usar el umbral de potencia para determinar el "silencio" y tener un tiempo de umbral para determinar si es lo suficientemente largo como para constituir una interrupción?
Jim Clay
@ JimClay Sí, eso es exactamente lo que estoy tratando de hacer. Nunca he oído hablar de umbral de potencia, pero parece algo que podría usar. ¿Es complicado? ¿Podrías ampliar eso un poco?
Eric Brotto
@EricBrotto Quizás debería contarnos un poco sobre las capacidades que tiene en sus bibliotecas. Eso nos permitirá dar un mejor masaje a la metodología actual.
Spacey
este enfoque para la detección de silencio es mejor: ¿cuál debería ser el nivel de retención distinto de 0.05 x = wavread ('s1.wav'); i = 1; mientras que abs (x (i)) <0.05% Detección de silencio i = i + 1; final x (1: i) = []; x (6000: 10000) = 0;
zeee

Respuestas:

26

Este es el problema clásico de la detección del habla . Lo primero que debería hacer sería buscar en Google el concepto. Es ampliamente utilizado en la comunicación digital y se han realizado muchas investigaciones sobre el tema y hay buenos documentos por ahí.

En general, cuanto más ruido de fondo tenga que tratar, más elaborado debe ser su método de detección de voz. Si está utilizando grabaciones tomadas en una habitación tranquila, puede hacerlo muy fácilmente (más adelante). Si tiene todo tipo de ruido mientras alguien habla (camiones que pasan, perros ladrando, platos que se estrellan, atacando extraterrestres), tendrá que usar algo mucho más inteligente.

Al observar la forma de onda que adjuntó, su ruido es mínimo, por lo que sugiero lo siguiente:

  1. Extraer envolvente de señal
  2. Elige un buen umbral
  3. Detectar lugares donde la magnitud de la envoltura excede el umbral

Qué significa todo esto? Una envolvente de una señal es una curva que describe su magnitud a lo largo del tiempo, independientemente de cómo su contenido de frecuencia la hace oscilar (ver imagen a continuación).

ingrese la descripción de la imagen aquí

La extracción de sobres se puede hacer creando una nueva señal que contenga valores absolutos de su señal original, por ejemplo, convierte en , y luego filtrar paso bajo el resultado. El filtro de paso bajo más simple puede implementarse reemplazando cada valor de muestra por un promedio de sus N vecinos en ambos lados. El mejor valor de N se puede encontrar experimentalmente y puede depender de varias cosas, como su frecuencia de muestreo.{ 1 , 45 , 6 , 2 , 43 , 2 ... }{1,45,6,2,43,2}{1,45,6,2,43,2}

Puede ver en la imagen que no tiene mucho ruido presente, su envolvente de señal siempre estará por encima de un cierto umbral (nivel de volumen), y puede considerar esas regiones como regiones detectadas por el habla .

Phonon
fuente
3
De hecho, había implementado esto como uno de los complementos en good'ol winamp. Lo que estás describiendo es bueno pero no suficiente. Por lo general, hay sonidos sonoros (vocales) y sonidos no sonoros (componentes). Si solo hubiera sonido sonoro, lo que está describiendo funcionará, pero el sonido sordo tiene muy poca energía y no se distingue del ruido general. Y las condiciones sin ruido también son muy raras incluso en los estudios.
Dipan Mehta
¿Cómo lograr esto en Python?
kRazzy R
26

Lo que realmente quieres hacer se llama esencialmente detección de actividad de voz o detección de voz.

Básicamente, cualquier señal de voz pura (que no contiene música) tiene tres partes.

  1. El sonido sonoro, que básicamente es causado por Vowels
  2. El sonido sordo, que contiene consonantes.

La característica del sonido humano es tal que, si bien se utiliza mucha energía en el sonido sonoro, la información real está contenida en las consonantes. Además, el sonido sonoro suele ser de frecuencia más baja, mientras que los sonidos no sonoros son frecuencias más altas. [Para ser precisos, todos los sonidos sonoros resuenan más o menos con una frecuencia constante para una persona determinada, que es su tono].

Ahora, como cualquier sistema, hay ruido. El sonido sonoro suele ser lo suficientemente potente como para distinguirse visiblemente. Cuando aplica un filtro de frecuencia más baja, es posible recopilar una buena magnitud de sonidos sonoros, sin embargo, el sonido sordo (con toda la información rica) se perderá.

Llegando a la pregunta de cómo resolverlo:

El truco radica en el hecho de que el sonido sordo aún proviene de una fuente resonante; e inherentemente restringido sobre cierta frecuencia. Donde como, el ruido es bastante uniforme. Entonces, una medida simple que distingue a los tres es el "poder local" o, alternativamente, pero equivalente es tomar la correlación automática en ventana.

Si toma a la vez 100 muestras, y se correlaciona automáticamente, si contiene solo ruido, los resultados serán prácticamente cero (esta es la propiedad del ruido blanco), mientras que en cuanto a la señal de voz, esta magnitud será observable porque la señal Aún tiene mejor estructura. Esto me ha funcionado en el pasado.

VAD ha sido un área de investigación activa, porque casi todas las comunicaciones de teléfonos móviles quieren detectar partes que no son del habla y eliminarlas de la codificación. Pero si eliminaran el discurso no sonoro, esto haría inútil la telefonía.

El estándar G.729 calcula VAD basado en características como: frecuencias espectrales de línea, energía de banda completa, energía de banda baja (<1 kHz) y velocidad de cruce por cero.

El estándar GSM funciona de la siguiente manera: la opción 1 calcula la SNR en nueve bandas y aplica un umbral a estos valores. La opción 2 calcula diferentes parámetros: potencia del canal, métricas de voz y potencia de ruido. Luego umbraliza las métricas de voz utilizando un umbral que varía de acuerdo con la SNR estimada. (de wikipedia)

Para técnicas más avanzadas, enumero algunas referencias sobre este tema.

  1. Referencia más localizada: Jongseo Sohn; Nam Soo Kim; Wonyong Sung; "Una detección de actividad de voz basada en un modelo estadístico" Signal Processing Letters, IEEE, enero de 1999, Volumen: 6 Edición: 1 pp: 1-3

  2. Lo más relevante para usted: Mark Marzinzik y Birger Kollmeier "Detección de pausa de voz para la estimación del espectro de ruido mediante el seguimiento de la dinámica de envolvente de potencia" TRANSACCIONES IEEE SOBRE EL PROCESAMIENTO DE HABLA Y AUDIO, VOL. 10, NO. 2, FEBRERO 2002 pp.109

  3. Ramírez, J .; JM Górriz, JC Segura (2007). "Detección de actividad de voz. Fundamentos y robustez del sistema de reconocimiento de voz". En M. Grimm y K. Kroschel. Robusto reconocimiento de voz y comprensión. pp. 1–22. ISBN 978-3-902613-08-0.

  4. Introducción: Jonathan Kola, Carol Espy-Wilson y Tarun Pruthi "Detección de actividad de voz"

Dipan Mehta
fuente
¿Cómo lograr esto en Python?
kRazzy R
9

Recomendaría totalmente a Jim Clay por su enfoque, pero variaría ligeramente el sabor usando el sobre:

Sabemos que el habla se produce principalmente alrededor de 1-2 kHz. Es probable que su muestreo de datos sea de 44 kHz (esto depende de su dispositivo de grabación). Entonces, lo que haría primero es un promedio móvil de la señal cuadrada en tiempo real a través de 10 puntos, para tener una envolvente de la potencia de la señal. Eso inducirá un retraso en la detección, por lo que desea mantener este nivel bajo.

Luego, agregaría una fase de calibración en su sistema: pídale al usuario que permanezca en silencio, presione un botón y registre el ruido de fondo durante unos 10 segundos. Tome la amplitud media o mediana del sobre, multiplique por 2 para tener seguridad, y eso le daría el umbral del que Jim ha estado hablando, automáticamente.

Si no se trata de una grabación en tiempo real, puede ser útil usar el promedio móvil de fase 0 para disminuir la molestia causada por el retraso. Díganos si funciona para usted tal como está.

Jean-Yves
fuente
9

Eric

Si realmente está buscando algo rápido y sucio, lo primero que debe obtener es el sobre, y lo haría simplemente (en MATLAB):

 envelope = abs(hilbert(yourSignal));

En ese punto, simplemente umbral, y 'la voz existe' si está por encima de cierto umbral.

Por cierto, esta es una solución muy simple, pero podría funcionar para usted.

Spacey
fuente
1
+1. ¿Quizás podría explicar el método detrás de esta línea de código? Estoy seguro de que el OP no está familiarizado con la extracción de sobres a través de la Transformación de Hilbert.
Phonon
@ Mohammad Gracias! Pero por favor vea mi EDIT 1. Definitivamente me gustaría rápido y sucio, pero también necesito hacer los algoritmos yo mismo :)
Eric Brotto
@EricBrotto Ah, ok, bueno, ¿puedo decirte cómo implementar un transformador hilbert, pero supongo que tienes la capacidad de hacer un FFT en tus bibliotecas C / Obj-C? Si no, eso va a ser un problema ... :-)
Spacey
¿Cómo lograr esto en Python?
kRazzy R
Amable Señor / Señora, ¿podría indicarme un recurso sobre cómo se implementará este hilbert en Python?
kRazzy R
6

Supongo que está tratando con señales reales, no complejas; si ese no es el caso, avíseme y puedo modificar la respuesta.

La potencia se define como el cuadrado de la señal (es decir, las muestras de señal multiplicadas por sí mismas). Puede comparar el poder con algún umbral para determinar si hay voz presente o no. Probablemente necesite hacer algunas mediciones en sus grabaciones para encontrar empíricamente un buen umbral.

Si sus grabaciones son "limpias" (es decir, no hay mucho ruido), probablemente iría lo más simple posible comparando la potencia instantánea (es decir, una sola muestra) con el umbral. Esto significa que ni siquiera tiene que cuadrarlo si no lo desea, solo necesita el valor absoluto y compararlo con la raíz cuadrada del umbral de potencia, que puede calcularse previamente. Cuando detecte el habla, agárrelo y grabe algo antes para asegurarse de obtener todo el discurso (¿quizás 1/10 de segundo?). Continúe hasta que encuentre un período prolongado sin muestras que excedan el umbral. Nuevamente, la duración del período debería determinarse empíricamente.

Enjuague y repita.

Jim Clay
fuente
4

He escrito una clase de detector de actividad en Java. Es parte de mi colección Java DSP de código abierto . Puede usar el programa de prueba WavSplitter.java para verificarlo con un archivo WAV como entrada.

Christian d'Heureuse
fuente
Tenga en cuenta que el OP dice específicamente que necesita escribir los algoritmos él mismo en C.
Sam Maloney
Es muy fácil convertir dichos algoritmos de Java a C.
Christian d'Heureuse
Señor, ¿cómo lograr esto en Python?
kRazzy R