# Spec: Fix Musical Coherence ## Requirements ### R1: Bass Pattern - 808 Bass MUST use i-iv-i-V pattern over 8 bars - Each chord gets 2 bars with 1 note on beat 1.0, duration 1.5 beats - Pitch sequence for Am: A1(33), D2(38), A1(33), E2(40) - Transposed by key difference from Am ### R2: Lead Melody - Lead notes MUST NOT exceed 12 semitones between consecutive notes - Melody MUST use chord tones on strong beats (1 and 3) - Scale-based passing tones allowed on weak beats - Octave range constrained to ±6 semitones from root ### R3: Chord Voicings - ChordEngine MUST produce 4-note voicings (root, 3rd, 5th, 7th) - Use m7 for minor chords, 7 for major chords - Voice leading keeps movement ≤4 semitones per voice - First chord respects requested inversion ### R4: Pad Movement - Pad MUST have rhythmic movement (arpeggiated eighth-notes) - Cycle through chord notes in ascending order - Volume: 0.55 (prevents masking) - Duration per note: 0.5 beats (eighth note) ### R5: Ozone 12 - Master chain PluginDef MUST have correct .vst3 path - Filename field MUST match PLUGIN_REGISTRY entry exactly - No fallback to empty string path ## Scenarios ### S1: Bass timing verification Given: 8-bar section, key Am, bpm=95 When: build_bass_track runs Then: First 4 notes at start positions 0.0, 8.0, 16.0, 24.0 (beats) And: durations all 1.5 And: pitches 33, 38, 33, 40 ### S2: Lead range constraint Given: 4-bar hook motif in Am When: build_motif(style="hook") runs Then: all(n.pitch for n in motif) within 12 semitones of tonic And: max pitch - min pitch ≤ 12 ### S3: Chord voicing size Given: Emotion "romantic", key "Am", 8 bars When: engine.progression(bars=8) runs Then: Each voicing has len() == 4 And: Notes include root, 3rd, 5th, 7th intervals ### S4: Pad arpeggiation Given: 8-bar section, Am key When: build_pad_track runs Then: Clip has >24 MIDI notes (arpeggiated, not 3 sustained) And: Each note duration ≤ 0.5 beats ### S5: Ozone vst3 path Given: SongDefinition with master_plugins after Calibrator.apply() When: RPPBuilder writes master FXCHAIN Then: VST element filename field is "Ozone 12 Equalizer.vst3"