Service both VST3 parameter channels, and promote pitch key-track and Trigger length so all 44 ids issue
The SDK's own single-component sample drains inputParameterChanges in process() and implements setParamNormalized; automation was reading the GUI channel alone. The audio thread now patches a block it solely owns.
This commit is contained in:
@@ -96,7 +96,7 @@ static Run renderWithLive(SampleData& sample, LiveParams* block, int blockFrames
|
||||
int changeAfter, const LiveValues* changed, int noteOffBlock = -1,
|
||||
int velocity = 100) {
|
||||
sample.live = block;
|
||||
if (block) block->publish(foldLive(sample.play));
|
||||
if (block) block->publish(foldLive(sample.play, sample.keyTrack));
|
||||
VoiceEngine engine(1, sample);
|
||||
engine.noteOn(kTestNote, velocity);
|
||||
Run r;
|
||||
@@ -320,7 +320,7 @@ static void testANoteStartedAfterAPublishSoundsThePublishedEnvelope() {
|
||||
SampleData s = periodicSine(200000, 64.0); // adsr default: attack 0, sustain 1.0
|
||||
LiveParams block;
|
||||
s.live = █
|
||||
LiveValues dialled = foldLive(s.play);
|
||||
LiveValues dialled = foldLive(s.play, s.keyTrack);
|
||||
dialled.adsr.attackFrames = 24000; // half a second of attack, dialled before the note
|
||||
block.publish(dialled);
|
||||
VoiceEngine engine(1, s);
|
||||
@@ -345,7 +345,7 @@ static void testANoteStartedAfterAPublishSoundsThePublishedEnvelope() {
|
||||
slow.play.adsr.attackFrames = 24000;
|
||||
LiveParams block2;
|
||||
slow.live = &block2;
|
||||
LiveValues snappy = foldLive(slow.play);
|
||||
LiveValues snappy = foldLive(slow.play, slow.keyTrack);
|
||||
snappy.adsr.attackFrames = 0;
|
||||
block2.publish(snappy);
|
||||
VoiceEngine fast(1, slow);
|
||||
@@ -368,7 +368,7 @@ static void assertLiveFieldMovesTheSoundingNote(const char* name, void (*rig)(Sa
|
||||
rig(still);
|
||||
rig(moved);
|
||||
LiveParams blockA, blockB;
|
||||
LiveValues target = foldLive(moved.play);
|
||||
LiveValues target = foldLive(moved.play, moved.keyTrack);
|
||||
mutate(target);
|
||||
|
||||
const Run baseline = renderWithLive(still, &blockA, 512, 24, -1, nullptr, noteOffBlock);
|
||||
@@ -616,7 +616,7 @@ static void testEveryLiveFilterControlMovesTheSoundingNote() {
|
||||
SampleData still = filteredSine();
|
||||
SampleData moved = filteredSine();
|
||||
LiveParams blockA, blockB;
|
||||
LiveValues target = foldLive(moved.play);
|
||||
LiveValues target = foldLive(moved.play, moved.keyTrack);
|
||||
c.mutate(target);
|
||||
|
||||
const Run baseline = renderWithLive(still, &blockA, 512, 24, -1, nullptr);
|
||||
@@ -688,7 +688,7 @@ static void testOneBlockServesTwoIndependentObservers() {
|
||||
LiveParams block;
|
||||
liveSnapshot.live = █
|
||||
drainSnapshot.live = █
|
||||
block.publish(foldLive(liveSnapshot.play));
|
||||
block.publish(foldLive(liveSnapshot.play, liveSnapshot.keyTrack));
|
||||
|
||||
VoiceEngine liveEngine(1, liveSnapshot);
|
||||
VoiceEngine drainEngine(1, drainSnapshot);
|
||||
@@ -696,7 +696,7 @@ static void testOneBlockServesTwoIndependentObservers() {
|
||||
drainEngine.noteOn(60, 100);
|
||||
|
||||
std::vector<AudioSample> a, b;
|
||||
LiveValues moved = foldLive(liveSnapshot.play);
|
||||
LiveValues moved = foldLive(liveSnapshot.play, liveSnapshot.keyTrack);
|
||||
moved.filterSettings.cutoffNorm = 0.2f;
|
||||
for (int blk = 0; blk < 24; ++blk) {
|
||||
if (blk == 8) block.publish(moved);
|
||||
@@ -746,7 +746,7 @@ static std::vector<AudioSample> renderPreserveCapable(SampleData& s, LiveParams&
|
||||
const LiveValues* changed, int changeAfter,
|
||||
int note) {
|
||||
s.live = █
|
||||
block.publish(foldLive(s.play));
|
||||
block.publish(foldLive(s.play, s.keyTrack));
|
||||
VoiceEngine engine(1, s, /*preserveVoiceCap=*/0, /*preserveWindowFrames=*/2048);
|
||||
engine.noteOn(note, 100);
|
||||
std::vector<AudioSample> out;
|
||||
@@ -765,7 +765,7 @@ static void testARateChangeSpareTheSoundingNoteAndReachesTheNextOne() {
|
||||
moved.play.pitchEngine = eng;
|
||||
|
||||
LiveParams blockA, blockB;
|
||||
LiveValues halfRate = foldLive(moved.play);
|
||||
LiveValues halfRate = foldLive(moved.play, moved.keyTrack);
|
||||
halfRate.playRate = 0.5;
|
||||
|
||||
// At the ROOT note, so Preserve's shifter runs at shift 1.0 and never splices — the
|
||||
@@ -795,7 +795,7 @@ static void testARateChangeSpareTheSoundingNoteAndReachesTheNextOne() {
|
||||
fresh.play.pitchEngine = eng;
|
||||
LiveParams block;
|
||||
fresh.live = █
|
||||
LiveValues published = foldLive(fresh.play);
|
||||
LiveValues published = foldLive(fresh.play, fresh.keyTrack);
|
||||
published.playRate = rate;
|
||||
block.publish(published);
|
||||
VoiceEngine engine(1, fresh, /*preserveVoiceCap=*/0, /*preserveWindowFrames=*/2048);
|
||||
@@ -827,7 +827,7 @@ static void testAPitchOffsetChangeMovesTheSoundingNoteInBothEngines() {
|
||||
moved.play.pitchEngine = eng;
|
||||
|
||||
LiveParams blockA, blockB;
|
||||
LiveValues target = foldLive(moved.play);
|
||||
LiveValues target = foldLive(moved.play, moved.keyTrack);
|
||||
target.pitchOffsetSemitones = -12.0;
|
||||
|
||||
const std::vector<AudioSample> baseline =
|
||||
@@ -859,7 +859,7 @@ static void testAPitchOffsetChangeMovesTheSoundingNoteInBothEngines() {
|
||||
static std::size_t soundingBlocksWithPublishedPitch(SampleData& s, double offsetSemis,
|
||||
std::size_t capFrames) {
|
||||
LiveParams block;
|
||||
LiveValues v = foldLive(s.play); // s.play keeps its own (zero) offset: the stale copy
|
||||
LiveValues v = foldLive(s.play, s.keyTrack); // s.play keeps its own (zero) offset: the stale copy
|
||||
v.pitchOffsetSemitones = offsetSemis;
|
||||
block.publish(v);
|
||||
s.live = █
|
||||
@@ -891,7 +891,7 @@ static void testAPublishedPitchOffsetLeavesTheStagedAttackWallClock() {
|
||||
s.play.trigAhd = AhdParams{kAttack, 0, 1.0, util::kCurveNeutral, util::kCurveNeutral};
|
||||
|
||||
LiveParams block;
|
||||
LiveValues v = foldLive(s.play);
|
||||
LiveValues v = foldLive(s.play, s.keyTrack);
|
||||
v.pitchOffsetSemitones = semis;
|
||||
block.publish(v);
|
||||
s.live = █
|
||||
@@ -960,12 +960,12 @@ static void testPitchRatioAndVelocityGainStayLatched() {
|
||||
|
||||
LiveParams block;
|
||||
s.live = █
|
||||
block.publish(foldLive(s.play));
|
||||
block.publish(foldLive(s.play, s.keyTrack));
|
||||
VoiceEngine engine(1, s);
|
||||
engine.noteOn(72, 64); // an octave up: ratio 2.0
|
||||
|
||||
std::vector<AudioSample> out;
|
||||
LiveValues hostile = foldLive(s.play);
|
||||
LiveValues hostile = foldLive(s.play, s.keyTrack);
|
||||
// Everything the block CAN carry, moved as far as it goes. None of it names velocity, the
|
||||
// note, the pitch ratio, or the PCM — that is the property under test.
|
||||
hostile.filterKeyTrack = 2.0;
|
||||
@@ -998,11 +998,11 @@ static void testPitchRatioAndVelocityGainStayLatched() {
|
||||
SampleData s2 = s;
|
||||
LiveParams block2;
|
||||
s2.live = &block2;
|
||||
block2.publish(foldLive(s2.play));
|
||||
block2.publish(foldLive(s2.play, s2.keyTrack));
|
||||
VoiceEngine engine2(1, s2);
|
||||
engine2.noteOn(72, 64);
|
||||
std::vector<AudioSample> out2;
|
||||
LiveValues quieter = foldLive(s2.play);
|
||||
LiveValues quieter = foldLive(s2.play, s2.keyTrack);
|
||||
quieter.adsr.sustainLevel = 0.25;
|
||||
for (int blk = 0; blk < 8; ++blk) {
|
||||
if (blk == 2) block2.publish(quieter);
|
||||
@@ -1024,7 +1024,7 @@ static void testVelocityGainSurvivesAHostilePublishThatReallyLands() {
|
||||
rig.play.pitchEnv.shape.decayFrames = 24000;
|
||||
rig.play.pitchEnv.peakSemitones = 3.0;
|
||||
|
||||
LiveValues hostile = foldLive(rig.play);
|
||||
LiveValues hostile = foldLive(rig.play, rig.keyTrack);
|
||||
hostile.filterKeyTrack = 2.0;
|
||||
hostile.filterSettings.cutoffNorm = 0.9f;
|
||||
hostile.filterModAmount = -1.0;
|
||||
|
||||
Reference in New Issue
Block a user