Skip to content

illobo/textStep

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

107 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸŽ›οΈ T E X T S T E P 🎹

A terminal-based step sequencer, drum machine, and synthesizer built entirely in Rust.

β™ͺ All DSP from scratch β€” no samples, no external audio libraries. Just your terminal and your speakers. β™«

Rust License: GPL v2 Platform: macOS Platform: Linux Audio: CoreAudio / ALSA TUI: ratatui Lines of Code Tests

TextStep Demo


✨ Features

  • πŸ₯ 8 Drum Tracks β€” Kick, Snare, Closed HiHat, Open HiHat, Ride, Clap, Cowbell, Tom β€” each fully synthesized with 8 tweakable sound parameters
  • 🎹 Dual Polyphonic Synths β€” Synth A + Synth B with DJ-style crossfader, each with 2 oscillators (4-voice supersaw) + selectable sub, portamento, osc sync, 2 ADSR envelopes, resonant filter with key follow, dual LFOs with 6 waveforms, independent patterns and kits
  • πŸ”² 32-Step Sequencer β€” 10 patterns and 8 kit slots with per-pattern BPM and swing
  • 🎬 16 Scene Slots β€” snapshot and recall full instrument states (all patterns, kits, BPM, swing) with queued or immediate switching
  • πŸ”Š Pro Audio Engine β€” FDN reverb (8-line stereo), tempo-synced delay, 2Γ—-oversampled tube saturator, SSL-style glue compressor, lookahead limiter, sidechain compression (kick ducks synths)
  • 🎀 Live Performance β€” drum pads, real-time recording, pattern queuing, scene-based arrangement
  • πŸ–±οΈ Mouse Support β€” click the grid, drag parameters Ableton-style, audition sounds from the activity bar
  • πŸ’Ύ Project System β€” save/load .tsp files, standalone kit export, preset browser
  • πŸ“ Collapsible Panels β€” minimize/expand synth, drum knobs, and waveform sections; auto-adapts to small terminals
  • πŸ“Š Spectrum Analyzer β€” real-time FFT spectrum display and VU meter with 90s Hi-Fi LED aesthetic
  • πŸ”— Ableton Link β€” sync tempo, start/stop, and beat position with other TextStep instances or any Link-enabled DAW on the network. Press F3 to toggle. Link-as-master: when enabled, the network's shared timeline drives this instance's clock continuously, eliminating drift.

Ships with 10 demo scenes ready to play: 🎡 Acid Techno, Classic House, Deep House, Driving Techno, Lo-Fi Hip Hop, Trance, Drum & Bass, Electro Funk, Dub Techno, and Ambient β€” each with matched drum patterns, synth patterns, and kits.

πŸš€ Getting Started

Prerequisites

  • Rust 1.70 or later
  • macOS with CoreAudio (primary target)

Build & Run

Requires Rust (1.70+). macOS with CoreAudio is the primary target; Linux with ALSA is also supported.

# Clone the repository
git clone https://github.com/illobo/textStep.git
cd textStep

# Build and run (release mode recommended for audio performance)
cargo build --release
cargo run --release

# Build without Ableton Link (skips link / tokio dependencies)
cargo build --release --no-default-features

Run Tests

On Linux, install ALSA development headers first:

sudo apt-get install libasound2-dev   # Debian/Ubuntu

Run the tests:

cargo test    # 55 tests, runs in <1s

Pre-built Binaries

Pre-built binaries for macOS (ARM, x86_64, universal) and Linux (x86_64) are available from GitHub Actions artifacts.

macOS note: Downloaded binaries will be blocked by Gatekeeper. Remove the quarantine flag before running:

xattr -d com.apple.quarantine ./textstep

🎚️ Quick Manual

▢️ Transport

Key Action
Space Play / Pause
Esc Stop (reset to step 0)
- / = BPM -1 / +1
_ / + BPM -10 / +10
` Toggle record mode
l Toggle loop on/off
L Cycle loop length: 8 / 16 / 24 / 32
Shift+C Cycle compressor: Off / Light / Medium / Heavy / Max
Shift+T Cycle tube saturator: Off / Light / Medium / Heavy / Max
Shift+D Cycle sidechain duck: Off / Light / Medium / Heavy / Max
Shift+V Adjust master volume
< / > Swing Β±5%
( / ) Crossfader toward A / B
Click A / B Mute/unmute Synth A / B
Click C Reset crossfader to center

🧭 Navigation

Key Action
Tab / Shift+Tab Cycle focus: Grid β†’ Controls β†’ Transport
Arrow keys Move cursor in grid or controls
Enter Toggle step (and advance β€” hold to fill)
; Cycle parameter page: SYN β†’ AMP β†’ FX
F2 Collapse/expand all synth panels (A + B)
F3 Toggle Ableton Link sync
~ Toggle spectrum analyzer / VU meter
? Help overlay

πŸŽ›οΈ Sound Design

Each drum track has 8 parameters across three pages:

Page Parameters Controls
SYN Tune, Sweep, Color, Snap Pitch, timbre, transient character
AMP Filter, Drive, Decay, Volume Tone shaping, saturation, envelope
FX Reverb Send, Delay Send Per-track effect routing

Tweak with Shift+Up/Down (adjust value) or Alt+Up/Down (adjust and audition simultaneously). With the mouse, click-drag any gauge vertically. Alt+R randomizes the current page across all tracks.

Mute (Shift+M) and Solo (Shift+S) are always accessible on any page.

πŸ₯ Drum Pads

The bottom keyboard row triggers sounds live:

z x c v b n m ,
Kick Snare CHH OHH Ride Clap Cowbell Tom

With record enabled and playback running, pad hits write steps at the playhead.

πŸ”€ Patterns & Kits

Patterns β€” 10 slots per section (Synth A, Synth B, Drums), each with its own step data:

Key Action
q w e r t y u i o p Queue pattern 1–10 (switches at loop end)
Shift+ above Switch pattern immediately
[ / ] Queue prev / next
{ / } Immediate prev / next

Kits β€” 8 slots of sound parameters, shared across patterns:

Key Action
1 through 8 Switch to kit slot

🎹 Dual Synths

TextStep features two independent polyphonic synthesizers (Synth A and Synth B), each with its own patterns, kits, 2 oscillators + sub, noise, 2 ADSR envelopes, 24dB resonant filter, and LFO with 6 waveforms. Toggle all synth panels with F2. Each synth has its own pattern/kit selectors shown in the transport bar.

Synth notes are triggered with z x c v when a synth grid is focused, with Up/Down for pitch and ( ) for octave shifts.

🎬 Scenes

Scenes are snapshots of the full instrument state: which pattern and kit is selected for drums, Synth A, and Synth B, plus BPM and swing. Use them to arrange your track.

Key Action
Ctrl+E Open scene browser
Return Queue scene (switches at drum loop end)
! Immediate scene switch
S Save current state to selected slot
R Rename scene
D Delete scene
Esc Close browser

πŸ’Ύ File Operations

Key Action
Ctrl+S Save project
Ctrl+O Load project
Ctrl+E Scene browser
Ctrl+N Rename current pattern
Ctrl+K Save kit as standalone .tsk file
Ctrl+J Load kit into active slot
Ctrl+P Preset browser
Ctrl+L Pattern browser
Ctrl+C / Ctrl+Q Quit

Projects are stored as JSON in ~/Library/Application Support/textstep/projects/.

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   UI Thread                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  ratatui   β”‚  β”‚ crosstermβ”‚  β”‚   App State   β”‚  β”‚
β”‚  β”‚  renderer  β”‚  β”‚  events  β”‚  β”‚  (app.rs)     β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                    β”‚
β”‚  crossbeam channels (lock-free, bounded)           β”‚
β”‚         β–Ό UiToAudio          β–² AudioToUi           β”‚
β”‚                                                    β”‚
β”‚                 Audio Thread                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Sequencer β”‚  β”‚  Voices  β”‚   Effects    β”‚  β”‚
β”‚  β”‚   Clock    β”‚  β”‚Drum+SynABβ”‚  β”‚ Rev/Dly/Comp β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                       β”‚                            β”‚
β”‚                  cpal/CoreAudio                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Two-thread model:

  • UI thread β€” ratatui + crossterm for rendering and input at ~60fps
  • Audio thread β€” cpal/CoreAudio callback running all DSP per-sample

Communication is lock-free via bounded crossbeam channels. The audio thread never blocks.

πŸ”§ DSP β€” All From Scratch

Every sound is synthesized in real-time with no external DSP dependencies:

  • Drum voices β€” TR-808/909-inspired kicks (dual-stage pitch envelope, bridged-T BP/LP click blend, subharmonic at octave below, asymmetric drive saturation), noise-blended snares with comb filter, 6-oscillator metallic banks for hats and rides (Mutable Instruments Plaits-style inharmonic ratios), ring-modulated open hats, bandpass claps, detuned pulse cowbells, FM toms
  • Synth voice β€” dual PolyBLEP anti-aliased oscillators (4-voice supersaw), selectable sub waveform (square/sine/saw), noise, two ADSR envelopes, resonant SVF filter with key follow, portamento/glide, oscillator hard sync, dual 6-waveform tempo-synced LFOs
  • Effects β€” 8-line FDN reverb with Householder feedback matrix (native stereo), tempo-synced filtered delay, 2Γ—-oversampled asymmetric tube saturator, feedforward RMS glue compressor with soft knee, true-peak lookahead limiter, sidechain envelope follower
  • Primitives β€” 1-pole HP/LP filters, state-variable filter, xorshift32 noise, stereo decorrelation

Source Map

Directory Purpose
src/ Core: entry point, app state, input handling, messages
src/ui/ Rendering: layout, theme, grids, knobs, transport, spectrum
src/audio/ DSP: engine, clock, drum/synth voices, effects, mixer, FFT
src/sequencer/ Data: patterns, transport, project serialization
src/presets/ Preset browser: drum/synth sounds and patterns by genre

🎨 Color Palette

Hardware/synthwave aesthetic β€” all rendered with UTF-8 block characters on a dark background.

Color Hex Usage
Amber #e8a838 Active steps, gauge fills, primary data
Cyan #61dafb Transport state, beat LEDs, playhead, focused borders
Pink #ff6b9d Focus/selection, current track, record
Gold #ffd700 Queued patterns, warnings

Dependencies

Crate Version Purpose
ratatui 0.29 TUI rendering framework
crossterm 0.28 Terminal backend (events, raw mode)
cpal 0.15 Cross-platform audio I/O (CoreAudio)
crossbeam-channel 0.5 Lock-free bounded MPSC channels
serde + serde_json 1 Project serialization (JSON)

No other runtime dependencies.

Project Structure

textStep/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.rs              # Entry point, thread spawning, event loop
β”‚   β”œβ”€β”€ app.rs               # Application state, focus, modals
β”‚   β”œβ”€β”€ keys.rs              # Keyboard input handler
β”‚   β”œβ”€β”€ mouse.rs             # Mouse input handler (mirrors UI layout)
β”‚   β”œβ”€β”€ messages.rs          # Cross-thread message enums
β”‚   β”œβ”€β”€ params.rs            # Shared effect parameters
β”‚   β”œβ”€β”€ ui/
β”‚   β”‚   β”œβ”€β”€ mod.rs           # Top-level render dispatch
β”‚   β”‚   β”œβ”€β”€ layout.rs        # Layout constants (single source of truth)
β”‚   β”‚   β”œβ”€β”€ theme.rs         # Color palette and styling
β”‚   β”‚   β”œβ”€β”€ transport_bar.rs # Transport controls rendering
β”‚   β”‚   β”œβ”€β”€ drum_grid.rs     # 8Γ—32 drum step grid
β”‚   β”‚   β”œβ”€β”€ synth_grid.rs    # Synth step grid with note display
β”‚   β”‚   β”œβ”€β”€ knobs.rs         # Drum parameter sliders
β”‚   β”‚   β”œβ”€β”€ synth_knobs.rs   # Synth parameter groups
β”‚   β”‚   β”œβ”€β”€ waveform.rs      # Spectrum analyzer / VU meter
β”‚   β”‚   β”œβ”€β”€ splash.rs        # Boot animation
β”‚   β”‚   └── help_overlay.rs  # Keyboard shortcut reference
β”‚   β”œβ”€β”€ audio/
β”‚   β”‚   β”œβ”€β”€ engine.rs        # Audio callback and voice management
β”‚   β”‚   β”œβ”€β”€ clock.rs         # Beat/step timing with swing
β”‚   β”‚   β”œβ”€β”€ drum_voice.rs    # 8 drum synth voices (all DSP)
β”‚   β”‚   β”œβ”€β”€ synth_voice.rs   # Polyphonic synth DSP
β”‚   β”‚   β”œβ”€β”€ effects.rs       # Reverb, delay, compressor, saturator
β”‚   β”‚   β”œβ”€β”€ mixer.rs         # Channel mixing, mute/solo
β”‚   β”‚   β”œβ”€β”€ display_buffer.rs # Lock-free audioβ†’UI waveform buffer
β”‚   β”‚   └── fft.rs           # FFT for spectrum analyzer
β”‚   β”œβ”€β”€ sequencer/
β”‚   β”‚   β”œβ”€β”€ drum_pattern.rs  # Drum pattern data (8 tracks Γ— 32 steps)
β”‚   β”‚   β”œβ”€β”€ synth_pattern.rs # Synth pattern data and parameters
β”‚   β”‚   β”œβ”€β”€ transport.rs     # Transport state (BPM, play, swing)
β”‚   β”‚   └── project.rs       # Project serialization (.tsp JSON)
β”‚   └── presets/
β”‚       β”œβ”€β”€ mod.rs           # Preset browser state machine
β”‚       β”œβ”€β”€ drum_presets.rs   # Drum sound presets
β”‚       β”œβ”€β”€ synth_presets.rs  # Synth sound presets
β”‚       β”œβ”€β”€ pattern_presets.rs      # Drum pattern presets by genre
β”‚       └── synth_pattern_presets.rs # Synth pattern presets
β”œβ”€β”€ assets/
β”‚   └── demo.gif             # Demo recording
β”œβ”€β”€ Cargo.toml
β”œβ”€β”€ BLUEPRINT.md             # Full technical documentation
└── LICENSE                  # GPL v2

πŸ“‹ Changelog

v2.0.3 β€” Kick Voice & Synth Engine Improvements

Kick Voice Realism

  • Dual-stage pitch envelope (2.5ms fast attack + color-controlled slow stage)
  • Bridged-T network: bandpass/lowpass click blend replacing simple LP impulse
  • Subharmonic at octave below (0.5Γ—) instead of 0.75Γ— β€” eliminates phase cancellation
  • Asymmetric tanh saturation for drive-dependent even harmonics
  • All 16 kick presets retuned for the new synthesis architecture

Synth Engine Features

  • Portamento/glide with exponential pitch smoothing
  • Oscillator hard sync (osc2 β†’ osc1)
  • Selectable sub waveform (square / sine / saw)
  • Filter key follow
  • Wider 4-voice supersaw with PolyBLEP anti-aliasing

CPU Optimizations

  • Cached SVF filter coefficients (skip per-sample tan() when cutoff unchanged)
  • fast_exp2 polynomial approximation replacing powf() in pitch calculations
  • Incremental O(1) peak tracking in lookahead limiter (full scan only on peak exit)
  • Inactive oscillator skip (zero-cost when osc2/sub level is 0)

🀝 Contributing

Contributions are welcome! Please ensure:

  1. All tests pass: cargo test
  2. Code compiles without warnings: cargo build --release
  3. Follow the existing code style and comment conventions

See BLUEPRINT.md for full technical documentation and architecture details.

License

This project is licensed under the GNU General Public License v2.0.


πŸ¦€ Built with Rust Β· πŸ”Š All DSP from scratch Β· 🎡 Zero audio dependencies

"Any sufficiently advanced terminal is indistinguishable from a drum machine."

About

A text-based rust synth+sequencer.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages