Changed around line 1
+ class AudioVisualizer {
+ constructor() {
+ this.canvas = document.getElementById('visualizer');
+ this.ctx = this.canvas.getContext('2d');
+ this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
+ this.analyser = this.audioContext.createAnalyser();
+ this.dataArray = new Uint8Array(this.analyser.frequencyBinCount);
+ this.isPlaying = false;
+ this.animationId = null;
+ this.currentVizType = 'bars';
+
+ this.setupEventListeners();
+ this.resizeCanvas();
+ window.addEventListener('resize', () => this.resizeCanvas());
+ }
+
+ resizeCanvas() {
+ this.canvas.width = this.canvas.offsetWidth * window.devicePixelRatio;
+ this.canvas.height = this.canvas.offsetHeight * window.devicePixelRatio;
+ this.ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
+ }
+
+ setupEventListeners() {
+ document.getElementById('audioFile').addEventListener('change', (e) => this.loadAudio(e));
+ document.getElementById('playBtn').addEventListener('click', () => this.play());
+ document.getElementById('pauseBtn').addEventListener('click', () => this.pause());
+ document.getElementById('stopBtn').addEventListener('click', () => this.stop());
+ document.getElementById('vizType').addEventListener('change', (e) => {
+ this.currentVizType = e.target.value;
+ });
+ document.getElementById('primaryColor').addEventListener('change', (e) => {
+ document.documentElement.style.setProperty('--primary', e.target.value);
+ });
+ document.getElementById('secondaryColor').addEventListener('change', (e) => {
+ document.documentElement.style.setProperty('--secondary', e.target.value);
+ });
+ document.getElementById('darkModeBtn').addEventListener('click', () => {
+ document.body.dataset.theme = document.body.dataset.theme === 'dark' ? 'light' : 'dark';
+ });
+ document.getElementById('fullscreenBtn').addEventListener('click', () => {
+ if (!document.fullscreenElement) {
+ document.documentElement.requestFullscreen();
+ } else {
+ document.exitFullscreen();
+ }
+ });
+ }
+
+ async loadAudio(event) {
+ const file = event.target.files[0];
+ if (file) {
+ const buffer = await file.arrayBuffer();
+ this.audioBuffer = await this.audioContext.decodeAudioData(buffer);
+ this.source = this.audioContext.createBufferSource();
+ this.source.buffer = this.audioBuffer;
+ this.source.connect(this.analyser);
+ this.analyser.connect(this.audioContext.destination);
+ }
+ }
+
+ play() {
+ if (this.source && !this.isPlaying) {
+ this.source = this.audioContext.createBufferSource();
+ this.source.buffer = this.audioBuffer;
+ this.source.connect(this.analyser);
+ this.source.start(0);
+ this.isPlaying = true;
+ this.animate();
+ }
+ }
+
+ pause() {
+ if (this.isPlaying) {
+ this.source.stop();
+ this.isPlaying = false;
+ cancelAnimationFrame(this.animationId);
+ }
+ }
+
+ stop() {
+ if (this.isPlaying) {
+ this.source.stop();
+ this.isPlaying = false;
+ cancelAnimationFrame(this.animationId);
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ }
+ }
+
+ animate() {
+ this.animationId = requestAnimationFrame(() => this.animate());
+ this.analyser.getByteFrequencyData(this.dataArray);
+
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+
+ switch(this.currentVizType) {
+ case 'bars':
+ this.drawBars();
+ break;
+ case 'waves':
+ this.drawWaves();
+ break;
+ case 'circles':
+ this.drawCircles();
+ break;
+ case 'particles':
+ this.drawParticles();
+ break;
+ }
+ }
+
+ drawBars() {
+ const barWidth = this.canvas.width / this.analyser.frequencyBinCount;
+ const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary');
+ const secondaryColor = getComputedStyle(document.documentElement).getPropertyValue('--secondary');
+
+ for(let i = 0; i < this.analyser.frequencyBinCount; i++) {
+ const barHeight = (this.dataArray[i] / 255) * this.canvas.height;
+ const gradient = this.ctx.createLinearGradient(0, this.canvas.height, 0, this.canvas.height - barHeight);
+ gradient.addColorStop(0, primaryColor);
+ gradient.addColorStop(1, secondaryColor);
+
+ this.ctx.fillStyle = gradient;
+ this.ctx.fillRect(i * barWidth, this.canvas.height - barHeight, barWidth - 1, barHeight);
+ }
+ }
+
+ // Additional visualization methods would be implemented here
+ // drawWaves(), drawCircles(), drawParticles()
+ }
+
+ document.addEventListener('DOMContentLoaded', () => {
+ new AudioVisualizer();
+ });