- 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.
2.4 KiB
2.4 KiB
Chords Specification
Purpose
Chord progression generation with voice leading, inversion selection, and emotion-aware patterns for reggaeton. Deterministic and testable.
Requirements
| # | Requirement | Strength | Key Scenarios |
|---|---|---|---|
| R1 | ChordEngine(key, seed) MUST produce identical progressions for same seed+key |
MUST | Same seed → same notes; different seed → different notes |
| R2 | Voice leading MUST minimize semitone movement between consecutive chords, capping at 4 semitones per voice | MUST | 2-chord transition ≤4 semitones per voice; 8-bar progression all leaps ≤4 |
| R3 | SHALL support 3 inversion modes: root, first, second |
SHALL | Root: lowest note = root; First: lowest = third; Second: lowest = fifth |
| R4 | MUST support 4 emotion modes: romantic, dark, club, classic |
MUST | Each emotion yields distinct degree sequence; unknown emotion → classic fallback |
| R5 | progression(bars, emotion, beats_per_chord, inversion) SHALL return list[list[int]] — ordered chord voicings as MIDI note lists |
SHALL | 8 bars @ 4 BpC → 8 chords; empty list for 0 bars |
| R6 | Reggaeton progressions SHOULD use genre-appropriate cadences per emotion | SHOULD | Romantic: i-VI-III-VII; Dark: i-iv-V-v; Club: i-VII-VI-V; Classic: i-VI-III-VII |
| R7 | build_chords_track() SHALL delegate to ChordEngine instead of hardcoded progression |
SHALL | CLI --emotion dark → dark progression in output |
Scenario: Deterministic reproducibility
- GIVEN
ChordEngine("Am", seed=42) - WHEN
progression(bars=8)called twice - THEN both calls return identical
list[list[int]]
Scenario: Voice leading within bounds
- GIVEN any 2 consecutive chords from a progression
- WHEN computing voice leading
- THEN no voice moves more than 4 semitones from its previous position
Scenario: Emotion modes diverge
- GIVEN
ChordEngine("Am", seed=0)with emotionsromantic,dark,club,classic - WHEN
progression(8)called per emotion - THEN all 4 output sequences differ
Scenario: Invalid emotion falls back
- GIVEN
ChordEngine("Am")with emotion"angry"(unknown) - WHEN
progression(8)called - THEN defaults to
classicprogression, no error raised
Scenario: Integration with compose.py
- GIVEN
python scripts/compose.py --key Am --emotion dark --output test.rpp - WHEN build completes
- THEN Chords track contains voicings matching dark-emotion progression