An accessibility-first, mouse-driven virtual MIDI keyboard for making music without a physical keyboard. Designed for creators who primarily use a mouse (including users with motor disabilities), Octavium focuses on clear visuals, reliable mouse interactions, and features like sustain and latch that make performance and composition possible without traditional keybeds.
Built with PySide6, mido, and pygame.
- Launcher Window — Central hub to open multiple keyboards and windows simultaneously
- Multiple Keyboards — 25-key, 49-key, 61-key, 73-key, 76-key, and 88-key pianos, plus Harmonic Table
- Standalone Windows — Chord Pad, Pad Grid, Faders, XY Fader, and Modulune can be opened independently
- Shared MIDI — All windows share a single MIDI output to avoid port conflicts
- Click to play — Click any key to play it
- Click and drag — Glide across keys for expressive runs
- Right-click latch — Right-click any key to toggle latch on that specific note (enabled by default)
- Clear visual feedback — Pressed and held states are visually distinct
- Sustain — Keeps notes sounding after mouse release; visuals clear on release so you can see what you touched
- Latch — Toggles notes on/off; click once to start, click again to stop
- Right-Click Latch — Latch individual notes with right-click while using normal clicks for regular playing
- Velocity slider — Adjust note velocity (20–127) with linear, soft, or hard response curves
- Octave controls — Shift the keyboard range up or down
- Scale quantization — Snap notes to a scale to avoid wrong notes
- Polyphony options — Limit voices (1–8) or run unlimited
- MIDI channel selection — Route to any of 16 MIDI channels
- 4×4 grid of chord cards for quick access to saved chords
- Hold-to-play — Hold a card to play the chord, release to stop
- Humanize controls — Add velocity and timing variation for natural feel
- Drag-and-drop — Rearrange cards or move to empty slots
- Drag-to-edit — Drag a card to the keyboard to load and edit, then drag back to save
- Harmonic Table — Isomorphic hex layout with harmonic relationships
- 4×4 Pad Grid — Drum pad grid for triggering samples
- Faders — 8 MIDI CC faders with configurable CC numbers
- XY Fader — 2D pad for expressive control of two CCs
- Python 3.9+ (tested with Python 3.13)
- Windows, macOS, or Linux
- Virtual MIDI port (e.g., loopMIDI on Windows)
# Clone the repository
git clone https://github.com/owenpkent/Octavium.git
cd Octavium
# Create and activate virtual environment
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS/Linux
# Install dependencies
pip install -r requirements.txt
# (Optional) Download the MIDI chord library for chord autofill
.\scripts\fetch_midi_library.ps1
# Run Octavium
python run.pyNote: The MIDI chord library (~30 MB) enables the "MIDI Library" autofill source in the Chord Pad. Octavium works without it — the library can be downloaded later at any time.
pip install -r requirements-dev.txt
python -m pytest tests/ -vCI stands for Continuous Integration — it means every time code is pushed to main (or a pull request is opened against it), GitHub automatically runs checks to make sure nothing is broken. You don't have to run anything manually — GitHub does it for you in the cloud.
The CI configuration lives in .github/workflows/ci.yml. Here's what it does:
| Check | What it does | Why it matters |
|---|---|---|
| Tests | Runs the full test suite (pytest) |
Catches bugs before they reach main |
| Type checking | Runs Pyright on core logic modules | Catches type errors (e.g., passing a string where a number is expected) |
- GitHub spins up fresh virtual machines (Ubuntu and Windows)
- It installs Python (both 3.11 and 3.13, so we test multiple versions)
- It installs the dev dependencies from
requirements-dev.txt - It runs
python -m pytest tests/ -v— the same command you'd run locally
This means tests run on 4 combinations: Ubuntu + Python 3.11, Ubuntu + Python 3.13, Windows + Python 3.11, Windows + Python 3.13. If any combination fails, the whole check fails — so we know the code works everywhere.
- GitHub spins up an Ubuntu machine with Python 3.13
- It installs both production and dev dependencies (Pyright needs to see the real imports)
- It runs Pyright on the pure-logic modules — files that don't depend on the GUI:
app/scale.py,app/models.py,app/chord_suggestions.py,app/preferences.pymodulune/harmony.py,modulune/melody.py,modulune/rhythm.py
We only type-check these files because the GUI modules (PySide6/pygame) have complex types that aren't worth fighting with Pyright over. The pure-logic modules are where type safety matters most.
- Go to the Actions tab on the GitHub repo
- Green checkmark = all checks passed
- Red X = something failed — click into the failed job to see the error output
- CI runs automatically on every push and PR; you never need to trigger it manually
You can run the same checks locally before pushing:
# Run tests (same as CI)
python -m pytest tests/ -v
# Run type checking (same as CI lint job)
pip install pyright
pyright app/scale.py app/models.py app/chord_suggestions.py app/preferences.py modulune/harmony.py modulune/melody.py modulune/rhythm.pyIf these pass locally, they'll pass in CI.
When you run Octavium, the launcher window appears with options to open:
| Keyboards | Windows | Generative |
|---|---|---|
| 25-Key Piano | Chord Pad | Modulune |
| 49-Key Piano | Pad Grid | |
| 61-Key Piano | Faders | |
| Harmonic Table | XY Fader |
Open multiple windows simultaneously — the launcher stays open for easy access.
| Action | Result |
|---|---|
| Click a key | Play the note |
| Click and drag | Glide across keys |
| Right-click a key | Toggle latch on that note |
| Release | Stop note (unless sustained or latched) |
| Key | Action |
|---|---|
Z |
Octave down |
X |
Octave up |
1 |
Soft velocity curve |
2 |
Linear velocity curve |
3 |
Hard velocity curve |
Q |
Toggle scale quantization |
Esc |
All notes off (panic) |
Ctrl++ / Ctrl+= |
Zoom in |
Ctrl+- |
Zoom out |
- Show Mod Wheel — Display modulation wheel
- Show Pitch Wheel — Display pitch bend wheel
- Hold Visuals During Sustain — Keep keys visually pressed while sustained
- Chord Pad — Open the chord pad window
- Drag While Sustain — Allow dragging across keys while sustain is on
- Right-Click Latch — Enable/disable right-click latch behavior
- Zoom — Scale the UI (50%–200%)
Switch between different layouts:
- Piano sizes: 25, 49, 61, 73, 76, 88 keys
- 4×4 Beat Grid: 16-pad drum grid
- Faders: 8 CC faders
- XY Fader: 2D control pad
- Harmonic Table: Isomorphic hex layout
The Harmonic Table is an isomorphic layout where:
- Horizontal movement = perfect fifths
- Diagonal movement = major/minor thirds
- Octave-based colors help with visual navigation
- Duplicate note highlighting shows all instances of the same pitch
- Default base note is C2 at the lower-left
- Download and install loopMIDI
- Create a virtual MIDI port (e.g., "loopMIDI Port 1")
- Configure your DAW to receive MIDI from this port
- Open Audio MIDI Setup
- Window → Show MIDI Studio
- Double-click IAC Driver
- Enable "Device is online"
- Add a port if needed
Use MIDI → Select Output Port to choose your MIDI destination. When using the launcher, all windows share the same MIDI output.
Octavium/
├── run.py # Entry point
├── app/
│ ├── launcher.py # Launcher window
│ ├── main.py # Main keyboard window
│ ├── keyboard_widget.py # Piano keyboard widget
│ ├── harmonic_table.py # Harmonic table widget
│ ├── chord_monitor_window.py # Chord monitor
│ ├── pad_grid.py # 4×4 pad grid
│ ├── faders.py # CC faders
│ ├── xy_fader.py # XY fader pad
│ ├── midi_io.py # MIDI output abstraction
│ ├── scale.py # Scale quantization
│ └── themes.py # UI styling
└── modulune/ # Generative engine (see below)
Generative Impressionistic Piano Engine
Modulune is Octavium's generative counterpart. While Octavium gives users direct expressive control over MIDI performance, Modulune creates musical intention autonomously—generating continuously evolving piano textures in real time.
| Octavium | Modulune |
|---|---|
| The instrument | The player |
| Direct expressive control | Algorithmic creativity |
| User-driven | System-driven |
Both share the same philosophy: accessibility, experimentation, and musical exploration—allowing anyone to produce rich, evolving piano textures either interactively or fully autonomously.
- Dual-hand generation — Independent left and right hand textures
- Right hand textures: Shimmering Chords, Flowing Arpeggios, Melodic Fragments, Sparse Meditation, Layered Voices, Impressionist Wash
- Left hand textures: Sustained Bass, Broken Chords, Alberti Bass, Block Chords, Rolling Octaves, Sparse Roots
- Real-time controls — Adjust tempo, key, mode, density, and tension while playing
- Expressive timing — Rubato, swing, and humanization
- Dynamic modulation — Automatic key and mode changes
- GUI and CLI — Launch from the Octavium launcher or run from command line
- Run Octavium:
python run.py - Click Modulune in the Generative section
- Use the GUI controls to adjust parameters
- Click Play to start generating
# Basic usage
python -m modulune.main
# With custom parameters
python -m modulune.main --tempo 60 --key Db --mode lydian
# List available MIDI ports
python -m modulune.main --list-ports| Option | Description | Default |
|---|---|---|
--tempo |
Tempo in BPM | 72 |
--key |
Key root (C, Db, F#, etc.) | C |
--mode |
Scale mode | major |
--density |
Note density (0.0–1.0) | 0.5 |
--tension |
Harmonic tension (0.0–1.0) | 0.3 |
--texture |
Texture type | impressionist_wash |
--port |
MIDI port name | auto |
major, natural_minor, harmonic_minor, melodic_minor, dorian, phrygian, lydian, mixolydian, aeolian, locrian, whole_tone, pentatonic_major, pentatonic_minor, blues
Windows: Use loopMIDI
macOS: Use IAC Driver (Audio MIDI Setup → Show MIDI Studio → IAC Driver)
| DAW | Setup |
|---|---|
| Ableton Live | Preferences → Link/Tempo/MIDI → Enable port → Create MIDI track → Set input |
| FL Studio | Options → MIDI Settings → Enable port → Add VST → Set input |
| Logic Pro | Preferences → MIDI → Create Software Instrument → Record-enable |
| Reaper | Preferences → MIDI Devices → Enable port → Create track → Arm |
Launch from the Octavium launcher or run:
python -m modulune.main --port "loopMIDI Port 1"This project is licensed under the MIT License - see the LICENSE file for details.
Happy music making! 🎵







