Oscillators, envelopes and voices
Build instruments from oscillators, envelopes, voice engines and physical resonators.
An instrument turns note events into sound. You can compose an oscillator, envelope and filter yourself, reuse a prepared voice engine, or excite a physical resonator. The module still owns its identity, parameters, presets, MIDI ports and face.
Start with a sound source
import {
initOscillatorNode, setOscillatorNodeFrequency,
setOscillatorNodeWaveform, oscillatorNodeTick,
} from "maruaudio/dsp/oscillators/polyblep"
const oscillator = initOscillatorNode(48_000)
setOscillatorNodeWaveform(oscillator, 1) // 0 sine, 1 saw, 2 square, 3 triangle
setOscillatorNodeFrequency(oscillator, 220)
// Call once per audio frame, after preparation:
const sample = 0.2 * oscillatorNodeTick(oscillator)
This is a continuous source. For a played instrument, add an amplitude envelope,
voice allocation and note-on/off handling. envelopes/adsr exposes
initAdsrNode, attack/decay/sustain/release setters, adsrNodeGateOn,
adsrNodeGateOff and adsrNodeTick; multiply the oscillator by the envelope.
Gate-off begins release, so keep rendering until the voice finishes.
The Processor instrument starter connects these responsibilities in a runnable project. Start there when your goal is an instrument you can play and publish.
Pick the level of reuse
| Approach | Useful starting points | Your responsibility |
|---|---|---|
| Oscillator-based synth | PolyBLEP, wavetable, variable-shape or formant oscillators | Pitch, envelopes, filters, notes, allocation and mix. |
| Reusable voice engine | Subtractive, FM, pluck, modal-struck or sampler voices | Map product controls/events/resources into that engine’s lifecycle. |
| Physical model | Modal resonators, struck exciters, felt contact and string recipes | Excitation, model data, decay, radiation/readout and musical calibration. |
Unison is a stack of oscillator lanes for one note; polyphony is the number of
simultaneous notes. Use voices/unison for lane detune/spread and the prepared
voice pools for note allocation. voices/mono-performance and
voices/portamento supply note priority, articulation and glide decisions.
The sampling reference covers sample-based voices separately.
Prepare for musical transitions
Allocate every voice’s state before rendering. Decide how repeated notes, sustain, release, stealing and a changing voice limit behave. Retire a stolen voice through a short transition rather than cutting a nonzero sample. Use phase-aware oscillator reset when a note restart needs matching triangle history. Resetting all voices on every note loses overlapping notes and tails.
Firmware-derived engines have specific model selections, rates and block formats. In particular, the Warps core is fixed to 96 kHz/60-frame PCM16; its stream adapter adds cadence buffering, not host-rate conversion. Clouds still has pending target qualification, and Plaits exposes only its listed engines. Choose these deliberately rather than assuming a generic oscillator interface.
Toolkit reference
Import paths below are suffixes of maruaudio/dsp/. Use the exported types
and setters in your installed version for complete signatures and defaults.
Oscillators
| Import suffix | Purpose | Selected API |
|---|---|---|
oscillators/polyblep | Sine, saw, square and triangle source with pitch offsets and band-limited discontinuity treatment. | initOscillatorNode, oscillatorNodeTick |
oscillators/lissajous-duo | Stereo dual oscillator with an integer frequency ratio driven by one master phase. | initLissajousDuoNode, setLissajousDuoNodeWaveform |
oscillators/daisysp-blep | DaisySP polynomial step/integrated-step corrections, turn-based sine and clamp helpers. | daisyClamp, daisyThisBlepSample |
oscillators/band-limited-table | Band-limited wavetable playback: per-frame FFT into a sixteen-level half-octave pyramid (256 down to 1 harmonic, like PeriodicWave), Nyquist-safe level crossfading, cubic cycle interpolation, and linear frame morphing. | initBandLimitedTable, bandLimitedLevelOffset |
oscillators/variable-shape | DaisySP VariableShapeOscillator port: a hard-syncable saw/triangle/square morph with band-limited pulse-edge and wrap transitions bounded to two per sample. | initVariableShapeOscillatorNode, variableShapeOscillatorNodeTick |
oscillators/z | DaisySP ZOscillator port: a phase-distortion carrier contour multiplied by a formant discontinuity, with the discontinuity reset band-limited and shape/mode double-buffered. | initZOscillatorNode, zOscillatorNodeTick |
oscillators/formant | DaisySP FormantOscillator port: a windowed-sine formant generator whose carrier reset is band-limited, with the phase shift applied as an explicit per-sample increment. | initFormantOscillatorNode, formantOscillatorNodeTick |
Envelopes
| Import suffix | Purpose | Selected API |
|---|---|---|
envelopes/adsr | Exponential ADSR envelope state machine in VCA form over the shared one-pole coefficient/step and stage thresholds: gate-on is a full retrigger, gate-off releases from the current level. | initAdsrNode, adsrNodeTick |
envelopes/linear-ar | Linear attack/release and optional AHDSR amplitude envelope; release starts from the current level. | createLinearArState, linearArTick |
envelopes/grain-windows | Hann, Tukey, exponential, reversed exponential and triangle grain windows, plus curve rendering and reading. | grainWindowValue, fillGrainWindowCurve |
envelopes/overshoot-adsr | DaisySP exponential-style ADSR with overshooting stage targets and soft/hard retrigger. | initOvershootAdsrNode, overshootAdsrNodeTick |
Noise
| Import suffix | Purpose | Selected API |
|---|---|---|
noise/coloured | Deterministic coloured-noise source: seed policy, [-1,1) white mapping, pink/brown colour filters, fixed-crossover signed tone tilt and output level. | initNoiseNode, noiseNodeTickWhite |
noise/xorshift32 | Unsigned xorshift32 transition and conversion to white noise; caller retains the seed/state. | xorshift32NextU32, rawU32ToBipolar |
noise/newlib-rand | Seeded newlib-compatible integer random sequence for firmware-derived engines. | initNewlibRand, seedNewlibRand |
noise/record-texture | Deterministic crackle, dust and mains-hum generators with prepared scalar/filter state. | initRecordTexture, recordTextureTick |
Physical models
| Import suffix | Purpose | Selected API |
|---|---|---|
physical/modal | Two-pole modal recurrence with displacement/velocity taps, mode roll-off and excitation shaping. | exciterLowpassTick, modalPoleRadius |
physical/modal-radiation | Bounded radiation weighting and displacement/velocity readout with stereo gain. | modalRadiationFrequencyWeight, modalRadiationReadout |
physical/modal-table | Prepare modal recipe tables with bounded mode counts, pitch-scaled frequencies and decay. | modalTableSlot, modalTableBoundedModeCount |
physical/modal-resonator | Single two-pole resonator with T60 decay, excitation and gain/readout. | initModalResonatorNode, modalResonatorNodeTick |
physical/modal-resonator-bank | Prepared 16-mode resonator banks and packed multi-bank pools; common excitation and displacement/velocity/radiation outputs. | initModalResonatorBank, modalResonatorBankTick |
physical/piano-scale | Provisional per-key string/hammer geometry, mass, tension and tuning equations for piano models. | createPianoKeyScale, pianoHammerContactDuration |
physical/felt-hammer | Nonlinear felt contact and hammer momentum against a passive load; no returning-wave feedback or hysteresis. | createFeltHammer, feltHammerTickRealtime |
physical/struck | Reusable struck-instrument excitation: velocity, hardness, contact time, noise, seeding and size-to-decay laws. | struckVelocityGain, struckEffectiveHardness |
physical/strike | Per-mode excitation gains at the moment of contact: free-free bar and gong/kettle mode-shape weights with a mallet-width floor, plus the contact-time velocity tilt across the bank. | strikeBarShape, strikeGongShape |
physical/mallet | Beater contribution to a struck plate's spectrum: softness-driven per-mode spectral tilt, a bounded normalized half-sine contact-force pulse, and the constant-energy roughness residual gain. | malletModeRolloff, malletContactForce |
physical/bloom | Tam-tam nonlinear upward energy cascade as a per-mode arrival-time split: deferred excitation fraction, one-pole rise coefficient, envelope step and the audible per-mode gain recombination. | bloomModeFraction, bloomRiseCoefficient |
Voice engines and performance
| Import suffix | Purpose | Selected API |
|---|---|---|
voices/stages | Oscillator, envelope and filter stages used to compose a subtractive voice. | polyBlep, oscSineSample |
voices/note-stack | Held-note stack for mono and legato play modes: held flags, per-note velocity, press order and last-note priority lookup. | initNoteStack, noteStackPush |
voices/grain-pool | Bounded granular voice storage and scheduling over prepared sample data. | initGrainPool, grainPoolRenderFrame |
voices/polyphonic-pool | Bounded note-slot allocation with same-note retrigger and voice-stealing policy. | initPolyphonicVoicePool, boundedPolyphonicCapacity |
voices/subtractive | Subtractive synth voice composition over shared oscillators, envelopes and filters. | initSubtractiveVoice, voiceTick |
voices/oscillo | Prepared Oscillo synthesis voice; use its own parameter and note lifecycle. | initOscilloVoice, oscilloLfoTick |
voices/gamelan | Prepared gamelan-style struck voice with modal synthesis and a caller-owned stereo output bus. | initGamelanVoice, gamelanExciterTick |
voices/gong | Prepared gong voice with modal synthesis and a caller-owned stereo output bus. | initGongVoice, gongExciterTick |
voices/fm-keys | Four-operator phase-modulation keyboard: six routings, per-operator envelopes, eight voices and feedback shaping. | initFmKeysVoice, fmKeysRenderFrame |
voices/fm-algorithms | Shared FM operator-routing algorithms and stable algorithm lookup. | fmWiringFromMatrix, dx7Algorithm |
voices/drum-kit-model | Shared drum-kit model data and contracts for percussion consumers. | drumVoiceForNote, drumVoiceById |
voices/fm-core | Prepared operator-count-flexible phase-modulation graph with weighted source-to-target routes, deterministic one-sample feedback for cyclic connections, and independent carrier output gains. | createFmCoreState, resetFmCoreState |
voices/mouth | Monophonic glottal source and vocal-tract waveguide with nasal branch, constrictions, turbulence and a reverb tail. Caller supplies noise. | initMouthVoice, mouthTick |
voices/modal-struck | Twelve-slot stereo struck-resonator pool with recipe/note tables, velocity-sensitive excitation, release and bounded tail retirement. | initModalStruckState, modalStruckV2VoiceTick |
voices/phase-7 | Six-operator FM instrument: 32 routings, operator/pitch envelopes, LFO, unison, mono/poly modes, portamento and pitch bend. | phase7Tick, phase7Ratio |
voices/rings | Rings modal-model resonator core with original parameter laws, bounded polyphony, separate odd/even taps and independent signal inputs; qualification remains module-owned. | initRingsState, tickRings |
voices/pluck | Twelve-voice extended Karplus–Strong strings with pick/noise excitation, stiffness, loss, body resonances and stereo detune. | createPluckVoiceState, pluckTick |
voices/stiff-string-piano | Register-scaled modal/shared-load/waveguide piano recipe with felt contact and reduced secondary resonances. | createStiffStringPiano, stiffStringPianoTick |
voices/chord-voicing | Root-position, voice-led, drop-2 and spread MIDI voicings with an optional bass note. | sortAscending, voiceChord |
voices/chord-colour | Scale-aware added chord tones, avoid-note rules and a decaying pitch-class histogram. | createChordColour, colourIntervalClassConsonance |
voices/portamento | Exact-duration semitone glide with an explicit preparation and note-transition lifecycle. | initPortamento, tickPortamento |
voices/mono-performance | Held-note selection, note priority and mono/legato retrigger decisions. | initMonoPerformance, resetMonoPerformanceConfiguration |
voices/unison | Symmetric detune/stereo lanes, bounded peak gain, smooth lane-count transitions and optional deterministic phase seeds. | initUnison, tickUnison |
voices/clouds | Original Clouds engine translation; only the initial model is supported and target qualification is pending. | initCloudsState, processCloudsBlock |
voices/peaks | Firmware-derived Twin ADSR/Split AD envelope function with independent gates; other modes are explicitly unsupported. | initPeaksState, tickPeaksRaw |
voices/warps | Firmware-derived crossmodulation/vocoder and frequency/phase-shifter core; requires 96 kHz, 60-frame interleaved PCM16 processing. | createWarpsState, processWarpsBlock |
voices/warps/controls | Warps ADC-domain control scaling and smoothing, with explicit connection presence; no physical voltage/jack interface. | createWarpsControlState, resetWarpsControlState |
voices/warps/stream | Cadence adapter for the 96 kHz PCM16 Warps core, retaining MAIN/AUX outputs and adding 60 frames; does not resample. | createWarpsStreamState, processWarpsStream |
voices/plaits | Firmware-derived Voice supporting the virtual-analog and additive engines; other engine selections are silent. | initPlaitsState, tickPlaits |
Return to DSP fundamentals for I/O, lifecycle, units and the category map.