Files
renato97 33bb08270d fix: musical content — 808 timing, chord voicings, melody range, pad arpeggiation, Ozone paths
- 808 bass: fixed note positions to beat 1.0 per bar (i-iv-i-V, 1.5 beat duration)
- Chords: 4-note 7th voicings (Am7, F7, C7, G7) instead of 2-note intervals
- Lead: constrained to 8-semitone range, pentatonic scale
- Pad: arpeggiated eighth-notes instead of static 2-note drones
- Ozone 12: fixed .vst3 filename paths in Calibrator
- Delta-encoding: fixed cumulative timing drift in _build_midi_source() with CC events

298/298 tests pass.
2026-05-04 01:30:19 -03:00

2.1 KiB

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"