11import { WebSocketServer } from 'ws'
22import fftjs from 'fft-js'
3- import MusicTempo from 'music-tempo '
3+ import { Essentia , EssentiaWASM } from 'essentia.js '
44// eslint-disable-next-line import/default
55import RingBufferTs from 'ring-buffer-ts'
66const RingBuffer = RingBufferTs . RingBuffer
@@ -29,8 +29,9 @@ const sampleRateDefault = 44100
2929const bpmWindow = sampleRateDefault * 8
3030const sampleBuffer = new RingBuffer < number > ( bpmWindow )
3131let lastBpmUpdate = 0
32+ const essentiaPromise = Promise . resolve ( new Essentia ( EssentiaWASM ) )
3233
33- export function processAudio ( buffer : Buffer , sampleRate = sampleRateDefault ) {
34+ export async function processAudio ( buffer : Buffer , sampleRate = sampleRateDefault ) {
3435 const samples = new Int16Array ( buffer . buffer , buffer . byteOffset , buffer . byteLength / 2 )
3536 const input = Array . from ( samples , s => s / 32768 )
3637 for ( const s of input ) sampleBuffer . add ( s )
@@ -56,8 +57,10 @@ export function processAudio(buffer: Buffer, sampleRate = sampleRateDefault) {
5657 if ( now - lastBpmUpdate > 2000 && sampleBuffer . getBufferLength ( ) >= sampleRate * 4 ) {
5758 lastBpmUpdate = now
5859 try {
59- const mt = new MusicTempo ( Float32Array . from ( sampleBuffer . toArray ( ) ) )
60- const tempo = parseFloat ( String ( mt . tempo ) )
60+ const essentia = await essentiaPromise
61+ const signal = essentia . arrayToVector ( Float32Array . from ( sampleBuffer . toArray ( ) ) )
62+ const res = essentia . RhythmExtractor2013 ( signal , 208 , 'multifeature' , 40 )
63+ const tempo = res . bpm
6164 if ( ! Number . isNaN ( tempo ) ) audioState . bpm = tempo
6265 } catch {
6366 // ignore errors
0 commit comments