Skip to content

EZ Web Audio / DistortionEffect

Class: DistortionEffect

Defined in: packages/core/src/effects/distortion-effect.ts:110

DistortionEffect - WaveShaper-based distortion with selectable curve types and tone control.

Supports four built-in curve types (soft, hard, fuzz, overdrive) plus custom curves. Includes a post-distortion tone control (lowpass filter) to shape the output. Uses 4x oversampling by default to prevent aliasing artifacts.

Extends BaseEffect for shared wet/dry mixing, bypass, and rampTo() functionality.

Example

typescript
import { createDistortion, createSound } from 'ez-web-audio'

const sound = await createSound('guitar.mp3')
const dist = createDistortion({ type: 'overdrive', amount: 50, tone: 0.6, mix: 0.7 })
sound.addEffect(dist)
sound.play()

// Real-time control
dist.amount = 80
dist.tone = 0.3  // Darker tone
dist.type = 'fuzz'  // Switch curve type

Extends

Constructors

Constructor

new DistortionEffect(audioContext, options): DistortionEffect

Defined in: packages/core/src/effects/distortion-effect.ts:131

Parameters

audioContext

AudioContext

options

DistortionOptions = {}

Returns

DistortionEffect

Overrides

BaseEffect.constructor

Accessors

amount

Get Signature

get amount(): number

Defined in: packages/core/src/effects/distortion-effect.ts:203

Distortion amount (0-100).

M8 fix (dual-waveshaper crossfade): curve is a plain array property, not an AudioParam, so it can't be smoothed with setTargetAtTime the way every other effect parameter in this library is — a synchronous swap on a single WaveShaperNode is a hard discontinuity in the transfer function and clicks if audio is actively flowing through it. This setter instead writes the new curve into the currently-inactive of two parallel WaveShaperNodes, then crossfades the two nodes' gains over ~15ms via setTargetAtTime so the swap is masked rather than heard. See crossfadeToCurve. The crossfade is entirely internal — amount still isn't rampable via rampTo() (it's not a single AudioParam), but ordinary synchronous sets like effect.amount = 80 are now click-free at knob-drag rates, including rapid successive changes mid-crossfade.

Returns

number

Set Signature

set amount(v): void

Defined in: packages/core/src/effects/distortion-effect.ts:207

Parameters
v

number

Returns

void


bypass

Get Signature

get bypass(): boolean

Defined in: packages/core/src/effects/base-effect.ts:95

When true, signal bypasses the effect entirely (100% dry).

Returns

boolean

Set Signature

set bypass(v): void

Defined in: packages/core/src/effects/base-effect.ts:99

When true, effect is bypassed (passthrough)

Parameters
v

boolean

Returns

void

When true, effect is bypassed (passthrough)

Inherited from

BaseEffect.bypass


input

Get Signature

get input(): AudioNode

Defined in: packages/core/src/effects/base-effect.ts:83

The input AudioNode (receives signal from chain)

Returns

AudioNode

The input AudioNode that receives signal from the chain

Inherited from

BaseEffect.input


mix

Get Signature

get mix(): number

Defined in: packages/core/src/effects/base-effect.ts:108

Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (all through effect). Uses equal-power crossfade for natural mixing.

Returns

number

Set Signature

set mix(v): void

Defined in: packages/core/src/effects/base-effect.ts:112

Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect)

Parameters
v

number

Returns

void

Wet/dry mix: 0 = fully dry (no effect), 1 = fully wet (full effect)

Inherited from

BaseEffect.mix


output

Get Signature

get output(): AudioNode

Defined in: packages/core/src/effects/base-effect.ts:88

The output AudioNode (sends signal to next in chain)

Returns

AudioNode

The output AudioNode that sends signal to the next in chain

Inherited from

BaseEffect.output


oversample

Get Signature

get oversample(): OverSampleType

Defined in: packages/core/src/effects/distortion-effect.ts:249

Oversampling mode for aliasing prevention

Returns

OverSampleType

Set Signature

set oversample(v): void

Defined in: packages/core/src/effects/distortion-effect.ts:253

Parameters
v

OverSampleType

Returns

void


tone

Get Signature

get tone(): number

Defined in: packages/core/src/effects/distortion-effect.ts:239

Post-distortion tone control (0 = dark/200Hz, 1 = bright/8000Hz)

Returns

number

Set Signature

set tone(v): void

Defined in: packages/core/src/effects/distortion-effect.ts:243

Parameters
v

number

Returns

void


type

Get Signature

get type(): DistortionType

Defined in: packages/core/src/effects/distortion-effect.ts:220

Distortion curve type.

M8 fix: same dual-waveshaper crossfade as amount — see its JSDoc for the full explanation.

Returns

DistortionType

Set Signature

set type(v): void

Defined in: packages/core/src/effects/distortion-effect.ts:224

Parameters
v

DistortionType

Returns

void

Methods

_clearListeners()

protected _clearListeners(): void

Defined in: packages/core/src/events/typed-event-emitter.ts:192

Remove every listener registered through this emitter (via addEventListener(), on(), or once()), regardless of how many or what event type they're bound to.

Native EventTarget has no removeAllListeners(). This works around that by aborting a shared AbortSignal threaded through every addEventListener() call this class makes, then swapping in a fresh AbortController so the instance can keep accepting new listeners afterward (e.g. if it's reused before being garbage collected).

Subclasses call this from their dispose() alongside neutering dispatchEvent — the neuter stops future emits, this stops stale listener closures from being retained/invoked at all.

Returns

void

Inherited from

BaseEffect._clearListeners


addEventListener()

Call Signature

addEventListener<K>(type, listener, options?): void

Defined in: packages/core/src/events/typed-event-emitter.ts:44

Add a typed event listener for known event types. Overloaded to provide type safety for known event types while remaining compatible with the native EventTarget API.

Type Parameters
K

K extends "dispose"

Parameters
type

K

The event type (key of TMap)

listener

(event) => void

Typed event handler

options?

Standard addEventListener options

boolean | AddEventListenerOptions

Returns

void

Inherited from

BaseEffect.addEventListener

Call Signature

addEventListener(type, listener, options?): void

Defined in: packages/core/src/events/typed-event-emitter.ts:49

Add a typed event listener for known event types. Overloaded to provide type safety for known event types while remaining compatible with the native EventTarget API.

Parameters
type

string

The event type (key of TMap)

listener

Typed event handler

EventListenerOrEventListenerObject | null

options?

Standard addEventListener options

boolean | AddEventListenerOptions

Returns

void

Inherited from

BaseEffect.addEventListener


dispose()

dispose(): void

Defined in: packages/core/src/effects/distortion-effect.ts:258

Disconnect all internal audio nodes and emit a 'dispose' event.

Subclass disposal contract: Subclasses that create additional audio nodes (e.g., BiquadFilterNode, DynamicsCompressorNode, WaveShaperNode) MUST override dispose() to disconnect those nodes before calling super.dispose().

Returns

void

Example

typescript
public override dispose(): void {
  try { this.myNode.disconnect() } catch { /* already disconnected */ }
  super.dispose()
}

Idempotent — safe to call multiple times.

Overrides

BaseEffect.dispose


emit()

protected emit<K>(type, detail): void

Defined in: packages/core/src/events/typed-event-emitter.ts:95

Emit a typed event with the given detail.

Creates a CustomEvent with the provided detail and dispatches it on this target. Subclasses call this internally to fire lifecycle events.

Type Parameters

K

K extends "dispose"

Parameters

type

K

The event type to emit (key of TMap)

detail

BaseEffectEventMap[K]["detail"]

The event detail object (typed by TMap)

Returns

void

Inherited from

BaseEffect.emit


getAudioContext()

getAudioContext(): AudioContext

Defined in: packages/core/src/effects/base-effect.ts:121

Get the AudioContext used by this effect. Useful for external tools (e.g., LFO) that need the context.

Returns

AudioContext

Inherited from

BaseEffect.getAudioContext


getAudioParam()

protected getAudioParam(name): AudioParam | null

Defined in: packages/core/src/effects/distortion-effect.ts:282

Map a parameter name to its underlying AudioParam. Subclasses implement this to expose their effect-specific parameters.

Parameters

name

string

The parameter name

Returns

AudioParam | null

The AudioParam, or null if not recognized

Overrides

BaseEffect.getAudioParam


getParam()

getParam(name): AudioParam | null

Defined in: packages/core/src/effects/base-effect.ts:134

Get a named AudioParam from this effect for external modulation.

Delegates to the subclass's getAudioParam() implementation. Returns null if the parameter name is not recognized.

Parameters

name

string

The parameter name (e.g., 'frequency', 'time', 'feedback')

Returns

AudioParam | null

The AudioParam, or null if not recognized

Inherited from

BaseEffect.getParam


getUnrampableParams()

protected getUnrampableParams(): readonly string[]

Defined in: packages/core/src/effects/distortion-effect.ts:298

amount and type are documented DistortionEffect properties but aren't backed by a single AudioParam — they drive a curve swap on one of two internal WaveShaperNodes, crossfaded via crossfadeToCurve() (see the M8 JSDoc on those setters). That crossfade is internal machinery, not something rampTo() can drive over an arbitrary caller duration, so rampTo() warns rather than silently no-op-ing if called with either name.

Returns

readonly string[]

Overrides

BaseEffect.getUnrampableParams


off()

off<K>(type, listener): this

Defined in: packages/core/src/events/typed-event-emitter.ts:167

Unsubscribe from an event.

Note: Due to native EventTarget limitations, you must provide the same listener function reference that was used when subscribing.

Type Parameters

K

K extends "dispose"

Parameters

type

K

The event type to unsubscribe from

listener

(event) => void

The event handler function to remove

Returns

this

this for chaining

Example

typescript
const handler = (e) => console.log(e.detail)
emitter.on('play', handler)
// later...
emitter.off('play', handler)

Inherited from

BaseEffect.off


on()

on<K>(type, listener): this

Defined in: packages/core/src/events/typed-event-emitter.ts:116

Subscribe to one or more events. Supports chaining.

Type Parameters

K

K extends "dispose"

Parameters

type

The event type(s) to subscribe to (key or array of keys of TMap)

K | K[]

listener

(event) => void

The event handler function

Returns

this

this for chaining

Example

typescript
emitter.on('play', handlePlay).on('stop', handleStop)
emitter.on(['play', 'stop'], handleBoth)

Inherited from

BaseEffect.on


once()

once<K>(type, listener): this

Defined in: packages/core/src/events/typed-event-emitter.ts:141

Subscribe to an event once. Handler is removed after first invocation.

Type Parameters

K

K extends "dispose"

Parameters

type

K

The event type to subscribe to

listener

(event) => void

The event handler function

Returns

this

this for chaining

Example

typescript
emitter.once('end', () => console.log('Finished'))

Inherited from

BaseEffect.once


onParamRamped()

protected onParamRamped(param, value): number

Defined in: packages/core/src/effects/distortion-effect.ts:312

ramp-setter-desync fix: tone's public domain is 0-1 (mapped exponentially to the toneFilter's Hz range by applyTone()), but getAudioParam('tone') exposes the underlying Hz-valued AudioParam directly — before this fix, rampTo('tone', v, duration) wrote the raw 0-1 v straight into the Hz AudioParam (e.g. rampTo('tone', 0.8, 1) set the filter to 0.8 Hz, not ~3.5kHz), silently diverging from what effect.tone = 0.8 actually does. This re-applies the exact same clamp + Hz mapping the tone setter uses, so both paths agree.

Parameters

param

string

value

number

Returns

number

Overrides

BaseEffect.onParamRamped


rampTo()

rampTo(param, value, duration): void

Defined in: packages/core/src/effects/base-effect.ts:164

Smoothly ramp a parameter to a target value over a duration.

Uses AudioParam.setTargetAtTime for glitch-free transitions. If the parameter name is not recognized, this is a no-op (a console.warn is emitted if the name is a real, documented effect property that just isn't backed by a single AudioParam — see getUnrampableParams).

Single write path: every ramped write is funneled through onParamRamped, the same hook subclasses use to keep their shadow getters honest. This guarantees effect.someParam reflects the ramp target immediately after calling rampTo(), and that the exact same validation/clamping a synchronous property-set would apply is also applied to ramped writes — the AudioParam and the getter can never diverge from each other.

Parameters

param

string

Parameter name (e.g., 'frequency', 'time', 'feedback')

value

number

Target value

duration

number

Ramp duration in seconds

Returns

void

Example

typescript
delay.rampTo('time', 0.5, 2)      // Ramp delay time to 0.5s over 2 seconds
filter.rampTo('frequency', 800, 1) // Ramp cutoff to 800Hz over 1 second

Inherited from

BaseEffect.rampTo


removeEventListener()

Call Signature

removeEventListener<K>(type, listener, options?): void

Defined in: packages/core/src/events/typed-event-emitter.ts:70

Remove a typed event listener for known event types. Overloaded to provide type safety for known event types while remaining compatible with the native EventTarget API.

Type Parameters
K

K extends "dispose"

Parameters
type

K

The event type (key of TMap)

listener

(event) => void

Typed event handler to remove

options?

Standard removeEventListener options

boolean | EventListenerOptions

Returns

void

Inherited from

BaseEffect.removeEventListener

Call Signature

removeEventListener(type, listener, options?): void

Defined in: packages/core/src/events/typed-event-emitter.ts:75

Remove a typed event listener for known event types. Overloaded to provide type safety for known event types while remaining compatible with the native EventTarget API.

Parameters
type

string

The event type (key of TMap)

listener

Typed event handler to remove

EventListenerOrEventListenerObject | null

options?

Standard removeEventListener options

boolean | EventListenerOptions

Returns

void

Inherited from

BaseEffect.removeEventListener