music/exemplars/instruments/GROOVE_VALIDATION.md
Tier: MEASURED INSTRUMENT. Produced byharness/music_gen/instr_groove.py, which writes this file, its machine record andGROOVE_BANDS.jsontogether and writes nothing else.
The law it measures: A cue must carry a pulse a listener can feel -- present, steady, and articulated against the metre by voices that tile rather than pile -- so that its rhythm is a structure and never merely a rate.
The grade it answers: Josh on round 3, 2026-08-08 — "it sounds just like a bunch of noise and these main melodies really suck. They clash and have no rythm or complexity." The battery scored round 3 57/57 on STRUCTURE while measuring zero rhythm. CANON SUBORDINATION: that ruling is the authority; this file is a measurement of it and changes no canon.
Machine record:build/audio/exemplars/instruments/GROOVE_VALIDATION.json. Bands:build/audio/exemplars/instruments/GROOVE_BANDS.json.
Legal posture: analysis for understanding only; audio is read from disk, measured, and never copied, redistributed, or used as model input.
On the SCORE, where there is no extraction error at all, the composer's percussion writing is measurably thin, and it is thin in a way nothing in the program could previously see. Round 2's articulated syncopation reads 0.056, 0.062, 0.000 and round 3's reads 0.161, 0.094, 0.108, against a symbolic ceiling of 1.0. The COMPOSITE syncopation — what the drums do together — reads 0.000, 0.000, 0.000, 0.000, 0.000, 0.000. Across all of these cues, not one onset in the whole groove core ever hangs over a stronger rest.
On the AUDIO, the honest accounting is 0 SEPARATES, 2 DEFECT-DETECTOR-ONLY and 5 NULL. Within-album prediction — can an axis tell a beloved track from competent filler on the same album — is priced against a multiplicity bar of 0.1833 (p95 deviation over 300 permutations of the label within album), and nothing clears it. Five sibling instruments in this program have returned honest nulls on that question; a sixth is not a disgrace, and it is also not a taste oracle.
AND THE MOST IMPORTANT AUDIO RESULT IS A DIRECTION, NOT A SCORE. 3 axis(es) run BACKWARDS against round 3 — the music Josh has loved for decades scores LOWER than the round he turned down: pulse salience (audio) (hits 0.263 vs round 3 0.414, AUC 0.222), beat consistency (hits 0.955 vs round 3 0.982, AUC 0.189), onset density per s (audio) (hits 0.931 vs round 3 2.317, AUC 0.256). Read that the right way round. A high pulse salience and a beat consistency near 1.0 are not virtues here; they are the signature of a GRID. Round 3's pulse is more present and more perfectly regular than the corpus's, and its articulation against the metre — the score tier's syncopation, above — is near zero. A rigid pulse with nothing played against it is what a listener calls no rhythm, and it is the one reading in this file that agrees with the grade on both tiers at once.
tempo_and_time_grammar.groove.onset_rate_per_s is the only rhythm number the formula cards carry, and it is degenerate. Re-derived live on this run over 1180 cards: min 10.7040, max 10.8900, median 10.7675, 20 distinct values at two decimal places, a span of 1.73% of its own median. A quarter of the analysis frame rate is 10.767. It is measuring the hop, not the music. No axis in this instrument reads it.
The replacement is onset_density_per_s, and the control that proves it is not the same defect is planted in code rather than argued:
| planted signal | must measure | measured |
|---|---|---|
| a click train at 2 onsets/s | ~2 | 1.967 |
| a click train at 12 onsets/s | ~12 | 11.967 |
| the card's field, over 1180 real tracks | should vary | 10.704 – 10.890 |
A measure that could not tell those two signals apart would return the same number for both. That is precisely what the card field does for every track in the corpus.
AUC is the probability that a randomly chosen corpus hit scores above a randomly chosen cue from that round: 0.5 is indistinguishable, below 0.5 means our own output scores HIGHER. The two Spearman columns are the density confound — an axis that is just note count wearing a rhythm name is a null, and this program has been burned by exactly that (phrase_count scored 0.928 against note count).
| axis | hit median | sibling | r1 | r2 | r3 | within-album AUC | AUC over r3 | ρ note count | ρ voiced frac | verdict |
|---|---|---|---|---|---|---|---|---|---|---|
| pulse salience (audio) | 0.263 | 0.312 | 0.186 | 0.392 | 0.414 | 0.476 | 0.222 | -0.024 | -0.310 | DEFECT-DETECTOR-ONLY |
| beat consistency | 0.955 | 0.961 | 0.957 | 0.983 | 0.982 | 0.472 | 0.189 | 0.035 | -0.034 | DEFECT-DETECTOR-ONLY |
| syncopation, LHL (audio) | 0.067 | 0.133 | 0.067 | 0.067 | 0.067 | 0.447 | 0.533 | -0.157 | -0.146 | NULL |
| off-beat weight share (audio) | 0.400 | 0.400 | 0.400 | 0.367 | 0.400 | 0.484 | 0.417 | 0.019 | -0.188 | NULL |
| onset density per s (audio) | 0.931 | 1.250 | 1.133 | 1.233 | 2.317 | 0.454 | 0.256 | 0.166 | -0.137 | NULL |
| percussive energy share | 0.115 | 0.147 | 0.066 | 0.057 | 0.080 | 0.420 | 0.689 | -0.293 | -0.711 | NULL |
| low-band pulse regularity | 0.118 | 0.105 | 0.087 | 0.130 | 0.156 | 0.549 | 0.356 | 0.032 | -0.204 | NULL |
The largest median gaps between the corpus and round 3, ranked, whatever the verdict says. A rank statistic that fails a multiplicity bar on 28 positives is not evidence that a gap this size is nothing; it is evidence that this pool cannot price it.
| axis | corpus hits | round 3 | gap | verdict |
|---|---|---|---|---|
| onset density per s (audio) | 0.931 | 2.317 | +149% | NULL |
| pulse salience (audio) | 0.263 | 0.414 | +57% | DEFECT-DETECTOR-ONLY |
| low-band pulse regularity | 0.118 | 0.156 | +32% | NULL |
| percussive energy share | 0.115 | 0.080 | −30% | NULL |
| beat consistency | 0.955 | 0.982 | +3% | DEFECT-DETECTOR-ONLY |
| cue | class | axis | value | band (class, n) | p10 | p50 | p90 | direction | axis verdict |
|---|---|---|---|---|---|---|---|---|---|
| PASS5_FLORES_FALLS | SANCTUARY | off-beat weight share (audio) | 0.543 | POOLED_ALL_CLASSES (n=30) | 0.200 | 0.400 | 0.535 | ABOVE p90 | NULL |
| PASS5_FLORES_FALLS | SANCTUARY | percussive energy share | 0.013 | POOLED_ALL_CLASSES (n=30) | 0.025 | 0.115 | 0.278 | BELOW p10 | NULL |
| PASS5_FLORES_ROUNDS | BATTLE | pulse salience (audio) | 0.491 | BATTLE (n=5) | 0.280 | 0.408 | 0.453 | ABOVE p90 | DEFECT-DETECTOR-ONLY |
| PASS5_FLORES_ROUNDS | BATTLE | beat consistency | 0.986 | BATTLE (n=5) | 0.940 | 0.961 | 0.973 | ABOVE p90 | DEFECT-DETECTOR-ONLY |
| PASS5_FLORES_ROUNDS | BATTLE | percussive energy share | 0.122 | BATTLE (n=5) | 0.132 | 0.197 | 0.257 | BELOW p10 | NULL |
Read the last column before acting on any row. A cue sitting outside the band of an axis whose verdict is NULL has been found different from the corpus on a number that does not distinguish loved music from filler. Only the rows whose axis SEPARATES or is a DEFECT-DETECTOR carry weight.
The plan IS the notes. pass2_realise.compile_plan produces exactly what the renderer plays, so these numbers are properties of the WRITING and carry no measurement error at all. The groove core is the percussion layers (the palette's own UNPITCHED_IDS) plus the articulated bass; pads, drones and beds are excluded because a sustained chord has a note-on and not an attack.
| cue | round | class | perc | bass | articulated sync | composite sync | pulse | interlock | synchrony mean | synchrony max | worst pair | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| PASS2_FLORES_CACI | round 2 | BATTLE | 9 | 6 | 0.056 | 0.000 | 0.663 | 0.461 | 0.188 | 0.504 | B08 | M06 0.504 |
| PASS2_FLORES_REST | round 2 | EXPLORATION | 7 | 4 | 0.062 | 0.000 | 1.000 | 0.412 | 0.192 | 0.510 | B04 | B07 0.510 |
| PASS2_FLORES_WATERFALL | round 2 | SANCTUARY | 2 | 0 | 0.000 | 0.000 | 0.660 | n/a | n/a | n/a | — n/a | |
| PASS5_FLORES_FALLS | round 3 | SANCTUARY | 4 | 0 | 0.161 | 0.000 | 0.660 | 0.333 | 0.100 | 0.179 | B02 | B03 0.179 |
| PASS5_FLORES_ROAD | round 3 | EXPLORATION | 8 | 3 | 0.094 | 0.000 | 0.663 | 0.549 | 0.123 | 0.500 | B04 | B07 0.500 |
| PASS5_FLORES_ROUNDS | round 3 | BATTLE | 9 | 4 | 0.108 | 0.000 | 0.656 | 0.452 | 0.211 | 0.671 | B02 | B04 0.671 |
The composite column is the sentence. Longuet-Higgins & Lee syncopation asks whether a note is left hanging over a stronger rest. Folded across the whole groove core, every one of these cues answers no, every cycle, in every cue. That is not an artifact of density alone — the articulated per-voice column, which excludes the colotomic clock and every carpet denser than one-and-a-half onsets per beat, is also small. groove.py's own library exists to repair exactly this, and these are the numbers it has to beat.
Derived from 30 measured corpus HITS on the audio tier. A class needs 5 rows to get its own band; the classes that did not are pooled and said so: BOSS (n=2), CREDITS_TRIUMPH (n=4), MELANCHOLIC (n=4), TENSION (n=3), TITLE_CHARACTER (n=4).
| axis | n | p10 | p50 | p90 |
|---|---|---|---|---|
| pulse salience (audio) | 5 | 0.280 | 0.408 | 0.453 |
| beat consistency | 5 | 0.940 | 0.961 | 0.973 |
| syncopation, LHL (audio) | 5 | 0.027 | 0.133 | 0.173 |
| off-beat weight share (audio) | 5 | 0.160 | 0.512 | 0.567 |
| onset density per s (audio) | 5 | 0.253 | 0.733 | 3.152 |
| percussive energy share | 5 | 0.132 | 0.197 | 0.257 |
| low-band pulse regularity | 5 | 0.093 | 0.149 | 0.219 |
| axis | n | p10 | p50 | p90 |
|---|---|---|---|---|
| pulse salience (audio) | 8 | 0.153 | 0.288 | 0.518 |
| beat consistency | 8 | 0.947 | 0.979 | 0.983 |
| syncopation, LHL (audio) | 8 | 0.000 | 0.050 | 0.173 |
| off-beat weight share (audio) | 8 | 0.293 | 0.400 | 0.466 |
| onset density per s (audio) | 8 | 0.567 | 2.109 | 3.428 |
| percussive energy share | 8 | 0.029 | 0.072 | 0.247 |
| low-band pulse regularity | 8 | 0.062 | 0.128 | 0.188 |
| axis | n | p10 | p50 | p90 |
|---|---|---|---|---|
| pulse salience (audio) | 30 | 0.079 | 0.263 | 0.501 |
| beat consistency | 30 | 0.929 | 0.955 | 0.983 |
| syncopation, LHL (audio) | 30 | 0.000 | 0.067 | 0.200 |
| off-beat weight share (audio) | 30 | 0.200 | 0.400 | 0.535 |
| onset density per s (audio) | 30 | 0.358 | 0.931 | 3.359 |
| percussive energy share | 30 | 0.025 | 0.115 | 0.278 |
| low-band pulse regularity | 30 | 0.064 | 0.118 | 0.219 |
No score-tier band exists and none is invented. The corpus is audio; we hold no scores for it.
| control | planted | recovered |
|---|---|---|
| C1 a 120 bpm click train | strong pulse, steady beat, 2/s | pulse 0.897, consistency 0.994, 1.967/s |
| C2 white noise | no pulse | 0.090 |
| C3 THE POSITIVE CONTROL | 2/s and 12/s | 1.967 and 11.967 |
| C4 the card field | must be degenerate | span 1.73% over 1180 cards |
| C5 tresillo vs four-on-the-floor | tresillo higher | 0.200 vs 0.000 |
| C5c the beat-tracker limit | the tracker can be pulled off the tactus | free tempo 79.5 against a planted 120.0 |
| C6 pulse is not density | pulse collapses, density holds | pulse 0.897 → 0.058, density 1.967 → 1.967 |
| C7 a held tone | degenerate, never a rhythm | env peak 0.038 < floor 1.0 |
| C7b amplitude invariance | the floor must be meaningful | envelope peak at ×0.01 / ×1 / ×100 = {'0.01': 47.438, '1.0': 49.66, '100.0': 49.66} |
| C8 drums vs a sustained pad | high vs low percussive share | 1.000 vs 0.001 |
| C9 a regular vs a jittered low pulse | regular higher | 0.897 vs 0.068 |
| C10 an empty card | available=False, never raises | no audio and no plan: every axis here needs one or the other, because … |
| C11 the toy plan (score tier) | two drums that tile | interlock 1.000, synchrony 0.000, sync_score 0.233 |
| mutation arm | must be caught by | fired | must hold | held |
|---|---|---|---|---|
| randomise the onset TIMES at a fixed count | pulse_salience_audio | yes | onset_density_per_s | yes |
| double the click rate | onset_density_per_s | yes | percussive_energy_share | yes |
| replace the drums with a sustained pad | percussive_energy_share | yes | onset_density_per_s (the pad is DEGENERATE and reads 0.0, not a rhythm) | yes |
| move a tresillo's off-beats onto the beat | syncopation_audio | yes | onset_density_per_s | yes |
| add a third drum that DOUBLES the tom's exact grid | onset_synchrony_max | yes | pulse_score and sync_composite (the composite UNION is unchanged, so both must be EXACTLY equal) | yes |
| move the tom's off-beats onto beats the bass drum does not occupy | sync_score | yes | interlock (the two voices still share no position) | yes |
A control without a mutation proof was never armed. Each arm breaks one axis on purpose, and each also names an axis that must NOT move — the pass2_plan.py:786-795 standard, because an arm that moves everything cannot show which axis was armed.
low_band_pulse_regularity means there is a bass. A short high-frequency burst leaks into the low band; the axis is a periodicity number and detail.low_band_energy_share is reported beside it.groove.onset_rate_per_s nowhere, and control C4 re-derives that field's degeneracy on every run so the refusal cannot go stale.