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);