audio bus crypto display ez global gps keyboard mesh net radio sprite storage synth system wifi

Multi-voice software synth (chip-tune SFX + simple music).

Drives a 4-voice synthesiser at 44.1 kHz mono into the same I2S audio output the rest of ez.audio uses. The shape is NES-derived: two pulse voices (variable duty), one triangle voice for sub-bass bodies, and one noise voice for percussion / explosions. Each voice has independent ADSR, an optional linear pitch sweep, and an optional vibrato. Voice indices (1-based from Lua): 1 = pulse A 2 = pulse B 3 = triangle 4 = noise

Functions

is_active() → boolean True if at least one voice is currently producing sound.
ez.synth.is_active() -> boolean
note_off() → nil Enter the release phase of the voice's envelope.
ez.synth.note_off(voice) -> nil
note_on() → nil Trigger a voice with a fresh envelope.
ez.synth.note_on(voice, hz, vol [, opts]) -> nil
Starts (or retriggers) the given voice. Resets the envelope to Attack, the oscillator phase to zero, and clears any pending sweep. `opts` is an optional table of per-trigger overrides: { duty = 0.25, // pulse only, 0.05..0.95 attack_ms = 0, decay_ms = 80, sustain = 0, // 0..255 release_ms = 0, sweep_hz = 200, sweep_ms = 80, vib_depth_hz = 8, vib_rate_hz = 5 } Anything missing keeps its previous setting; this matches the expectation that game patches set most params once via set_envelope etc. and just retrigger pitch+volume each shot.
ParameterDescription
voiceinteger 1..4
hznumber frequency in Hz (or LFSR tap rate for the noise voice)
volinteger 0..255
optstable (optional) — see description
ez.synth.note_on(1, 880, 200, { duty = 0.25, attack_ms = 0,
decay_ms = 80, sustain = 0 })
set_duty() → nil Set pulse duty (0.05..0.95). Ignored for non-pulse voices.
ez.synth.set_duty(voice, duty) -> nil
set_envelope() Set the ADSR envelope shape for a voice.
ez.synth.set_envelope(voice, attack_ms, decay_ms, sustain, release_ms)
ParameterDescription
sustain0..255 — fraction of peak; 0 = AD-only one-shot
set_master() → nil Set engine master volume 0..255. Independent of ez.audio's volume.
ez.synth.set_master(v) -> nil
set_sweep() → nil Linear pitch sweep from current freq to `target_hz` over `ms`.
ez.synth.set_sweep(voice, target_hz, ms) -> nil
set_vibrato() → nil Sinusoidal pitch wobble around the current freq.
ez.synth.set_vibrato(voice, depth_hz, rate_hz) -> nil
silence() → nil Stop every voice immediately. Drops audio mode back to Off.
ez.synth.silence() -> nil