╔══════════════════════════════════════════════════════════════════════════════╗
║ ∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿ ║
║ ║
║ ███████╗██╗ ██╗ ██╗ ██████╗ ███████╗██╗ ██╗███╗ ██╗████████╗██╗ ██╗ ║
║ ██╔════╝██║ ██║███║██╔════╝ ██╔════╝╚██╗ ██╔╝████╗ ██║╚══██╔══╝██║ ██║ ║
║ █████╗ ██║ █╗ ██║╚██║███████╗ ███████╗ ╚████╔╝ ██╔██╗ ██║ ██║ ███████║ ║
║ ██╔══╝ ██║███╗██║ ██║██╔═══██╗ ╚════██║ ╚██╔╝ ██║╚██╗██║ ██║ ██╔══██║ ║
║ ██║ ╚███╔███╔╝ ██║╚██████╔╝ ███████║ ██║ ██║ ╚████║ ██║ ██║ ██║ ║
║ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ║
║ ║
║ ──────── ╭─────╮╭╮╭──╮╭╮╭─────╮ ──────── ║
║ ║
║ ██████╗ ███████╗███╗ ███╗ ██████╗ ██████╗ ║
║ ██╔══██╗██╔════╝████╗ ████║██╔═══██╗██╔══██╗ ║
║ ██║ ██║█████╗ ██╔████╔██║██║ ██║██║ ██║ ║
║ ██║ ██║██╔══╝ ██║╚██╔╝██║██║ ██║██║ ██║ ║
║ ██████╔╝███████╗██║ ╚═╝ ██║╚██████╔╝██████╔╝ ║
║ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ║
║ ║
║ « Design ≠ Marketing » ║
║ ║
║ ┃█┃█┃┃█┃█┃█┃┃█┃█┃┃█┃█┃█┃┃█┃█┃┃█┃█┃█┃┃█┃█┃┃█┃█┃█┃┃█┃█┃┃█┃█┃█┃┃█┃█┃┃█┃█┃█┃ ║
║ ∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿ ║
╚══════════════════════════════════════════════════════════════════════════════╝
Transform your Framework 16 into a professional synthesizer.
A low-latency FluidSynth controller with real-time TUI, SoundFont browser, arpeggiator, layer mode, and touchpad modulation. Built for performance.
- MIDI Input Support — Connect USB MIDI controllers including the FW16 Piano Keyboard Module
- SoundFont Browser — Press
Tabto browse, preview, and load soundfonts - SoundFont Downloader — Press
Dto download popular soundfonts from the internet - Bundled SoundFonts — FluidR3_GM and GeneralUser_GS included out of the box
- Help Overlay — Press
?for quick reference - Arpeggiator — Press
Ato cycle through Up/Down/UpDown/Random modes - Layer Mode — Press
Lto play two instruments simultaneously - Transpose — Press
Shift + </>to transpose ±12 semitones - Velocity Meter — Real-time velocity visualization
- Chord Display — See currently held notes
- Favorites — Star your favorite soundfonts
The Nix package includes high-quality soundfonts ready to use:
| SoundFont | Size | Description |
|---|---|---|
| FluidR3_GM | 141 MB | Industry standard General MIDI |
| GeneralUser_GS | 30 MB | Excellent quality, compact GM/GS set |
Press D in-app to download additional soundfonts including pianos, orchestras, and synths!
# Run directly from GitHub (requires Nix with flakes enabled)
nix run github:ALH477/fw16-synth
# Or clone and run locally
git clone https://github.com/ALH477/fw16-synth.git
cd fw16-synth
nix flake update # Generate/update flake.lock
nix run .
# Development shell
nix develop
python fw16_synth.py# Install dependencies
pip install evdev pyfluidsynth
# Install FluidSynth and a SoundFont
# Debian/Ubuntu: sudo apt install fluidsynth fluid-soundfont-gm
# Fedora: sudo dnf install fluidsynth fluid-soundfont-gm
# Arch: sudo pacman -S fluidsynth soundfont-fluid
# Run
python fw16_synth.py
# Or use the launcher (does pre-flight checks)
./launch.sh-
Input group membership (required for keyboard/touchpad access):
sudo usermod -aG input $USER # Log out and back in
-
Audio server: PipeWire, PulseAudio, or JACK
-
SoundFont: The app auto-discovers soundfonts, or specify with
--soundfont
╔═══ FW16 SYNTH ═══════════════════════════════════ FluidR3_GM ═══╗
║ Oct:4 T:+0 │ Prog:000 Acoustic Grand │ SUS LYR ARP:--- TCH ║
╟──────────────────────────────────────────────────────────────────────╢
║ [`][1][2][3][4][5][6][7][8][9][0][-][=][⌫] ║
║ [⇥][Q][W][E][R][T][Y][U][I][O][P][[][]][\\] ║
║ [⇪][A][S][D][F][G][H][J][K][L][;]['][↵] ║
║ [⇧][Z][X][C][V][B][N][M][,][.][/][⇧] ║
║ [Ctrl] [❖] [Alt] [━━━━━ SUSTAIN ━━━━━] [Alt] [Fn] [Ctrl] ║
╟──────────────────────────────────────────────────────────────────────╢
║ ·····+·····│····· │ ├─ Meters ─┤ ║
║ ·····│·····│····· │ Vel ████████ 98 ║
║ ─────●─────│───── │ Bend ████░░░░ +25% ║
║ ·····│·····│····· │ Filt ██████░░ 89 ║
║ ·····+·····│····· │ Expr ████████ 112 ║
║ Touchpad (X=Bend) │ Chord: C4 E4 G4 ║
╟──────────────────────────────────────────────────────────────────────╢
║ 14:32:05 Program → 0: Acoustic Grand ║
║ 14:32:08 ♪ C4 ON vel=98 ║
╟──────────────────────────────────────────────────────────────────────╢
║ [?] Help [Tab] SoundFonts [+/-] Oct [</>] Transpose [L] Layer ║
╚══════════════════════════════════════════════════════════════════════╝
┌───────────────────────────────────────────────────────────────────┐
│ ` 1 2 3 4 5 6 7 8 9 0 - = ⌫ │
│ C# D# F# G# A# C# D# Oct Oct │
├───────────────────────────────────────────────────────────────────┤
│ ⇥ Q W E R T Y U I O P [ ] \ │
│ C D E F G A B C D E F G │
│ Main Octave │
├───────────────────────────────────────────────────────────────────┤
│ ⇪ A S D F G H J K L ; ' ↵ │
│ C D E F G A B C D E F │
│ Lower Octave (-1) │
├───────────────────────────────────────────────────────────────────┤
│ ⇧ Z X C V B N M , . / ⇧ │
│ C D E F G A B C D E │
│ Bass Octave (-2) │
├───────────────────────────────────────────────────────────────────┤
│ Ctrl ❖ Alt ━━━━━━━━ SUSTAIN ━━━━━━━━ Alt Fn Ctrl │
└───────────────────────────────────────────────────────────────────┘
| Key | Function |
|---|---|
Space |
Sustain pedal |
+ / - |
Octave up/down |
Shift + < |
Transpose down |
Shift + > |
Transpose up |
Page Up/Down |
Previous/next instrument |
F1-F12 |
Quick presets |
Tab |
Open SoundFont browser |
D |
Open SoundFont downloader |
M |
Toggle MIDI input (FW16 Piano Module) |
L |
Toggle layer mode |
A |
Cycle arpeggiator modes |
? |
Show help overlay |
Esc |
Panic (all notes off) |
Ctrl+C |
Exit |
| Key | Instrument | Key | Instrument |
|---|---|---|---|
| F1 | Acoustic Grand | F7 | Brass Section |
| F2 | Electric Piano 1 | F8 | Tenor Sax |
| F3 | Drawbar Organ | F9 | Flute |
| F4 | Nylon Guitar | F10 | Saw Lead |
| F5 | Synth Strings | F11 | Warm Pad |
| F6 | Choir Aahs | F12 | Atmosphere |
Press Tab to open the browser:
╔══════════════════════════════════════════════════════════════════╗
║ SOUNDFONT BROWSER ║
║ [↑/↓] Select [Enter] Load [F] Favorite [Tab/Esc] Close ║
╟──────────────────────────────────────────────────────────────────╢
║ ▶ ★ FluidR3_GM 140.2MB ║
║ ★ GeneralUser_GS 29.8MB ║
║ Arachno_SoundFont 148.1MB ║
║ Nice-Keys-Ultimate 52.3MB ║
║ SGM-V2.01 235.8MB ║
╟──────────────────────────────────────────────────────────────────╢
║ /usr/share/soundfonts/FluidR3_GM.sf2 ║
╚══════════════════════════════════════════════════════════════════╝
Features:
- Auto-scans common locations (
~/.local/share/soundfonts,/usr/share/soundfonts, Nix store) - Favorites persist across sessions (★ indicator)
- Recent files remembered
- Hot-reload without stopping playback
- File size display
Press A to cycle modes:
- OFF — Normal playing
- UP — Ascending arpeggio
- DOWN — Descending arpeggio
- UP_DOWN — Alternating direction
- RANDOM — Random note selection
Hold notes and they'll be arpeggiated automatically.
Press L to enable layering. Plays two instruments simultaneously:
- Main: Current program
- Layer: Strings (program 48)
Great for creating rich, full sounds.
| Axis | MIDI Control | Effect |
|---|---|---|
| X (horizontal) | Pitch Bend | ±2 semitones |
| Y (vertical) | CC 74 | Filter cutoff |
| Pressure | CC 11 | Expression |
Visual feedback in the TUI shows current position and values.
FW16 Synth supports external MIDI input devices, including the community-made FW16 Piano Keyboard Module by pitstop_tech — a velocity-sensitive piano keyboard that fits in the Framework 16's input module slot.
Connecting MIDI Devices:
- In-app toggle: Press
Mto connect/disconnect MIDI input - Command line:
fw16-synth --midito auto-connect at startup - Specific port:
fw16-synth --midi --midi-port "Piano"to connect by name
List available MIDI ports:
fw16-synth --midi-listSupported MIDI messages:
- Note On/Off with velocity
- Channel Aftertouch (mapped to expression)
- Pitch Bend
- Control Change (all CCs passed through)
- Program Change
The FW16 Piano Keyboard Module features:
- Velocity-sensitive capacitive piano keys
- Aftertouch support for expressive playing
- Standard USB MIDI protocol
- Hot-swap compatible with Framework 16 input deck
When connected, the MIDI indicator lights up in the status bar and notes played on the hardware keyboard trigger FluidSynth directly with true velocity.
# flake.nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
fw16-synth.url = "github:ALH477/fw16-synth";
};
outputs = { nixpkgs, fw16-synth, ... }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [
fw16-synth.nixosModules.default
{
programs.fw16-synth = {
enable = true;
users = [ "your-username" ];
audioDriver = "pipewire"; # pipewire/pulseaudio both use PulseAudio API
enableRealtimeAudio = true;
};
}
];
};
};
}# In your home.nix or home-manager flake config
{ inputs, ... }: {
imports = [ inputs.fw16-synth.homeManagerModules.default ];
programs.fw16-synth = {
enable = true;
audioDriver = "pipewire";
defaultOctave = 4;
defaultProgram = 0; # Acoustic Grand Piano
};
}# Debian/Ubuntu
sudo apt install fluidsynth fluid-soundfont-gm
pip install evdev pyfluidsynth
# Arch
sudo pacman -S fluidsynth soundfont-fluid
pip install evdev pyfluidsynth
# Run
python fw16_synth.py# Add to input group
sudo usermod -aG input $USER
# Log out and back inusage: fw16_synth.py [-h] [--soundfont PATH] [--driver DRIVER]
[--octave N] [--program N] [--velocity N]
[--no-tui] [--verbose] [--log-file PATH]
Options:
--soundfont, -s SoundFont file (.sf2)
--driver, -d Audio: pipewire, pulseaudio, jack, alsa
--octave, -o Starting octave (0-8, default: 4)
--program, -p Starting program (0-127, default: 0)
--velocity Fixed velocity (disables dynamic)
--no-tui Text-only mode
--verbose, -v Debug logging
Note: The pipewire and pulseaudio options both use FluidSynth's PulseAudio driver.
PipeWire provides PulseAudio compatibility, so both work with modern PipeWire setups.
The browser searches:
~/.local/share/soundfonts/(download destination)~/soundfonts/~/Music/soundfonts//usr/share/soundfonts//usr/share/sounds/sf2//nix/store/*soundfont*/(Nix bundled)- Environment paths (BUNDLED_SOUNDFONTS, etc.)
State saved to ~/.config/fw16-synth/soundfonts.json
Press D to open the download browser. Available soundfonts:
| Name | Size | Quality | Description |
|---|---|---|---|
| FluidR3 GM | 141 MB | ★★★★★ | Industry standard, excellent across all instruments |
| GeneralUser GS | 30 MB | ★★★★★ | Compact yet high-quality GM/GS set |
| TimGM6mb | 6 MB | ★★★☆☆ | Tiny but surprisingly good for low-resource systems |
| Name | Size | Quality | Description |
|---|---|---|---|
| Salamander Grand | 440 MB | ★★★★★ | Concert Yamaha C5 with velocity layers |
| YDP Grand Piano | 37 MB | ★★★★☆ | Compact Yamaha grand piano |
| Nice Keys Suite | 69 MB | ★★★★☆ | Piano, electric piano, and organ collection |
| Name | Size | Quality | Description |
|---|---|---|---|
| Sonatina Orchestra | 503 MB | ★★★★★ | Full symphony with multiple articulations |
| Vintage Dreams Waves | 19 MB | ★★★★☆ | Classic analog synth sounds |
Downloads are saved to ~/.local/share/soundfonts/
| Component | Latency |
|---|---|
| Keyboard → evdev | <1ms |
| Processing | <1ms |
| FluidSynth | 1-2ms |
| PipeWire (128 samples) | ~2.7ms |
| Total | ~5ms |
# If you get HTTP 404 or lock file errors:
rm flake.lock
nix flake update
nix run .
# For "cannot write lock file" errors:
nix run . --no-write-lock-file# Check if you're in the input group
groups | grep input
# If not, add yourself:
sudo usermod -aG input $USER
# IMPORTANT: Log out and back in (or reboot) for group change to take effect!
# Then verify with:
groups | grep input
evtest # Should show available devices# Test audio
pactl info # PulseAudio/PipeWire
jack_lsp # JACK
# Test FluidSynth directly
fluidsynth -a pulseaudio /usr/share/soundfonts/FluidR3_GM.sf2FluidSynth doesn't have a native "pipewire" driver. It uses PulseAudio which PipeWire provides:
# These are equivalent for PipeWire users:
fw16-synth --driver pipewire # Uses pulseaudio internally
fw16-synth --driver pulseaudio # Same thing# Check search paths
ls ~/.local/share/soundfonts/
ls /usr/share/soundfonts/
# Specify directly
fw16-synth --soundfont /path/to/soundfont.sf2nix develop
# Run with debug
python fw16_synth.py --verbose
# Format
black fw16_synth.py
# Type check
mypy fw16_synth.pyMIT License — DeMoD LLC
╔══════════════════════════════════════════════════════════════════════════════╗
║ ║
║ ██████╗ ███████╗███╗ ███╗ ██████╗ ██████╗ ║
║ ██╔══██╗██╔════╝████╗ ████║██╔═══██╗██╔══██╗ ║
║ ██║ ██║█████╗ ██╔████╔██║██║ ██║██║ ██║ ║
║ ██║ ██║██╔══╝ ██║╚██╔╝██║██║ ██║██║ ██║ ║
║ ██████╔╝███████╗██║ ╚═╝ ██║╚██████╔╝██████╔╝ ║
║ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ║
║ ║
║ ╭──────────────────────────────╮ ║
║ │ « Design ≠ Marketing » │ ║
║ ╰──────────────────────────────╯ ║
║ ║
║ ┃█┃█┃┃█┃█┃█┃┃█┃█┃┃█┃█┃█┃┃█┃█┃┃█┃█┃█┃┃█┃█┃┃█┃█┃█┃┃█┃█┃┃█┃█┃█┃┃█┃█┃┃█┃█┃█┃ ║
║ ║
║ ∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿ ║
╚══════════════════════════════════════════════════════════════════════════════╝