https://github.com/ruelalarcon/desmos_midi
A Rust-based CLI tool for converting MIDI files into formulas for Desmos.
https://github.com/ruelalarcon/desmos_midi
cli desmos midi music rust
Last synced: over 1 year ago
JSON representation
A Rust-based CLI tool for converting MIDI files into formulas for Desmos.
- Host: GitHub
- URL: https://github.com/ruelalarcon/desmos_midi
- Owner: ruelalarcon
- License: mit
- Created: 2025-02-16T22:45:08.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-02-21T09:19:51.000Z (over 1 year ago)
- Last Synced: 2025-02-21T10:23:49.956Z (over 1 year ago)
- Topics: cli, desmos, midi, music, rust
- Language: Rust
- Homepage:
- Size: 146 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Desmos MIDI Player
> A Rust-based CLI tool for converting MIDI files into formulas for Desmos. Complete with support for note velocity, tempo changes, and even custom soundfonts for different channels/instruments.
## Installation
To use the MIDI Player, you must have [Rust](https://www.rust-lang.org/tools/install) installed on your system.
### Prerequisites
**Windows:**
- No additional prerequisites
**Linux/WSL (Ubuntu/Debian):**
```bash
# Install X11 development libraries
sudo apt update
sudo apt install libxcb1-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
```
**Other Linux distributions:**
- Equivalent X11 development packages for your package manager
### Building
Clone this repository and navigate to the directory:
```bash
git clone https://github.com/ruelalarcon/desmos_midi.git
cd desmos_midi
```
Then build the project using the provided script:
**Windows:**
```bash
./build.bat
```
**Linux/Mac:**
```bash
./build.sh
```
> Note: You may need to run `chmod +x *.sh` first to make the scripts executable if they aren't by default.
To clean build artifacts at any time, you can use:
```bash
./clean.bat # Windows
./clean.sh # Linux/Mac
```
## Usage
Navigate to [this Desmos graph](https://www.desmos.com/calculator/dgkzdezlzf).
Once you have a MIDI file you wish to use, run the following command:
**Basic Usage:**
```bash
./run.bat # Windows
./run.sh # Linux/Mac
```
> Note: From now on, we will use `.sh` for the rest of the examples, but if you are on Windows make sure to use the `.bat` versions instead.
**Advanced Usage:**
```bash
./run.sh -s ... # Specify soundfonts for each channel
./run.sh -i # Show channel information
```
### Arguments
- ``: Path to the input MIDI file to convert
- `-s, --soundfonts `: Soundfont files to use for each channel (optional)
- `-i, --info`: Show MIDI channel information and exit
- `-c, --copy`: Copy output to clipboard instead of console
### Soundfonts
By default:
- Regular channels use `default.txt` soundfont
- Drum channels (channel 10) are automatically ignored
- To include drum sounds or use different soundfonts, use the `-s` option and specify a soundfont for each channel
- Use `-` as a soundfont name to ignore that channel
### Usage Examples
1. Basic conversion with default settings (drums ignored):
```bash
./run.sh song.mid
```
2. View channel information:
```bash
./run.sh song.mid -i
```
3. Specify custom soundfonts:
```bash
./run.sh song.mid -s default.txt sine.txt - default.txt
```
This will use:
- `default.txt` for channel 1
- `sine.txt` for channel 2
- ignore channel 3
- `default.txt` for channel 4
4. Copy to clipboard instead of console output:
```bash
./run.sh song.mid -c
```
Now enable audio in Desmos through the button in the top left:

### Graph Controls
- To play the song, hit the arrow button to the left of the `t -> 0` formula.
- To end the song, hit the arrow button to the left of the `t -> ∞` formula.
- You may also set the value of `t` manually to seek to a specific point in the song.
- Open the "Settings" folder to adjust:
- `velocity`: Animation phase speed
- `scale`: Visual waveform amplitude
- `hertz`: Base frequency (default 440Hz)
- `detune`: The amount of detune applied to the secondary tone
- `volume`: Global volume control
- `transpose`: Global pitch shift in semitones
## Technical Details
### MIDI Processing
1. **MIDI Parsing**:
- Uses the `midly` crate to parse MIDI files
- Extracts note events (Note On/Off) and timing information
- Handles tempo changes to ensure accurate timing
- Preserves note velocities (0-127) for dynamic volume control
- Properly tracks note durations for accurate playback
2. **Timing Conversion**:
- Converts MIDI ticks to milliseconds using the formula:
```
ms = (ticks * tempo) / (ticks_per_quarter * 1000)
```
- Where:
- `ticks`: MIDI event time in ticks
- `tempo`: Microseconds per quarter note (default: 500000 = 120 BPM)
- `ticks_per_quarter`: MIDI file's time division (ticks per quarter note)
3. **Note Processing**:
- Tracks active notes and their velocities at each timestamp
- Converts MIDI note numbers to relative positions from A (MIDI note 69 / 440 Hz)
- Each note is paired with its velocity value and duration
- Generates a Desmos piecewise function in the format:
```
A=\left\{t<1:\left[0,100,0\right],t<2:\left[2,85,0\right],...\right\}
```
- Where each note is represented by three values:
- Semitones relative to A4 (440Hz)
- Velocity (0-127)
- Soundfont index
4. **Section Processing**:
- If a MIDI file is too long for Desmos to parse, the program will automatically split it into sections
- The sections are named `A_{1}`, `A_{2}`, etc.
- The main `A` formula selects the appropriate section based on time
5. **Soundfont Processing**:
- Soundfonts are stored in the `soundfonts/` directory and are text files containing comma-separated floating point values representing harmonic weights (weights for each frequency in the harmonic series, which can be used to generate a static waveform)
- The `B` is a "list of lists" of harmonic weights, however, Desmos does not support nested lists so instead, the `C` value is the maximum size of the soundfont arrays (after padding) and we use that to index sublists in `B`
## Dependencies
- `midly`: MIDI file parsing
- `clipboard`: System clipboard integration
- `clap`: Command line argument parsing
## Credits
- [Desmos](https://www.desmos.com/) for the formula visualization
- [Berrynote](https://www.youtube.com/@berrynote/videos) for the initial graph for playing notes on Desmos. [Berrynote's recent video](https://www.youtube.com/watch?v=g2Lp-gIa3es) was the inspiration and base for this project.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
This project is licensed under the MIT License - see the LICENSE file for details.