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:
@@ -146,6 +146,7 @@ void ReaSamplerEditor::refreshFromBank() {
|
||||
banks_ = banksJson ? listBanks(*banksJson) : std::vector<BankChoice>{};
|
||||
selectedId_ = processor_->selectedSampleId();
|
||||
map_ = processor_->performanceMap();
|
||||
channelMode_ = processor_->channelMode();
|
||||
if (selectedZone_ >= static_cast<int>(map_.zones.size())) selectedZone_ = -1;
|
||||
// Drop a filter that names a bank no longer present.
|
||||
if (!activeFilterBankId_.empty()) {
|
||||
@@ -334,6 +335,22 @@ Rect zonesStripArea(const EditorBands& bands) {
|
||||
return Rect{bands.content.left + pad, stripTop, bands.content.right - pad,
|
||||
stripTop + kStripBandHeight};
|
||||
}
|
||||
|
||||
// The S7 mono/stereo toggle, a two-segment control anchored to the RIGHT of the setup band's
|
||||
// header row (same y as the sample-name header, so it reads as "this capture's output mode").
|
||||
// `area` is the full setup Rect. Returns {mono-segment, stereo-segment}; each is kSegW wide,
|
||||
// kSegH tall, side by side. Kept to a small fenced block (S11 owns the waveform region).
|
||||
constexpr int kChanSegW = 52;
|
||||
constexpr int kChanSegH = 18;
|
||||
struct ChannelToggleRects { Rect mono; Rect stereo; };
|
||||
ChannelToggleRects channelToggleRects(const Rect& area) {
|
||||
constexpr int pad = 8;
|
||||
const int top = area.top + 4;
|
||||
const int right = area.right - pad;
|
||||
const Rect stereo{right - kChanSegW, top, right, top + kChanSegH};
|
||||
const Rect mono{stereo.left - kChanSegW, top, stereo.left, top + kChanSegH};
|
||||
return {mono, stereo};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void ReaSamplerEditor::paint(HDC hdc) {
|
||||
@@ -477,10 +494,22 @@ void ReaSamplerEditor::paintSetup(LICE_IBitmap* bmp, const Rect& area) {
|
||||
}
|
||||
|
||||
const int pad = 8;
|
||||
Rect headerR{area.left + pad, area.top + 4, area.right - pad, area.top + 22};
|
||||
// The mono/stereo toggle sits at the right of the header row; keep the name text clear of it.
|
||||
const ChannelToggleRects chan = channelToggleRects(area);
|
||||
Rect headerR{area.left + pad, area.top + 4, chan.mono.left - 8, area.top + 22};
|
||||
std::string header = sampleLabel(samples_, selectedId_) + " root " + noteLabel(root);
|
||||
drawText(bmp, headerR, header.c_str(), kRgbText);
|
||||
|
||||
// S7 mono | stereo output-mode toggle. The active segment highlights (kColTabActiveBg),
|
||||
// the inactive is kColTabBg — the same visual grammar as the Browser/Zones toggle.
|
||||
const bool isStereo = (channelMode_ == ChannelMode::Stereo);
|
||||
LICE_FillRect(bmp, chan.mono.left, chan.mono.top, chan.mono.width(), chan.mono.height(),
|
||||
isStereo ? kColTabBg : kColTabActiveBg, 1.0f, 0);
|
||||
LICE_FillRect(bmp, chan.stereo.left, chan.stereo.top, chan.stereo.width(),
|
||||
chan.stereo.height(), isStereo ? kColTabActiveBg : kColTabBg, 1.0f, 0);
|
||||
drawTextCentered(bmp, chan.mono, "Mono", kRgbText);
|
||||
drawTextCentered(bmp, chan.stereo, "Stereo", kRgbText);
|
||||
|
||||
Rect hintR{area.left + pad, headerR.bottom, area.right - pad, headerR.bottom + 16};
|
||||
drawText(bmp, hintR, "Drag on the keyboard to set the root note.", kRgbDim);
|
||||
|
||||
@@ -597,9 +626,25 @@ void ReaSamplerEditor::onMouseDown(int x, int y) {
|
||||
commitAndReload(); // publishes the pick + reloads; process() plays it repitched
|
||||
return;
|
||||
}
|
||||
// The setup strip: grab the root marker (drag to set the picked capture's root).
|
||||
// The setup band: the mono/stereo toggle (header row), then the root-marker strip.
|
||||
if (havePick) {
|
||||
const Rect area{bands.content.left, setupTop, bands.content.right, bands.content.bottom};
|
||||
// S7: a click on a channel-mode segment sets the instance mode (setChannelMode
|
||||
// re-negotiates the bus + reloads; a no-op set for the already-active mode is ignored
|
||||
// by the processor). Snapshot the new mode locally so the paint reflects it at once.
|
||||
const ChannelToggleRects chan = channelToggleRects(area);
|
||||
if (contains(chan.mono, x, y)) {
|
||||
channelMode_ = ChannelMode::Mono;
|
||||
processor_->setChannelMode(ChannelMode::Mono);
|
||||
invalidate();
|
||||
return;
|
||||
}
|
||||
if (contains(chan.stereo, x, y)) {
|
||||
channelMode_ = ChannelMode::Stereo;
|
||||
processor_->setChannelMode(ChannelMode::Stereo);
|
||||
invalidate();
|
||||
return;
|
||||
}
|
||||
const Rect stripArea = setupStripArea(area);
|
||||
const StripLayout sl = layoutStrip(stripArea.width(), stripArea.height());
|
||||
const int note = keyAtPoint(sl, x - stripArea.left, y - stripArea.top);
|
||||
|
||||
Reference in New Issue
Block a user