ez-web-audio
Version:
Making the Web Audio API super EZ since 2024.
230 lines • 8.26 kB
TypeScript
import { TimeObject } from './utils/create-time-object';
import { ControlType, RampType } from './controllers/base-param-controller';
import { OscillatorController } from './controllers/oscillator-controller';
import { BaseSoundOptions, BaseSound } from './base-sound';
import { EnvelopeOptions } from './envelope';
/**
* Filter configuration for oscillator frequency shaping.
*/
export interface OscillatorOptsFilterValues {
/** Filter cutoff frequency in Hz. */
frequency?: number;
/** Filter Q factor (resonance). Higher values create more pronounced peaks. */
q?: number;
}
/**
* Configuration options for creating an Oscillator.
*
* @example
* ```typescript
* const opts: OscillatorOpts = {
* frequency: 440, // A4
* type: 'sawtooth', // Rich harmonic content
* gain: 0.5, // Half volume
* lowpass: { // Filter out harsh highs
* frequency: 2000,
* q: 1
* },
* envelope: { // ADSR for note shaping
* attack: 0.01,
* decay: 0.2,
* sustain: 0.5,
* release: 0.3
* }
* }
* ```
*/
export interface OscillatorOpts extends BaseSoundOptions {
/** Starting offset in seconds (rarely used for oscillators). */
startOffset?: number;
/** Base frequency in Hz (default: 440). */
frequency?: number;
/** Detune in cents (100 cents = 1 semitone). */
detune?: number;
/** Initial gain/volume (0-1). */
gain?: number;
/** Waveform type: 'sine', 'square', 'sawtooth', or 'triangle'. */
type?: OscillatorType;
/** Highpass filter - removes frequencies below cutoff. */
highpass?: OscillatorOptsFilterValues;
/** Bandpass filter - allows frequencies near cutoff, attenuates others. */
bandpass?: OscillatorOptsFilterValues;
/** Lowpass filter - removes frequencies above cutoff. */
lowpass?: OscillatorOptsFilterValues;
/** Lowshelf filter - boosts/cuts frequencies below cutoff. */
lowshelf?: OscillatorOptsFilterValues;
/** Highshelf filter - boosts/cuts frequencies above cutoff. */
highshelf?: OscillatorOptsFilterValues;
/** Peaking filter - boosts/cuts frequencies around cutoff. */
peaking?: OscillatorOptsFilterValues;
/** Notch filter - attenuates frequencies at cutoff. */
notch?: OscillatorOptsFilterValues;
/** Allpass filter - shifts phase without changing amplitude. */
allpass?: OscillatorOptsFilterValues;
/** ADSR envelope for amplitude shaping. */
envelope?: EnvelopeOptions;
}
/**
* Synthesizer that generates audio from oscillator waveforms.
*
* Oscillator creates sound from scratch using sine, square, sawtooth, or triangle
* waves. Supports ADSR envelopes for professional-quality synthesis, filters for
* tone shaping, and all the gain/pan controls from {@link BaseSound}.
*
* Unlike {@link Sound} which plays pre-recorded audio, Oscillator generates audio
* in real-time. Oscillators have infinite duration and must be explicitly stopped.
*
* @example
* ```typescript
* import { createOscillator } from 'ez-web-audio'
*
* // Simple sine wave at 440Hz (A4)
* const synth = await createOscillator({ frequency: 440, type: 'sine' })
* synth.play()
* setTimeout(() => synth.stop(), 500)
*
* // With ADSR envelope for piano-like decay
* const piano = await createOscillator({
* frequency: 440,
* type: 'triangle',
* envelope: { attack: 0.01, decay: 0.1, sustain: 0.7, release: 0.3 }
* })
* piano.play()
* setTimeout(() => piano.stop(), 500) // Release phase plays after stop
*
* // With lowpass filter
* const muted = await createOscillator({
* frequency: 440,
* type: 'sawtooth',
* lowpass: { frequency: 800, q: 1 }
* })
* muted.play()
* ```
*/
export declare class Oscillator extends BaseSound {
/** The underlying OscillatorNode that generates the audio signal. */
audioSourceNode: OscillatorNode;
/** Array of BiquadFilterNodes for frequency filtering. */
private filters;
/** Oscillator waveform type (sine, square, sawtooth, triangle). */
private type;
/** Base frequency in Hz. */
protected freq: number;
/** Controller for managing gain, pan, frequency, and detune parameters. */
protected controller: OscillatorController;
/** Optional ADSR envelope for amplitude shaping. */
private envelope?;
/**
* Create an Oscillator instance.
*
* Note: Use {@link createOscillator} factory function instead of calling this directly.
*
* @param audioContext - The AudioContext to use for audio operations
* @param options - Oscillator configuration (frequency, type, filters, envelope)
*/
constructor(audioContext: AudioContext, options?: OscillatorOpts);
/**
* Schedule a parameter value to be set when play() is called.
*
* Oscillator supports additional parameters beyond Sound:
* - 'gain': Volume level (0-1)
* - 'pan': Stereo position (-1 to 1)
* - 'frequency': Oscillator frequency in Hz
* - 'detune': Detune in cents
*
* @param type - The parameter to control
* @returns Fluent builder for setting value and timing
*
* @example
* ```typescript
* // Start at frequency 220, glide up to 440 over 0.5 seconds
* osc.onPlaySet('frequency').to(220).at(0)
* osc.onPlaySet('frequency').to(440).endingAt(0.5, 'linear')
* osc.play()
* ```
*/
onPlaySet(type: ControlType): {
to: (value: number) => {
at: (time: number) => void;
endingAt: (time: number, rampType?: RampType) => void;
};
};
/**
* Schedule a parameter ramp when play() is called.
*
* @param type - The parameter to ramp ('gain', 'pan', 'frequency', 'detune')
* @param rampType - Type of ramp curve ('linear' or 'exponential')
* @returns Fluent builder for setting start value, end value, and duration
*
* @example
* ```typescript
* // Vibrato effect: ramp frequency up and down
* osc.onPlayRamp('frequency', 'linear').from(440).to(450).in(0.1)
* osc.play()
* ```
*/
onPlayRamp(type: ControlType, rampType?: RampType): {
from: (startValue: number) => {
to: (endValue: number) => {
in: (endTime: number) => void;
};
};
};
/**
* Set up a fresh OscillatorNode for playback.
* Called automatically before each play() since OscillatorNode is single-use.
* @protected
*/
protected setup(): void;
/**
* Wire oscillator through filters and connections to effect chain.
* @protected
*/
protected wireConnections(): void;
/**
* Get the duration of the oscillator.
*
* Oscillators have no inherent duration - they play indefinitely until stopped.
* Returns Infinity to indicate continuous playback, distinguishing from finite
* Sound/Track durations.
*
* @example
* ```typescript
* const osc = await createOscillator({ frequency: 440 })
* console.log(osc.duration.raw) // Infinity
*
* // Oscillators must be explicitly stopped
* osc.play()
* setTimeout(() => osc.stop(), 1000)
* ```
*/
get duration(): TimeObject;
/**
* Stop the oscillator.
*
* If an ADSR envelope is configured, triggers the release phase and schedules
* the actual stop after the release completes. This ensures the release tail
* plays fully rather than being cut off abruptly.
*
* Note: stopAt() and stopIn() bypass the envelope release phase. For scheduled
* stops with proper release, use the regular stop() method.
*
* @example
* ```typescript
* // Without envelope - stops immediately
* const simple = await createOscillator({ frequency: 440 })
* simple.play()
* await simple.stop() // Immediate stop
*
* // With envelope - release phase plays
* const piano = await createOscillator({
* frequency: 440,
* envelope: { attack: 0.01, decay: 0.1, sustain: 0.7, release: 0.5 }
* })
* piano.play()
* await piano.stop() // Fades out over 0.5 seconds
* ```
*/
stop(): Promise<void>;
}
//# sourceMappingURL=oscillator.d.ts.map