Files
reaper-control/.sdd/changes/presets-pack/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

4.0 KiB

Proposal: presets-pack

Intent

All plugins use the SAME flat preset regardless of track role (bass/lead/chords/pad) or genre context. A Serum_2 on a bass track gets the same sound as Serum_2 on a lead track. Professional reggaeton needs role-specific timbres: deep sine 808 for bass, detuned saw for lead, warm pad for chords, evolving texture for pad. Same for FX: Decapitator on drums needs aggressive drive, on bass needs subtle warmth.

Scope

In Scope

  • Restructure PLUGIN_PRESETS from flat {plugin: [chunks]} to role-aware {plugin: {role: [chunks]}}
  • Create role-specific presets for plugins used in multiple roles: Serum_2 (bass/lead), Omnisphere (chords/pad), Decapitator (drums/bass)
  • Programmatically derive new presets by base64-decoding existing presets (Serum=JSON, SoundToys=key=value), modifying genre-specific parameters, re-encoding
  • Update make_plugin() in compose.py and _build_plugin() in __init__.py to resolve role-aware presets
  • Add fallback: if no role-specific preset exists, use existing default preset

Out of Scope

  • Creating presets from scratch in REAPER (requires GUI — can't programmatically)
  • ReaScript-based preset capture (Phase 2)
  • Presets for all 113 plugins — only multi-role targets initially
  • Pro-Q 3 reggaeton EQ curve (no decodable format available)

Capabilities

New Capabilities

  • presets-pack: Role-specific plugin preset resolution and preset data management

Modified Capabilities

None — existing plugin resolution unchanged; backward-compatible fallback to default preset.

Approach

Option B — Programmatic modification of decodable presets:

  1. Serum_2: Decode base64 → JSON. Serum preset JSON has component: "processor" block with oscillator/wavetable/filter data. Create variants by modifying oscillator type (sine for bass, saw for lead), filter cutoff, envelope settings. Re-encode.

  2. Decapitator (SoundToys): Decode base64 → key=value text (WIDGET = Decapitator;...). Create "aggressive" (high Drive, Tone bright) for drums, "warm" (low Drive, Tone dark) for bass. Re-encode.

  3. Omnisphere: Decode base64 → SynthMaster text block. Create "warm pad" variant with slow attack, filter modulation; "evolving texture" with movement/LFO. Re-encode.

No GUI or REAPER needed — pure Python string processing over decoded preset text.

Affected Areas

Area Impact Description
src/reaper_builder/__init__.py Modified PLUGIN_PRESETS restructured; _build_plugin() accepts role param
src/composer/templates.py Modified _parse_vst_block(), make_plugin() resolution updated
scripts/compose.py Modified make_plugin() passes role; FX_CHAINS keys used for role
src/core/schema.py Unchanged PluginDef already has preset_data field

Risks

Risk Likelihood Mitigation
Modified preset crashes plugin on load Low Each variant derived from working ground-truth preset; only tweak known-safe params
Base64 decode/re-encode breaks binary integrity Low Round-trip test per plugin: decode → encode → bytes equal
Omnisphere text format undocumented Med Preserve structure, only modify known ATTRIBUTE values visible in decoded text

Rollback Plan

Revert PLUGIN_PRESETS to flat dict. Remove role param from _build_plugin() and make_plugin(). Existing tests verify preset injection still works.

Dependencies

  • data/sample_index.json (independent — not affected)
  • Existing ground-truth presets in PLUGIN_PRESETS (source material for variants)

Success Criteria

  • python scripts/compose.py --bpm 99 --key Am produces .rpp where Serum_2 on bass track has different preset data than Serum_2 on lead track
  • 110 existing tests continue to pass (backward-compatible fallback)
  • Round-trip test: decode → modify → encode produces valid base64 matching original length structure
  • At least 3 (plugin, role) combinations have distinct preset variants