fix(vst): pin output bus to stereo (mode is decode-only) killing the hard-right pan; auto-default channel mode from the loaded capture (state v9)
This commit is contained in:
@@ -851,6 +851,35 @@ static void testMonoSamplePlaysDualMonoInStereo() {
|
||||
}
|
||||
}
|
||||
|
||||
static void testDualMonoStereoSampleRendersCentered() {
|
||||
// GA Bug 1 (pure-layer proof): a STEREO sample whose two channels are IDENTICAL (a
|
||||
// dual-mono capture) must render EXACTLY equal L and R — bitwise, every frame — under
|
||||
// BOTH pitch engines. Any asymmetry here (a silent L, a channel offset, divergent
|
||||
// shifter state) would pan the output; hard-panned output from a dual-mono capture
|
||||
// therefore cannot originate in the engine.
|
||||
auto renderBoth = [](PitchEngine engine, int note) {
|
||||
SampleData s = sineSample(600, 12.0, 60);
|
||||
s.framesR = s.frames; // dual-mono: identical channels
|
||||
s.play.pitchEngine = engine;
|
||||
Keymap km = Keymap::singleSampleChromatic(std::move(s));
|
||||
VoiceEngine eng(1, km, /*preserveCap=*/0, /*preserveWindowFrames=*/128);
|
||||
eng.noteOn(note, 127);
|
||||
std::vector<AudioSample> left(256, 0.f), right(256, 0.f);
|
||||
eng.render(left.data(), right.data(), 256);
|
||||
bool sound = false, equal = true;
|
||||
for (std::size_t i = 0; i < left.size(); ++i) {
|
||||
if (left[i] != 0.0f) sound = true;
|
||||
if (left[i] != right[i]) equal = false; // EXACT: dual-mono must be centered
|
||||
}
|
||||
CHECK(sound); // the render actually produced signal (a 0==0 pass would be vacuous)
|
||||
CHECK(equal);
|
||||
};
|
||||
renderBoth(PitchEngine::Varispeed, 60);
|
||||
renderBoth(PitchEngine::Varispeed, 67); // off-root: repitch rides both channels equally
|
||||
renderBoth(PitchEngine::Preserve, 60); // both shifters run (no unity demotion in MIDI)
|
||||
renderBoth(PitchEngine::Preserve, 67); // off-root Preserve: per-channel shift, same state
|
||||
}
|
||||
|
||||
static void testMonoRenderUnchangedByStereoData() {
|
||||
// Regression: the mono render path (renderFrame) reads channel 0 ONLY and is byte-identical
|
||||
// whether or not a second channel is present. A stereo sample rendered mono == its L channel.
|
||||
@@ -1975,6 +2004,7 @@ int main() {
|
||||
testChannelCount();
|
||||
testStereoRenderKeepsChannelsDistinct();
|
||||
testMonoSamplePlaysDualMonoInStereo();
|
||||
testDualMonoStereoSampleRendersCentered();
|
||||
testMonoRenderUnchangedByStereoData();
|
||||
testStereoRenderAdvancesLikeMonoRepitch();
|
||||
testStereoRenderSumsVoicesPerChannel();
|
||||
|
||||
Reference in New Issue
Block a user