Lab

Mono synth

A monophonic analog synth device: a saw, square or triangle oscillator, a sub oscillator and noise into a resonant filter, an envelope, a glide and a vibrato, with eight presets, a panel with a keyboard, a Web Audio engine and tools for agents.

Audio UI

A monophonic analog synth, for basses, leads and acid lines. An oscillator (a saw, a square of any width or a triangle), a square sub oscillator an octave down and noise are mixed into a resonant low-pass filter, which an envelope opens along with the level. It plays one note at a time: a note played while another is held glides to it. Start from one of its eight presets (Init Saw, Warm Pad, Acid Bass, Pluck, Brass, Sub Bass, Lead, Wind), then shape it. It is a device: a state, a panel, an engine and tools, each its own file.

Installation

pnpm dlx shadcn@latest add @audio-ui/mono-synth

It installs the device's state, its engine and its panel to components/audio-ui/devices/mono-synth/. The demo above, which wires them to a loop, is @audio-ui/block-mono-synth.

Controls

Every number reads 0 to 10, as a panel's sliders do, and shows the value it sets in the unit the sound takes.

Controls · 18

Panel

The panel loads a preset from the menu in its title bar, beside the oscillator's wave and the range, lays the other controls out by what they do (oscillators, filter, envelope, pitch, output) and has a keyboard of two octaves that plays the synth. monoSynthPreset(name) gives a preset's whole state, and MONO_SYNTH_PRESETS lists them. With activeNotes, the notes held now, such as on a MIDI keyboard, light up their keys. The panel sends notes out and does not make the sound, so it plays through any engine.

import { MonoSynthPanel } from "@/components/audio-ui/devices/mono-synth/panel";
import { monoSynthDevice } from "@/components/audio-ui/devices/mono-synth/device";

const [state, setState] = useState(() => monoSynthDevice.defaults());

<MonoSynthPanel onValueChange={setState} value={state} />;

Engine

Create it, connect it and update it as for any device: see The engine.

engine.noteOn({ frequency: 110, velocity: 0.8 }, { id: "a2" }); // the envelope opens
engine.noteOn({ frequency: 165 }, { id: "e3" }); // held: glides to it
engine.noteOff({ id: "e3" }); // glides back to A2, still held
engine.noteOff({ id: "a2" }); // the last one: fades over the release

The engine is the whole synth: give it every note, each with its own id, rather than one engine a note. The first note opens the amplifier and the filter along the envelope. A note played while one is held glides the pitch to it over the glide and leaves the envelope as it is; let go of it, and the pitch glides back to the note still held. Once every note is let go, both fall back over the release from where they had got to, so a short note never clicks. A noteOff with no id lets every note go. Notes take a time of the audio clock, { at, id }, for a host that schedules ahead, and the arrangement's engine gives a MIDI track's notes to the one engine. Every control moves with a ramp, a held note included. An agent plays the synth with the play tool.

Built by Ouest Labs, the source code is available on GitHub.
RSS