Batidas por minuto da input de áudio em tempo real

Eu gostaria de escrever um aplicativo C # simples para monitorar o áudio de input de linha e me dar as batidas atuais (bem, a média móvel) por minuto.

Eu vi este artigo gamedev , e isso não ajudou em nada. Eu passei e tentei implementar o que ele estava fazendo, mas simplesmente não estava funcionando.

Eu sei que tem que haver toneladas de soluções para isso, porque muitos softwares de DJ fazem isso, mas eu não estou tendo nenhuma sorte em encontrar qualquer biblioteca de código aberto ou instruções sobre como fazer isso sozinho.

Calcule um powerspectrum com uma janela deslizante FFT: Pegue 1024 amostras:

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

Alimente-o a um algoritmo FFT:

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

Você terá uma parte real e uma parte imaginária. NÃO jogue fora a parte imaginária. Faça o mesmo com a parte real do imaginário. Embora seja verdade que a parte imaginária é pi / 2 fora de fase com o real, ela ainda contém 50% da informação do espectro.

EDITAR:

Calcule a potência em oposição à amplitude para que você tenha um número alto quando estiver alto e próximo de zero quando estiver silencioso:

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

Da mesma forma para a parte imaginária.

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

Agora você tem um espectro de energia para as últimas 1024 amostras. Onde a primeira parte do espectro é as baixas frequências e a última parte do espectro são as altas frequências.

Se você quiser encontrar o BPM na música popular, você provavelmente deve se concentrar no baixo. Você pode pegar a intensidade do baixo sumndo a parte inferior do espectro de potência. Quais números usar depende da frequência de amostragem:

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

Agora faça o mesmo novamente, mas mova a janela de 256 amostras antes de calcular um novo espectro. Agora você acaba calculando o bassIntensity para cada 256 samples.

Esta é uma boa input para sua análise de BPM. Quando o baixo está quieto você não tem uma batida e quando está alto você tem uma batida.

Boa sorte!

Há um excelente projeto chamado Dancing Monkeys, que processualmente gera passos de dança DDR a partir da música. Uma grande parte do que ele faz é baseada em análises de batidas (necessariamente muito precisas), e seu trabalho de projeto detalha os vários algoritmos de detecção de batidas e sua adequação à tarefa. Eles incluem referências aos documentos originais para cada um dos algoritmos. Eles também publicaram o código matlab para sua solução. Tenho certeza que entre os que você pode encontrar o que você precisa.

Está tudo disponível aqui: http://monket.net/dancing-monkeys-v2/Main_Page

Não que eu tenha uma ideia de como implementar isso, mas a partir de uma perspectiva de engenharia de áudio, você precisaria filtrar primeiro. Batidas de bumbo seriam as primeiras a serem verificadas. Um filtro low pass que lhe dê qualquer coisa abaixo de 200Hz deve dar uma imagem bem clara do bumbo. Um portão também pode ser necessário para limpar qualquer desordem de outros instrumentos com harmônicos tão baixos.

O próximo a checar seria o de laços. Você teria que EQ este aqui. O “crack” de uma armadilha é em torno de 1.5kHz de memory, mas você precisa definitivamente bloquear este.

O próximo desafio seria elaborar um algoritmo para batidas funky. Como você programaticamente encontrar a batida 1? Eu acho que você iria acompanhar batidas anteriores e usar um padrão correspondente a algo ou outro. Então, você provavelmente precisará de alguns compassos para encontrar a batida com precisão. Então há problemas de tempo como 4/4, 3/4, 6/8, uau, eu não posso imaginar o que seria necessário para fazer isso com precisão! Tenho certeza de que valeria muito dinheiro para empresas de hardware / software de áudio.

Isso não é de forma alguma um problema fácil. Vou tentar dar apenas uma visão geral.

O que você poderia fazer é algo como o seguinte:

  1. Calcule o volume médio (raiz quadrada média) do sinal em blocos de, digamos, 5 milissegundos. (Nunca fiz isso antes, não sei o tamanho de um bloco bom).
  2. Pegue a transformada de Fourier do sinal “bloqueado”, usando o algoritmo FFT.
  3. Encontre o componente no sinal transformado que possui a maior magnitude.

Uma transformada de Fourier é basicamente uma maneira de calcular a força de todas as freqüências presentes no sinal. Se você fizer isso através do sinal “bloqueado”, a frequência da batida provavelmente será a mais forte.

Talvez você precise aplicar um filtro primeiro, para focar em freqüências específicas (como o baixo) que geralmente contêm mais informações sobre o BPM.

Eu encontrei esta biblioteca que parece ter uma implementação bastante sólida para detectar batidas por minuto . http://soundtouchdotnet.codeplex.com/

É baseado em http://www.surina.net/soundtouch/index.html que é usado em vários projetos de DJs http://www.surina.net/soundtouch/applications.html

Primeiro de tudo, o que Hallgrim está produzindo não é a function de densidade espectral de potência. Periodicidades statistics em qualquer sinal podem ser trazidas através de uma function de autocorrelação. A transformada de fourier do sinal de autocorrelação é a densidade espectral de potência. Os picos dominantes no PSD, exceto em 0 Hz, corresponderão à periodicidade efetiva do sinal (em Hz) …

A maneira mais fácil de fazer isso é fazer com que o usuário toque um botão no ritmo da batida e conte o número de toques dividido pelo tempo.

Eu recomendo verificar a biblioteca de áudio BASS e o wrapper BASS.NET. Foi construído em uma class BPMCounter.

Detalhes para esta function específica podem ser encontrados em http://bass.radio42.com/help/html/0833aa5a-3be9-037c-66f2-9adfd42a8512.htm .