This page is a complete browser-based JavaScript music visualizer. It uses ordinary HTML for the controls, CSS for the dark glass-style interface, the Canvas API for drawing, and the Web Audio API for reading sound from an audio file or the microphone.
Creates the sidebar controls, audio file picker, microphone button, range sliders, statistics panel and canvas drawing area.
Creates the two-column layout, dark background, rounded cards, responsive mobile layout and high-contrast focus states.
Draws rings, waves, spirals, radial bars and particles for every animation frame.
Converts sound into frequency and waveform arrays that JavaScript can use for animation.
The page starts with the usual document structure: <!DOCTYPE html>, <html>,
<head> and <body>. The head contains the title, description, Open Graph
tags, Twitter Card tags, analytics, advertisement script, CSS and structured data. The body contains the header
placeholder, the visualizer app and the footer placeholder.
The left sidebar is an <aside>. It contains the audio controls and settings. The user can
choose microphone input, stop the input, choose a file, change the visualizer mode, change sensitivity, change
trail/fade, change zoom and save the current canvas frame as a PNG image.
<button id="micBtn">Use Microphone</button>
<input id="fileInput" type="file" accept="audio/*">
<select id="mode">...</select>
<input id="sens" type="range" min="0.5" max="3" step="0.1">
The main visual area is a <canvas>. Canvas is like a programmable drawing board. JavaScript
gets the drawing context with canvas.getContext("2d"). After that, it can draw lines, circles, arcs,
particles and backgrounds.
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
The function resizeCanvas() reads the visible size of the canvas and multiplies it by the device
pixel ratio. This makes the animation sharper on high-resolution screens. Without this step, the canvas can look
blurry.
const dpr = Math.max(1, window.devicePixelRatio || 1);
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
The Web Audio API begins with an AudioContext. Inside it, this page creates an
AnalyserNode. The analyser does not understand music emotionally. It simply gives numerical data:
frequency values and waveform values.
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
analyser = audioCtx.createAnalyser();
analyser.fftSize = 2048;
analyser.smoothingTimeConstant = 0.82;
fftSize controls how much audio data is analyzed at once. A larger value gives more detailed
frequency data. smoothingTimeConstant makes the movement less jumpy.
When the user chooses an audio file, the page creates a temporary browser URL with
URL.createObjectURL(file). The audio player plays that file, and JavaScript connects it to the
analyser. The file stays inside the browser session.
const url = URL.createObjectURL(file);
audioPlayer.src = url;
audioPlayer.play();
When the user clicks the microphone button, the browser asks for permission. If permission is granted,
navigator.mediaDevices.getUserMedia() gives a microphone stream. That stream is connected to the
analyser. The page uses the data for drawing only.
micStream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: false
});
sourceNode = audioCtx.createMediaStreamSource(micStream);
sourceNode.connect(analyser);
The page uses two arrays. dataArray stores frequency data. Low indexes roughly represent low sounds,
and higher indexes represent higher sounds. timeArray stores waveform data, which is useful for
drawing wave lines.
analyser.getByteFrequencyData(dataArray);
analyser.getByteTimeDomainData(timeArray);
The page calculates volume by averaging the frequency array. Bass, mid and treble are calculated by averaging different sections of that array. This is not studio-grade audio engineering, but it is perfect for a learning visualizer.
volume = average of all frequency values
bass = average of low frequency values
mid = average of middle frequency values
treble = average of higher frequency values
The ring visualizer draws circles from the center of the canvas. Louder sound increases the circle radius and line width. Bass makes the rings feel heavier. Treble changes brightness.
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
ctx.stroke();
The wave visualizer uses waveform data. Each waveform value becomes a point on a line. The result looks like a moving sound wave across the screen.
const centered = (waveformValue - 128) / 128;
const y = h / 2 + centered * amplitude;
The radial bars visualizer places many small lines around a circle. Each line uses one part of the frequency array. Higher frequency values create longer bars.
const angle = (i / bars) * Math.PI * 2;
const x1 = cx + Math.cos(angle) * radius;
const y1 = cy + Math.sin(angle) * radius;
The particles are small circles with positions and velocities. Music energy pushes them around. When they leave one side of the canvas, they re-enter from the opposite side.
p.x += p.vx;
p.y += p.vy;
if (p.x < 0) p.x = width;
The function render() is the heart of the page. It reads fresh audio metrics, updates the visible
statistics, fades the old frame, draws the selected visualizer and then asks the browser to call it again using
requestAnimationFrame().
function render() {
const m = getMetrics();
drawBackground(fade);
drawSelectedVisualizer(m);
requestAnimationFrame(render);
}
The save button converts the current canvas picture into a PNG data URL. Then JavaScript creates a temporary download link and clicks it.
const a = document.createElement("a");
a.href = canvas.toDataURL("image/png");
a.download = "visualizer-frame.png";
a.click();
Modern browsers usually require a real user click before entering fullscreen. That is why this page uses clear Full Screen buttons instead of forcing fullscreen automatically after a timer. One button is in the sidebar and another is placed over the canvas so it remains easy to find. In fullscreen mode, an Exit Full Screen button appears over the canvas.