#!/usr/bin/env python3 """MIDI Demo Page generator — Bach Prelude BWV 846 × Muse VCS. Outputs: artifacts/midi-demo.html Demonstrates Muse's 21-dimensional MIDI version control using Bach's Prelude No. 1 in C Major (BWV 846). Note data sourced from the music21 corpus (MuseScore 1.3 transcription, 2013-07-09, musescore.com/score/117279). Bach died 1750 — public domain. Format: [pitch_midi, velocity, start_sec, duration_sec, measure, voice] """ import json import logging import pathlib logger = logging.getLogger(__name__) # ────────────────────────────────────────────────────────────────────────────── # Bach BWV 846 — note data extracted from music21 corpus MusicXML # Voices: 1=treble arpeggios (pitch 55-81), 5=bass long notes (36-60), # 6=inner voice (47-64). Tempo: 66 BPM, Duration: ~127s. # ────────────────────────────────────────────────────────────────────────────── _BACH_NOTES_JSON = ( "[[60,64,0.0,1.5833,1,5],[64,64,0.2083,0.5938,1,6],[67,80,0.4167,0.1979,1,1]," "[72,80,0.625,0.1979,1,1],[76,80,0.8333,0.1979,1,1],[67,80,1.0417,0.1979,1,1]," "[72,80,1.25,0.1979,1,1],[76,80,1.4583,0.1979,1,1],[60,64,1.6667,1.5833,1,5]," "[64,64,1.875,0.5938,1,6],[67,80,2.0833,0.1979,1,1],[72,80,2.2917,0.1979,1,1]," "[76,80,2.5,0.1979,1,1],[67,80,2.7083,0.1979,1,1],[72,80,2.9167,0.1979,1,1]," "[76,80,3.125,0.1979,1,1],[60,64,3.3333,1.5833,2,5],[62,64,3.5417,0.5938,2,6]," "[69,80,3.75,0.1979,2,1],[74,80,3.9583,0.1979,2,1],[77,80,4.1667,0.1979,2,1]," "[69,80,4.375,0.1979,2,1],[74,80,4.5833,0.1979,2,1],[77,80,4.7917,0.1979,2,1]," "[60,64,5.0,1.5833,2,5],[62,64,5.2083,0.5938,2,6],[69,80,5.4167,0.1979,2,1]," "[74,80,5.625,0.1979,2,1],[77,80,5.8333,0.1979,2,1],[69,80,6.0417,0.1979,2,1]," "[74,80,6.25,0.1979,2,1],[77,80,6.4583,0.1979,2,1],[59,64,6.6667,1.5833,3,5]," "[62,64,6.875,0.5938,3,6],[67,80,7.0833,0.1979,3,1],[74,80,7.2917,0.1979,3,1]," "[77,80,7.5,0.1979,3,1],[67,80,7.7083,0.1979,3,1],[74,80,7.9167,0.1979,3,1]," "[77,80,8.125,0.1979,3,1],[59,64,8.3333,1.5833,3,5],[62,64,8.5417,0.5938,3,6]," "[67,80,8.75,0.1979,3,1],[74,80,8.9583,0.1979,3,1],[77,80,9.1667,0.1979,3,1]," "[67,80,9.375,0.1979,3,1],[74,80,9.5833,0.1979,3,1],[77,80,9.7917,0.1979,3,1]," "[60,64,10.0,1.5833,4,5],[64,64,10.2083,0.5938,4,6],[67,80,10.4167,0.1979,4,1]," "[72,80,10.625,0.1979,4,1],[76,80,10.8333,0.1979,4,1],[67,80,11.0417,0.1979,4,1]," "[72,80,11.25,0.1979,4,1],[76,80,11.4583,0.1979,4,1],[60,64,11.6667,1.5833,4,5]," "[64,64,11.875,0.5938,4,6],[67,80,12.0833,0.1979,4,1],[72,80,12.2917,0.1979,4,1]," "[76,80,12.5,0.1979,4,1],[67,80,12.7083,0.1979,4,1],[72,80,12.9167,0.1979,4,1]," "[76,80,13.125,0.1979,4,1],[60,64,13.3333,1.5833,5,5],[64,64,13.5417,0.5938,5,6]," "[69,80,13.75,0.1979,5,1],[76,80,13.9583,0.1979,5,1],[81,80,14.1667,0.1979,5,1]," "[69,80,14.375,0.1979,5,1],[76,80,14.5833,0.1979,5,1],[81,80,14.7917,0.1979,5,1]," "[60,64,15.0,1.5833,5,5],[64,64,15.2083,0.5938,5,6],[69,80,15.4167,0.1979,5,1]," "[76,80,15.625,0.1979,5,1],[81,80,15.8333,0.1979,5,1],[69,80,16.0417,0.1979,5,1]," "[76,80,16.25,0.1979,5,1],[81,80,16.4583,0.1979,5,1],[60,64,16.6667,1.5833,6,5]," "[62,64,16.875,0.5938,6,6],[66,80,17.0833,0.1979,6,1],[69,80,17.2917,0.1979,6,1]," "[74,80,17.5,0.1979,6,1],[66,80,17.7083,0.1979,6,1],[69,80,17.9167,0.1979,6,1]," "[74,80,18.125,0.1979,6,1],[60,64,18.3333,1.5833,6,5],[62,64,18.5417,0.5938,6,6]," "[66,80,18.75,0.1979,6,1],[69,80,18.9583,0.1979,6,1],[74,80,19.1667,0.1979,6,1]," "[66,80,19.375,0.1979,6,1],[69,80,19.5833,0.1979,6,1],[74,80,19.7917,0.1979,6,1]," "[59,64,20.0,1.5833,7,5],[62,64,20.2083,0.5938,7,6],[67,80,20.4167,0.1979,7,1]," "[74,80,20.625,0.1979,7,1],[79,80,20.8333,0.1979,7,1],[67,80,21.0417,0.1979,7,1]," "[74,80,21.25,0.1979,7,1],[79,80,21.4583,0.1979,7,1],[59,64,21.6667,1.5833,7,5]," "[62,64,21.875,0.5938,7,6],[67,80,22.0833,0.1979,7,1],[74,80,22.2917,0.1979,7,1]," "[79,80,22.5,0.1979,7,1],[67,80,22.7083,0.1979,7,1],[74,80,22.9167,0.1979,7,1]," "[79,80,23.125,0.1979,7,1],[59,64,23.3333,1.5833,8,5],[60,64,23.5417,0.5938,8,6]," "[64,80,23.75,0.1979,8,1],[67,80,23.9583,0.1979,8,1],[72,80,24.1667,0.1979,8,1]," "[64,80,24.375,0.1979,8,1],[67,80,24.5833,0.1979,8,1],[72,80,24.7917,0.1979,8,1]," "[59,64,25.0,1.5833,8,5],[60,64,25.2083,0.5938,8,6],[64,80,25.4167,0.1979,8,1]," "[67,80,25.625,0.1979,8,1],[72,80,25.8333,0.1979,8,1],[64,80,26.0417,0.1979,8,1]," "[67,80,26.25,0.1979,8,1],[72,80,26.4583,0.1979,8,1],[57,64,26.6667,1.5833,9,5]," "[60,64,26.875,0.5938,9,6],[64,80,27.0833,0.1979,9,1],[67,80,27.2917,0.1979,9,1]," "[72,80,27.5,0.1979,9,1],[64,80,27.7083,0.1979,9,1],[67,80,27.9167,0.1979,9,1]," "[72,80,28.125,0.1979,9,1],[57,64,28.3333,1.5833,9,5],[60,64,28.5417,0.5938,9,6]," "[64,80,28.75,0.1979,9,1],[67,80,28.9583,0.1979,9,1],[72,80,29.1667,0.1979,9,1]," "[64,80,29.375,0.1979,9,1],[67,80,29.5833,0.1979,9,1],[72,80,29.7917,0.1979,9,1]," "[50,64,30.0,1.5833,10,5],[57,64,30.2083,0.5938,10,6],[62,80,30.4167,0.1979,10,1]," "[66,80,30.625,0.1979,10,1],[72,80,30.8333,0.1979,10,1],[62,80,31.0417,0.1979,10,1]," "[66,80,31.25,0.1979,10,1],[72,80,31.4583,0.1979,10,1],[50,64,31.6667,1.5833,10,5]," "[57,64,31.875,0.5938,10,6],[62,80,32.0833,0.1979,10,1],[66,80,32.2917,0.1979,10,1]," "[72,80,32.5,0.1979,10,1],[62,80,32.7083,0.1979,10,1],[66,80,32.9167,0.1979,10,1]," "[72,80,33.125,0.1979,10,1],[55,64,33.3333,1.5833,11,5],[59,64,33.5417,0.5938,11,6]," "[62,80,33.75,0.1979,11,1],[67,80,33.9583,0.1979,11,1],[71,80,34.1667,0.1979,11,1]," "[62,80,34.375,0.1979,11,1],[67,80,34.5833,0.1979,11,1],[71,80,34.7917,0.1979,11,1]," "[55,64,35.0,1.5833,11,5],[59,64,35.2083,0.5938,11,6],[62,80,35.4167,0.1979,11,1]," "[67,80,35.625,0.1979,11,1],[71,80,35.8333,0.1979,11,1],[62,80,36.0417,0.1979,11,1]," "[67,80,36.25,0.1979,11,1],[71,80,36.4583,0.1979,11,1],[55,64,36.6667,1.5833,12,5]," "[58,64,36.875,0.5938,12,6],[64,80,37.0833,0.1979,12,1],[67,80,37.2917,0.1979,12,1]," "[73,80,37.5,0.1979,12,1],[64,80,37.7083,0.1979,12,1],[67,80,37.9167,0.1979,12,1]," "[73,80,38.125,0.1979,12,1],[55,64,38.3333,1.5833,12,5],[58,64,38.5417,0.5938,12,6]," "[64,80,38.75,0.1979,12,1],[67,80,38.9583,0.1979,12,1],[73,80,39.1667,0.1979,12,1]," "[64,80,39.375,0.1979,12,1],[67,80,39.5833,0.1979,12,1],[73,80,39.7917,0.1979,12,1]," "[53,64,40.0,1.5833,13,5],[57,64,40.2083,0.5938,13,6],[62,80,40.4167,0.1979,13,1]," "[69,80,40.625,0.1979,13,1],[74,80,40.8333,0.1979,13,1],[62,80,41.0417,0.1979,13,1]," "[69,80,41.25,0.1979,13,1],[74,80,41.4583,0.1979,13,1],[53,64,41.6667,1.5833,13,5]," "[57,64,41.875,0.5938,13,6],[62,80,42.0833,0.1979,13,1],[69,80,42.2917,0.1979,13,1]," "[74,80,42.5,0.1979,13,1],[62,80,42.7083,0.1979,13,1],[69,80,42.9167,0.1979,13,1]," "[74,80,43.125,0.1979,13,1],[53,64,43.3333,1.5833,14,5],[56,64,43.5417,0.5938,14,6]," "[62,80,43.75,0.1979,14,1],[65,80,43.9583,0.1979,14,1],[71,80,44.1667,0.1979,14,1]," "[62,80,44.375,0.1979,14,1],[65,80,44.5833,0.1979,14,1],[71,80,44.7917,0.1979,14,1]," "[53,64,45.0,1.5833,14,5],[56,64,45.2083,0.5938,14,6],[62,80,45.4167,0.1979,14,1]," "[65,80,45.625,0.1979,14,1],[71,80,45.8333,0.1979,14,1],[62,80,46.0417,0.1979,14,1]," "[65,80,46.25,0.1979,14,1],[71,80,46.4583,0.1979,14,1],[52,64,46.6667,1.5833,15,5]," "[55,64,46.875,0.5938,15,6],[60,80,47.0833,0.1979,15,1],[67,80,47.2917,0.1979,15,1]," "[72,80,47.5,0.1979,15,1],[60,80,47.7083,0.1979,15,1],[67,80,47.9167,0.1979,15,1]," "[72,80,48.125,0.1979,15,1],[52,64,48.3333,1.5833,15,5],[55,64,48.5417,0.5938,15,6]," "[60,80,48.75,0.1979,15,1],[67,80,48.9583,0.1979,15,1],[72,80,49.1667,0.1979,15,1]," "[60,80,49.375,0.1979,15,1],[67,80,49.5833,0.1979,15,1],[72,80,49.7917,0.1979,15,1]," "[52,64,50.0,1.5833,16,5],[53,64,50.2083,0.5938,16,6],[57,80,50.4167,0.1979,16,1]," "[60,80,50.625,0.1979,16,1],[65,80,50.8333,0.1979,16,1],[57,80,51.0417,0.1979,16,1]," "[60,80,51.25,0.1979,16,1],[65,80,51.4583,0.1979,16,1],[52,64,51.6667,1.5833,16,5]," "[53,64,51.875,0.5938,16,6],[57,80,52.0833,0.1979,16,1],[60,80,52.2917,0.1979,16,1]," "[65,80,52.5,0.1979,16,1],[57,80,52.7083,0.1979,16,1],[60,80,52.9167,0.1979,16,1]," "[65,80,53.125,0.1979,16,1],[50,64,53.3333,1.5833,17,5],[53,64,53.5417,0.5938,17,6]," "[57,80,53.75,0.1979,17,1],[60,80,53.9583,0.1979,17,1],[65,80,54.1667,0.1979,17,1]," "[57,80,54.375,0.1979,17,1],[60,80,54.5833,0.1979,17,1],[65,80,54.7917,0.1979,17,1]," "[50,64,55.0,1.5833,17,5],[53,64,55.2083,0.5938,17,6],[57,80,55.4167,0.1979,17,1]," "[60,80,55.625,0.1979,17,1],[65,80,55.8333,0.1979,17,1],[57,80,56.0417,0.1979,17,1]," "[60,80,56.25,0.1979,17,1],[65,80,56.4583,0.1979,17,1],[43,64,56.6667,1.5833,18,5]," "[50,64,56.875,0.5938,18,6],[55,80,57.0833,0.1979,18,1],[59,80,57.2917,0.1979,18,1]," "[65,80,57.5,0.1979,18,1],[55,80,57.7083,0.1979,18,1],[59,80,57.9167,0.1979,18,1]," "[65,80,58.125,0.1979,18,1],[43,64,58.3333,1.5833,18,5],[50,64,58.5417,0.5938,18,6]," "[55,80,58.75,0.1979,18,1],[59,80,58.9583,0.1979,18,1],[65,80,59.1667,0.1979,18,1]," "[55,80,59.375,0.1979,18,1],[59,80,59.5833,0.1979,18,1],[65,80,59.7917,0.1979,18,1]," "[48,64,60.0,1.5833,19,5],[52,64,60.2083,0.5938,19,6],[55,80,60.4167,0.1979,19,1]," "[60,80,60.625,0.1979,19,1],[64,80,60.8333,0.1979,19,1],[55,80,61.0417,0.1979,19,1]," "[60,80,61.25,0.1979,19,1],[64,80,61.4583,0.1979,19,1],[48,64,61.6667,1.5833,19,5]," "[52,64,61.875,0.5938,19,6],[55,80,62.0833,0.1979,19,1],[60,80,62.2917,0.1979,19,1]," "[64,80,62.5,0.1979,19,1],[55,80,62.7083,0.1979,19,1],[60,80,62.9167,0.1979,19,1]," "[64,80,63.125,0.1979,19,1],[48,64,63.3333,1.5833,20,5],[55,64,63.5417,0.5938,20,6]," "[58,80,63.75,0.1979,20,1],[60,80,63.9583,0.1979,20,1],[64,80,64.1667,0.1979,20,1]," "[58,80,64.375,0.1979,20,1],[60,80,64.5833,0.1979,20,1],[64,80,64.7917,0.1979,20,1]," "[48,64,65.0,1.5833,20,5],[55,64,65.2083,0.5938,20,6],[58,80,65.4167,0.1979,20,1]," "[60,80,65.625,0.1979,20,1],[64,80,65.8333,0.1979,20,1],[58,80,66.0417,0.1979,20,1]," "[60,80,66.25,0.1979,20,1],[64,80,66.4583,0.1979,20,1],[41,64,66.6667,1.5833,21,5]," "[53,64,66.875,0.5938,21,6],[57,80,67.0833,0.1979,21,1],[60,80,67.2917,0.1979,21,1]," "[64,80,67.5,0.1979,21,1],[57,80,67.7083,0.1979,21,1],[60,80,67.9167,0.1979,21,1]," "[64,80,68.125,0.1979,21,1],[41,64,68.3333,1.5833,21,5],[53,64,68.5417,0.5938,21,6]," "[57,80,68.75,0.1979,21,1],[60,80,68.9583,0.1979,21,1],[64,80,69.1667,0.1979,21,1]," "[57,80,69.375,0.1979,21,1],[60,80,69.5833,0.1979,21,1],[64,80,69.7917,0.1979,21,1]," "[42,64,70.0,1.5833,22,5],[48,64,70.2083,0.5938,22,6],[57,80,70.4167,0.1979,22,1]," "[60,80,70.625,0.1979,22,1],[63,80,70.8333,0.1979,22,1],[57,80,71.0417,0.1979,22,1]," "[60,80,71.25,0.1979,22,1],[63,80,71.4583,0.1979,22,1],[42,64,71.6667,1.5833,22,5]," "[48,64,71.875,0.5938,22,6],[57,80,72.0833,0.1979,22,1],[60,80,72.2917,0.1979,22,1]," "[63,80,72.5,0.1979,22,1],[57,80,72.7083,0.1979,22,1],[60,80,72.9167,0.1979,22,1]," "[63,80,73.125,0.1979,22,1],[44,64,73.3333,1.5833,23,5],[53,64,73.5417,0.5938,23,6]," "[59,80,73.75,0.1979,23,1],[60,80,73.9583,0.1979,23,1],[62,80,74.1667,0.1979,23,1]," "[59,80,74.375,0.1979,23,1],[60,80,74.5833,0.1979,23,1],[62,80,74.7917,0.1979,23,1]," "[44,64,75.0,1.5833,23,5],[53,64,75.2083,0.5938,23,6],[59,80,75.4167,0.1979,23,1]," "[60,80,75.625,0.1979,23,1],[62,80,75.8333,0.1979,23,1],[59,80,76.0417,0.1979,23,1]," "[60,80,76.25,0.1979,23,1],[62,80,76.4583,0.1979,23,1],[43,64,76.6667,1.5833,24,5]," "[53,64,76.875,0.5938,24,6],[55,80,77.0833,0.1979,24,1],[59,80,77.2917,0.1979,24,1]," "[62,80,77.5,0.1979,24,1],[55,80,77.7083,0.1979,24,1],[59,80,77.9167,0.1979,24,1]," "[62,80,78.125,0.1979,24,1],[43,64,78.3333,1.5833,24,5],[53,64,78.5417,0.5938,24,6]," "[55,80,78.75,0.1979,24,1],[59,80,78.9583,0.1979,24,1],[62,80,79.1667,0.1979,24,1]," "[55,80,79.375,0.1979,24,1],[59,80,79.5833,0.1979,24,1],[62,80,79.7917,0.1979,24,1]," "[43,64,80.0,1.5833,25,5],[52,64,80.2083,0.5938,25,6],[55,80,80.4167,0.1979,25,1]," "[60,80,80.625,0.1979,25,1],[64,80,80.8333,0.1979,25,1],[55,80,81.0417,0.1979,25,1]," "[60,80,81.25,0.1979,25,1],[64,80,81.4583,0.1979,25,1],[43,64,81.6667,1.5833,25,5]," "[52,64,81.875,0.5938,25,6],[55,80,82.0833,0.1979,25,1],[60,80,82.2917,0.1979,25,1]," "[64,80,82.5,0.1979,25,1],[55,80,82.7083,0.1979,25,1],[60,80,82.9167,0.1979,25,1]," "[64,80,83.125,0.1979,25,1],[43,64,83.3333,1.5833,26,5],[50,64,83.5417,0.5938,26,6]," "[55,80,83.75,0.1979,26,1],[59,80,83.9583,0.1979,26,1],[65,80,84.1667,0.1979,26,1]," "[55,80,84.375,0.1979,26,1],[59,80,84.5833,0.1979,26,1],[65,80,84.7917,0.1979,26,1]," "[43,64,85.0,1.5833,26,5],[50,64,85.2083,0.5938,26,6],[55,80,85.4167,0.1979,26,1]," "[59,80,85.625,0.1979,26,1],[65,80,85.8333,0.1979,26,1],[55,80,86.0417,0.1979,26,1]," "[59,80,86.25,0.1979,26,1],[65,80,86.4583,0.1979,26,1],[43,64,86.6667,1.5833,27,5]," "[51,64,86.875,0.5938,27,6],[57,80,87.0833,0.1979,27,1],[60,80,87.2917,0.1979,27,1]," "[66,80,87.5,0.1979,27,1],[57,80,87.7083,0.1979,27,1],[60,80,87.9167,0.1979,27,1]," "[66,80,88.125,0.1979,27,1],[43,64,88.3333,1.5833,27,5],[51,64,88.5417,0.5938,27,6]," "[57,80,88.75,0.1979,27,1],[60,80,88.9583,0.1979,27,1],[66,80,89.1667,0.1979,27,1]," "[57,80,89.375,0.1979,27,1],[60,80,89.5833,0.1979,27,1],[66,80,89.7917,0.1979,27,1]," "[43,64,90.0,1.5833,28,5],[52,64,90.2083,0.5938,28,6],[55,80,90.4167,0.1979,28,1]," "[60,80,90.625,0.1979,28,1],[67,80,90.8333,0.1979,28,1],[55,80,91.0417,0.1979,28,1]," "[60,80,91.25,0.1979,28,1],[67,80,91.4583,0.1979,28,1],[43,64,91.6667,1.5833,28,5]," "[52,64,91.875,0.5938,28,6],[55,80,92.0833,0.1979,28,1],[60,80,92.2917,0.1979,28,1]," "[67,80,92.5,0.1979,28,1],[55,80,92.7083,0.1979,28,1],[60,80,92.9167,0.1979,28,1]," "[67,80,93.125,0.1979,28,1],[43,64,93.3333,1.5833,29,5],[50,64,93.5417,0.5938,29,6]," "[55,80,93.75,0.1979,29,1],[60,80,93.9583,0.1979,29,1],[65,80,94.1667,0.1979,29,1]," "[55,80,94.375,0.1979,29,1],[60,80,94.5833,0.1979,29,1],[65,80,94.7917,0.1979,29,1]," "[43,64,95.0,1.5833,29,5],[50,64,95.2083,0.5938,29,6],[55,80,95.4167,0.1979,29,1]," "[60,80,95.625,0.1979,29,1],[65,80,95.8333,0.1979,29,1],[55,80,96.0417,0.1979,29,1]," "[60,80,96.25,0.1979,29,1],[65,80,96.4583,0.1979,29,1],[43,64,96.6667,1.5833,30,5]," "[50,64,96.875,0.5938,30,6],[55,80,97.0833,0.1979,30,1],[59,80,97.2917,0.1979,30,1]," "[65,80,97.5,0.1979,30,1],[55,80,97.7083,0.1979,30,1],[59,80,97.9167,0.1979,30,1]," "[65,80,98.125,0.1979,30,1],[43,64,98.3333,1.5833,30,5],[50,64,98.5417,0.5938,30,6]," "[55,80,98.75,0.1979,30,1],[59,80,98.9583,0.1979,30,1],[65,80,99.1667,0.1979,30,1]," "[55,80,99.375,0.1979,30,1],[59,80,99.5833,0.1979,30,1],[65,80,99.7917,0.1979,30,1]," "[36,64,100.0,1.5833,31,5],[48,64,100.2083,0.5938,31,6],[55,80,100.4167,0.1979,31,1]," "[58,80,100.625,0.1979,31,1],[64,80,100.8333,0.1979,31,1],[55,80,101.0417,0.1979,31,1]," "[58,80,101.25,0.1979,31,1],[64,80,101.4583,0.1979,31,1],[36,64,101.6667,1.5833,31,5]," "[48,64,101.875,0.5938,31,6],[55,80,102.0833,0.1979,31,1],[58,80,102.2917,0.1979,31,1]," "[64,80,102.5,0.1979,31,1],[55,80,102.7083,0.1979,31,1],[58,80,102.9167,0.1979,31,1]," "[64,80,103.125,0.1979,31,1],[36,64,103.3333,1.5833,32,5],[48,64,103.5417,0.5938,32,6]," "[53,80,103.75,0.1979,32,1],[57,80,103.9583,0.1979,32,1],[60,80,104.1667,0.1979,32,1]," "[65,80,104.375,0.1979,32,1],[60,80,104.5833,0.1979,32,1],[57,80,104.7917,0.1979,32,1]," "[60,80,105.0,0.1979,32,1],[57,80,105.2083,0.1979,32,1],[53,80,105.4167,0.1979,32,1]," "[57,80,105.625,0.1979,32,1],[53,80,105.8333,0.1979,32,1],[50,80,106.0417,0.1979,32,1]," "[53,80,106.25,0.1979,32,1],[50,80,106.4583,0.1979,32,1],[36,64,116.3636,1.7273,33,5]," "[47,64,116.5909,0.6477,33,6],[67,80,116.8182,0.2159,33,1],[71,80,117.0455,0.2159,33,1]," "[74,80,117.2727,0.2159,33,1],[77,80,117.5,0.2159,33,1],[74,80,117.7273,0.2159,33,1]," "[71,80,117.9545,0.2159,33,1],[74,80,118.1818,0.2159,33,1],[71,80,118.4091,0.2159,33,1]," "[67,80,118.6364,0.2159,33,1],[71,80,118.8636,0.2159,33,1],[62,80,119.0909,0.2159,33,1]," "[65,80,119.3182,0.2159,33,1],[64,80,119.5455,0.2159,33,1],[62,80,119.7727,0.2159,33,1]," "[64,80,120.0,3.4545,34,1],[36,64,120.0,3.4545,34,5],[67,80,123.6364,3.4545,34,1]," "[72,80,123.6364,3.4545,34,1],[48,64,123.6364,3.4545,34,5]]" ) # ────────────────────────────────────────────────────────────────────────────── # 21 MIDI Dimensions # ────────────────────────────────────────────────────────────────────────────── _DIMS_21: list[dict[str, str]] = [ {"id": "notes", "label": "Notes", "group": "core", "color": "#00d4ff", "desc": "note_on/note_off — the musical content itself"}, {"id": "pitch_bend", "label": "Pitch Bend", "group": "expr", "color": "#7c6cff", "desc": "pitchwheel — semitone-accurate pitch deviation"}, {"id": "channel_pressure", "label": "Ch. Pressure", "group": "expr", "color": "#9d8cff", "desc": "aftertouch — mono channel pressure"}, {"id": "poly_pressure", "label": "Poly Aftertouch","group": "expr", "color": "#b8a8ff", "desc": "polytouch — per-note polyphonic aftertouch"}, {"id": "cc_modulation", "label": "Modulation", "group": "cc", "color": "#ff6b9d", "desc": "CC 1 — modulation wheel depth"}, {"id": "cc_volume", "label": "Volume", "group": "cc", "color": "#ff8c42", "desc": "CC 7 — channel volume level"}, {"id": "cc_pan", "label": "Pan", "group": "cc", "color": "#ffd700", "desc": "CC 10 — stereo pan position"}, {"id": "cc_expression", "label": "Expression", "group": "cc", "color": "#00ff87", "desc": "CC 11 — expression controller"}, {"id": "cc_sustain", "label": "Sustain Pedal", "group": "cc", "color": "#00d4ff", "desc": "CC 64 — damper/sustain pedal"}, {"id": "cc_portamento", "label": "Portamento", "group": "cc", "color": "#66e0ff", "desc": "CC 65 — portamento on/off"}, {"id": "cc_sostenuto", "label": "Sostenuto", "group": "cc", "color": "#99eaff", "desc": "CC 66 — sostenuto pedal"}, {"id": "cc_soft_pedal", "label": "Soft Pedal", "group": "cc", "color": "#aaeeff", "desc": "CC 67 — soft pedal (una corda)"}, {"id": "cc_reverb", "label": "Reverb Send", "group": "fx", "color": "#e879f9", "desc": "CC 91 — reverb send level"}, {"id": "cc_chorus", "label": "Chorus Send", "group": "fx", "color": "#c084fc", "desc": "CC 93 — chorus send level"}, {"id": "cc_other", "label": "Other CC", "group": "fx", "color": "#a78bfa", "desc": "All remaining CC numbers"}, {"id": "program_change", "label": "Program/Patch", "group": "meta", "color": "#fb923c", "desc": "program_change — instrument/patch select"}, {"id": "tempo_map", "label": "Tempo Map", "group": "meta", "color": "#f87171", "desc": "set_tempo meta events (non-independent)"}, {"id": "time_signatures", "label": "Time Signatures","group": "meta", "color": "#fbbf24", "desc": "time_signature meta events (non-independent)"}, {"id": "key_signatures", "label": "Key Signatures", "group": "meta", "color": "#a3e635", "desc": "key_signature meta events"}, {"id": "markers", "label": "Markers", "group": "meta", "color": "#34d399", "desc": "marker, cue, text, lyrics, copyright events"}, {"id": "track_structure", "label": "Track Structure","group": "meta", "color": "#94a3b8", "desc": "track_name, sysex, unknown meta (non-independent)"}, ] # ────────────────────────────────────────────────────────────────────────────── # Commit graph definition # dagX: column (0=lower-register, 1=main, 2=upper-register) # dagY: row (0=top) # filter: {minM, maxM, voices[]} or null for no notes # dims: dimension IDs active/modified in this commit # dimAct: activity level per dimension (0-4) # ────────────────────────────────────────────────────────────────────────────── _COMMITS: list[dict[str, object]] = [ { "id": "c0", "sha": "0000000", "branch": "main", "label": "muse init", "message": "Initial commit — muse init --domain midi", "command": "muse init --domain midi", "output": "✓ Initialized Muse repository\n Domain : midi\n Dimensions: 21\n Location : .muse/\n Tracking : muse-work/", "parents": [], "dagX": 1, "dagY": 0, "filter": None, "newVoices": [], "newMeasures": [], "dims": [], "dimAct": {}, "stats": "0 notes · 0 dimensions", "noteCount": 0, }, { "id": "c1", "sha": "a1b2c3d", "branch": "feat/lower-register", "label": "bass + inner\nbars 1–12", "message": "feat: bass and inner voices, bars 1–12", "command": 'muse commit -m "feat: bass and inner voices, bars 1–12"', "output": "✓ [feat/lower-register a1b2c3d]\n 48 notes added\n Dimensions modified: notes, tempo_map,\n time_signatures, track_structure\n Key detected: C major", "parents": ["c0"], "dagX": 0, "dagY": 1, "filter": {"minM": 1, "maxM": 12, "voices": [5, 6]}, "newVoices": [5, 6], "newMeasures": [1, 12], "dims": ["notes", "tempo_map", "time_signatures", "track_structure"], "dimAct": {"notes": 3, "tempo_map": 2, "time_signatures": 2, "track_structure": 1}, "stats": "+48 notes · 4 dimensions", "noteCount": 48, }, { "id": "c2", "sha": "b3c4d5e", "branch": "feat/lower-register", "label": "lower voices\nbars 13–24", "message": "feat: bass and inner voices extended, bars 13–24", "command": 'muse commit -m "feat: bass and inner voices extended, bars 13–24"', "output": "✓ [feat/lower-register b3c4d5e]\n 40 notes added\n Dimensions modified: notes, cc_sustain,\n cc_volume\n Chord progression: Fm → C7 → Dm", "parents": ["c1"], "dagX": 0, "dagY": 2, "filter": {"minM": 1, "maxM": 24, "voices": [5, 6]}, "newVoices": [5, 6], "newMeasures": [13, 24], "dims": ["notes", "cc_sustain", "cc_volume"], "dimAct": {"notes": 3, "cc_sustain": 2, "cc_volume": 1}, "stats": "+40 notes · 3 dimensions", "noteCount": 88, }, { "id": "c3", "sha": "c4d5e6f", "branch": "feat/lower-register", "label": "lower voices\nbars 25–34 + FX", "message": "feat: complete lower register + reverb + expression", "command": 'muse commit -m "feat: complete lower register + reverb + expression"', "output": "✓ [feat/lower-register c4d5e6f]\n 42 notes added\n Dimensions modified: notes, cc_sustain,\n cc_reverb, cc_expression, markers\n Bass descends to C2 (MIDI 36) — full range", "parents": ["c2"], "dagX": 0, "dagY": 3, "filter": {"minM": 1, "maxM": 34, "voices": [5, 6]}, "newVoices": [5, 6], "newMeasures": [25, 34], "dims": ["notes", "cc_sustain", "cc_reverb", "cc_expression", "markers"], "dimAct": {"notes": 3, "cc_sustain": 2, "cc_reverb": 2, "cc_expression": 3, "markers": 1}, "stats": "+42 notes · 5 dimensions", "noteCount": 130, }, { "id": "c4", "sha": "d5e6f7a", "branch": "feat/upper-register", "label": "treble arpeggios\nbars 1–12", "message": "feat: treble arpeggios, bars 1–12", "command": 'muse commit -m "feat: treble arpeggios, bars 1–12"', "output": "✓ [feat/upper-register d5e6f7a]\n 144 notes added\n Dimensions modified: notes, cc_volume,\n program_change\n Voice 1: soprano arpeggios reach A5 (MIDI 81)", "parents": ["c0"], "dagX": 2, "dagY": 1, "filter": {"minM": 1, "maxM": 12, "voices": [1]}, "newVoices": [1], "newMeasures": [1, 12], "dims": ["notes", "cc_volume", "program_change"], "dimAct": {"notes": 4, "cc_volume": 2, "program_change": 1}, "stats": "+144 notes · 3 dimensions", "noteCount": 144, }, { "id": "c5", "sha": "e6f7a8b", "branch": "feat/upper-register", "label": "arpeggios\nbars 13–24", "message": "feat: treble arpeggios, bars 13–24 + modulation", "command": 'muse commit -m "feat: treble arpeggios, bars 13–24 + modulation"', "output": "✓ [feat/upper-register e6f7a8b]\n 120 notes added\n Dimensions modified: notes, cc_modulation,\n cc_expression, key_signatures\n Development section — chromatic tensions", "parents": ["c4"], "dagX": 2, "dagY": 2, "filter": {"minM": 1, "maxM": 24, "voices": [1]}, "newVoices": [1], "newMeasures": [13, 24], "dims": ["notes", "cc_modulation", "cc_expression", "key_signatures"], "dimAct": {"notes": 4, "cc_modulation": 2, "cc_expression": 3, "key_signatures": 1}, "stats": "+120 notes · 4 dimensions", "noteCount": 264, }, { "id": "c6", "sha": "f7a8b9c", "branch": "feat/upper-register", "label": "coda\nbars 25–34", "message": "feat: coda arpeggios bars 25–34 + final dynamics", "command": 'muse commit -m "feat: coda arpeggios bars 25–34 + final dynamics"', "output": "✓ [feat/upper-register f7a8b9c]\n 139 notes added\n Dimensions modified: notes, cc_expression,\n cc_soft_pedal, markers\n Coda: bars 33–34 hold final C major chord", "parents": ["c5"], "dagX": 2, "dagY": 3, "filter": {"minM": 1, "maxM": 34, "voices": [1]}, "newVoices": [1], "newMeasures": [25, 34], "dims": ["notes", "cc_expression", "cc_soft_pedal", "markers"], "dimAct": {"notes": 4, "cc_expression": 3, "cc_soft_pedal": 2, "markers": 2}, "stats": "+139 notes · 4 dimensions", "noteCount": 403, }, { "id": "c7", "sha": "9a0b1c2", "branch": "main", "label": "muse merge\nPrelude complete ✓", "message": "merge: unite lower and upper registers — Prelude BWV 846 complete", "command": "muse merge feat/lower-register feat/upper-register", "output": "✓ [main 9a0b1c2] merge: Prelude BWV 846 complete\n Auto-merged: notes (no pitch conflicts —\n registers non-overlapping)\n Merged dimensions: 10 / 21\n 533 notes · 2:07 duration · Key: C major", "parents": ["c3", "c6"], "dagX": 1, "dagY": 4, "filter": {"minM": 1, "maxM": 34, "voices": [1, 5, 6]}, "newVoices": [1, 5, 6], "newMeasures": [1, 34], "dims": [ "notes", "tempo_map", "time_signatures", "track_structure", "cc_sustain", "cc_volume", "cc_expression", "cc_reverb", "cc_modulation", "cc_soft_pedal", "markers", "program_change", "key_signatures", ], "dimAct": { "notes": 4, "tempo_map": 2, "time_signatures": 2, "track_structure": 1, "cc_sustain": 2, "cc_volume": 2, "cc_expression": 3, "cc_reverb": 2, "cc_modulation": 2, "cc_soft_pedal": 2, "markers": 2, "program_change": 1, "key_signatures": 1, }, "stats": "533 notes · 13 dimensions · 2:07", "noteCount": 533, }, ] def render_midi_demo() -> str: """Generate the complete self-contained MIDI demo HTML page.""" notes_json = _BACH_NOTES_JSON commits_json = json.dumps(_COMMITS, separators=(",", ":")) dims_json = json.dumps(_DIMS_21, separators=(",", ":")) html = _HTML_TEMPLATE html = html.replace("__NOTES_JSON__", notes_json) html = html.replace("__COMMITS_JSON__", commits_json) html = html.replace("__DIMS_JSON__", dims_json) return html # ────────────────────────────────────────────────────────────────────────────── # HTML template (no Python f-strings — JS braces are literal) # ────────────────────────────────────────────────────────────────────────────── _HTML_TEMPLATE = """
Watch Bach's Prelude built commit-by-commit across two parallel branches — then merged automatically using Muse's 21-dimensional MIDI diff engine. 533 authentic notes. Real piano audio. Zero conflicts.
All standard VCS commands (commit, log, branch, merge, diff, …) work on MIDI files. The commands below are MIDI-specific additions provided by MidiPlugin.