songhash 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- songhash-0.1.0/.gitignore +17 -0
- songhash-0.1.0/AESTHETICS.md +73 -0
- songhash-0.1.0/BYTES.md +112 -0
- songhash-0.1.0/CHANGELOG.md +104 -0
- songhash-0.1.0/DESIGN.md +363 -0
- songhash-0.1.0/LICENSE +21 -0
- songhash-0.1.0/PKG-INFO +246 -0
- songhash-0.1.0/README.md +201 -0
- songhash-0.1.0/assets/v1/aux_layers.json +205 -0
- songhash-0.1.0/assets/v1/bass/bass_articulation.json +47 -0
- songhash-0.1.0/assets/v1/bass/bass_patterns.json +2084 -0
- songhash-0.1.0/assets/v1/bass/bass_synths.json +255 -0
- songhash-0.1.0/assets/v1/comp/arp_shapes.json +115 -0
- songhash-0.1.0/assets/v1/comp/chord_rhythm_patterns.json +144 -0
- songhash-0.1.0/assets/v1/comp/comp_roles.json +264 -0
- songhash-0.1.0/assets/v1/comp/comp_synths.json +149 -0
- songhash-0.1.0/assets/v1/comp/strum_patterns.json +178 -0
- songhash-0.1.0/assets/v1/drums/drumkits.json +421 -0
- songhash-0.1.0/assets/v1/drums/escalation_algorithms.json +363 -0
- songhash-0.1.0/assets/v1/drums/fills/acoustic-studio.json +250 -0
- songhash-0.1.0/assets/v1/drums/fills/brushes.json +212 -0
- songhash-0.1.0/assets/v1/drums/fills/dnb-breakbeat.json +188 -0
- songhash-0.1.0/assets/v1/drums/fills/hand-perc.json +170 -0
- songhash-0.1.0/assets/v1/drums/fills/house-909.json +172 -0
- songhash-0.1.0/assets/v1/drums/fills/jazz-kit.json +212 -0
- songhash-0.1.0/assets/v1/drums/fills/kalimba-tick.json +156 -0
- songhash-0.1.0/assets/v1/drums/fills/latin-conga.json +174 -0
- songhash-0.1.0/assets/v1/drums/fills/lo-fi-tape.json +198 -0
- songhash-0.1.0/assets/v1/drums/fills/mallets.json +150 -0
- songhash-0.1.0/assets/v1/drums/fills/music-box-tick.json +154 -0
- songhash-0.1.0/assets/v1/drums/fills/trap-808.json +158 -0
- songhash-0.1.0/assets/v1/drums/patterns/acoustic-studio.json +596 -0
- songhash-0.1.0/assets/v1/drums/patterns/brushes.json +392 -0
- songhash-0.1.0/assets/v1/drums/patterns/dnb-breakbeat.json +532 -0
- songhash-0.1.0/assets/v1/drums/patterns/hand-perc.json +482 -0
- songhash-0.1.0/assets/v1/drums/patterns/house-909.json +610 -0
- songhash-0.1.0/assets/v1/drums/patterns/jazz-kit.json +390 -0
- songhash-0.1.0/assets/v1/drums/patterns/kalimba-tick.json +364 -0
- songhash-0.1.0/assets/v1/drums/patterns/latin-conga.json +400 -0
- songhash-0.1.0/assets/v1/drums/patterns/lo-fi-tape.json +486 -0
- songhash-0.1.0/assets/v1/drums/patterns/mallets.json +325 -0
- songhash-0.1.0/assets/v1/drums/patterns/music-box-tick.json +375 -0
- songhash-0.1.0/assets/v1/drums/patterns/trap-808.json +536 -0
- songhash-0.1.0/assets/v1/energy_curves.json +22 -0
- songhash-0.1.0/assets/v1/expression/articulation.json +36 -0
- songhash-0.1.0/assets/v1/expression/cc_routing.json +27 -0
- songhash-0.1.0/assets/v1/expression/humanization_profiles.json +13 -0
- songhash-0.1.0/assets/v1/expression/velocity_curves.json +30 -0
- songhash-0.1.0/assets/v1/family_to_moods.json +140 -0
- songhash-0.1.0/assets/v1/forms.json +35 -0
- songhash-0.1.0/assets/v1/groove_overlays.json +155 -0
- songhash-0.1.0/assets/v1/groove_templates.json +300 -0
- songhash-0.1.0/assets/v1/harmony/progressions.json +3620 -0
- songhash-0.1.0/assets/v1/harmony/resolution_rules.json +174 -0
- songhash-0.1.0/assets/v1/harmony/voicings.json +125 -0
- songhash-0.1.0/assets/v1/labels.json +27 -0
- songhash-0.1.0/assets/v1/layer_activation.json +23 -0
- songhash-0.1.0/assets/v1/manifest.json +43 -0
- songhash-0.1.0/assets/v1/melody/accent_skeleton.json +22 -0
- songhash-0.1.0/assets/v1/melody/contours.json +979 -0
- songhash-0.1.0/assets/v1/melody/motif_rhythms.json +2534 -0
- songhash-0.1.0/assets/v1/melody/mutation_operators.json +26 -0
- songhash-0.1.0/assets/v1/melody/phrase_shapes.json +22 -0
- songhash-0.1.0/assets/v1/melody/scale_subsets.json +24 -0
- songhash-0.1.0/assets/v1/meter_accents.json +69 -0
- songhash-0.1.0/assets/v1/mime_families.json +100 -0
- songhash-0.1.0/assets/v1/moods.json +305 -0
- songhash-0.1.0/assets/v1/synth_pool.json +59 -0
- songhash-0.1.0/assets/v1/tempo_pools.json +168 -0
- songhash-0.1.0/assets/v1/versions.lock.json +31 -0
- songhash-0.1.0/pyproject.toml +109 -0
- songhash-0.1.0/src/mhash/__init__.py +7 -0
- songhash-0.1.0/src/mhash/cli.py +181 -0
- songhash-0.1.0/src/mhash/dashboard.py +393 -0
- songhash-0.1.0/src/mhash/decode.py +924 -0
- songhash-0.1.0/src/mhash/mhash.py +275 -0
- songhash-0.1.0/src/mhash/mime.py +74 -0
- songhash-0.1.0/src/mhash/play.py +26 -0
- songhash-0.1.0/src/mhash/quality.py +318 -0
- songhash-0.1.0/src/mhash/render/__init__.py +0 -0
- songhash-0.1.0/src/mhash/render/audio.py +244 -0
- songhash-0.1.0/src/mhash/render/fx.py +162 -0
- songhash-0.1.0/src/mhash/render/midi.py +1493 -0
- songhash-0.1.0/src/mhash/setup_assets.py +106 -0
- songhash-0.1.0/src/mhash/sf3_to_sf2.py +181 -0
- songhash-0.1.0/src/mhash/showcase.py +246 -0
- songhash-0.1.0/src/mhash/spec.py +127 -0
- songhash-0.1.0/src/mhash/tables/__init__.py +27 -0
- songhash-0.1.0/src/mhash/theory.py +173 -0
- songhash-0.1.0/tests/conftest.py +4 -0
- songhash-0.1.0/tests/test_byte_budget.py +56 -0
- songhash-0.1.0/tests/test_corpus.py +159 -0
- songhash-0.1.0/tests/test_decode_invariants.py +59 -0
- songhash-0.1.0/tests/test_label_registry.py +64 -0
- songhash-0.1.0/tests/test_midi_render.py +73 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Mood aesthetics
|
|
2
|
+
|
|
3
|
+
Per-mood design intent. Useful for understanding what a mhash is *trying* to do, separate from any one render's particular output.
|
|
4
|
+
|
|
5
|
+
| Mood | Intent | Tempo | Modes | Groove pool | Form pool | FX chain |
|
|
6
|
+
|---|---|---|---|---|---|---|
|
|
7
|
+
| **M0 Ambient** | floating, no goal, pad-led | 54-80 | ionian / aeolian / dorian / lydian / phrygian | ambient_drift / neo_soul / straight_4_4 | through_composed / A_Aprime / theme_var / ostinato_layer / pulse_only | big plate reverb + chorus + low-shelf cut |
|
|
8
|
+
| **M1 Ballad** | warm, hopeful, song-form | 64-80 | ionian / aeolian / dorian | straight_4_4 / neo_soul / gospel_12_8 | A_Aprime / ABA / intro_A_fill_A_out / A_outro / AABA / two_arches | medium hall + low-shelf boost + air shelf |
|
|
9
|
+
| **M2 Hip-hop** | boom-bap, head-nod, dusty | 70-94 | aeolian / dorian / phrygian / jazz_minor | boom_bap_60 / dilla_feel / mpc60_swing | AB_simple / ABAB / theme_var / AABA / ABCA | short room + tape high-cut + light drive |
|
|
10
|
+
| **M3 Downtempo** | meditative groove, off-beat-comfortable | 90-105 | ionian / aeolian / dorian / lydian / jazz_minor | neo_soul / mpc60_swing / dilla_feel / straight_4_4 | through_composed / A_Aprime / theme_var / ostinato_layer / two_arches | wide chorus + dotted-eighth delay + warm room |
|
|
11
|
+
| **M4 Latin** | percussive, dance-leaning, modal | 92-112 | ionian / phrygian / mixolydian / aeolian | latin_clave_pocket / dembow_pocket / mpc60_swing | ABAB / AABA / ABCA / theme_var | dry room + presence shelf |
|
|
12
|
+
| **M5 Synthwave** | nostalgic glow, neon dusk | 100-120 | ionian / aeolian / lydian | synthwave_tight / straight_4_4 | ABAB / A_build_drop_A / AABA / ABCA / late_drop | chorus + dotted-eighth delay + plate |
|
|
13
|
+
| **M6 House** | groove pump, club-shaped | 120-128 | ionian / aeolian / mixolydian | house_pocket / amapiano_pocket / straight_4_4 | ABAB / ABCA / breakdown_form / late_drop / riser_drop_loop | glue compressor → tight room |
|
|
14
|
+
| **M7 Techno** | hypnotic loop, dark drive | 128-138 | aeolian / phrygian / dorian | techno_push / straight_4_4 | breakdown_form / riser_drop_loop / late_drop / pyramid / pulse_only | short room + light delay + dark high-shelf |
|
|
15
|
+
| **M8 DnB** | snappy break, half-time-feel possible | 85 / 130 / 170-176 | aeolian / dorian / phrygian | dnb_amen_lean / straight_4_4 | ABAB / A_build_drop_A / riser_drop_loop / late_drop | snappy comp + tight room |
|
|
16
|
+
| **M9 Glitch / IDM** | broken grid, dissonance-friendly | 90-135 | dorian / phrygian / aeolian / locrian | trap_triplet_hat / straight_4_4 | theme_var / two_arches / pyramid / medley | phaser + ping-pong delay + small room |
|
|
17
|
+
| **M10 Cinematic** | breath, build, score-like | 54-110 | aeolian / dorian / lydian / phrygian | straight_4_4 / gospel_12_8 / ambient_drift | ABA / intro_A_fill_A_out / AABA / ABCA / two_arches / plateau_fall | large hall + sub shelf + air shelf |
|
|
18
|
+
| **M11 Lofi** | vinyl warmth, jazzy | 70-92 | ionian / aeolian / dorian / jazz_minor / lydian | dilla_feel / boom_bap_60 / mpc60_swing / neo_soul | A_Aprime / ABA / theme_var / ostinato_layer / AABA | tape sat + high-cut + slow chorus + small room |
|
|
19
|
+
| **M12 Chillout** | smooth, ambient-leaning, minor-key-comfort | 80-100 | ionian / lydian / aeolian / dorian | ambient_drift / neo_soul / straight_4_4 | through_composed / A_Aprime / ABA / theme_var | wide chorus + 0.45 s delay + plate + air shelf |
|
|
20
|
+
| **M13 Simple** | stripped, song-shape, kid-piano | 70-110 | ionian / aeolian | straight_4_4 | A_Aprime / ABA / AABA / pulse_only | barely-there room |
|
|
21
|
+
| **M14 Gameboy** | chiptune approximation (LSDj-flavor) | 110-150 | ionian / aeolian / dorian / mixolydian | straight_4_4 | ABAB / AABA / ABCA / ABA / pyramid | dark high-shelf cut + light drive + tiny room |
|
|
22
|
+
|
|
23
|
+
## Per-mood layer programs (from `_GM_PALETTE`)
|
|
24
|
+
|
|
25
|
+
| Mood | bass | comp | lead candidates | pad |
|
|
26
|
+
|---|---|---|---|---|
|
|
27
|
+
| M0 Ambient | 32 (Acoustic Bass) | 88 / 89 / 91 (pads) | 54 / 75 / 73 / 91 / 11 / 70 | 88 / 89 / 94 |
|
|
28
|
+
| M1 Ballad | 32 / 33 | 0 (Piano) / 4 (EP1) / 24 (Nylon) | 73 (Flute) / 71 (Clarinet) / 56 (Trumpet) / 68 (Oboe) / 41 (Viola) / 11 (Vibes) | 89 / 91 / 95 |
|
|
29
|
+
| M2 Hip-hop | 33 / 34 / 36 | 4 / 5 / 11 | 80 / 81 / 28 / 4 / 5 / 6 | 89 / 95 / 91 |
|
|
30
|
+
| M3 Downtempo | 33 / 36 | 4 / 5 / 88 / 89 | 80 / 73 / 78 / 4 / 5 / 11 | 89 / 91 / 94 |
|
|
31
|
+
| M4 Latin | 32 / 35 | 24 / 25 / 32 (steel-string family) | 56 / 11 / 24 / 73 / 12 / 25 | 89 / 91 / 94 |
|
|
32
|
+
| M5 Synthwave | 38 / 39 / 33 | 81 / 89 / 80 | 81 / 80 / 84 / 87 / 88 / 89 | 90 / 89 / 94 |
|
|
33
|
+
| M6 House | 38 / 39 / 36 | 16 / 17 / 81 (organ + lead) | 80 / 81 / 53 / 87 / 89 / 84 | 90 / 89 / 95 |
|
|
34
|
+
| M7 Techno | 38 / 39 | 81 / 89 / 90 | 80 / 81 / 87 / 88 / 89 / 90 | 90 / 94 / 89 |
|
|
35
|
+
| M8 DnB | 38 / 39 / 36 | 89 / 88 / 91 | 81 / 80 / 88 / 84 / 90 / 87 | 89 / 91 / 94 |
|
|
36
|
+
| M9 Glitch | 38 / 39 / 87 | 90 / 91 / 102 | 88 / 81 / 102 / 87 / 100 / 99 | 95 / 91 / 94 |
|
|
37
|
+
| M10 Cinematic | 32 / 43 (cello) / 44 (tremolo strings) | 48 / 49 / 50 / 89 (string ensembles) | 60 (French Horn) / 73 / 71 / 11 / 49 / 91 | 49 / 51 / 94 |
|
|
38
|
+
| M11 Lofi | 33 / 32 / 35 | 4 / 5 / 0 / 24 (Rhodes / EP / Piano / Nylon) | 4 / 5 / 11 / 73 / 71 / 26 (Jazz Guitar) | 89 / 91 / 94 |
|
|
39
|
+
| M12 Chillout | 32 / 33 / 38 | 88 / 89 / 91 / 4 | 73 / 71 / 75 / 91 / 89 / 11 | 89 / 91 / 95 |
|
|
40
|
+
| M13 Simple | 32 / 33 | 0 (Piano) / 4 / 24 | 0 / 73 / 11 / 24 / 71 / 25 | 89 / 88 |
|
|
41
|
+
| M14 Gameboy | 38 / 39 / 80 | 80 / 81 / 71 (Square / Saw / Clarinet-triangle) | 80 / 81 / 88 / 84 / 99 / 38 | 90 / 88 / 95 |
|
|
42
|
+
|
|
43
|
+
GM program references: 0 piano, 4 EP1, 11 vibes, 24 nylon, 32 acoustic bass, 33 fingered bass, 38 synth bass 1, 39 synth bass 2, 49/50 strings, 80 square lead, 81 saw lead, 88-95 pads.
|
|
44
|
+
|
|
45
|
+
## Drum kits per mood
|
|
46
|
+
|
|
47
|
+
| Mood | Eligible kits |
|
|
48
|
+
|---|---|
|
|
49
|
+
| M0 Ambient | acoustic-studio / brushes / lo-fi-tape / hand-perc / mallets / music-box-tick / kalimba-tick |
|
|
50
|
+
| M1 Ballad | acoustic-studio / brushes / jazz-kit / mallets / music-box-tick |
|
|
51
|
+
| M2 Hip-hop | trap-808 / lo-fi-tape |
|
|
52
|
+
| M3 Downtempo | jazz-kit / lo-fi-tape / hand-perc / latin-conga / kalimba-tick |
|
|
53
|
+
| M4 Latin | hand-perc / latin-conga |
|
|
54
|
+
| M5 Synthwave | acoustic-studio / house-909 |
|
|
55
|
+
| M6 House | house-909 |
|
|
56
|
+
| M7 Techno | house-909 |
|
|
57
|
+
| M8 DnB | trap-808 / dnb-breakbeat |
|
|
58
|
+
| M9 Glitch | dnb-breakbeat |
|
|
59
|
+
| M10 Cinematic | acoustic-studio / brushes / jazz-kit / hand-perc / mallets / latin-conga / music-box-tick / kalimba-tick |
|
|
60
|
+
| M11 Lofi | (inherits from M0/M2 fallbacks — no exclusive kit yet) |
|
|
61
|
+
| M12 Chillout | (inherits from M0 fallbacks) |
|
|
62
|
+
| M13 Simple | (inherits — minimal_pad activation matrix often silences drums) |
|
|
63
|
+
| M14 Gameboy | (inherits — GM doesn't have a true chip drum kit; uses house-909 as closest) |
|
|
64
|
+
|
|
65
|
+
## Listening notes
|
|
66
|
+
|
|
67
|
+
- **M5 Synthwave** scores lower than its "feel" suggests because the GM saw lead at low velocity in MS-Basic SF3 sounds thin. The arrangement is correct — the soundfont ceiling shows up here.
|
|
68
|
+
- **M9 Glitch** is intentionally sharp (DIN sharpness ~1.9 acum across the corpus) — that's the genre.
|
|
69
|
+
- **M0 Ambient** outputs land 90% mid-band (4% low / 1% high) on the heuristic. Genre-correct: ambient is mid-range pad music. The heuristic doesn't penalize this any more (relaxed `<8% in any band` rule).
|
|
70
|
+
- **M14 Gameboy** is the closest GM patches can get to chiptune. The square+saw+clarinet trio is a deliberate approximation; a true chiptune pass would need a custom synth or a chip-specific soundfont.
|
|
71
|
+
- **M2 Hip-hop + jazz_minor** is musically valid (jazz hip-hop crossover) but scores lower because trap-808 + jazz-minor melody is a less-conventional combo than M2 + dorian.
|
|
72
|
+
|
|
73
|
+
The mood ↔ score correlation isn't strong: a mood's *intent* is more about timbre and arrangement than any single quality number.
|
songhash-0.1.0/BYTES.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Byte budget — mhash v1
|
|
2
|
+
|
|
3
|
+
How the SHA-256's 32 bytes (after HKDF expansion) map to musical decisions.
|
|
4
|
+
|
|
5
|
+
## Macro stream (`HKDF-Expand(prk, "soundhash/v1/macro", 32)`)
|
|
6
|
+
|
|
7
|
+
| Byte | Decision | Filter chain | Table size |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| 0 | macro mood | family-of-MIME → 4 candidates | 4 of 15 |
|
|
10
|
+
| 1 | mood sub-flavor (4 shades: stock/brighter/darker/tighter) | mood | 4 |
|
|
11
|
+
| 2 | tempo | mood's `tempo_pool` | 5–8 BPMs |
|
|
12
|
+
| 3 | key root | uniform 0–11 | 12 |
|
|
13
|
+
| 4 | mode | mood's `modes` list | 2–5 |
|
|
14
|
+
| 5 | groove template | mood's `_MOOD_GROOVE_POOL` | 1–4 |
|
|
15
|
+
| 6 | form | tempo-tier × `_MOOD_FORM_PREF` | 4–7 |
|
|
16
|
+
| 7 | progression | mood-tag ∩ mode | 2–10 |
|
|
17
|
+
| 8 | voicing style | progression's `allowed_voicing_styles` | 1–5 of 10 |
|
|
18
|
+
| 9 | drum kit | mood-filtered | 1–6 of 12 |
|
|
19
|
+
| 10 | drum pattern (low + high nibbles) | kit + density 1-2 / 3-4 | 8 each |
|
|
20
|
+
| 11 | drum fill | kit's fill bank | 4–5 / kit |
|
|
21
|
+
| 12 | drum escalation algo (high) + de-escalation (low) | always | 8 each (2 implemented) |
|
|
22
|
+
| 13 | bass archetype | mood ∩ time-sig | 2–8 |
|
|
23
|
+
| 14 | bass synth + octave | mood ∩ pattern_compat | 1–4 |
|
|
24
|
+
| 15 | comp role | mood | 1–6 of 12 |
|
|
25
|
+
| 16 | comp synth | role-compatible × mood | 1–6 of 16 |
|
|
26
|
+
| 17 | comp pattern variant | role × mood | 6–11 |
|
|
27
|
+
| 18 | melody scale subset | mode | 1–8 |
|
|
28
|
+
| 19 | melody motif rhythm | time-sig × mood | 32 / 4-4 |
|
|
29
|
+
| 20 | melody contour | mood | 7–32 of 32 |
|
|
30
|
+
| 21 | melody phrase shape | always | 16 (recorded on SongSpec; render-side hook reserved) |
|
|
31
|
+
| 22 | melody tessitura + lead synth | mood | 5–8 leads / mood |
|
|
32
|
+
| 23 | aux-layer mask + counter mode | always | counter mode = 4 |
|
|
33
|
+
| 24 | energy curve | form × `_MOOD_CURVE_PREF` | 3–7 of 16 |
|
|
34
|
+
| 25 | layer activation matrix | form-compatible × lead-audible | 3–10 of 16 |
|
|
35
|
+
| 26 | per-bar mutation seed | per-bar HKDF spillover | n/a |
|
|
36
|
+
| 27 | humanization profile (vel-jitter scale) | always | 6 |
|
|
37
|
+
| 28 | FX preset (per-mood chain in `render/fx.py`) | mood | n/a |
|
|
38
|
+
| 29 | FX wet-level scale (dry/85%/normal/wet) | always | 4 |
|
|
39
|
+
| 30 | mix balance preset (CC7 per layer) | always | 4 |
|
|
40
|
+
| 31 | counter-mode (low 2 bits) + variation salt | always | counter mode = 4 |
|
|
41
|
+
|
|
42
|
+
## Per-bar / per-section sub-streams
|
|
43
|
+
|
|
44
|
+
Spillover over the 32-byte macro budget; consumed via separate HKDF labels.
|
|
45
|
+
|
|
46
|
+
| Label | Length | Consumer |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| `perbar/melody/<i>` | 4 B / bar | melody mutation (transpose / invert) per bar |
|
|
49
|
+
| `perbar/bass/<i>` | 2 B / bar | bass octave shift, skip-last, ghost-first |
|
|
50
|
+
| `perbar/comp/<i>` | 2 B / bar | comp drop-last, ±5 vel pull |
|
|
51
|
+
| `perbar/aux/<i>` | 4 B / bar | layer dropouts (drums/lead/comp/pad) |
|
|
52
|
+
| `form/section/<letter>` | 4 B / section | section-specific motif/contour/comp pattern |
|
|
53
|
+
| `aux/earcandy/main/<i>` | 4 B / bar | ear-candy stab positions per bar |
|
|
54
|
+
| `expression/velocity/L<n>` | 256 B / layer | per-note velocity jitter |
|
|
55
|
+
| `melody/accent_skeleton` | 5 B | song-wide accent skeleton + 4 strong-beat targets |
|
|
56
|
+
| `meter/timesig` | 1 B | time-signature pick (94% bias to 4/4, else mood's `time_sigs` ∩ {3/4, 6/8, 12/8}) |
|
|
57
|
+
|
|
58
|
+
## Dimension → byte mapping
|
|
59
|
+
|
|
60
|
+
A given musical dimension's primary entropy:
|
|
61
|
+
|
|
62
|
+
| Dim | Bytes | Helper |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| 01 Key & Mode | 3, 4 | `_pick_mode` |
|
|
65
|
+
| 02 Tempo & Groove | 2, 5 | `_pick_tempo`, `_pick_groove_template` |
|
|
66
|
+
| 03 Form & Energy | 6, 24, 25 | `_pick_form_unconstrained`, `_pick_energy_curve`, `_pick_activation_matrix` |
|
|
67
|
+
| 04 Harmony & Voicing | 7, 8 | `_pick_progression`, voicing style |
|
|
68
|
+
| 05 Drums & Fills | 9, 10, 11, 12 | `_pick_drum_kit`, `_pick_drum_pattern_pair`, `_pick_drum_fill` |
|
|
69
|
+
| 06 Bass | 13, 14 | `_pick_bass_pattern`, `_pick_bass_synth` |
|
|
70
|
+
| 07 Comping | 15, 16, 17 | `_pick_comp_role`, `_pick_comp_synth`, `_pick_comp_pattern`, `_pick_arp_shape` |
|
|
71
|
+
| 08 Melody | 18, 19, 20, 22, `melody/accent_skeleton` | `_pick_melody_motif`, `_pick_contour`, `_pick_scale_subset`, accent skeleton |
|
|
72
|
+
| 09 Aux Layers | 23 | drone enable, counter mode, ear-candy gate |
|
|
73
|
+
| 10 MIDI Expression | 27 (reserved) | velocity jitter via per-layer HKDF |
|
|
74
|
+
| 11 MIME → Mood | 0 + MIME family | `_pick_mood`, `family_for_mime` |
|
|
75
|
+
| 12 Rendering | 28, 29, 30 (reserved) | per-mood FX in `render/fx.py` |
|
|
76
|
+
| 13 Hash Architecture | n/a | HKDF labels in `assets/v1/labels.json` |
|
|
77
|
+
| 14 Perceptual & Determinism | n/a | LUFS, FX-after-LUFS, peak limit, pyloudnorm |
|
|
78
|
+
|
|
79
|
+
## Empirical distributions (500-hash audit, mixed MIME)
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
mood: M0 52, M1 34, M2 21, M3 48, M4 18, M5 11, M6 14, M7 9,
|
|
83
|
+
M8 14, M9 20, M10 39, M11 51, M12 46, M13 78, M14 45
|
|
84
|
+
modes: aeolian 164, ionian 126, dorian 84, lydian 47, phrygian 33,
|
|
85
|
+
jazz_minor 32, locrian 7, mixolydian 7
|
|
86
|
+
keys: 33–55 hits per chromatic root (uniform within ~±20%)
|
|
87
|
+
voicing: close_triad 53, open_triad 48, sus_open 37, quartal 27,
|
|
88
|
+
power 17, drop2_7th 8, shell 5, drop3_7th 2, rootless_B 2,
|
|
89
|
+
rootless_A 1
|
|
90
|
+
groove: straight_4_4 30%, neo_soul 16%, ambient_drift 8%, dilla_feel 6%,
|
|
91
|
+
mpc60_swing 5%, gospel_12_8 5%, others <5% each
|
|
92
|
+
counter: parallel_3rd / parallel_6th / contrary / octave_below
|
|
93
|
+
(uniform on byte 31's low 2 bits)
|
|
94
|
+
matrix: arp_lead, 4floor_house, bass_lead_duo, band_basic, band_full,
|
|
95
|
+
bolero_additive, ambient_drone, staccato_stab, pad_lead,
|
|
96
|
+
minimal_pad — 10 of 16 reachable (lead-silent matrices filtered)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Reserved bytes (all consumed)
|
|
100
|
+
|
|
101
|
+
Every macro byte 0..31 now drives at least one observable decision (recorded on SongSpec or directly affecting render). Byte 21's `phrase_shape_id` is surfaced on SongSpec but not yet consulted at render time — render uses form-driven section letters for phrase structure today.
|
|
102
|
+
|
|
103
|
+
**#84** Meter is now hash-driven via the dedicated `meter/timesig` HKDF label:
|
|
104
|
+
- 4/4 stays the overwhelming default (~94% of hashes overall, ~98% in
|
|
105
|
+
4/4-only moods like M2/M5/M11/M13/M14, ~6% odd-meter in opt-in moods like
|
|
106
|
+
M0/M1/M4/M9/M10/M12).
|
|
107
|
+
- Render is fully parameterized on `spec.time_sig` already; pattern banks
|
|
108
|
+
filter by `valid_time_sigs`/`time_sigs` and fall back to 4/4 when a meter
|
|
109
|
+
has no matching pattern in a given bank.
|
|
110
|
+
- Swing remains carried by `groove_template_id` (the groove-template's
|
|
111
|
+
per-step PPQ offsets are the actual swing implementation); no separate
|
|
112
|
+
`swing` enum byte is consumed.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the mhash project. Format: reverse chronological, grouped by milestone.
|
|
4
|
+
|
|
5
|
+
## v0.0.1 — initial scaffold + research
|
|
6
|
+
|
|
7
|
+
- Repo scaffold: pyproject, src/mhash skeleton, asset stubs.
|
|
8
|
+
- 14 dimensions of research under `research/<NN-slug>/`.
|
|
9
|
+
- 58 curated JSON tables under `assets/v1/`.
|
|
10
|
+
- Decoder skeleton consumes 32-byte HKDF macro stream.
|
|
11
|
+
- DESIGN.md, README.md, MIME family resolver, soundfont bootstrap.
|
|
12
|
+
|
|
13
|
+
## v0.1.0 — first PyPI release
|
|
14
|
+
|
|
15
|
+
- Bumped version to 0.1.0; added MIT LICENSE.
|
|
16
|
+
- Filled in PyPI metadata: authors, license, classifiers, project URLs,
|
|
17
|
+
keywords, full README rendering.
|
|
18
|
+
- Wheel build: pure-Python `py3-none-any` (~144 KB). Asset bundle ships
|
|
19
|
+
inside the wheel as `mhash/_assets/v1/...`; SoundFonts are
|
|
20
|
+
excluded and downloaded on first run.
|
|
21
|
+
- All asset-loading modules (`tables`, `mime`, `render.audio`,
|
|
22
|
+
`setup_assets`) check the dev path first and fall back to the wheel
|
|
23
|
+
layout, so `pip install mhash` works the same as `-e .`.
|
|
24
|
+
- `dev` extra now pulls `build` + `twine` for release tooling.
|
|
25
|
+
- Self-test SHA unchanged; 23/23 fast tests green on the wheel.
|
|
26
|
+
|
|
27
|
+
## Meter flexibility (post-M2)
|
|
28
|
+
|
|
29
|
+
- New HKDF label `meter/timesig` drives `time_sig` from a dedicated 1-byte
|
|
30
|
+
spillover. ~94% of hashes still land on 4/4; ~6% of opt-in moods land on
|
|
31
|
+
3/4, 6/8, or 12/8 (drawn from each mood's `time_sigs` list).
|
|
32
|
+
- Self-test seed unchanged (byte = 147, below the 240 threshold).
|
|
33
|
+
- 7/8 and 5/4 declared by some moods but held back until drum/comp/motif
|
|
34
|
+
banks have coverage; falls back to 4/4 transparently.
|
|
35
|
+
|
|
36
|
+
## Milestone 2 — vertical slice
|
|
37
|
+
|
|
38
|
+
- 9-layer MIDI render: drums, bass, comp, lead, pad, counter, drone, riser, ear-candy.
|
|
39
|
+
- WAV render via `fluidsynth -ni` shell-out + MS-Basic.sf3 SoundFont.
|
|
40
|
+
- LUFS norm to -16 / true-peak limit / cosine fades.
|
|
41
|
+
- Per-mood pedalboard FX chains (reverb / delay / chorus / phaser / EQ).
|
|
42
|
+
- 11-mood showcase generator (`python -m mhash.showcase`) + browser HTML.
|
|
43
|
+
- MP3 + FLAC export.
|
|
44
|
+
- Heuristic (LUFS / crest / spectrum / width) + mosqito psychoacoustic scoring.
|
|
45
|
+
- 4 new moods added per user feedback: M11 lofi, M12 chillout, M13 simple, M14 gameboy.
|
|
46
|
+
|
|
47
|
+
## Adversarial-review batch
|
|
48
|
+
|
|
49
|
+
5 parallel reviewers (codex + gemini × 5 areas: implementation, sound design, musical spectrum, quality measurement, dimensions audit) flagged 18 P0/P1/P2 items.
|
|
50
|
+
|
|
51
|
+
### P0 — correctness bugs
|
|
52
|
+
- Reorder `_postprocess_wav`: FX → LUFS → fades → peak limit (was LUFS-before-FX, so the -16 LUFS contract was a lie).
|
|
53
|
+
- Clear `_GROOVE_CACHE` per-render (asymmetric leak vs. `_VEL_JITTER_CACHE`).
|
|
54
|
+
- `_lead_octave(spec)` actually used by `_counter_track` (was hardcoding 72).
|
|
55
|
+
- Dropped duplicate `counter_program` assignment.
|
|
56
|
+
- Empty-progression infinite-loop guard.
|
|
57
|
+
|
|
58
|
+
### P1 — spec gaps
|
|
59
|
+
- **Accent skeleton wired** (highest-distinguishability-per-byte feature). HKDF byte from `melody/accent_skeleton` picks 4 strong-beat chord-tone targets weighted [R 35%, 3 30%, 5 25%, 7 10%] + a 3-value micro_shape applied to weak slots.
|
|
60
|
+
- **Layer activation matrix** (byte 25) consumed; 16 matrices on disk filtered to 10 lead-audible ones.
|
|
61
|
+
- **Voicing style** (byte 8) with 10 implementations: close_triad / open_triad / sus_open / quartal / power / shell / drop2_7th / drop3_7th / rootless_A / rootless_B.
|
|
62
|
+
- Mood family rebalance (no mood in >5 family slots; M4/M8 raised from 1 → 3 each).
|
|
63
|
+
- M11–M14 progressions explicitly tagged (39 progressions tagged, was 0).
|
|
64
|
+
- Triage metrics added: `level_range_db`, `loop_repetition`, `low_band_side_width`.
|
|
65
|
+
|
|
66
|
+
### P2 — polish
|
|
67
|
+
- Counter-melody now has 4 modes (parallel_3rd / parallel_6th / contrary / octave_below).
|
|
68
|
+
- Bass + comp register guards (comp.top ≤ lead.median - 5).
|
|
69
|
+
- Drum escalation algos picked from byte 12 (2 of 8 implemented in render: `linear_add`, `ghost_note_stack`).
|
|
70
|
+
- Locrian + jazz_minor reachable; sub-60 BPM for M0/M10.
|
|
71
|
+
- Label registry test un-skipped; 2 live unregistered labels added.
|
|
72
|
+
|
|
73
|
+
### Sound-design adversarial pass
|
|
74
|
+
- MIME resolver promoted from top-level stub to exact → prefix → fallback against `mime_families.json`.
|
|
75
|
+
- Master EQ retargeted at MS-Basic SF3's actual problem bands (200-400 Hz mud, 2.5-4.5 kHz plastic).
|
|
76
|
+
- Dropped GM 82 Calliope + GM 87 from inappropriate slots; M2 counter de-aliased from comp.
|
|
77
|
+
- M6 chain reordered so reverb tails don't pump.
|
|
78
|
+
- Lead palettes expanded 3 → 5-8 candidates per mood for "main voice variety".
|
|
79
|
+
|
|
80
|
+
## Reserved-byte wiring (post-review)
|
|
81
|
+
|
|
82
|
+
After P-stack closed, all remaining "reserved/unused" macro bytes were wired:
|
|
83
|
+
|
|
84
|
+
- **byte 1** — 4 mood sub-flavors (stock / brighter / darker / tighter), each tweaks tempo and lead octave.
|
|
85
|
+
- **byte 27** — 6 humanization profiles scaling vel-jitter (machine / groove-tight / groove-loose / acoustic-lively / ballad-rubato / swing-jazz).
|
|
86
|
+
- **byte 29** — 4 FX wet scales (0.6 / 0.9 / 1.0 / 1.15) multiplying any plugin `wet_level` / `mix` kwargs.
|
|
87
|
+
- **byte 30** — 4 mix-balance presets (balanced / bass_forward / lead_forward / minimal) emitting per-layer CC7 channel volume.
|
|
88
|
+
|
|
89
|
+
## Documentation
|
|
90
|
+
|
|
91
|
+
- BYTES.md — full byte-by-byte map with filter chain, table size, empirical distributions.
|
|
92
|
+
- DESIGN.md §13 — implementation status with 31/32 bytes wired, only #84 invasive deferred.
|
|
93
|
+
- showcase/showcase.html — browser preview of 15-mood demo.
|
|
94
|
+
|
|
95
|
+
## Late additions
|
|
96
|
+
|
|
97
|
+
- **All 8 drum escalation algos** now render-active (linear_add, ghost_note_stack, subdivision_double, snare_roll_crescendo, tom_rollup, hat_density_ramp, polyrhythm_overlay, reverse_cymbal_sweep). Each picks deterministically from byte 12; render applies on rising-energy bars (Δ ≥ 0.08).
|
|
98
|
+
- **`--self-test` CLI** subcommand: renders a fixed seed and verifies its MIDI SHA against a baseline. Catches accidental output drift from refactors / dep upgrades.
|
|
99
|
+
|
|
100
|
+
## Known deferred work
|
|
101
|
+
|
|
102
|
+
- **#84 time_sig + swing de-hardcode** — render currently assumes 4/4 in dozens of places (drum patterns 16-cell grid, comp chord_rhythm grid, melody motif `total_beats`). Multi-day rework.
|
|
103
|
+
- **Phrase shape (byte 21)** — phrase_shapes.json on disk; phrase shape is implicit in motif `total_beats` for now.
|
|
104
|
+
- **Cross-arch determinism** — host-bound to Apple Silicon + fluidsynth 2.5.4 + MS-Basic SF3. Docker canonical or per-arch wheel matrix is the next step.
|