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.
This commit is contained in:
95
.sdd/changes/transitions-fx/spec.md
Normal file
95
.sdd/changes/transitions-fx/spec.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Transition FX Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
Glue sections together by placing audio FX clips at arrangement boundaries using existing `role="fx"` library samples.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: FX Track Existence
|
||||
|
||||
The system MUST create a dedicated "Transition FX" audio track with clips at 7 section boundaries.
|
||||
|
||||
#### Scenario: FX track present in arrangement
|
||||
|
||||
- GIVEN a 9-section song
|
||||
- WHEN `compose.py` runs
|
||||
- THEN a track named "Transition FX" exists with 7+ audio clips at boundary positions
|
||||
|
||||
### Requirement: Riser Before Climax
|
||||
|
||||
A riser/wash FX MUST start 2–4 beats before build→chorus and bridge→final boundaries, ending ON the boundary downbeat.
|
||||
|
||||
#### Scenario: Riser before chorus
|
||||
|
||||
- GIVEN build ends at beat 64 (bar 16)
|
||||
- WHEN FX is built
|
||||
- THEN a riser at position 60 (beat 60), length 4, `fade_in` ≥ 1.0s
|
||||
|
||||
#### Scenario: Riser before final
|
||||
|
||||
- GIVEN bridge ends at beat 176 (bar 44)
|
||||
- WHEN FX is built
|
||||
- THEN a riser at position 172, length 4, `fade_in` ≥ 1.0s
|
||||
|
||||
#### Scenario: Riser before chorus2
|
||||
|
||||
- GIVEN verse2 ends at beat 128 (bar 32)
|
||||
- WHEN FX is built
|
||||
- THEN a riser at position 124, length 4, `fade_in` ≥ 1.0s
|
||||
|
||||
### Requirement: Impact on Section Downbeat
|
||||
|
||||
An impact/stab FX MUST start on beat 1 of CHORUS (beat 64) and FINAL (beat 176).
|
||||
|
||||
#### Scenario: Impact on chorus beat 1
|
||||
|
||||
- GIVEN chorus starts at beat 64
|
||||
- WHEN FX is built
|
||||
- THEN an impact clip at position 64, length 1–2 beats, `fade_out` ≥ 0.2s
|
||||
|
||||
#### Scenario: Impact on final beat 1
|
||||
|
||||
- GIVEN final starts at beat 176
|
||||
- WHEN FX is built
|
||||
- THEN an impact clip at position 176, length 1–2 beats
|
||||
|
||||
### Requirement: Transition Sweeps Between Verses
|
||||
|
||||
Short transition FX MUST bridge chorus→verse2 (beat 96) and chorus2→bridge (beat 160).
|
||||
|
||||
#### Scenario: Sweep bridges chorus to verse2
|
||||
|
||||
- GIVEN chorus ends at beat 96
|
||||
- WHEN FX is built
|
||||
- THEN a transition clip at position 94, length 2 beats, `fade_in` and `fade_out` > 0
|
||||
|
||||
### Requirement: FX Sample Selection
|
||||
|
||||
The system SHALL select FX samples via `SampleSelector.select_one(role="fx")`, favoring short samples for impacts, long for risers.
|
||||
|
||||
#### Scenario: FX role returns candidates
|
||||
|
||||
- GIVEN 57 FX samples in library with ATONAL_ROLES including "fx"
|
||||
- WHEN `select(role="fx")` is called
|
||||
- THEN non-empty result returned; key scoring skipped (neutral 0.5)
|
||||
|
||||
### Requirement: Fade Curves
|
||||
|
||||
FX clips MUST use `fade_in`/`fade_out`. Risers: `fade_in` ≥ 0.3s. Impacts: `fade_out` ≥ 0.2s.
|
||||
|
||||
#### Scenario: Riser fades in, impact fades out
|
||||
|
||||
- GIVEN riser and impact clips defined
|
||||
- WHEN ClipDef is created
|
||||
- THEN riser.fade_in > 0 AND impact.fade_out > 0
|
||||
|
||||
### Requirement: FX Track Mixing
|
||||
|
||||
The FX track SHALL have volume ≤ 0.80 and send to Reverb/Delay returns.
|
||||
|
||||
#### Scenario: FX track has moderate volume and sends
|
||||
|
||||
- GIVEN "Transition FX" track created
|
||||
- WHEN track is defined
|
||||
- THEN volume = 0.72, send_level includes reverb (0.08) and delay (0.05)
|
||||
Reference in New Issue
Block a user