GROOVE_VALIDATION.md

music/exemplars/instruments/GROOVE_VALIDATION.md

GROOVE — the validation of the rhythm instrument

Tier: MEASURED INSTRUMENT. Produced by harness/music_gen/instr_groove.py, which writes this file, its machine record and GROOVE_BANDS.json together 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.

1. The one-paragraph answer

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.

2. The poisoned well, and the positive control

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 signalmust measuremeasured
a click train at 2 onsets/s~21.967
a click train at 12 onsets/s~1211.967
the card's field, over 1180 real tracksshould vary10.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.

3. THE HEADLINE TABLE — the seven audio axes

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).

axishit mediansiblingr1r2r3within-album AUCAUC over r3ρ note countρ voiced fracverdict
pulse salience (audio)0.2630.3120.1860.3920.4140.4760.222-0.024-0.310DEFECT-DETECTOR-ONLY
beat consistency0.9550.9610.9570.9830.9820.4720.1890.035-0.034DEFECT-DETECTOR-ONLY
syncopation, LHL (audio)0.0670.1330.0670.0670.0670.4470.533-0.157-0.146NULL
off-beat weight share (audio)0.4000.4000.4000.3670.4000.4840.4170.019-0.188NULL
onset density per s (audio)0.9311.2501.1331.2332.3170.4540.2560.166-0.137NULL
percussive energy share0.1150.1470.0660.0570.0800.4200.689-0.293-0.711NULL
low-band pulse regularity0.1180.1050.0870.1300.1560.5490.3560.032-0.204NULL

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.

axiscorpus hitsround 3gapverdict
onset density per s (audio)0.9312.317+149%NULL
pulse salience (audio)0.2630.414+57%DEFECT-DETECTOR-ONLY
low-band pulse regularity0.1180.156+32%NULL
percussive energy share0.1150.080−30%NULL
beat consistency0.9550.982+3%DEFECT-DETECTOR-ONLY

4. WHERE ROUND 3 FALLS OUTSIDE THE CORPUS BANDS

cueclassaxisvalueband (class, n)p10p50p90directionaxis verdict
PASS5_FLORES_FALLSSANCTUARYoff-beat weight share (audio)0.543POOLED_ALL_CLASSES (n=30)0.2000.4000.535ABOVE p90NULL
PASS5_FLORES_FALLSSANCTUARYpercussive energy share0.013POOLED_ALL_CLASSES (n=30)0.0250.1150.278BELOW p10NULL
PASS5_FLORES_ROUNDSBATTLEpulse salience (audio)0.491BATTLE (n=5)0.2800.4080.453ABOVE p90DEFECT-DETECTOR-ONLY
PASS5_FLORES_ROUNDSBATTLEbeat consistency0.986BATTLE (n=5)0.9400.9610.973ABOVE p90DEFECT-DETECTOR-ONLY
PASS5_FLORES_ROUNDSBATTLEpercussive energy share0.122BATTLE (n=5)0.1320.1970.257BELOW p10NULL

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.

5. THE SCORE TIER — no extraction error, and the strongest result in this file

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.

cueroundclasspercbassarticulated synccomposite syncpulseinterlocksynchrony meansynchrony maxworst pair
PASS2_FLORES_CACIround 2BATTLE960.0560.0000.6630.4610.1880.504B08M06 0.504
PASS2_FLORES_RESTround 2EXPLORATION740.0620.0001.0000.4120.1920.510B04B07 0.510
PASS2_FLORES_WATERFALLround 2SANCTUARY200.0000.0000.660n/an/an/a— n/a
PASS5_FLORES_FALLSround 3SANCTUARY400.1610.0000.6600.3330.1000.179B02B03 0.179
PASS5_FLORES_ROADround 3EXPLORATION830.0940.0000.6630.5490.1230.500B04B07 0.500
PASS5_FLORES_ROUNDSround 3BATTLE940.1080.0000.6560.4520.2110.671B02B04 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.

6. The bands, and what they rest on

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).

BATTLE

axisnp10p50p90
pulse salience (audio)50.2800.4080.453
beat consistency50.9400.9610.973
syncopation, LHL (audio)50.0270.1330.173
off-beat weight share (audio)50.1600.5120.567
onset density per s (audio)50.2530.7333.152
percussive energy share50.1320.1970.257
low-band pulse regularity50.0930.1490.219

EXPLORATION

axisnp10p50p90
pulse salience (audio)80.1530.2880.518
beat consistency80.9470.9790.983
syncopation, LHL (audio)80.0000.0500.173
off-beat weight share (audio)80.2930.4000.466
onset density per s (audio)80.5672.1093.428
percussive energy share80.0290.0720.247
low-band pulse regularity80.0620.1280.188

POOLED_ALL_CLASSES

axisnp10p50p90
pulse salience (audio)300.0790.2630.501
beat consistency300.9290.9550.983
syncopation, LHL (audio)300.0000.0670.200
off-beat weight share (audio)300.2000.4000.535
onset density per s (audio)300.3580.9313.359
percussive energy share300.0250.1150.278
low-band pulse regularity300.0640.1180.219

No score-tier band exists and none is invented. The corpus is audio; we hold no scores for it.

7. The controls, and which mutation proved which

controlplantedrecovered
C1 a 120 bpm click trainstrong pulse, steady beat, 2/spulse 0.897, consistency 0.994, 1.967/s
C2 white noiseno pulse0.090
C3 THE POSITIVE CONTROL2/s and 12/s1.967 and 11.967
C4 the card fieldmust be degeneratespan 1.73% over 1180 cards
C5 tresillo vs four-on-the-floortresillo higher0.200 vs 0.000
C5c the beat-tracker limitthe tracker can be pulled off the tactusfree tempo 79.5 against a planted 120.0
C6 pulse is not densitypulse collapses, density holdspulse 0.897 → 0.058, density 1.967 → 1.967
C7 a held tonedegenerate, never a rhythmenv peak 0.038 < floor 1.0
C7b amplitude invariancethe floor must be meaningfulenvelope peak at ×0.01 / ×1 / ×100 = {'0.01': 47.438, '1.0': 49.66, '100.0': 49.66}
C8 drums vs a sustained padhigh vs low percussive share1.000 vs 0.001
C9 a regular vs a jittered low pulseregular higher0.897 vs 0.068
C10 an empty cardavailable=False, never raisesno audio and no plan: every axis here needs one or the other, because …
C11 the toy plan (score tier)two drums that tileinterlock 1.000, synchrony 0.000, sync_score 0.233
mutation armmust be caught byfiredmust holdheld
randomise the onset TIMES at a fixed countpulse_salience_audioyesonset_density_per_syes
double the click rateonset_density_per_syespercussive_energy_shareyes
replace the drums with a sustained padpercussive_energy_shareyesonset_density_per_s (the pad is DEGENERATE and reads 0.0, not a rhythm)yes
move a tresillo's off-beats onto the beatsyncopation_audioyesonset_density_per_syes
add a third drum that DOUBLES the tom's exact gridonset_synchrony_maxyespulse_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 occupysync_scoreyesinterlock (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.

8. What this instrument refuses to claim

Generated by harness/site/structure_site.py — the URL path is the repo path. review root