audio visualizer (written primarily by chatgpt)

by Spencer Smith

HTML

<!DOCTYPE html>
<html>
<head>
    <title>MP3 Visualizer</title>
</head>
<body>
    <input type="file" id="fileInput" accept="audio/*">
    <audio id="audio" controls></audio>
    <canvas id="canvas"></canvas>
    <script src="visualizer.js"></script>
</body>
</html>

CSS

canvas {
  width: 200px;
  height: 200px;
}

body {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background-color: #f3f3f3;
  font-family: Arial, sans-serif;
}

#fileInputWrapper {
  margin-bottom: 20px;
  background-color: #fff;
  border-radius: 5px;
  padding: 10px;
  box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}

#audio {
  margin-bottom: 20px;
}

#canvas {
  box-shadow: 0 2px 5px rgba(0,0,0,0.2);
  width: 200px;
  height: 200px;
}

JavaScript

document.addEventListener('DOMContentLoaded', function() {
  const fileInput = document.getElementById('fileInput');
  const audio = document.getElementById('audio');
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');

  let audioContext;
  let analyser;
  let source;

  fileInput.addEventListener('change', function(e) {
    const file = e.target.files[0];
    if (audioContext) {
      audioContext.close(); // Close the previous AudioContext, if any
    }
    audioContext = new (window.AudioContext || window.webkitAudioContext)();
    analyser = audioContext.createAnalyser();

    audio.src = URL.createObjectURL(file);
    audio.load();
    audio.play();

    source = audioContext.createMediaElementSource(audio);
    source.connect(analyser);
    analyser.connect(audioContext.destination);

    visualize();
  });

  function visualize() {
    analyser.fftSize = 256;
    const bufferLength = analyser.frequencyBinCount;
    const dataArray = new Uint8Array(bufferLength);

    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    function draw() {
      requestAnimationFrame(draw);

      analyser.getByteFrequencyData(dataArray);

      ctx.fillStyle = 'rgb(0, 0, 0)';
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      const barWidth = (canvas.width / bufferLength) * 2.5;
      let barHeight;
      let x = 0;

      for (let i = 0; i < bufferLength; i++) {
        barHeight = dataArray[i];

        // Scale the bar height to fill the canvas
        const scaledHeight = (barHeight / 255) * canvas.height;

        ctx.fillStyle = 'rgb(' + (barHeight + 100) + ',50,50)';
        ctx.fillRect(x, canvas.height - scaledHeight, barWidth, scaledHeight);

        x += barWidth + 1;
      }
    }

    draw();
  }
});