JSFiddle - React, Tailwind, and code Playground
by alexvestin
HTML
<input id="file" type="file">Select song</input>
<canvas id="canvas"></canvas>
<canvas id="canvas2"></canvas>
CSS
#canvas {
background-color: black;
width: 400;
height: 400;
}
#canvas2 {
background-color: black;
width: 400;
height: 400;
}
JavaScript
let fftMult = 1;
let height = 400, width = 400, fftSize = 2048 * fftMult;
let canvas = document.getElementById("canvas");
let canvas2 = document.getElementById("canvas2");
canvas.width = width;
canvas.height = height;
canvas2.height = height;
canvas2.width = width;
let ctx = canvas.getContext("2d");
let button = document.getElementById("file");
let audioCtx = new AudioContext();
let bufferSource, loaded = false;
let analyzer = audioCtx.createAnalyser();
ctx.fillStyle = "green";
analyzer.fftSize = fftSize;
button.onchange = (e) => {
let reader = new FileReader();
reader.readAsArrayBuffer(button.files[0]);
reader.onload = function(ev) {
audioCtx.decodeAudioData(ev.target.result, function(buffer) {
console.log(buffer);
/*bufferSource = audioCtx.createBuffer(buffer.number, buffer.length, buffer.sampleRate); */
bufferSource = audioCtx.createBufferSource();
bufferSource.buffer = buffer;
bufferSource.connect(analyzer);
analyzer.connect(audioCtx.destination);
loaded = true;
bufferSource.start(0);
});
};
}
anim
let animate = () => {
ctx.clearRect(0,0,width, height);
if (loaded) {
let arr = new Uint8Array(fftSize / 2);
analyzer.getByteFrequencyData(arr);
let nrBins = 256;
let stepSize = fftSize / nrBins / 2;
// we only draw 40 bins, since we want the bass part
for(var i = 0; i < 40; i++) {
let avg = 0;
for(var j = 0; j < stepSize; j++) {
avg += arr[i*stepSize+j];
}
avg = Math.floor(avg / 8 / fftMult);
ctx.fillRect(i*10, height, 5, -avg);
}
}
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);