A generative AI project that composes two-part harmony in the style of J.S. Bach. Given a soprano melody, the system learns to generate a counterpoint bass line using LSTM neural networks trained on the JSB Chorales corpus.
| File | Description |
|---|---|
train.py |
Trains an LSTM model on soprano-only melodies |
generate.py |
Generates soprano-only output from chorale_lstm.pt |
train_bass.py |
Trains a bass model conditioned on existing soprano lines |
generate_bass.py |
Generates a bass line given a soprano sequence and trained bass_lstm.pt |
train_joint_bass_and_soprano.py |
Trains a joint model that learns soprano + bass interaction in interleaved form |
generate_joint_bass_and_soprano.py |
Generates both soprano and bass lines using the joint model joint_lstm.pt |
bach_dataset.py |
Loads JSB chorale data and processes them into token sequences |
model.py |
Contains the PyTorch ChoraleLSTM class definition |
This project uses uv for dependency management:
uv venv && source .venv/bin/activate
uv pip install -r uv.lockTo install dependencies manually:
uv pip install torch music21python train.pySaves model to chorale_lstm.pt
python train_bass.pySaves model to bass_lstm.pt
python train_joint_bass_and_soprano.pySaves model to joint_lstm.pt
python generate.pyCreates output/generated.mid and generated.xml
python generate_bass.pyLoads chorale_lstm_with_keys.pt and bass_lstm.pt, creates output/soprano_bass.mid
python generate_joint_bass_and_soprano.pyParses generated.xml, completes with bass, saves to output/joint_generated.mid/xml
Inside examples/ you'll find chronological generations:
| File | Description |
|---|---|
generated.xml/mid |
Soprano-only melody |
soprano_bass_old.mid/xml → _old_1 → _old_4 |
Early attempts at melody-conditioned bass generation |
joint_generated.xml/mid |
✅ Best result to date — generated using the interleaved Soprano + Bass joint model |
- PyTorch
- music21
- uv (package manager)
- Add Alto and Tenor for full SATB
- Visualization (piano roll / staff preview)
- Longer-form chorale generation
- Music-theory-aware loss constraints
Built by Timothy Williams using open-source data from music21.
Inspired by J.S. Bach's chorale harmonizations.