Skip to main content

Tiny VAE that writes loopable, catchy MIDI riffs.

Project description

Riffly

A tiny VAE that writes loopable, catchy MIDI riffs.

Riffly trains a Variational Autoencoder on piano-roll segments from a folder of MIDI files, then samples short loops you can save as MIDI, render to audio, or plot. Models are small enough to train on a single GPU in minutes and to run inference on CPU.

Sample output

Unconditional samples — piano rolls with pitch on the y axis (low → high) and time on the x axis.

pop preview   single generated melody

Left: from the bundled pop checkpoint (see Pretrained checkpoint). Listen: melody_3.wav; MIDI in assets/preview/. Right: a single roll plotted with riffly.plot().

Pretrained checkpoint

from riffly import Riffly

model = Riffly("pop")            # downloads on first use, then cached
model.generate(n=4, save="out/", multi_track=True)

Riffly("pop") fetches a ~6 MB ConvVAE trained on the Pop subset of the ADL Piano MIDI Dataset (CC BY 4.0) from this repo's GitHub Releases. The file lands in $XDG_CACHE_HOME/riffly/weights/ (or ~/.cache/riffly/weights/); override with $RIFFLY_HOME. The sha256 is verified on every load.

Install

pip install riffly                   # core (training + MIDI export)
pip install "riffly[interactive]"    # + audio rendering and plotting

Training, plotting, and .wav rendering need the interactive extra. With core only, pass wav=False, png=False to generate(save=...).

torch installs the CUDA (GPU) build by default. On a CPU-only machine, force the CPU build:

uv pip install torch --torch-backend=cpu     # or set UV_TORCH_BACKEND=cpu

Quickstart

from riffly import Riffly

model = Riffly("convvae")                      # or "vae", "transformer"
model.train(data="datasets/adl-piano-midi", epochs=100)
model.generate(n=8, save="out/")               # writes MIDI + WAV + PNG for each melody
model.save("riffly.pt")

Riffly("riffly.pt").generate(n=4, save="more/", wav=False)   # opt out: MIDI + PNG only

That is the whole workflow: construct, train, generate, save.

Pass generate(..., multi_track=True) to split each melody into three voices, melody, chord, and 808 bass, in the saved .mid and .wav.

Plotting a generation

generate(save="out/") writes a .png for every melody. To show one on screen instead (the right-hand image at the top of this README):

from riffly import Riffly, plot

model = Riffly("convvae")
roll = model.generate(n=1)[0]
plot(roll)

Plotting needs the interactive extra (see Install).

Datasets

Point train(data=...) at any folder of .mid files. Three open datasets that work well out of the box:

Dataset Size Source
ADL Piano MIDI ~11k piano MIDIs across many genres https://github.com/lucasnfe/adl-piano-midi
Classical MIDI (Kaggle) ~300 classical MIDIs https://www.kaggle.com/datasets/soumikrakshit/classical-music-midi
The Magic of MIDI v1 ~169k MIDIs scraped from the web https://archive.org/details/themagicofmidi

Download one, unzip it, and pass the folder path. The first run caches the preprocessed dataset under ~/.cache/riffly (override with $RIFFLY_CACHE or train(..., cache_dir=...)) so later runs start instantly.

Advanced usage

The facade wraps lower-level modules that you can still use directly for full control:

  • riffly.modelsVAE, ConvVAE, TransformerVAE.
  • riffly.datasets.MIDIDataset — MIDI folder to (rows, columns) tensors.
  • riffly.traintrain(), validation_loop().
  • riffly.processesMIDIPostprocess, MultiTrackPostprocess (melody + chords + 808 bass), MIDIPreprocess.
  • riffly.plots — dataset previews, training curves, reconstruction grids.

License

MIT. See LICENSE.

The pretrained pop checkpoint distributed via GitHub Releases was trained on the ADL Piano MIDI Dataset (Ferreira & Whitehead, 2020), licensed CC BY 4.0. Attribution is preserved when the checkpoint is redistributed.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

riffly-0.1.0.tar.gz (58.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

riffly-0.1.0-py3-none-any.whl (64.5 kB view details)

Uploaded Python 3

File details

Details for the file riffly-0.1.0.tar.gz.

File metadata

  • Download URL: riffly-0.1.0.tar.gz
  • Upload date:
  • Size: 58.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for riffly-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9261fb81745c1ef07466c647f78ce369edfdfbb6c483734f4ea4884a5e6f8996
MD5 573babda607fb86325c1dd0fa7b619d6
BLAKE2b-256 90ee51c0e83a784b451f2142c6b00b5a85b4a429b90f2c2e0dffd50a28d66092

See more details on using hashes here.

File details

Details for the file riffly-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: riffly-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 64.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for riffly-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 da55de23519d843b0c2fcfa18ace30a06b2654f4036621a8f07a2cde6ec60ee4
MD5 3a47c1091dc3c458baeb6df99f6e22f7
BLAKE2b-256 7c752519504bf5646361414964a7f1d4d3c4633171c3863dea5970ef80196ef3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page