Generate MIDI with algorithms and models

Choose algorithmic composition, a locally loaded model or remote inference, then turn the result into editable, playable MIDI.

MIDI generation produces musical events: pitches, start times, durations, velocities and tracks. Choose an algorithm when you want explicit musical rules, a model when you want learned patterns, or combine them. Local and remote execution describe where a model runs, not a different kind of music.

The result still needs an instrument to make sound. Keep generation separate from playback so you can audition the same phrase with different instruments, edit it, save it and export it as MIDI.

Choose an approach

ApproachUseful whenWhat you supplyMain tradeoff
Algorithmic compositionYou need clear harmony, rhythm, range or repeatabilityRules, musical context and a seed when randomness is usedVariation follows the rules you chose
Local model inferenceYou want learned continuation or variation on the user's deviceA compatible checkpoint, tokenizer, runtime and musical promptInitial download, loading time and device memory
Remote model inferenceYou want a model to run on your own server or an external serviceAn inference service and its supported request formatNetwork latency, service capacity and handling uploaded musical material
HybridYou want model variation within a deliberate musical structureAn algorithmic scaffold, model output and validation rulesEach stage needs an explicit musical-data contract

Downloading weights is not remote inference. A browser can download model files from a server and then generate locally. Remote inference sends a request to another process that executes the model and returns the notes.

Start with an algorithm

Useful strategies include step sequences, arpeggios, Euclidean rhythms, weighted note choices, Markov transitions, chord-tone selection and voice-leading rules. Start with the smallest strategy that expresses your idea. A bassline that follows roots and fifths may need no model at all.

Maru's Symbolic library provides musical values and transformations. Symbolic Cycle composes them into patterns in the Code Sequencer. Its generators can draft a progression, melody and bassline without loading model weights. Paste this into Code Sequencer's Symbolic interpreter:

js
const chords = generateProgression({
  scale: "F:major",
  chords: 4,
  seed: 7,
})

export const keys = chords.voicing("open").velocity(0.45)
export const lead = generateMelody({
  over: chords,
  rhythm: "x ~ x x@2 x x@2",
  range: "f4:a5",
  seed: 11,
})
export const bass = generateBassline({
  over: chords,
  rhythm: "x ~ ~ x ~ ~ x ~",
  style: "root-fifth",
})

Keep the seeds fixed while changing the range, rhythm or harmony. This lets you hear what each choice does. Change a seed to explore another take. These functions belong to the Symbolic Cycle environment; this snippet is not a standalone JavaScript file or a model-loading API.

Load a model locally

A note model predicts musical tokens from a context, such as an existing phrase and constraints. Its tokens must be decoded into notes before playback. MIDI pitch numbers are not interchangeable with model token IDs.

Prepare a compatible set of assets: checkpoint, tokenizer, vocabulary, generation configuration and any grammar constraints. An ONNX file alone does not establish that the model's input shapes, token format and decoding behavior are supported.

For a local integration:

  1. Load the runtime and model outside the realtime audio callback. Show loading, failure and cancellation states, and reuse a loaded session across takes.
  2. Encode the musical context using that model's tokenizer. Bound the context and requested output length to what the model supports.
  3. Generate in a worker or another suitable execution boundary, then decode and validate the notes before handing them to playback.
  4. Keep accepted takes independently of the loaded model. Release sessions and their memory when they are no longer needed.

Maru's experimental browser MIDI-GPT implementation uses ONNX graphs with matching tokenization and grammar. The portable midi-gpt-core and midi-gpt-runtime packages are private workspace components; they are not a published general-purpose MIDI model loader. Raw token inference alone does not provide a complete MIDI generator. Check the exact implementation and target before promising browser, native or offline support.

Run inference remotely

Use a server when its hardware, shared model lifetime or service integration fits your product better. The server loads the model; the client sends musical context and generation settings, follows progress or waits for completion, and receives a score or MIDI file.

Keep service credentials on your backend. Support cancellation, bounded request sizes and recovery from an unavailable service. Preserve the source phrase and accepted takes when a request fails. If you offer a local alternative, make the change of execution location explicit before sending material remotely.

Maru has a development MIDI-GPT HTTP bridge configured through the server-side MIDI_GPT_SERVER_URL. It checks the service's /info endpoint and sends score and request data to /generate. The website bridge is development-only; it does not establish a public hosted MIDI generation API or a service available to every account.

For your own remote integration, use the chosen model service's actual contract. Maru's audio generation API returns audio; a generate_audio job is not a MIDI composition request. Audio to MIDI transcribes a recording and is another distinct task.

Combine rules and learned variation

One useful pipeline is to generate chords algorithmically, ask a compatible model to continue a short melody, then inspect the result with Symbolic. Check pitch range, timing, note density and how the melody relates to the harmony. Preserve the raw take alongside any edits, quantization or transposition.

Choose one time representation at each boundary: ticks with a resolution, beats with a tempo map, or seconds. Preserve tempo, time signatures, tracks, channels and note durations when converting to a Standard MIDI File. The host owns scheduling and device access; generated notes reach a module through its declared MIDI ports and existing playback path.

Compare useful musical results

Audition algorithms and models through the same instrument at the same tempo. Judge phrase shape, repetition, harmonic fit, useful variation and the edits needed to make a take work. Measure model loading separately from generation time. Retain checkpoint and tokenizer identities, prompt, seed and sampling settings with each model take; for algorithmic takes, retain the rules and their parameters. A seed alone does not guarantee identical results across different runtimes.

Check the selected model's code, weight and output terms for your intended use. For tokenizer round trips, training comparisons and experiment records, continue with audio and MIDI model experiments. For the musical ideas behind token prediction, see Generating notes.