Virtual instrument playground for sound design and synthesis
Terminal-based TUI synthesizer built in Rust with ratatui. Real-time audio synthesis via cpal, multiple oscillator types, effects processing, arpeggiator, and preset management.
arco is a terminal-based TUI synthesizer built in Rust. Design sounds using a keyboard-driven interface with real-time audio synthesis and waveform visualization.
Rust 1.70+ - Rustup toolchainALSA development libs - alsa-lib-devel on Fedora/RHELPulseAudio (optional) - For PulseAudio backendratatui 0.29 - TUI frameworkcrossterm 0.28 - Terminal backendcpal 0.15 - Cross-platform audiorustfft 6.2 - FFT for visualizationLaunch arco in your terminal to start the TUI synthesizer:
arco is configured entirely through its UI - all parameters are accessible via the control panels. No configuration files required.
Core synthesis parameters available in the main controls panel:
| Option | Type | Default | Description |
|---|---|---|---|
oscillatorType | string | sine | Primary waveform: sine, square, sawtooth, triangle |
detune | cents | 0 | Primary oscillator detune (±100 cents) |
filterCutoff | Hz | 8000 | Filter cutoff frequency (20-20000 Hz) |
filterResonance | Q | 2 | Filter resonance (1-30) |
attack | seconds | 0.01 | Amplitude envelope attack (0-2s) |
decay | seconds | 0.1 | Amplitude envelope decay (0-2s) |
sustain | 0-1 | 0.7 | Amplitude envelope sustain level |
release | seconds | 0.3 | Amplitude envelope release (0-2s) |
LFO and modulation settings:
| Option | Type | Default | Description |
|---|---|---|---|
lfoRate | Hz | 4 | LFO 1 frequency (0.1-20 Hz) |
lfoAmount | percent | 0 | LFO 1 pitch modulation depth (0-100%) |
lfo2Rate | Hz | 4 | LFO 2 frequency (0.1-20 Hz) |
lfo2Amount | percent | 0 | LFO 2 modulation depth |
lfo2Target | string | filter | LFO 2 target: pitch, filter, amplitude |
portamento | seconds | 0 | Glide time between notes (0-2s) |
pwmRate | Hz | 0.5 | Pulse width modulation rate |
pwmAmount | percent | 0 | PWM depth |
Secondary oscillator and sub-oscillator controls in the Advanced panel:
| Option | Type | Default | Description |
|---|---|---|---|
osc2Enabled | boolean | false | Enable oscillator 2 |
osc2Type | string | sawtooth | Oscillator 2 waveform |
osc2Detune | cents | 0 | Oscillator 2 detune |
osc2PitchOffset | semitones | 0 | Pitch offset (-24 to +24) |
subOscEnabled | boolean | false | Enable sub-oscillator (1 octave below) |
subOscLevel | percent | 50 | Sub-oscillator volume |
subOscType | string | sine | Sub-oscillator waveform |
noiseLevel | percent | 0 | Noise generator level |
noiseType | string | white | Noise type: white, pink |
Standard effects controls:
| Option | Type | Default | Description |
|---|---|---|---|
reverb | percent | 0 | Reverb wet/dry mix (0-100%) |
delay | percent | 0 | Delay wet/dry mix (0-100%) |
delayTime | seconds | 0.3 | Delay time (0-1s) |
delayFeedback | percent | 50 | Delay feedback amount |
distortion | percent | 0 | Distortion amount (0-100%) |
Digital effects in the Advanced panel:
| Option | Type | Default | Description |
|---|---|---|---|
bitCrushEnabled | boolean | false | Enable bit crusher effect |
bitCrushBits | bits | 8 | Bit depth reduction (1-16) |
bitCrushRate | Hz | 22050 | Sample rate reduction |
waveFoldEnabled | boolean | false | Enable wave folder |
waveFoldAmount | percent | 50 | Folding intensity |
hardClipEnabled | boolean | false | Enable hard clipper |
hardClipThreshold | 0-1 | 0.8 | Clipping threshold |
freqShiftEnabled | boolean | false | Enable frequency shifter |
freqShiftAmount | Hz | 0 | Frequency shift amount |
formantEnabled | boolean | false | Enable formant filter |
formantVowel | string | a | Vowel shape (a, e, i, o, u, etc.) |
granularEnabled | boolean | false | Enable granular buffer |
granularSize | ms | 100 | Grain size |
granularFreeze | boolean | false | Freeze playback |
arco is a virtual instrument playground - a terminal-based TUI synthesizer for creating, configuring, and playing custom virtual instruments with real-time audio synthesis.
arco uses subtractive synthesis as its core with additive and FM capabilities. The audio engine supports up to 20 simultaneous voices.
Four sound sources can be combined:
Layer 1-8 voices with detune spread and stereo panning for thick, chorus-like sounds. Higher voice counts increase CPU usage.
State-variable filter with four modes:
The filter has its own ADSR envelope for dynamic timbral control. Higher resonance values create emphasis at the cutoff frequency.
Two ADSR envelopes shape the sound over time:
Controls volume from note-on to note-off. Fast attack for plucks, slow attack for pads.
Modulates filter cutoff. Use with high envelope amount for classic synth filter sweeps.
Multiple modulation sources add movement and expression:
Two LFOs provide cyclic modulation:
Dedicated pitch modulation. Rate 0.1-20 Hz, amount controls depth.
Selectable target: pitch (vibrato), filter (wah), or amplitude (tremolo).
Pulse Width Modulation on square waves. Creates movement in the harmonic content for classic analog-style sounds.
Advanced synthesis modes using oscillator 2:
Standard effects chain plus experimental digital processors:
6-tap delay simulation. Adds space and depth.
Up to 1 second, with feedback. Echo and rhythmic effects.
Waveshaper with 44100-sample curve. Adds harmonics and grit.
Reduces bit depth (1-16) and sample rate for lo-fi sounds
Folds waveform on itself for complex harmonics
10 vowel presets for vocal-like filtering
Grain-based buffer with size, speed, freeze modes
Inharmonic pitch shifting via single-sideband modulation
Metallic resonance with feedback control
Factory presets demonstrate different synthesis techniques:
Save your own presets using the preset manager. Presets store all 60+ parameters.
arco is built in Rust using ratatui for the TUI and cpal for cross-platform audio. The architecture separates UI rendering from audio processing using async channels for thread-safe communication.
arco/src/ ├── main.rs # Entry point, terminal setup ├── app.rs # Application state, modal panels ├── ui/ # TUI rendering (ratatui) │ ├── mod.rs # Layout and drawing │ └── widgets/ # Custom widgets ├── audio/ # Sound synthesis (cpal) │ ├── mod.rs # Audio engine coordination │ ├── synth.rs # Oscillators, filters │ └── effects.rs # Reverb, delay, distortion ├── input/ # Keyboard handling ├── arpeggiator.rs # Pattern sequencer ├── preset.rs # Preset management └── recorder.rs # Audio recording
Each module has a focused responsibility:
The core audio engine in src/audio/:
// Voice structure (Rust)
pub struct Voice {
pub osc1: Oscillator, // Primary oscillator
pub osc2: Option<Oscillator>, // Secondary oscillator
pub sub_osc: Option<Oscillator>, // Sub-octave
pub noise: Option<NoiseGen>, // Noise generator
pub filter: Filter, // SVF filter
pub amp_env: Envelope, // Amplitude ADSR
pub filter_env: Envelope, // Filter ADSR
pub note: u8, // MIDI note
pub velocity: f32, // Note velocity
} Polyphonic voice handling within SandboxSynth:
Real-time audio visualization in WaveformVisualizer.js:
Signal flow through the Web Audio API nodes:
Oscillators (1/2/sub/noise)
↓
Voice Gain (envelope)
↓
Filter (LP/HP/BP/Notch)
↓
Filter Envelope
↓
Distortion (waveshaper)
↓
Experimental Effects
↓
Delay → Reverb
↓
Master Gain
↓
Analyser → Destination User interactions flow through React state to the audio engine:
Complete keyboard and interface controls for arco.
Use the lower rows of your QWERTY keyboard as a piano:
| Option | Type | Default | Description |
|---|---|---|---|
Z | note | - | C3 |
S | note | - | C#3 |
X | note | - | D3 |
D | note | - | D#3 |
C | note | - | E3 |
V | note | - | F3 |
G | note | - | F#3 |
B | note | - | G3 |
H | note | - | G#3 |
N | note | - | A3 |
J | note | - | A#3 |
M | note | - | B3 |
Second octave on the top row:
| Option | Type | Default | Description |
|---|---|---|---|
Q | note | - | C4 |
2 | note | - | C#4 |
W | note | - | D4 |
3 | note | - | D#4 |
E | note | - | E4 |
R | note | - | F4 |
5 | note | - | F#4 |
T | note | - | G4 |
6 | note | - | G#4 |
Y | note | - | A4 |
7 | note | - | A#4 |
U | note | - | B4 |
Lower row (C3-B3): ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │ Z │ S │ X │ D │ C │ V │ G │ B │ H │ N │ J │ M │ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤ │ C │C# │ D │D# │ E │ F │F# │ G │G# │ A │A# │ B │ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘ Upper row (C4-B4): ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │ Q │ 2 │ W │ 3 │ E │ R │ 5 │ T │ 6 │ Y │ 7 │ U │ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤ │ C │C# │ D │D# │ E │ F │F# │ G │G# │ A │A# │ B │ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
Common issues and solutions when using arco.
Problem: Keys pressed but no audio.
Solutions:
Problem: QWERTY keys don't play notes.
Solutions:
Problem: Distorted or crackling audio.
Solutions:
Problem: Browser becoming slow or unresponsive.
Solutions:
Problem: Audio won't stop playing.
Solutions:
Problem: Custom preset fails to load.
Solutions:
Problem: High-pitched whine from filter.
Solution: Reduce filter resonance (Q value). Very high resonance causes the filter to ring at the cutoff frequency.
arco requires Web Audio API support: