Effects
Shape your audio with filters, gain effects, and custom audio processing. This page covers the built-in effects, effect chains, and integrating external effect libraries.
Try It: Real-Time Filter Control
Experiment with different filter types and parameters. Try switching between the oscillator and white noise sources to hear how filters affect different signals.
Effect Types
EZ Web Audio provides two built-in effect types and a wrapper for external effects:
| Effect | Purpose | Use Cases |
|---|---|---|
FilterEffect | Frequency-based tone shaping | EQ, bass boost, removing harshness |
GainEffect | Volume control in effect chain | Ducking, sidechain, level matching |
EffectWrapper | Wrap external effects | Tuna.js, custom AudioNodes |
FilterEffect
Filters modify the frequency content of audio. The FilterEffect wraps the Web Audio BiquadFilterNode with wet/dry mixing and bypass controls.
Filter Types
| Type | Description | Key Parameters |
|---|---|---|
lowpass | Passes frequencies below cutoff | frequency, q |
highpass | Passes frequencies above cutoff | frequency, q |
bandpass | Passes frequencies around center | frequency, q |
lowshelf | Boosts/cuts below frequency | frequency, gain |
highshelf | Boosts/cuts above frequency | frequency, gain |
peaking | Boosts/cuts around frequency | frequency, q, gain |
notch | Removes specific frequency | frequency, q |
allpass | Phase shift at frequency | frequency, q |
Creating Filters
import { createFilterEffect, createSound } from 'ez-web-audio'
const sound = await createSound('/audio/music.mp3')
// Lowpass filter - remove high frequencies
const lowpass = createFilterEffect('lowpass', {
frequency: 1000, // Cutoff frequency in Hz
q: 1 // Resonance (default: 1)
})
sound.addEffect(lowpass)
sound.play()Adjusting Filter Parameters
const filter = createFilterEffect('lowpass', { frequency: 800 })
// Adjust parameters in real-time
filter.frequency = 1200 // Move cutoff higher
filter.q = 4 // Increase resonance
// For shelf and peaking filters
const shelf = createFilterEffect('highshelf', {
frequency: 3000,
gain: 6 // Boost by 6dB
})Common Filter Recipes
Bass Boost
const bassBoost = createFilterEffect('lowshelf', {
frequency: 200,
gain: 8 // +8dB boost below 200Hz
})Remove Harsh Frequencies
const deHarsh = createFilterEffect('lowpass', {
frequency: 8000,
q: 0.7 // Gentle rolloff
})Telephone/Radio Effect
// Remove lows
const highpass = createFilterEffect('highpass', {
frequency: 300
})
// Remove highs
const lowpass = createFilterEffect('lowpass', {
frequency: 3400
})
sound.addEffect(highpass)
sound.addEffect(lowpass)Notch Filter (Remove Hum)
const removeHum = createFilterEffect('notch', {
frequency: 60, // 60Hz power line hum
q: 30 // Narrow notch
})GainEffect
GainEffect provides volume control within the effect chain. Unlike the sound's built-in gain, this can be positioned anywhere in the effect chain.
import { createGainEffect } from 'ez-web-audio'
const gainEffect = createGainEffect(0.5) // 50% volume
// Adjust volume
gainEffect.value = 0.8 // 80% volume
gainEffect.value = 1.5 // 150% (boost)Gain Before vs After Filter
// Gain BEFORE filter: affects what goes into the filter
const preGain = createGainEffect(2.0)
const filter = createFilterEffect('lowpass', { frequency: 1000 })
sound.addEffect(preGain) // First: boost signal
sound.addEffect(filter) // Second: filter boosted signal
// Gain AFTER filter: affects final output
const postGain = createGainEffect(0.5)
sound.addEffect(filter)
sound.addEffect(postGain)Effect Chains
Effects are processed in order. The audio signal flows through each effect sequentially.
Audio Source -> Effect 1 -> Effect 2 -> Effect 3 -> Gain -> Pan -> DestinationBuilding an Effect Chain
const sound = await createSound('/audio/sample.mp3')
// Create effects
const highpass = createFilterEffect('highpass', { frequency: 80 })
const lowpass = createFilterEffect('lowpass', { frequency: 8000 })
const boost = createGainEffect(1.2)
// Add in order (highpass first, then lowpass, then boost)
sound.addEffect(highpass)
sound.addEffect(lowpass)
sound.addEffect(boost)
sound.play()Managing Effects
// Get current effects
const effects = sound.getEffects()
console.log(`${effects.length} effects in chain`)
// Remove a specific effect
sound.removeEffect(lowpass)
// Insert effect at specific position
const newEffect = createFilterEffect('peaking', { frequency: 1000 })
sound.addEffect(newEffect, 0) // Insert at beginningBypass and Mix Controls
Every effect supports bypass (on/off) and mix (wet/dry blend):
const filter = createFilterEffect('lowpass', { frequency: 800 })
// Bypass: temporarily disable the effect
filter.bypass = true // Effect is bypassed (100% dry signal)
filter.bypass = false // Effect is active
// Mix: blend between dry (original) and wet (processed) signal
filter.mix = 0 // 0% wet = original signal only
filter.mix = 0.5 // 50% wet = equal blend
filter.mix = 1 // 100% wet = fully processed (default)Wet/Dry Mixing
The mix control uses equal-power crossfade for natural-sounding blending. This prevents volume dips when mixing between dry and wet signals.
Toggling Effects On/Off
const filter = createFilterEffect('lowpass', { frequency: 800 })
sound.addEffect(filter)
// Toggle effect bypass
function toggleFilter() {
filter.bypass = !filter.bypass
// When bypass changes, call rewireEffects if needed
sound.rewireEffects()
}External Effects with wrapEffect
Use wrapEffect to integrate effects from external libraries (like Tuna.js) or custom AudioNodes.
Wrapping a WaveShaper (Distortion)
import { getAudioContext, wrapEffect } from 'ez-web-audio'
const ctx = await getAudioContext()
// Create a WaveShaperNode for distortion
const distortion = ctx.createWaveShaper()
distortion.curve = makeDistortionCurve(400)
distortion.oversample = '4x'
// Wrap it to get bypass/mix controls
const wrapped = wrapEffect(ctx, distortion)
wrapped.mix = 0.7 // 70% distortion
sound.addEffect(wrapped)Wrapping Tuna.js Effects
Tuna.js provides additional effects like chorus, phaser, and tremolo.
import { getAudioContext, wrapEffect } from 'ez-web-audio'
import Tuna from 'tunajs'
const ctx = await getAudioContext()
const tuna = new Tuna(ctx)
// Create a chorus effect
const chorus = new tuna.Chorus({
rate: 1.5,
feedback: 0.2,
delay: 0.0045,
bypass: false
})
// Wrap it for standard Effect interface
const wrapped = wrapEffect(ctx, chorus)
wrapped.mix = 0.5 // 50% chorus blend
sound.addEffect(wrapped)
// Access original effect parameters
wrapped.effect.rate = 2.0 // Adjust Tuna's parametersThe ExternalEffect Interface
Any object with a connect() method can be wrapped:
interface ExternalEffect {
connect: (destination: AudioNode) => void
}This includes:
- Native AudioNodes (WaveShaperNode, ConvolverNode, DelayNode)
- Tuna.js effects
- Custom effect chains
- Third-party Web Audio libraries
Using an Analyzer for Visualization
Attach an Analyzer to visualize the processed audio signal:
import { createAnalyzer, createFilterEffect, createSound, getAudioContext } from 'ez-web-audio'
const sound = await createSound('/audio/music.mp3')
const ctx = await getAudioContext()
// Add effects
const filter = createFilterEffect('lowpass', { frequency: 2000 })
sound.addEffect(filter)
// Create and attach analyzer
const analyzer = createAnalyzer(ctx, {
fftSize: 2048,
smoothingTimeConstant: 0.8
})
sound.setAnalyzer(analyzer)
// Get frequency data for visualization
const dataArray = new Uint8Array(analyzer.frequencyBinCount)
function draw() {
requestAnimationFrame(draw)
analyzer.getByteFrequencyData(dataArray)
// Use dataArray to draw visualization
}
sound.play()
draw()Analyzer Position
The analyzer is always at the end of the signal chain (after all effects, gain, and pan). This means it visualizes the fully processed audio that you hear.
Complete Example: DJ-Style EQ
import { createFilterEffect, createTrack } from 'ez-web-audio'
const track = await createTrack('/audio/song.mp3')
// Three-band EQ
const lowEQ = createFilterEffect('lowshelf', {
frequency: 320,
gain: 0 // Will be adjusted by user
})
const midEQ = createFilterEffect('peaking', {
frequency: 1000,
q: 0.5,
gain: 0
})
const highEQ = createFilterEffect('highshelf', {
frequency: 3200,
gain: 0
})
track.addEffect(lowEQ)
track.addEffect(midEQ)
track.addEffect(highEQ)
// Adjust EQ from UI sliders
function updateEQ(band: 'low' | 'mid' | 'high', dB: number) {
switch (band) {
case 'low': lowEQ.gain = dB; break
case 'mid': midEQ.gain = dB; break
case 'high': highEQ.gain = dB; break
}
}
track.play()Next Steps
- Basic Playback - Load and play audio files
- Synthesis - Generate sounds with oscillators
- Audio Routing - Connect sounds to custom effects
- Synth Drum Kit - Build synthesized percussion
- Core Concepts - Understand the audio system architecture