Scrolling Waveform Visualizer Using Web Audio API
const targetLength = this.analyser.fftSize * 8 // or however long // if you want 4 bars at x bpm (4/4): // 60 / bpm * 4 * 4 * this.audioCtx.sampleRate let displayArray = new Uint8Array(targetLength).fill(128) let prevTime = 0 const updateData = (t) => { this.requestAnimId = requestAnimationFrame(updateData) const frameOffset = Math.floor( (this.audioCtx.currentTime - prevTime) * this.audioCtx.sampleRate ) prevTime = this.audioCtx.currentTime displayArray = concatenate( Uint8Array, displayArray, this.getAnalyserData().slice(-frameOffset) ).slice(-targetLength) canvasCtx.fillStyle = 'rgba(255, 255, 255, 1)' canvasCtx.fillRect(0, 0, this.state.width, this.state.height) canvasCtx.lineWidth = 1 canvasCtx.strokeStyle = defaultColors.paleVioletRed canvasCtx.beginPath() const sliceWidth = this.state.width * 1.0 / targetLength let x = 0 for (let i = 0; i < targetLength; i++) { const v = displayArray[i] / 128.0 const y = v * this.state.height / 2 if (i === 0) { canvasCtx.moveTo(x, y) } else { canvasCtx.lineTo(x, y) } x += sliceWidth } canvasCtx.lineTo(this.state.width, this.state.height / 2) canvasCtx.stroke() } updateData()

Trying to build a smooth waveform visualizer à la Traktor using the Web Audio API that shows a longer section of the waveform than the FFT size of the analyzer node. Normally you can't do that by default as the buffer length is tied to the FFT, it's more suitable for oscilloscopes and such. So far I've got it working with an approach of concatenating Uint8Arrays into a bigger target, but it's a real CPU killer (chrome task manager shows 99-102% 😄). This code is embedded within a React component lifecycle method. Here's how it looks like in action:

https://cdn.haywirez.com/file/haywirez-cdn/temp/songsling_io_scrolling_waveform.mp4

Performance improvement suggestions very welcome 😄