| --- |
| datasets: |
| - loubb/aria-midi |
| - projectlosangeles/maestro-v3.0.0 |
| language: |
| - en |
| tags: |
| - music_infilling |
| - modulation |
| - music_generation |
| --- |
| # ๐น Change is Key: A Generative Framework for Controllable Musical Modulations |
|
|
| [](#) |
| [](https://irrazzib.github.io/modulation-jnmr/) |
| [](https://huggingface.co/keshavbhandari/modulator) |
|
|
| This repository contains the official implementation for **"Change is Key: A Generative Framework for Controllable Musical Modulations"**. |
|
|
| The framework formulates musical modulation as a generative Fill-In-The-Middle (FIM) task using a LLaMA-based architecture. It allows users to select a structural turning point in a MIDI composition, transpose subsequent material to a target key, and autonomously or interactively synthesize a smooth, musically coherent transition bridge. |
|
|
| ## **โ๏ธ Installation** |
|
|
| First, clone this repository and navigate into the modulator folder: |
|
|
| git clone https://github.com/keshavbhandari/modulator.git |
| cd modulator |
|
|
| Set up your environment using Conda: |
|
|
| module load cuda/12.4.0-gcc-12.2.0 \# Optional: For HPC clusters |
| conda create \-n modulate python=3.11 \-y |
| conda activate modulate |
| conda install pytorch torchvision torchaudio pytorch-cuda=12.4 \-c pytorch \-c nvidia \-y |
|
|
| Install the project and its dependencies: |
|
|
| pip install \-e . |
|
|
| ## **๐ Quickstart & Usage** |
|
|
| The primary script for users is modulate\_midi.py. It automatically fetches our pre-trained model weights directly from [Hugging Face (keshavbhandari/modulator)](https://huggingface.co/keshavbhandari/modulator). |
| |
| Run the commands below from the root modulator folder. |
| |
| ### **1\. Autonomous Infilling (No Chord Conditioning)** |
| |
| The model relies strictly on left/right musical context and temporal boundary tokens to autonomously bridge into the new key. |
| |
| python modulate/modulate\_midi.py \\ |
| \--midi\_file path/to/input.mid \\ |
| \--output\_path path/to/output.mid \\ |
| \--semitone\_shift 4 \\ |
| \--chord\_mode none |
| |
| ### **2\. Rule-Guided Modulation (Dynamic Chord Baseline)** |
|
|
| Condition generation on a dynamically calculated functional chord progression that back-cycles diatonic chords to resolve smoothly into the target key. |
|
|
| python modulate/modulate\_midi.py \\ |
| \--midi\_file path/to/input.mid \\ |
| \--output\_path path/to/output.mid \\ |
| \--semitone\_shift 5 \\ |
| \--chord\_mode dynamic |
| |
| ### **3\. LLM-Guided Modulation (Groq API)** |
|
|
| Use a Large Language Model (via the Groq API) to plan custom harmonic progression instructions for the generative bridge based on the surrounding harmonic context. |
|
|
| python modulate/modulate\_midi.py \\ |
| \--midi\_file path/to/input.mid \\ |
| \--output\_path path/to/output.mid \\ |
| \--semitone\_shift 2 \\ |
| \--chord\_mode llm \\ |
| \--api\_key YOUR\_GROQ\_API\_KEY |
| |
| ### **4\. Optimal Modulation Boundary Detection** |
|
|
| Automatically analyze the harmony to identify a structural turning point (e.g., resolving to the tonic) rather than cutting at a generic midpoint. |
|
|
| python modulate/modulate\_midi.py \\ |
| \--midi\_file path/to/input.mid \\ |
| \--output\_path path/to/output.mid \\ |
| \--enable\_optimal\_modulation\_point \\ |
| \--gap\_duration 10000 |
| |
| *(Note: \--gap\_duration is specified in milliseconds. 10000 \= 10 seconds).* |
|
|
| ### **5\. Manual Timestamp Control (Milliseconds)** |
|
|
| Explicitly define exact start and end boundaries (in milliseconds) for the left context, the generative gap, and the right context. |
|
|
| python modulate/modulate\_midi.py \\ |
| \--midi\_file path/to/input.mid \\ |
| \--output\_path path/to/output.mid \\ |
| \--left\_segment\_start\_time 70000 \\ |
| \--left\_segment\_end\_time 110000 \\ |
| \--right\_segment\_start\_time 117000 \\ |
| \--right\_segment\_end\_time 140000 \\ |
| \--semitone\_shift 7 |
| |
| ### **6\. Simple Infilling (Zero Key Change)** |
|
|
| Repair or infill missing segments without transposing the target key by setting the semitone shift to 0\. |
|
|
| python modulate/modulate\_midi.py \\ |
| \--midi\_file path/to/input.mid \\ |
| \--output\_path path/to/output.mid \\ |
| \--semitone\_shift 0 \\ |
| \--chord\_mode none |
| |
| ## **๐๏ธ Script Arguments Reference** |
|
|
| | Argument | Default | Description | |
| | :---- | :---- | :---- | |
| | \--midi\_file | *Required* | Path to the input .mid file. | |
| | \--output\_path | infilled\_output.mid | Target save location for output MIDI. | |
| | \--semitone\_shift | 4 | Semitone transposition for target key (0 for simple infilling). | |
| | \--chord\_mode | none | Conditioning strategy: none, dynamic, or llm. | |
| | \--api\_key | None | Groq API key (required when \--chord\_mode llm). | |
| | \--enable\_optimal\_modulation\_point | False | Analyzes harmony to pick the best structural cut point. | |
| | \--left\_segment\_start\_time | None | Manual left segment start (ms). | |
| | \--left\_segment\_end\_time | None | Manual left segment end / gap start (ms). | |
| | \--right\_segment\_start\_time | None | Manual gap end / right segment start (ms). | |
| | \--right\_segment\_end\_time | None | Manual right segment end (ms). | |
| | \--left\_segment\_duration | 30000 | Fallback left context duration (ms). | |
| | \--right\_segment\_duration | 30000 | Fallback right context duration (ms). | |
| | \--gap\_duration | 5000 | Fallback generated bridge duration (ms). | |
| | \--temperature | 1.0 | Sampling temperature for the LLaMA model generation. | |
| |
| ## **๐ง Model Training** |
| |
| If you would like to continue training the model or train it on your own custom datasets, you can launch the training script using Accelerate: |
| |
| accelerate launch \--num\_processes 1 /data/home/acw769/modulator/modulate/models/infiller\_llama/train.py |
| |
| ## **๐ Citation** |
| |
| If you use this code, model weights, or evaluation framework in your research, please cite our paper: |
| |
| @article{bhandari2026change, |
| title={Change is Key: A Generative Framework for Controllable Musical Modulations}, |
| author={Bhandari, Keshav and Bizzarri, Matteo and Wiggins, Geraint A. and Colton, Simon}, |
| year={2026} |
| } |