commit 4a197c2d25ac438008eb51009e07c6f8892b2c3a Author: Evert Prants Date: Sat Sep 26 14:53:16 2020 +0300 initial commit diff --git a/index.html b/index.html new file mode 100644 index 0000000..3989ca4 --- /dev/null +++ b/index.html @@ -0,0 +1,37 @@ + + + + + Audio Spectrum Visualizer + + + +
+ +
+
+ + +
+ + + diff --git a/index.js b/index.js new file mode 100644 index 0000000..6951a14 --- /dev/null +++ b/index.js @@ -0,0 +1,78 @@ +(function () { + const graph = document.getElementById('graph') + const bars = document.getElementById('bars') + const file = document.getElementById('track') + const gctx = graph.getContext('2d') + const bctx = bars.getContext('2d') + let context + let analyser + let dataArray + let bufferLength + let source + let started = false + + const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) + const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0) - 5 + + graph.width = vw - 100 + graph.height = vh + bars.height = vh + bars.width = 100 + + function analyse () { + window.requestAnimationFrame(analyse) + analyser.getFloatFrequencyData(dataArray) + + gctx.drawImage(graph, -2, 0) + bctx.clearRect(0, 0, bars.width, bars.height) + + const dheight = (1 / dataArray.length) * graph.height + + for (let i = 0; i < dataArray.length; i++) { + const p = i / dataArray.length + const h = graph.height - p * graph.height + const c = Math.max((dataArray[i] - analyser.minDecibels) / 95, 0) + const s = 'hsl(0, 100%, ' + Math.floor(c * 100 - 10) + '%)' + gctx.fillStyle = s + gctx.fillRect(graph.width - 2, h, 2, dheight) + + // const freq = i * context.sampleRate / analyser.fftSize + const bar = (dataArray[i] + 100) + bctx.fillStyle = s + bctx.fillRect(0, h, bar, dheight) + } + } + + async function start (arrayBuffer) { + if (!context) context = new window.AudioContext() + const audioBuffer = await context.decodeAudioData(arrayBuffer) + + analyser = context.createAnalyser() + analyser.buffer = audioBuffer + analyser.connect(context.destination) + + if (source) source.stop() + source = context.createBufferSource() + source.buffer = audioBuffer + source.connect(analyser) + source.start() + + bufferLength = analyser.frequencyBinCount + dataArray = new Float32Array(bufferLength) + + if (started) return + started = true + analyse() + } + + file.addEventListener('change', function (e) { + const fp = file.files[0] + if (!fp) return window.alert('Invalid file.') + const fr = new window.FileReader() + fr.addEventListener('loadend', function (e) { + if (fr.readyState !== 2) return window.alert('File reading failed.') + start(fr.result) + }) + fr.readAsArrayBuffer(fp) + }) +})()