Files
reaper-control/.sdd/changes/hook-melody/proposal.md
renato97 014e636889 feat: professional reggaeton production engine — 7 SDD changes, 302 tests
- section-energy: track activity matrix + volume/velocity multipliers per section
- smart-chords: ChordEngine with voice leading, inversions, 4 emotion modes
- hook-melody: melody engine with hook/stabs/smooth styles, call-and-response
- mix-calibration: Calibrator module (LUFS volumes, HPF/LPF, stereo, sends, master)
- transitions-fx: FX track with risers/impacts/sweeps at section boundaries
- sidechain: MIDI CC11 bass ducking on kick hits via DrumLoopAnalyzer
- presets-pack: role-aware plugin presets (Serum/Decapitator/Omnisphere per role)

Full SDD pipeline (propose→spec→design→tasks→apply→verify) for all 7 changes.
302/302 tests passing.
2026-05-03 23:54:29 -03:00

87 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Proposal: Hook-Based Reggaeton Melody
## Intent
`build_lead_track()` generates random pentatonic notes — no hook, no identity, no rhythmic motif. Professional reggaeton leads have memorable hooks (repeating motif), rhythmic alignment with the dembow grid, call-and-response structure, and chord-tone emphasis on strong beats. This change replaces random generation with a structured hook engine producing identifiable, repeating motifs with controlled variation.
## Scope
### In Scope
- **Hook engine module** (`src/composer/melody_engine.py`) — generates motifs, variations, call-response
- **3 reggaeton styles**: "stabs" (syncopated hits on 1, 2.5, 3, 3.5), "smooth" (stepwise eighth notes), "hook" (arch contour, chord tones on strong beats)
- **Motif + variation loop**: 24 bar motif repeated 24x with transpose/rhythmic-shift variations
- **Call-and-response**: first half = call (ends on V/VII), second half = response (resolves to i)
- **Chord-aware note selection**: strong beats (1, 3) favor chord tones; weak beats use scale passing tones
- **Replace `build_lead_track()`** in `compose.py` to delegate to the new engine
- **Tests** for deterministic output, motif identity preserved across variations, call-response resolution
### Out of Scope
- MIDI velocity humanization / groove quantization
- User-selectable style at CLI (hardcoded to "hook" style initially)
- Chord progression generation (uses existing `CHORD_PROGRESSION` from compose.py)
- Pad/chords/bass refactoring — lead only
## Capabilities
### New Capabilities
- `melody-engine`: Deterministic hook generation with motif, variation, call-response, and 3 reggaeton styles. Chord-aware via `CHORD_PROGRESSION` input.
### Modified Capabilities
- None at spec level. `build_lead_track()` API unchanged (same signature). Behavior changes from random to deterministic, but callers see same interface.
## Approach
New module `src/composer/melody_engine.py` with:
1. **`build_motif(key_root, key_minor, style, bars=4)`** → `list[MidiNote]`
- Style "hook": arch contour, chord tones on 0, 2, 4... beats, 48 notes
- Style "stabs": short 16th hits on [1.0, 2.5, 3.0, 3.5] per bar
- Style "smooth": stepwise scalar motion at eighth-note density
- Chords resolved from `CHORD_PROGRESSION` for chord-tone selection
2. **`apply_variation(motif, shift=0, transpose=0)`** → variation
- Rhythmic shift: offset within the grid
- Transpose: ±octave or ±third within scale
3. **`build_call_response(motif, sections, key_root, key_minor)`** → `list[ClipDef]`
- First half = call (motif + slight variation, ends on tension note)
- Second half = response (motif, resolves to tonic)
- Repeats for section length
`compose.py` `build_lead_track()` becomes thin wrapper calling `melody_engine`. All existing tests pass with updated expected values.
## Affected Areas
| Area | Impact | Description |
|------|--------|-------------|
| `src/composer/melody_engine.py` | New | Hook engine — motifs, variations, call-response |
| `scripts/compose.py` | Modified | `build_lead_track()` delegates to melody_engine; `get_pentatonic()` stays as helper |
| `tests/test_compose_integration.py` | Modified | Update `test_melody_uses_pentatonic` to assert motif structure |
| `tests/test_section_builder.py` | None | `get_pentatonic` tests unaffected |
## Risks
| Risk | Likelihood | Mitigation |
|------|------------|------------|
| Deterministic melody sounds repetitive | Med | 3 style options + variation params provide diversity; section energy scales velocity |
| Chord-awareness breaks if CHORD_PROGRESSION changes format | Low | Hardcoded in compose.py — same module owns both; integration test catches mismatch |
| Motif too short for long sections (8+ bars) | Low | Call-response repeats motif to fill bars; edge case validated in tests |
## Rollback Plan
Revert `build_lead_track()` to original random-pentatonic implementation (git revert). No schema or API changes — pure function replacement.
## Dependencies
- `CHORD_PROGRESSION` constant from `compose.py` (existing)
- `get_pentatonic()` helper from `compose.py` (kept, reused)
## Success Criteria
- [ ] `build_lead_track()` produces identical output for same seed+key input (deterministic)
- [ ] Generated melody contains a repeating 24 bar motif with ≤2 variations
- [ ] Call section ends on V or VII degree; response resolves to i
- [ ] Strong beats (quarter positions) use chord tones ≥70% of the time
- [ ] All 110+ existing tests pass
- [ ] 5+ new tests for melody_engine: motif identity, variation bounds, call-response resolution