Math MIDI Studio is a desktop application that turns mathematical
functions and sequences into music. Pick one or more generators - sine
waves, the Fibonacci sequence, prime numbers, the Collatz conjecture, a
chaotic logistic map, L-systems, cellular automata, or a Mandelbrot
escape-time scan - map the resulting values onto pitch, velocity, and
rhythm, preview the result in a DAW-style piano roll, listen to it, and
export it as a standard .mid file ready to drop into Ableton Live (or
any other DAW).
- Ten mathematical generators, each with its own set of live-editable parameters (frequency/amplitude for waves, growth rate for the logistic map, axiom/rules for L-systems, rule number for cellular automata, and so on).
- Multiple layers. Combine several generators in the same project. Each layer has its own source, scale/key, octave range, velocity range, note gate, and rhythm settings, and is color-coded in the piano roll.
- Musical mapping controls - 14 scales (major, natural/harmonic/ melodic minor, modes, pentatonics, blues, whole tone, chromatic), all 12 keys, octave range, velocity range, and note gate (how much of each beat is actually sounded).
- Rhythm engine with three modes: uniform note lengths, lengths derived from the generator's own values, or lengths driven by a second, independent generator.
- Live preview - a raw function/sequence plot above a piano roll that updates automatically (with a short debounce) whenever you change a parameter. Heavy generation runs on a background thread so the UI never freezes.
- Transport controls - play, pause, stop, loop, click-to-seek on the piano roll ruler, and a playhead that follows playback.
- Optional audio preview through a user-supplied SoundFont (
.sf2) via FluidSynth. Without a SoundFont (or withoutpyfluidsynth/FluidSynth installed), everything else - generation, the piano roll, transport position, and MIDI export - still works; only audible playback is disabled. - MIDI export to a
.midfile, with an option to write each layer to its own track/channel and a General MIDI program (instrument) number. - JSON presets - save and load your entire project (all layers,
generator parameters, musical settings, rhythm settings, and global
transport/export settings) as a single
.jsonfile. A few example presets are included inpresets/.
See requirements.txt. The core dependencies are:
- Python 3.10+
numpymidoPySide6pyqtgraph
Optionally, pyfluidsynth (plus the native FluidSynth library and a
.sf2 SoundFont file) enables in-app audio playback.
Install dependencies with:
pip install -r requirements.txtpython3 main.py-
Add layers. The app starts with one layer (a sine wave). Use + Add Layer in the sidebar to add more, and the
\u2715button on a layer's header to remove it (at least one layer is always kept). Each layer can be collapsed with the\u25be/\u25b8button, enabled/disabled with the checkbox, renamed, and re-colored automatically. -
Pick a generator from the dropdown in the layer header. The Function Settings panel below rebuilds itself with the controls for that generator (every numeric value has a slider, a spin box, and - where relevant - a dropdown).
-
Map it to music in Musical Settings: scale, key, octave range, velocity range, and gate (what fraction of each note's slot is actually held).
-
Shape the rhythm in Rhythm Settings:
- Uniform - every note uses the chosen note length.
- Derived from values - the note length is picked from the
Multiplierslist based on the generator's own value at that step. - Secondary source - note lengths are instead driven by a second, independent generator (with its own parameter panel).
-
Global Settings (top of the sidebar) control BPM, time signature, loop length in bars, the maximum number of notes generated per layer, and whether the piano roll colors notes by velocity or by layer.
-
Transport - press play to preview. If a SoundFont is loaded you'll hear the result; either way the playhead moves across the piano roll and you can click the ruler to seek.
-
Export - click Export MIDI... in the toolbar to save a
.midfile. "Separate MIDI track per layer" writes each layer to its own track/channel (each named after the layer); the GM Program field sets the instrument number written into the file. -
Presets - Save Preset... / Load Preset... in the toolbar write/read a JSON file containing the entire project. Try the examples in
presets/:sine_melody.json- a gentle single-layer sine melody.fibonacci_arpeggio.json- a Fibonacci-sequence pentatonic arpeggio with derived rhythm.chaos_lsystem.json- a two-layer combination of a logistic-map lead and an L-system texture layer.cellular_groove.json- a cellular-automaton bassline whose rhythm is driven by a secondary sine generator.
| File | Purpose |
|---|---|
main.py |
Application entry point. |
main_window.py |
The DAW-style main window, layer UI, generation worker, transport, export, and presets. |
math_generators.py |
The ten mathematical generators, scales/keys/note-length tables, and the pipeline that turns generator output into Note objects. |
midi_builder.py |
Builds and writes standard MIDI files from Note objects. |
piano_roll_widget.py |
The custom piano-roll/timeline widget (keyboard sidebar, ruler, note view, zoom). |
playback.py |
Real-time playback engine (optional FluidSynth audio backend + transport thread). |
presets/ |
Example JSON presets. |
Math MIDI Studio looks for pyfluidsynth at startup. If it - or the
native FluidSynth library - isn't available, the status bar's transport
area will say so, and the Load SoundFont (.sf2)... button will simply
report that loading failed. This does not affect generation, the piano
roll, or MIDI export in any way; it only disables the audible "Play"
preview.