TL;DR
We train a Swin-Transformer masked-autoencoder ("representation autoencoder") on piano-roll images of MIDI, using only internal-consistency objectives (LeJEPA attraction + SIGReg, factorization, cross-level masked-embedding prediction) — no reconstruction loss. This page collects the supplemental evidence that the learned six-level hierarchy encodes musical structure: probe suites over nine encoder variants, equivariance measurements, phrase-boundary detection against human annotations, and ablations of auxiliary harmonic supervision.
STORMBIRD probe results
STORMBIRD (Sweeping Test Of Representational Music Benchmarks, Information Retrieval & Diagnostics) is our suite of probes of musical qualities, available at github.com/drscotthawley/stormbird. Every encoder variant is evaluated with the full suite: linear probes on frozen embeddings at all six hierarchy levels (L0 = coarsest, one global vector per 128×128 crop; L5 = finest, 4×4-pixel patches). Cell shading is a per-row plasma heatmap (yellow = best in row); bold = best per row. Equivariance is reported as the R² of a linear fit of per-level embedding distance versus shift magnitude.
Encoder roster
| label | run tag | characteristics |
| baseline | c55enc3_vkrDxf | C55cUL recipe, no auxiliary supervision. 250 epochs, POP909. The unsupervised reference. |
| chord-0.5 | chord_ynHbKs | + chord heads (root 12-way, quality 4-way) on coarse levels L0–L3, λ=0.5. 250 epochs, POP909. |
| chord-0.1 | chord01b | Chord heads L0–L3, λ=0.1, 250 epochs. |
| chord-1.0 | chord10 | Chord heads L0–L3, λ=1.0, 250 epochs. |
| phrase | phrase_B2AWUj | + phrase-boundary head (1 logit/patch, Dai et al. annotations) on L0–L3, λ=0.5. 250 epochs. |
| chall-scr1 | mchordall_screen | Chord heads on ALL levels L0–L5, λ=1.0 (0.167/level after 6-level averaging). 100-epoch screen tier. |
| chall-scr1.5 | mchordall_matched | Chord heads on all levels, λ=1.5 = 0.25/level, weight-matched to the coarse-only λ=1.0 arm. 100-epoch screen tier. |
| lakh1x | lakh1x_DKCVEJ | Baseline recipe on Lakh512_1x (909 Lakh images); probes are cross-domain. |
| lakh4x | lakh4x_qw3nqL | Same, on the nested 4× Lakh subset (3636 images). |
Probe tables
Chord quality accuracy
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0 | .527 | .530 | .526 | .524 | .516 | .549 | .502 | .539 | .534 |
| L1 | .526 | .522 | .532 | .540 | .548 | .536 | .516 | .545 | .538 |
| L2 | .540 | .513 | .536 | .548 | .519 | .551 | .544 | .549 | .534 |
| L3 | .540 | .543 | .517 | .492 | .510 | .544 | .534 | .548 | .528 |
| L4 | .540 | .534 | .528 | .523 | .529 | .555 | .540 | .534 | .533 |
| L5 | .536 | .549 | .526 | .524 | .537 | .549 | .532 | .541 | .546 |
Root note accuracy (12-class, chance .083)
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0 | .094 | .457 | .090 | .480 | .086 | .229 | .418 | .101 | .106 |
| L1 | .090 | .570 | .102 | .555 | .102 | .313 | .541 | .111 | .104 |
| L2 | .107 | .594 | .138 | .607 | .118 | .330 | .578 | .132 | .109 |
| L3 | .132 | .582 | .212 | .627 | .160 | .328 | .564 | .169 | .161 |
| L4 | .203 | .405 | .246 | .442 | .199 | .305 | .563 | .206 | .198 |
| L5 | .243 | .242 | .253 | .251 | .221 | .242 | .254 | .220 | .263 |
Chroma regression R²
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0 | -.019 | .686 | -.020 | .704 | -.011 | .188 | .676 | -.006 | -.016 |
| L1 | -.019 | .692 | .016 | .733 | .019 | .300 | .711 | .032 | .004 |
| L2 | .064 | .731 | .133 | .737 | .096 | .444 | .760 | .132 | .073 |
| L3 | .277 | .826 | .380 | .825 | .286 | .563 | .823 | .396 | .296 |
| L4 | .310 | .828 | .380 | .835 | .509 | .635 | .824 | .621 | .424 |
| L5 | .646 | .824 | .460 | .839 | .751 | .726 | .813 | .758 | .614 |
Key detection accuracy
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0 | .043 | .415 | .041 | .396 | .052 | .154 | .349 | .054 | .053 |
| L1 | .047 | .602 | .047 | .572 | .047 | .228 | .575 | .065 | .055 |
| L2 | .054 | .688 | .068 | .706 | .073 | .277 | .681 | .075 | .062 |
| L3 | .077 | .698 | .113 | .737 | .097 | .256 | .674 | .089 | .111 |
| L4 | .128 | .403 | .146 | .415 | .134 | .232 | .615 | .135 | .134 |
| L5 | .158 | .174 | .172 | .189 | .171 | .173 | .185 | .151 | .178 |
Note density R²
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0 | .413 | .584 | .414 | .597 | .437 | .620 | .683 | .631 | .527 |
| L1 | .508 | .655 | .525 | .656 | .546 | .660 | .680 | .673 | .593 |
| L2 | .611 | .745 | .593 | .732 | .617 | .762 | .760 | .763 | .730 |
| L3 | .723 | .803 | .676 | .765 | .740 | .808 | .840 | .796 | .786 |
| L4 | .769 | .889 | .753 | .869 | .813 | .829 | .844 | .881 | .866 |
| L5 | .884 | .913 | .787 | .885 | .890 | .925 | .841 | .936 | .938 |
Cross-song distance ratio (↓ lower is better)
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0 | .803 | .745 | .731 | .728 | .600 | .714 | .636 | .785 | .822 |
| L1 | .814 | .729 | .721 | .736 | .586 | .757 | .750 | .745 | .830 |
| L2 | .848 | .745 | .731 | .755 | .610 | .774 | .774 | .749 | .829 |
| L3 | .799 | .837 | .724 | .787 | .566 | .767 | .783 | .651 | .849 |
| L4 | .847 | .993 | .700 | .731 | .605 | .862 | .938 | .619 | .814 |
| L5 | .925 | 1.062 | .755 | .731 | .648 | .884 | .921 | .676 | .770 |
Time-translation R²
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0 | .194 | .192 | .180 | .180 | .182 | .171 | .186 | .212 | .181 |
| L1 | .248 | .242 | .230 | .235 | .240 | .194 | .203 | .241 | .203 |
| L2 | .250 | .231 | .242 | .236 | .241 | .196 | .187 | .249 | .219 |
| L3 | .239 | .226 | .241 | .209 | .234 | .198 | .173 | .232 | .220 |
| L4 | .261 | .208 | .237 | .159 | .212 | .109 | .101 | .192 | .215 |
| L5 | .211 | .157 | .190 | .127 | .152 | .135 | .099 | .140 | .176 |
EMOPIA 4-class accuracy (chance .25)
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0 | .476 | .449 | .461 | .457 | .469 | .473 | .458 | .487 | .484 |
| L1 | .486 | .460 | .487 | .440 | .465 | .462 | .455 | .494 | .492 |
| L2 | .483 | .474 | .488 | .457 | .478 | .475 | .468 | .496 | .487 |
| L3 | .467 | .483 | .475 | .465 | .481 | .462 | .482 | .486 | .468 |
| L4 | .444 | .451 | .417 | .451 | .468 | .452 | .444 | .459 | .460 |
| L5 | .403 | .426 | .393 | .400 | .408 | .410 | .400 | .417 | .422 |
EMOPIA arousal (binary)
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0 | .765 | .750 | .763 | .771 | .763 | .750 | .747 | .756 | .755 |
| L1 | .765 | .761 | .768 | .759 | .770 | .753 | .749 | .769 | .759 |
| L2 | .769 | .764 | .768 | .764 | .761 | .759 | .763 | .772 | .768 |
| L3 | .762 | .755 | .766 | .758 | .770 | .753 | .745 | .768 | .767 |
| L4 | .767 | .763 | .743 | .752 | .769 | .753 | .741 | .757 | .767 |
| L5 | .758 | .754 | .763 | .725 | .755 | .727 | .697 | .774 | .755 |
EMOPIA valence (binary)
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0 | .600 | .602 | .593 | .599 | .600 | .594 | .605 | .599 | .610 |
| L1 | .611 | .639 | .606 | .596 | .615 | .604 | .611 | .605 | .619 |
| L2 | .627 | .628 | .628 | .605 | .611 | .626 | .610 | .631 | .599 |
| L3 | .618 | .618 | .625 | .620 | .626 | .594 | .613 | .622 | .602 |
| L4 | .585 | .552 | .559 | .583 | .612 | .577 | .571 | .594 | .598 |
| L5 | .535 | .553 | .537 | .547 | .545 | .548 | .551 | .557 | .555 |
Pitch transposition equivariance R²
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0_128px | 1.000 | .999 | .996 | .995 | .999 | .999 | .997 | .998 | .999 |
| L1_64px | .997 | .995 | .991 | .986 | .996 | .996 | .993 | .994 | .998 |
| L2_32px | .991 | .992 | .986 | .984 | .990 | .987 | .985 | .983 | .997 |
| L3_16px | .990 | .985 | .988 | .974 | .991 | .981 | .971 | .989 | .990 |
| L4_8px | .963 | .871 | .963 | .805 | .966 | .125 | .199 | .963 | .968 |
| L5_4px | .878 | .747 | .872 | .700 | .912 | .478 | .388 | .834 | .893 |
Time translation equivariance R²
| baseline | chord-0.5 | chord-0.1 | chord-1.0 | phrase | chall-scr1 | chall-scr1.5 | lakh1x | lakh4x | |
|---|---|---|---|---|---|---|---|---|---|
| L0_128px | .980 | .938 | .964 | .933 | .978 | .925 | .946 | .982 | .981 |
| L1_64px | .911 | .801 | .905 | .795 | .920 | .765 | .743 | .940 | .962 |
| L2_32px | .848 | .680 | .835 | .710 | .853 | .644 | .586 | .905 | .941 |
| L3_16px | .730 | .569 | .762 | .565 | .751 | .571 | .495 | .782 | .790 |
| L4_8px | .539 | .431 | .536 | .398 | .530 | .314 | .325 | .506 | .562 |
| L5_4px | .408 | .366 | .403 | .347 | .423 | .335 | .321 | .388 | .412 |
Structure analyses
Phrase-boundary detection vs. human annotations
We slide each encoder over full-song piano rolls, compute per-level self-similarity, extract Foote novelty curves, and score detected boundaries against the human-verified phrase annotations of Dai et al. (2020) (700 songs after alignment verification). F1 with tolerance in image columns (8 columns = 1 beat).
| level | L0 | L1 | L2 | L3 | L4 | L5 | pixel |
|---|---|---|---|---|---|---|---|
| baseline · F1@16 | .170 | .149 | .150 | .148 | .125 | .100 | .048 |
| baseline · F1@32 | .303 | .277 | .248 | .229 | .201 | .182 | .098 |
| chord-0.5 · F1@16 | .134 | .115 | .075 | .120 | .114 | .093 | .048 |
| chord-0.5 · F1@32 | .246 | .225 | .163 | .202 | .191 | .165 | .098 |
| phrase-encoder · F1@16 | .179 | .154 | .159 | .141 | .123 | .100 | .048 |
| phrase-encoder · F1@32 | .308 | .274 | .243 | .230 | .199 | .194 | .098 |
A linear probe asks whether a human-annotated boundary lies within half a bar of a 4-bar crop's center, from mean-pooled frozen embeddings per level (train/test split by song). Boundary information is real but weak, concentrated at coarse levels, and raw pixels carry none.
Linear boundary-detection probe — AP (chance = .17 (crop base rate))
| L0 | L1 | L2 | L3 | L4 | L5 | pixels | |
|---|---|---|---|---|---|---|---|
| model | |||||||
| MRJS | .273 | .269 | .263 | .210 | .205 | .191 | .181 |
| +chords | .241 | .239 | .248 | .194 | .184 | .175 | .181 |
| +phrases | .279 | .282 | .294 | .224 | .177 | .186 | .181 |
| Lakh1x | .267 | .283 | .272 | .257 | .171 | .189 | .181 |
| Lakh4x | .262 | .261 | .258 | .212 | .189 | .184 | .181 |
| MRJ48 | .224 | .277 | .267 | .222 | .182 | .196 | .181 |
| DINOv2 | .210 | .200 | — | — | — | — | .181 |
Linear boundary-detection probe — AUC (chance = .50)
| L0 | L1 | L2 | L3 | L4 | L5 | pixels | |
|---|---|---|---|---|---|---|---|
| model | |||||||
| MRJS | .613 | .603 | .594 | .562 | .544 | .514 | .508 |
| +chords | .580 | .563 | .574 | .537 | .510 | .502 | .508 |
| +phrases | .617 | .605 | .605 | .567 | .513 | .513 | .508 |
| Lakh1x | .594 | .608 | .586 | .583 | .493 | .512 | .508 |
| Lakh4x | .614 | .596 | .598 | .559 | .525 | .505 | .508 |
| MRJ48 | .563 | .598 | .613 | .573 | .517 | .529 | .508 |
| DINOv2 | .572 | .549 | — | — | — | — | .508 |
Equivariance curves
Per-level embedding distance as a function of pitch transposition / time translation, per encoder. Figures regenerate from the probe runs.
Pitch transposition



Time translation



Probe summaries



Soft factorization of pitch and time
A cosine-similarity loss on augmentation difference vectors pulls pitch- and time-shift directions toward parallel, anti-parallel, or orthogonal geometry depending on augmentation type; no directions are prescribed, only their pairwise relationships. The loss is applied only at the three coarsest levels (L0–L2).






Per level: PCA of normalized embedding difference vectors (left) and cosine-similarity histograms per pair type (right). The geometry visible at L3–L5 is inherited through the shared backbone rather than directly enforced.
Ablation studies
Design decisions behind the production recipe, from screening campaigns run during development: how transformer depth is allocated across the hierarchy, and how the main loss weights were chosen. Cells are shaded per row (plasma, yellow = best in row, honoring each row's arrow).
Ablations: model architecture
Eight alternative allocations of transformer blocks across the six Swin levels, trained and probed identically to the baseline (100-epoch screens, scalar λ=0.15, SIGReg on L0–L3). Content probes quoted at L5, their best level; ✗ = catastrophic L5 chroma collapse (R² of −77 to −713 despite normal training curves).
| baseline [2,2,2,6,2,2] |
uniform3 [3,3,3,3,3,3] |
plus1 [3,3,3,6,3,3] |
deep8 [2,2,2,8,2,2] |
plus2 ⚠ [4,4,4,6,4,4] |
uniform4 [4,4,4,4,4,4] |
coarse ⚠ [4,4,4,6,2,2] |
pyramid ⚠ [2,3,4,6,4,3] |
fine [2,2,2,6,4,4] |
|
|---|---|---|---|---|---|---|---|---|---|
| Blocks | 16 | 18 | 22 | 18 | 26 | 24 | 22 | 22 | 20 |
| Chroma R² L5 ↑ | .701 | .736 | .583 | .746 | ✗ | .537 | ✗ | ✗ | −.070 |
| Key L5 ↑ | .178 | .234 | — | .200 | .192 | .210 | .222 | .218 | .189 |
| Root L5 ↑ | .264 | .301 | .263 | .262 | .265 | .264 | .272 | .275 | .248 |
| Density L5 ↑ | .893 | .907 | .891 | .892 | .903 | .892 | .929 | .946 | .920 |
| Cross-song min ↓ | .631 | .715 | .507 | .727 | .751 | .789 | .652 | .661 | .683 |
| Val loss ↓ | — | .358 | .340 | .359 | .335 | .321 | .321 | .324 | .341 |
Depth buys little and risks a lot: the only decisive wins over the 16-block baseline are deep8's chroma and uniform3's root/key, while every variant with L2≥4 and L3=6 collapsed. The two best validation losses belong to a collapsed model and the worst-chroma survivor — val loss is a poor architecture-selection criterion here.
Ablations: hyperparameters
Per-level SIGReg strength (λ schedule)
Nine per-level λ schedules on the uniform3 backbone, all applying SIGReg to every level (n_skip=0); the reference applies scalar λ=0.15 to L0–L3 only. xmep1 adds cross-level masked-embedding prediction — the seed of the eventual production recipe.
| reference 0.15 scalar, L0–L3 |
min [.15×4,.10,.05] |
gentle [.15,.13,.12,.11,.10,.05] |
std [.30,.25,.20,.15,.10,.05] |
steep [.50,.35,.25,.15,.10,.05] |
inv1 [.10,.13,.15,.15,.10,.05] |
inv2 [.05,.10,.15,.20,.10,.05] |
peak ⚠ [.10,.15,.20,.20,.10,.05] |
lowflat [.10×4,.08,.05] |
lowest [.07×5,.05] |
xmep1 ⚠ cross-level MEP |
|
|---|---|---|---|---|---|---|---|---|---|---|---|
| Chroma R² L5 ↑ | .562 | .582 | .559 | .629 | .625 | .576 | .512 | ✗ | .609 | .578 | ✗ |
| Key L5 ↑ | .208 | .155 | .137 | .175 | .179 | .175 | .185 | .166 | .160 | .187 | .218 |
| Root L5 ↑ | .267 | .226 | .213 | .233 | .245 | .245 | .255 | .230 | .216 | .240 | .267 |
| Density L5 ↑ | .790 | .811 | .860 | .868 | .790 | .821 | .723 | .901 | .760 | .829 | .918 |
| Cross-song min ↓ | .539 | .571 | .659 | .498 | .537 | .537 | .666 | .621 | .671 | .820 | .655 |
| Val loss ↓ | .362 | .517 | .479 | .539 | .554 | .476 | .397 | .492 | .397 | .350 | .317 |
No schedule beat the scalar reference on key/root — with the caveat, noted by the sweep itself, that the reference also skips SIGReg at L4/L5 entirely, so schedule shape and level count are confounded. The lightest schedule won val loss while its L5 cross-song ratio exceeded 1.0, and xmep1 won val loss while destroying L5 chroma: both dissociate loss from representation quality.
Chord-supervision weight λchord
Auxiliary chord heads (root + quality) at increasing loss weight, on coarse levels L0–L3 unless marked "/all" (all six levels; the per-level weight is the total divided by six). Values are each metric's best across levels, one consistent probe-suite vintage. The "/all" arms are 100-epoch screens; the rest are 250-epoch runs.
| 0 (baseline) |
0.1 | 0.5 | 1.0 | 1.0 / all (=0.167/level) |
1.5 / all (=0.25/level) |
|
|---|---|---|---|---|---|---|
| Root ↑ | .229 | .253 | .602 | .627 | .330 | .578 |
| Key ↑ | .171 | .172 | .681 | .737 | .277 | .681 |
| Chroma R² ↑ | .680 | .460 | .824 | .839 | .726 | .824 |
| Density ↑ | .881 | .787 | .921 | .885 | .925 | .844 |
| Cross-song min ↓ | .836 | .700 | .813 | .728 | .714 | .636 |
Chord supervision switches on between λ=0.1 (indistinguishable from baseline) and λ=0.5, with λ=1.0 marginally stronger. Spreading λ=1.0 over six levels cuts the effect to a third, and weight-matching (1.5/all = 0.25/level) restores it — the "all-levels hurts" reading was per-level dilution, not cross-level interference.
Listening examples
Each example takes a 4-bar crop from a held-out POP909 song (the Input tab), paints a blob-shaped mask over part of it, and asks the flow model to re-imagine the masked region four times (seeds 0–3) with conditioning dropout of 0.85 on the two finest hierarchy levels (L4/L5) — the demo's default “magic strength.” Music outside the mask is preserved exactly. Generated with the live demo's API (10 flow steps, guidance 1.0). Players need network access for the soundfont.
Example 1 — POP909 song 007
Example 2 — POP909 song 072
Example 3 — POP909 song 128
Example 4 — POP909 song 197
Example 5 — POP909 song 251
Runtime performance
Wall-clock execution time for the full pipeline (encode → sample → render) across hardware backends. Shading is a per-row plasma heatmap, inverted relative to the result tables: yellow = fastest. Parenthesized values are speedups relative to the 2-thread CPU baseline.
These are general-case timings (guidance strength ≠ 1.0, two function evaluations per Euler step). At the default strength of exactly 1.0 the unconditional branch is skipped and sampling times halve.
| CPU 2 threads |
CPU all cores |
MPS (M1 Max) |
CUDA (4090 Laptop) |
|
|---|---|---|---|---|
| encode (ms) | 8.6 (1×) | 8.7 (0.99×) | 19.9 (0.43×) | 5.8 (1.49×) |
| sample (ms) | 7,475 (1×) | 5,586 (1.34×) | 1,178 (6.34×) | 194 (38.6×) |
| render (ms) | 2.7 | 1.7 | 1.9 | 1.6 |
| end-to-end (s) | 7.49 (1×) | 5.6 (1.34×) | 1.2 (6.24×) | 0.2 (37.2×) |
Links & citation
- POP909 dataset: music-x-lab/POP909-Dataset
- Phrase annotations: Dai, Zhang & Dannenberg (2020)
- EMOPIA: Hung et al. (2021)
- MIDI player: html-midi-player by Ondřej Cífka
@misc{midiraejepason2026,
author = {Scott H. Hawley},
title = {Helping Music Co-Creation Agents `Listen' Well:
Hierarchical Self-Supervised World Models for
Understanding and Generation},
note = {Submitted to NeurIPS Creative AI Track},
year = {2026}
}