it-swarm-es.tech

Latidos por minuto desde la entrada de audio en tiempo real

Me gustaría escribir una aplicación simple de C # para monitorear el audio de entrada de línea y darme los latidos actuales (bueno, el promedio móvil) por minuto.

He visto este artículo de gamedev , y eso no fue de ninguna ayuda. Revisé e intenté implementar lo que estaba haciendo, pero simplemente no estaba funcionando.

Sé que tiene que haber toneladas de soluciones para esto, porque muchos softwares de DJ lo hacen, pero no tengo suerte de encontrar una biblioteca de código abierto o instrucciones para hacerlo yo mismo.

43
Karl

Calcule un espectro de potencia con una ventana deslizante FFT: tome 1024 muestras:

double[] signal = stream.Take(1024);

Alimentarlo a un algoritmo FFT:

double[] real = new double[signal.Length];
double[] imag = new double[signal.Length);
FFT(signal, out real, out imag);

Obtendrá una parte real y una parte imaginaria. NO deseche la parte imaginaria. Haz lo mismo con la parte real que con lo imaginario. Si bien es cierto que la parte imaginaria está desfasada pi/2 con la real, todavía contiene el 50% de la información del espectro.

EDITAR:

Calcule la potencia en lugar de la amplitud para que tenga un número alto cuando sea alto y cercano a cero cuando esté en silencio:

for (i=0; i < real.Length; i++) real[i] = real[i] * real[i];

Del mismo modo para la parte imaginaria.

for (i=0; i < imag.Length; i++) imag[i] = imag[i] * imag[i];

Ahora tiene un espectro de potencia para las últimas 1024 muestras. Donde la primera parte del espectro son las frecuencias bajas y la última parte del espectro son las frecuencias altas.

Si quieres encontrar BPM en la música popular, probablemente deberías enfocarte en el bajo. Puede captar la intensidad de graves sumando la parte inferior del espectro de potencia. Qué números usar depende de la frecuencia de muestreo:

double bassIntensity = 0;
for (i=8; i < 96; i++) bassIntensity += real[i];

Ahora haga lo mismo nuevamente pero mueva la ventana 256 muestras antes de calcular un nuevo espectro. Ahora terminas calculando la intensidad de graves por cada 256 muestras.

Esta es una buena entrada para su análisis BPM. Cuando el bajo es silencioso, no tienes un ritmo y cuando es fuerte, tienes un ritmo.

¡Buena suerte!

26
Hallgrim

Hay un excelente proyecto llamado Dancing Monkeys, que genera pasos de baile DDR a partir de la música. Una gran parte de lo que hace se basa en un análisis de ritmo (necesariamente muy preciso), y su documento de proyecto entra en muchos detalles describiendo los diversos algoritmos de detección de ritmo y su idoneidad para la tarea. Incluyen referencias a los documentos originales para cada uno de los algoritmos. También han publicado el código matlab para su solución. Estoy seguro de que entre ellos puedes encontrar lo que necesitas.

Todo está disponible aquí: http://monket.net/dancing-monkeys-v2/Main_Page

15
Nick Johnson

No es que tenga una idea de cómo implementar esto, pero desde una perspectiva de ingeniería de audio, primero debe filtrar. Los golpes de bombo serían los primeros en comprobarlo. Un filtro de paso bajo que le dé algo por debajo de unos 200Hz debería darle una imagen bastante clara del bombo. También podría ser necesaria una compuerta para limpiar cualquier desorden de otros instrumentos con armónicos tan bajos.

Lo siguiente en comprobar sería golpes de caja. Tendrías que ecualizar este. El "crack" de una trampa es de alrededor de 1,5 kHz de la memoria, pero definitivamente necesitarías cerrar esta.

El próximo desafío sería desarrollar un algoritmo para ritmos funky. ¿Cómo encontrarías programáticamente el ritmo 1? Supongo que harías un seguimiento de los ritmos anteriores y usarías un patrón que coincida con algo u otro. Por lo tanto, probablemente necesitará algunas barras para encontrar con precisión el ritmo. Luego hay problemas de tiempo como 4/4, 3/4, 6/8, ¡no puedo imaginar qué se necesitaría para hacer esto con precisión! Estoy seguro de que valdría mucho dinero para las compañías de hardware/software de audio.

8
Dan Harper

Esto no es en absoluto un problema fácil. Trataré de darle solo una descripción general.

Lo que podría hacer es algo como lo siguiente:

  1. Calcule el volumen promedio (raíz cuadrática media) de la señal en bloques de, digamos, 5 milisegundos. (Nunca antes había hecho esto, no sé cuál sería un buen tamaño de bloque).
  2. Tome la transformada de Fourier de la señal "bloqueada", utilizando el algoritmo FFT.
  3. Encuentre el componente en la señal transformada que tiene la mayor magnitud.

Una transformación de Fourier es básicamente una forma de calcular la fuerza de todas las frecuencias presentes en la señal. Si lo hace sobre la señal "bloqueada", es de esperar que la frecuencia del latido sea la más fuerte.

Tal vez necesite aplicar un filtro primero, para enfocarse en frecuencias específicas (como el bajo) que generalmente contienen la mayor cantidad de información sobre BPM.

6
Thomas

Encontré esta biblioteca que parece tener una implementación bastante sólida para detectar latidos por minuto . http://soundtouchdotnet.codeplex.com/

Se basa en http://www.surina.net/soundtouch/index.html que se usa en bastantes proyectos de DJ http://www.surina.net/soundtouch/ aplicaciones.html

5
eandersson

En primer lugar, lo que Hallgrim está produciendo no es la función de densidad espectral de potencia. Las periodicidades estadísticas en cualquier señal se pueden obtener a través de una función de autocorrelación. La transformada de Fourier de la señal de autocorrelación es la densidad espectral de potencia. Los picos dominantes en el PSD que no sean 0 Hz corresponderán a la periodicidad efectiva en la señal (en Hz) ...

1
pete

Recomiendo revisar la biblioteca de audio BASS y el contenedor BASS.NET. Tiene una clase incorporada de BPMCounter.

Los detalles para esta función específica se pueden encontrar en http://bass.radio42.com/help/html/0833aa5a-3be9-037c-66f2-9adfd42a8512.htm .

0
Matt Williams

La manera fácil de hacerlo es hacer que el usuario toque un botón al ritmo del ritmo y cuente el número de toques divididos por el tiempo.

0
Lucius Kwok