S7: stereo channel mode — core channel dimension, v4 mode state, VST3 bus negotiation, editor toggle
Per-instance mono|stereo (default mono, byte-identical). Stereo grows SampleData a 2nd channel + a per-channel VoiceEngine render; decodeChannels applies the cross-mode policy; setBusArrangements pins the mode's arrangement and restartComponent(kIoChanged) re-negotiates.
This commit is contained in:
@@ -285,25 +285,28 @@ unchanged (regression).
|
||||
**Depends on:** S3 (extends the core), S4 (extends the process/bus shell). Independent of
|
||||
S8/S9.
|
||||
|
||||
- [ ] Core channel dimension (pure, S3 extension): `SampleData` carries N-channel
|
||||
(1 or 2) decoded PCM; `Voice::renderFrame` and `VoiceEngine::render` produce a
|
||||
per-channel frame; stereo linear interpolation + loop read per channel. Mono stays the
|
||||
degenerate case (single channel) — no behavior change for existing mono play. Tests:
|
||||
stereo render asserted against a known 2-channel signal; mono render unchanged.
|
||||
- [ ] Channel-mode toggle as per-instance state: `mono | stereo` in the instrument's own
|
||||
component state (setState/getState, alongside the selected sample); default preserves
|
||||
current behavior (mono). Cross-mode policy: **mono source + stereo mode → dual-mono**
|
||||
(same signal both channels, centered); **stereo source + mono mode → downmix** (the
|
||||
existing decode-side policy). The toggle lives in the instrument, never written to the
|
||||
bank (a performance choice, not a file fact — D-B).
|
||||
- [ ] Shell: decode fills 1- or 2-channel `SampleData` per the source's channel count
|
||||
(the S2/bank channel-count intrinsic already exists); the process path renders the
|
||||
active mode's channel count into the output bus.
|
||||
- [ ] VST3 bus negotiation: implement `setBusArrangements` so the output bus reports
|
||||
mono or stereo per the instance's channel mode, and REAPER's routing follows
|
||||
automatically (no manual channel wiring). **Must-verify before build:** the
|
||||
`setBusArrangements` / `getBusArrangement` contract and REAPER's mono/stereo instrument
|
||||
bus expectations against the vendored Steinberg SDK + `reaper_vst3_interfaces.h`.
|
||||
- [x] Core channel dimension (pure, S3 extension): `SampleData` carries 1- or 2-channel
|
||||
decoded PCM (`frames` + optional length-matched `framesR`; `channelCount()`);
|
||||
`Voice::renderFrameStereo` + a `VoiceEngine::render(left,right,n)` overload produce a
|
||||
per-channel frame sharing one read head + one envelope tick; stereo linear interpolation +
|
||||
loop read per channel. Mono stays the degenerate case (`renderFrame` reads channel 0 only,
|
||||
byte-identical). Tests: stereo render asserted against a known 2-channel signal; dual-mono;
|
||||
per-channel repitch + additive mix; mono render unchanged (regression) — sampler_core_tests.
|
||||
- [x] Channel-mode toggle as per-instance state: `ChannelMode {Mono,Stereo}` in the
|
||||
instrument's own component state (v4 = v3 + a channel-mode byte; setState/getState);
|
||||
default mono. Cross-mode policy in `decodeChannels`: **mono source + stereo mode →
|
||||
dual-mono**; **stereo source + mono mode → downmix** (existing decode-side policy). The
|
||||
toggle lives in the instrument, never written to the bank (D-B). v1/v2/v3 blobs lift to v4
|
||||
with mono default; round-trip + lift tests — sample_map_tests.
|
||||
- [x] Shell: `decodeRelative` fills 1- or 2-channel `DecodedZonePcm` per the active mode
|
||||
(source channel count from the WAV layout); the process path renders the host's negotiated
|
||||
output channel count (stereo into ch0/ch1, mono into ch0) — RT discipline unchanged.
|
||||
- [x] VST3 bus negotiation: `setBusArrangements` accepts only the mode's arrangement
|
||||
(kMono/kStereo), else rejects (kResultFalse) but keeps a valid mode arrangement so
|
||||
`getBusArrangement` (base default) reports it; a runtime mode change repoints the output bus
|
||||
+ calls `restartComponent(kIoChanged)` so REAPER re-negotiates. **Verified** against the
|
||||
vendored Steinberg SDK (`ivstaudioprocessor.h` contract, `vstsinglecomponenteffect.cpp`
|
||||
base impl, `ivsteditcontroller.h` kIoChanged); see handoff notes.
|
||||
|
||||
## S8 — ingest through the bank (one gesture: capture/import into bank + assign to instance)
|
||||
**Goal:** Loading a sample into the sampler is **one gesture** — capture/import-into-bank
|
||||
|
||||
Reference in New Issue
Block a user