detectar el número de picos en la grabación de audio

12

Estoy tratando de descubrir cómo detectar la cantidad de sílabas en un corpus de grabaciones de audio. Creo que un buen proxy podría ser picos en el archivo de onda.

Esto es lo que probé con un archivo de mí hablando en inglés (mi caso de uso real está en kiswahili). La transcripción de este ejemplo de grabación es: "Este soy yo tratando de usar la función de temporizador. Estoy viendo pausas, vocalizaciones". Hay un total de 22 sílabas en este pasaje.

Archivo wav: https://www.dropbox.com/s/koqyfeaqge8t9iw/test.wav?dl=0

El seewavepaquete en R es excelente, y hay varias funciones potenciales. Lo primero es lo primero, importa el archivo wave.

library(seewave)
library(tuneR)
w <- readWave("YOURPATHHERE/test.wav")  
w
# Wave Object
# Number of Samples:      278528
# Duration (seconds):     6.32
# Samplingrate (Hertz):   44100
# Channels (Mono/Stereo): Stereo
# PCM (integer format):   TRUE
# Bit (8/16/24/32/64):    16

Lo primero que probé fue la timer()función. Una de las cosas que devuelve es la duración de cada vocalización. Esta función identifica 7 vocalizaciones, que es muy inferior a 22 sílabas. Un vistazo rápido a la trama sugiere que las vocalizaciones no son iguales a las sílabas.

t <- timer(w, threshold=2, msmooth=c(400,90), dmin=0.1)
length(t$s)
# [1] 7

ingrese la descripción de la imagen aquí

También probé la función fpeaks sin establecer un umbral. Regresó 54 picos.

ms <- meanspec(w)
peaks <- fpeaks(ms)

ingrese la descripción de la imagen aquí

Esto traza la amplitud por frecuencia en lugar de tiempo. Agregar un parámetro de umbral igual a 0.005 filtra el ruido y reduce el recuento a 23 picos, que es bastante cercano al número real de sílabas (22).

ingrese la descripción de la imagen aquí

No estoy seguro de que este sea el mejor enfoque. El resultado será sensible al valor del parámetro de umbral, y tengo que procesar un gran lote de archivos. ¿Alguna idea mejor sobre cómo codificar esto para detectar picos que representan sílabas?

Eric Green
fuente
2
Esta es una pregunta muy interesante, pero puede obtener una mejor ayuda sobre los métodos en el sitio de Preguntas y respuestas sobre el procesamiento de señales de Stack Exchange .
eipi10
OK gracias. lo verificará si nadie responde. muy apreciado.
Eric Green
Solo una idea, pero ¿valdría la pena considerar realizar un análisis de puntos de cambio ? El análisis se puede realizar fácilmente en R con el uso del changepointpaquete. En pocas palabras, el análisis del punto de cambio se centra en detectar el cambio, el ejemplo vinculado se refiere a los datos comerciales, pero podría ser interesante aplicar esta técnica a los datos de sonido.
Konrad
Voy a aceptar la respuesta que tenga más votos, que es mi intento de implementar otra idea de CV. Sin embargo, creo que la pregunta central sigue siendo: cómo usar las características de las grabaciones para detectar con precisión una cantidad de picos que corresponde a la cantidad de sílabas habladas. Gracias por todas las ideas. Volveré a publicar aquí cuando tenga una solución.
Eric Green

Respuestas:

5

No creo que lo que sigue sea la mejor solución, pero @ eipi10 tenía una buena sugerencia para consultar esta respuesta en CrossValidated . Así que lo hice.

Un enfoque general es suavizar los datos y luego encontrar picos comparando un filtro máximo local con el suavizado.

El primer paso es crear la argmaxfunción:

argmax <- function(x, y, w=1, ...) {
  require(zoo)
  n <- length(y)
  y.smooth <- loess(y ~ x, ...)$fitted
  y.max <- rollapply(zoo(y.smooth), 2*w+1, max, align="center")
  delta <- y.max - y.smooth[-c(1:w, n+1-1:w)]
  i.max <- which(delta <= 0) + w
  list(x=x[i.max], i=i.max, y.hat=y.smooth)
}

Su valor de retorno incluye los argumentos de los máximos locales (x), que responden a la pregunta, y los índices en las matrices x e y donde ocurren esos máximos locales (i).

Hice pequeñas modificaciones a la testfunción de trazado: (a) para definir explícitamente x e y y (b) para mostrar el número de picos:

test <- function(x, y, w, span) {
  peaks <- argmax(x, y, w=w, span=span)

  plot(x, y, cex=0.75, col="Gray", main=paste("w = ", w, ", span = ", 
                                              span, ", peaks = ", 
                                              length(peaks$x), sep=""))
  lines(x, peaks$y.hat,  lwd=2) #$
  y.min <- min(y)
  sapply(peaks$i, function(i) lines(c(x[i],x[i]), c(y.min, peaks$y.hat[i]),
                                    col="Red", lty=2))
  points(x[peaks$i], peaks$y.hat[peaks$i], col="Red", pch=19, cex=1.25)
}

Al igual que el fpeaksenfoque que mencioné en mi pregunta original, este enfoque también requiere una gran cantidad de ajustes. No sabré la respuesta "correcta" (es decir, el número de sílabas / picos) que entra en esto, así que no estoy seguro de cómo definir una regla de decisión.

par(mfrow=c(3,1))
test(ms[,1], ms[,2], 2, 0.01)
test(ms[,1], ms[,2], 2, 0.045)
test(ms[,1], ms[,2], 2, 0.05)

ingrese la descripción de la imagen aquí

En este punto me fpeaksparece un poco menos complicado, pero aún no es satisfactorio.

Eric Green
fuente
Puede ser insatisfactorio porque los parámetros de loess no suavizan lo suficiente. La elección de suavizador debe guiarse por la naturaleza de los datos y los objetivos; no es algo que se deje a lo que ofrece la plataforma informática y a los valores predeterminados que proporciona.
whuber
Estos no son valores predeterminados. Solo ejemplos. Estoy desconcertado por el gran desafío del aprendizaje no supervisado en este caso. No sé la cantidad de sílabas en las grabaciones, por lo que no estoy seguro de cómo ajustar un lote de archivos. Los parámetros constantes probablemente no tengan sentido, pero no estoy seguro de cómo configurar otras reglas de decisión (por ejemplo, otras métricas de la onda que podrían usarse para determinar los valores óptimos para estos parámetros). Estoy pensando que necesito crear un conjunto de entrenamiento que ayude a algunos algoritmos a establecer estos parámetros. Aunque no estoy seguro.
Eric Green
En su comando para loess, no veo argumentos explícitamente dados para el grado de suavizado. En realidad, no tiene mucho sentido ejecutar loess sobre una ventana en movimiento: ya lo hace internamente.
whuber
Te entiendo. Asumí que wera un argumento en el alisamiento. Así es como el autor de la solución original describió la función: "Hay dos parámetros que deben ajustarse a las circunstancias: w es el ancho medio de la ventana utilizada para calcular el máximo local ... Otro - no explícito en esto código - es el argumento de la extensión del loess más suave ".
Eric Green
Ese autor lo incluyó wcomo uno de los parámetros porque tenía en mente un enfoque muy general en el que el más suave podría no ser loess, pero tal vez sería una mediana con ventana, o Hanning, o cualquier otra cosa que se considere apropiada para el comportamiento estadístico de los datos y el objetivos del analista. Las propiedades de muchos de esos suavizadores dependerían del ancho de la ventana.
whuber
1

Tuve problemas similares para analizar los perfiles de electroforesis de proteínas. Los resolví aplicando algunas de las funciones del paquete msprocess R en las segundas derivadas de los perfiles (consulte https://fr.wikipedia.org/wiki/D%C3%A9pouillement_d 'une_courbe # Position_et_hauteur_du_pic). Esto se ha publicado aquí: http://onlinelibrary.wiley.com/doi/10.1111/1755-0998.12389/abstract;jsessionid=8EE0B64238728C0979FF71C576884771.f02t03

No tengo idea si una solución similar puede funcionar para usted. Buena suerte

user17493.bis
fuente
gracias, @ user17493.bis. felicitaciones por publicar con material complementario. ¡me resultará mucho más fácil probar esta idea!
Eric Green
0

Aquí hay una biblioteca en Python que usé antes al intentar estimar la periodicidad al encontrar picos en la función de autocorrelación.

Utiliza diferencias de primer orden / derivadas discretas para la detección de picos y admite ajustes por parámetros de umbral y distancia mínima (entre picos consecutivos). También se puede mejorar la resolución máxima utilizando la estimación de densidad gaussiana y la interpolación (ver enlace).

Funcionó bastante bien de fábrica para mí sin muchos ajustes, incluso para datos ruidosos. Darle una oportunidad.

tool.ish
fuente
Gracias, @ tool.ish. Parece una buena alternativa a los métodos R que cité. Sin embargo, creo que todavía tendría el desafío de ajuste.
Eric Green
0

Me gustaría sugerir una solución utilizando el changepointpaquete. El siguiente ejemplo simplista intenta identificar picos, definidos aquí como puntos de cambio al mirar un canal de los datos disponibles.

Ejemplo

Abastecimiento de datos

# Libs
library(seewave)
library(tuneR)

# Download
tmpWav <- tempfile(fileext = ".wav")
download.file(url = "https://www.dropbox.com/s/koqyfeaqge8t9iw/test.wav?dl=0",
              destfile = tmpWav)

# Read
w <- readWave(filename = tmpWav)

Preparación de datos

# Libs
require(changepoint)

# Create time series data for one channel as an example
leftTS <- ts(data = w@left)

## Preview
plot.ts(leftTS)

Gráfico generado a través de la plot.tsllamada: Canal como series de tiempo

Análisis de punto de cambio

El changepointpaquete proporciona varias opciones para identificar cambios / picos en los datos. El siguiente código proporciona solo un ejemplo simple de encontrar 3 picos usando el método BinSeg :

# BinSeg method (example)
leftTSpelt <- cpt.var(data = leftTS, method = "BinSeg", penalty = "BIC", Q = 3)
## Preview
plot(leftTSpelt, cpt.width = 3)

Gráfico obtenido: Algunos puntos de cambio también es posible obtener valores:

cpts(leftTSpelt)
[1]  89582 165572 181053

Notas al margen

El ejemplo proporcionado se ocupa principalmente de ilustrar cómo se puede aplicar el análisis del punto de cambio a los datos proporcionados; Se debe tener precaución con respecto a los parámetros pasados ​​a la cp.varfunción. En el siguiente documento se ofrece una explicación detallada del paquete y las funcionalidades disponibles:

Killick, Rebecca y Eckley, Idris (2014) punto de cambio: un paquete R para el análisis del punto de cambio. Revista de software estadístico, 58 (3). pp. 1-19.

ecp

ecp, es otro que vale la pena mencionar el paquete R. Esto ecpfacilita la realización de análisis de puntos de cambio multivariados no paramétricos, que pueden ser útiles si uno quisiera identificar los puntos de cambio que ocurren a través de múltiples canales.

Konrad
fuente
Gracias, @konrad. No conocía ninguno de los paquetes, así que gracias por tomarse el tiempo para hacer una demostración. Creo que el desafío fundamental que tengo con todos estos paquetes es que no sé cuántos picos buscar, por lo que no estoy seguro de cómo ajustar los parámetros. Esto todavía parece una situación en la que tengo que usar algún algoritmo para determinar cómo establecer los parámetros para identificar con precisión el número correcto de picos (es decir, sílabas).
Eric Green
@EricGreen En principio, el análisis del punto de cambio le permitiría identificar sus picos con solo mirar la distribución. Sería cuestión de aplicar un método adecuado, sanciones, etc. Sugeriría que eche un vistazo al sitio web vinculado en mi comentario anterior, ya que describe el proceso en detalle.
Konrad
No estoy seguro de si literalmente te refieres a la distribución del globo ocular. Tengo 2000 archivos y necesito una forma de automatizar esto. Incluso si pudiera examinar cada archivo, me resulta difícil ver la cantidad de sílabas como picos. Tal vez estoy siendo denso y llegaré a ver los méritos de este enfoque. Todavía estoy atascado en la necesidad de una forma de autoajustar los parámetros de cada archivo para que el número resultante de picos detectados sea un proxy preciso para el número de sílabas.
Eric Green
@EricGreen No, no literario, por supuesto. Si descubre los parámetros apropiados que deberían pasarse a una de las funciones de cpt , podrá ejecutarlo en cualquier cantidad de objetos. Como no tengo experiencia en lingüística, no sé si las sílabas corresponderían a los picos habituales observados en los datos de series temporales.
Konrad
te tengo Creo que me encuentro con el paso "averiguar los parámetros apropiados" para este caso de uso en particular. Pero aprecié todas las ideas y aprendí sobre algunos paquetes nuevos que podrían ser buenas alternativas a los que probé.
Eric Green