Web Audio Synthesizers, 60fps Canvas Visualizers & Decibel SPL Engineering
How we built hardware-accelerated 60fps canvas audio renderers, multi-oscillator polyphonic synths with ADSR envelopes, and real-time microphone decibel sound pressure level meters.
Key Architectural Takeaways
1. Web Audio Polyphony & ADSR Envelope Shaping
Triggering raw oscillator frequencies abruptly produces harsh electrical click artifacts because the audio waveform starts or ends at a non-zero amplitude crossing. To achieve musical warmth, every voice passes through an Attack-Decay-Sustain-Release (ADSR) gain node curve:
// Smooth ADSR Envelope Ramp
const now = ctx.currentTime;
gainNode.gain.setValueAtTime(0, now);
// Attack: 0 -> 1.0
gainNode.gain.linearRampToValueAtTime(1.0, now + envelope.attack);
// Decay: 1.0 -> Sustain Level
gainNode.gain.linearRampToValueAtTime(
envelope.sustain,
now + envelope.attack + envelope.decay
);
// Release: Sustain Level -> 0
export function triggerRelease(gainNode: GainNode, releaseTime: number, now: number) {
gainNode.gain.cancelScheduledValues(now);
gainNode.gain.setValueAtTime(gainNode.gain.value, now);
gainNode.gain.linearRampToValueAtTime(0, now + releaseTime);
}2. 60fps Canvas Visualizer Algorithms
The CanvasAudioVisualizer connects directly to an AnalyserNode, computing frequency bins and time-domain waveforms per animation frame with High-DPI Retina scaling:
Equalizer Bars
Multi-stop linear gradient spectrum bars with independent gravity-decay peak markers.
Retro LED Blocks
Quantized vertical block matrix transitioning from Cyan (bass) to Fuchsia (mids) to Red (clipping).
Pulsing Aura Circle
Radial gradient breathing aura tied to bass energy with smooth circular waveform perimeter.
Lissajous Oscilloscope
Real-time XY phase projection rendering beam traces like a cathode-ray tube oscilloscope.
3. Root Mean Square (RMS) Decibel SPL Metering
Measuring sound pressure levels from a microphone input requires computing the Root Mean Square (RMS) of the raw time-domain PCM samples and converting them against the standard acoustic reference level (20 µPa):
export function calculateDecibels(timeData: Uint8Array, calibrationOffset = 0): number {
let sum = 0;
for (let i = 0; i < timeData.length; i++) {
const amplitude = (timeData[i] - 128) / 128; // Normalize to -1.0 .. +1.0
sum += amplitude * amplitude;
}
const rms = Math.sqrt(sum / timeData.length);
if (rms <= 0.000001) return 0;
const referenceLevel = 0.00002;
const rawDb = 20 * Math.log10(rms / referenceLevel);
return Math.round(Math.max(0, Math.min(140, rawDb + calibrationOffset)));
}Available Open Source on npm & GitHub
Install @epheos/audio-canvas to integrate 60fps canvas visualizers and Web Audio synths into your apps.
