it-swarm-eu.dev

Battiti al minuto dall'input audio in tempo reale

Mi piacerebbe scrivere una semplice applicazione C # per monitorare l'audio line-in e darmi i battiti al minuto correnti (beh, la media mobile).

Ho visto questo articolo di gamedev , e questo non mi è stato di alcun aiuto. Ho attraversato e ho cercato di implementare quello che stava facendo, ma non funzionava.

So che ci devono essere tonnellate di soluzioni per questo, perché molti software DJ lo fanno, ma non ho alcuna fortuna nel trovare una libreria open source o le istruzioni per farlo da solo.

42
Karl

Calcola un powerspectrum con una finestra scorrevole FFT: Prendi 1024 campioni: 

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

Alimentalo con un algoritmo FFT: 

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

Otterrai una parte reale e una parte immaginaria. NON buttare via la parte immaginaria. Fai lo stesso con la parte reale dell'immaginario. Mentre è vero che la parte immaginaria è più sfasata rispetto al reale, essa contiene ancora il 50% delle informazioni sullo spettro.

MODIFICARE:

Calcola la potenza rispetto all'ampiezza in modo da avere un numero elevato quando è forte e vicino a zero quando è silenzioso:

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

Allo stesso modo per la parte immaginaria.

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

Ora hai uno spettro di potenza per gli ultimi 1024 campioni. Dove la prima parte dello spettro è le basse frequenze e l'ultima parte dello spettro sono le alte frequenze .

Se vuoi trovare BPM nella musica popolare dovresti probabilmente concentrarti sul basso. È possibile rilevare l'intensità del basso sommando la parte inferiore dello spettro di potenza. Quali numeri utilizzare dipende dalla frequenza di campionamento:

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

Ora fai lo stesso, ma sposta la finestra 256 campioni prima di calcolare un nuovo spettro. Ora finisci col calcolare il bassIntensity per ogni 256 campioni. 

Questo è un buon input per la tua analisi BPM. Quando il basso è silenzioso non hai un ritmo e quando è forte hai un ritmo. 

In bocca al lupo!

26
Hallgrim

C'è un eccellente progetto chiamato Dancing Monkeys, che genera proceduralmente passi di danza DDR dalla musica. Gran parte di ciò che fa si basa su un'analisi di battimento (necessariamente molto accurata), e il loro articolo di progetto contiene molti dettagli che descrivono i vari algoritmi di rilevamento dei battiti e la loro idoneità al compito. Includono riferimenti ai documenti originali per ciascuno degli algoritmi. Hanno anche pubblicato il codice MATLAB per la loro soluzione. Sono sicuro che tra quelli puoi trovare quello che ti serve.

È tutto disponibile qui: http://monket.net/dancing-monkeys-v2/Main_Page

15
Nick Johnson

Non che io abbia la minima idea di come implementarlo, ma da un punto di vista dell'ingegneria audio dovresti prima filtrare. Colpi di batteria grossi sarebbero i primi a controllare. Un filtro passa-basso che ti dà qualcosa sotto i 200Hz dovrebbe darti un'immagine chiara della cassa. Potrebbe anche essere necessario un cancello per ripulire qualsiasi disordine da altri strumenti con armoniche così basse.

Il prossimo a controllare sarebbero i colpi di rullante. Dovresti equalizzare questo. Il "crack" di un rullante è di circa 1.5kHz dalla memoria, ma avresti bisogno di chiudere definitivamente questo.

La prossima sfida sarebbe quella di elaborare un algoritmo per i ritmi funky. Come troveresti automaticamente il battito 1? Immagino che tu tenga traccia dei battiti precedenti e usi un modello che corrisponda a qualcosa-o-altro. Quindi, probabilmente avrai bisogno di alcune barre per trovare con precisione il ritmo. Poi ci sono problemi di temporizzazione come 4/4, 3/4, 6/8, wow, non riesco a immaginare cosa sarebbe richiesto per farlo in modo accurato! Sono sicuro che varrà qualcosa di serio per le aziende di hardware/software audio.

8
Dan Harper

Questo non è affatto un problema facile. Proverò a darti solo una panoramica.

Quello che potresti fare è qualcosa di simile al seguente:

  1. Calcola il volume medio (quadratura media) del segnale su blocchi di, ad esempio, 5 millisecondi. (Non avendolo mai fatto prima, non so quale sarebbe una buona dimensione del blocco.)
  2. Prendi la trasformata di Fourier del segnale "bloccato", usando l'algoritmo FFT.
  3. Trova il componente nel segnale trasformato che ha la maggiore ampiezza.

Una trasformata di Fourier è fondamentalmente un modo per calcolare la forza di tutte le frequenze presenti nel segnale. Se lo fai sopra il segnale "bloccato", la frequenza del battito sarà probabilmente la più forte.

Forse è necessario applicare prima un filtro, per concentrarsi su frequenze specifiche (come il basso) che di solito contengono la maggior parte delle informazioni sul BPM.

6
Thomas

Ho trovato questa libreria che sembra avere un'implementazione piuttosto solida per il rilevamento di Beats per Minute . http://soundtouchdotnet.codeplex.com/

Si basa su http://www.surina.net/soundtouch/index.html che viene utilizzato in molti progetti DJ http://www.surina.net/soundtouch/applications.html

5
eandersson

Prima di tutto, ciò che Hallgrim sta producendo non è la funzione di densità spettrale di potenza. Periodicità statistiche in qualsiasi segnale possono essere evidenziate attraverso una funzione di autocorrelazione. La trasformata di Fourier del segnale di autocorrelazione è la densità spettrale di potenza. Picchi dominanti nella PSD diversa da 0 Hz corrisponderanno alla periodicità effettiva nel segnale (in Hz) ... 

1
pete

Ti consiglio di controllare la libreria audio BASS e il wrapper BASS.NET. Ha una classe BPMCounter integrata. 

Dettagli per questa specifica funzione sono disponibili su http://bass.radio42.com/help/html/0833aa5a-3be9-037c-66f2-9adfd42a8512.htm .

0
Matt Williams

Il modo più semplice per farlo è di fare in modo che l'utente tocchi un pulsante a ritmo con il ritmo e contenga il numero di tocchi divisi per il tempo.

0
Lucius Kwok