Non-periodic replacement for OscillatorNode from Web Audio API
import {UnisonOscillator} from 'aperiodic-oscillator';
const context = new AudioContext();
const supersaw = new UnisonOscillator(context, {
type: 'sawtooth',
numberOfVoices: 5,
spread: 6.9,
frequency: 110,
});
const output = context.createGain();
output.gain.value = 0.2;
supersaw.connect(output);
output.connect(context.destination);
supersaw.start();
supersaw.stop(context.currentTime + 2);
import {AperiodicOscillator, AperiodicWave} from 'aperiodic-oscillator';
const context = new AudioContext();
const partials = Array.from({length: 128}, (_, i) => i + 1);
const spectrum = partials.map(n => n ** 1.5); // inharmonic partial ratios
const amplitudes = partials.map(n => 0.3 * n ** -1.5);
const timbre = new AperiodicWave(
context,
spectrum,
amplitudes,
7, // maxNumberOfVoices
0.1 // tolerance in cents
);
const tine = new AperiodicOscillator(context, {
aperiodicWave: timbre,
frequency: 220,
});
const output = context.createGain();
output.gain.value = 0.2;
tine.connect(output);
output.connect(context.destination);
// Optionally schedule a finite note.
tine.start();
tine.stop(context.currentTime + 2);
Browser autoplay note: Most browsers block audio until a user gesture occurs (for example, a button click). If you hear silence, create/resume the
AudioContextinside a click/tap handler.
The package exports four primary public classes from src/index.ts: AperiodicWave, MultiOscillator, UnisonOscillator, and AperiodicOscillator.
AperiodicWaveBuilds an aperiodic timbre description that can be applied to an AperiodicOscillator.
Constructor:
new AperiodicWave(context, spectrum, amplitudes, maxNumberOfVoices, tolerance)
maxNumberOfVoices (count, integer): no default in the constructor; caller must provide a finite integer >= 1.tolerance (cents): no default in the constructor; caller must provide a finite number >= 0.MultiOscillatorA base class wrapping one or more OscillatorNode voices and exposing oscillator-like behavior as one unit.
Constructor:
new MultiOscillator(context, options?)
options (all optional):
frequency (Hz): default 440.detune (cents): default 0.UnisonOscillatorExtends MultiOscillator with evenly distributed voice spread.
Constructor:
new UnisonOscillator(context, options?, mode?)
mode defaults to 'detune'.options (all optional):
frequency (Hz): default 440 (inherited).detune (cents): default 0 (inherited).numberOfVoices (count): default 1.spread:
mode = 'detune' (default), spread is in cents and is distributed symmetrically from negative to positive offsets across voices.mode = 'frequency', spread is in Hz and is distributed symmetrically from negative to positive frequency offsets across voices.0 in either mode.AperiodicOscillatorExtends MultiOscillator to apply AperiodicWave data per voice.
Constructor:
new AperiodicOscillator(context, options?)
options (all optional):
frequency (Hz): default 440 (inherited).detune (cents): default 0 (inherited).aperiodicWave: no default; when provided, setAperiodicWave() is called during construction.| Class | Method | Purpose |
|---|---|---|
MultiOscillator |
setPeriodicWave(wave) |
Set a shared PeriodicWave for all voices (switches behavior to custom waveform). |
AperiodicOscillator |
setAperiodicWave(wave) |
Apply per-voice detunings and per-voice PeriodicWave data from an AperiodicWave. |
MultiOscillator / subclasses |
dispose() |
Disconnect and stop managed audio nodes/voices safely. |
Input validation in src/harmonic-allocator.ts enforces:
spectrum.length === amplitudes.length.maxNumberOfVoices must be a finite integer >= 1.tolerance must be a finite number >= 0.spectrum[i] must be a finite number > 0.amplitudes[i] must be a finite number >= 0.Violations throw Error with a message naming the invalid parameter and the received value.
Install the published package:
npm install aperiodic-oscillator
Set up the repository locally:
npm install
Documentation is hosted at the project Github pages.
To generate documentation locally run:
npm run doc