Changed around line 1
+ document.addEventListener('DOMContentLoaded', () => {
+ const canvas = document.getElementById('visualizer');
+ const ctx = canvas.getContext('2d');
+ const audioInput = document.getElementById('audio-upload');
+ const playBtn = document.getElementById('play-btn');
+ const progressBar = document.querySelector('.progress');
+
+ let audioContext;
+ let analyser;
+ let source;
+ let audioElement;
+ let animationId;
+ let isPlaying = false;
+
+ function initAudio() {
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
+ analyser = audioContext.createAnalyser();
+ analyser.fftSize = 256;
+ }
+
+ function handleFile(file) {
+ const reader = new FileReader();
+ reader.onload = (e) => {
+ if (audioElement) {
+ audioElement.pause();
+ URL.revokeObjectURL(audioElement.src);
+ }
+
+ audioElement = new Audio();
+ audioElement.src = URL.createObjectURL(file);
+
+ source = audioContext.createMediaElementSource(audioElement);
+ source.connect(analyser);
+ analyser.connect(audioContext.destination);
+
+ playBtn.disabled = false;
+
+ audioElement.addEventListener('timeupdate', () => {
+ const progress = (audioElement.currentTime / audioElement.duration) * 100;
+ progressBar.style.width = `${progress}%`;
+ });
+ };
+ reader.readAsArrayBuffer(file);
+ }
+
+ function visualize() {
+ canvas.width = canvas.offsetWidth;
+ canvas.height = canvas.offsetHeight;
+
+ const bufferLength = analyser.frequencyBinCount;
+ const dataArray = new Uint8Array(bufferLength);
+
+ function draw() {
+ animationId = requestAnimationFrame(draw);
+
+ analyser.getByteFrequencyData(dataArray);
+
+ ctx.fillStyle = 'rgba(42, 8, 69, 0.2)';
+ 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] * 2;
+
+ const gradient = ctx.createLinearGradient(0, canvas.height - barHeight, 0, canvas.height);
+ gradient.addColorStop(0, '#f72585');
+ gradient.addColorStop(1, '#6441A5');
+
+ ctx.fillStyle = gradient;
+ ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
+
+ x += barWidth + 1;
+ }
+ }
+
+ draw();
+ }
+
+ playBtn.addEventListener('click', () => {
+ if (!isPlaying) {
+ audioElement.play();
+ visualize();
+ playBtn.querySelector('.play-icon').style.borderStyle = 'double';
+ } else {
+ audioElement.pause();
+ cancelAnimationFrame(animationId);
+ playBtn.querySelector('.play-icon').style.borderStyle = 'solid';
+ }
+ isPlaying = !isPlaying;
+ });
+
+ audioInput.addEventListener('change', (e) => {
+ if (e.target.files[0]) {
+ if (!audioContext) initAudio();
+ handleFile(e.target.files[0]);
+ }
+ });
+ });