From f3bb501dd02235501fba9bc6c9934405387366fb Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 12 Sep 2024 21:29:07 -0400 Subject: [PATCH] Int and Power on Runnign Voices and Groups for procs (#1320) * Int and Power on Runnign Voices and Groups for procs 1. Int values snap every block from zone (voice) and group (group) meaning running voices experience and reset int params 2. The power/bypass button works on voices and groups for processors. this does change the voice allocation pattern slightly in that we init a processor on voice on whether active or not since we don't want to do mid-init power on for a bypassed processor which becomes unbypassed, but we don't run it, just init it 3. Add the gnarly per-block logic to deal with processor type changes in running voices, not just running groups. Closes #957 --- src/dsp/processor/processor.h | 2 ++ src/dsp/processor/routing.h | 3 +++ src/engine/group.cpp | 9 +++++++ src/voice/voice.cpp | 47 ++++++++++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/dsp/processor/processor.h b/src/dsp/processor/processor.h index 78bd94d1..97c3fa6e 100644 --- a/src/dsp/processor/processor.h +++ b/src/dsp/processor/processor.h @@ -250,6 +250,8 @@ struct Processor : MoveableOnly, SampleRateSupport const ProcessorStorage &ps, float *fp, int *ip, bool needsMetadata); public: + bool bypassAnyway{false}; + size_t preReserveSize[16]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; size_t preReserveSingleInstanceSize[16]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; diff --git a/src/dsp/processor/routing.h b/src/dsp/processor/routing.h index 4670c628..00fb98dc 100644 --- a/src/dsp/processor/routing.h +++ b/src/dsp/processor/routing.h @@ -41,6 +41,9 @@ inline void runSingleProcessor(int i, float fpitch, Processor *processors[engine Mix &outLev, Endpoints *endpoints, bool &chainIsMono, float input[2][N], float output[2][N]) { + if (processors[i]->bypassAnyway) + return; + namespace mech = sst::basic_blocks::mechanics; float tempbuf alignas(16)[2][N]; diff --git a/src/engine/group.cpp b/src/engine/group.cpp index 69a89ad9..a3fe54f8 100644 --- a/src/engine/group.cpp +++ b/src/engine/group.cpp @@ -172,6 +172,15 @@ template void Group::processWithOS(scxt::engine::Engine &e) if (processors[0] || processors[1] || processors[2] || processors[3]) { + for (int i = 0; i < processorsPerZoneAndGroup; ++i) + { + if (processors[i]) + { + memcpy(&processorIntParams[i][0], processorStorage[i].intParams.data(), + sizeof(processorIntParams[i])); + processors[i]->bypassAnyway = !processorStorage[i].isActive; + } + } #define CALL_ROUTE(FNN) \ if constexpr (OS) \ diff --git a/src/voice/voice.cpp b/src/voice/voice.cpp index 2fda663e..7274a351 100644 --- a/src/voice/voice.cpp +++ b/src/voice/voice.cpp @@ -381,7 +381,51 @@ template bool Voice::processWithOS() } \ } - if (processors[0] || processors[1] || processors[2] || processors[3]) + /* + * This is all voice time type reset logic basically. + */ + bool hasProcs{false}; + for (int i = 0; i < processorsPerZoneAndGroup; ++i) + { + auto proct = processors[i] ? processors[i]->getType() : dsp::processor::proct_none; + if (zone->processorStorage[i].type != proct) + { + if (processors[i]) + dsp::processor::unspawnProcessor(processors[i]); + processors[i] = nullptr; + proct = zone->processorStorage[i].type; + } + + if (!processors[i] && zone->processorStorage[i].isActive && + zone->processorStorage[i].type != dsp::processor::proct_none) + { + processorType[i] = proct; + // this is copied below in the init. + processors[i] = dsp::processor::spawnProcessorInPlace( + processorType[i], zone->getEngine()->getMemoryPool().get(), + processorPlacementStorage[i], dsp::processor::processorMemoryBufferSize, + zone->processorStorage[i], endpoints->processorTarget[i].fp, processorIntParams[i], + forceOversample, false); + + processors[i]->setSampleRate(sampleRate * (forceOversample ? 2 : 1)); + processors[i]->setTempoPointer(&(zone->getEngine()->transport.tempo)); + + processors[i]->init(); + processors[i]->setKeytrack(zone->processorStorage[i].isKeytracked); + + processorConsumesMono[i] = monoGenerator && processors[i]->canProcessMono(); + } + if (processors[i]) + { + memcpy(&processorIntParams[i][0], zone->processorStorage[i].intParams.data(), + sizeof(processorIntParams[i])); + processors[i]->bypassAnyway = !zone->processorStorage[i].isActive; + } + + hasProcs = hasProcs || processors[i]; + } + + if (hasProcs) { switch (zone->outputInfo.procRouting) { @@ -689,6 +733,7 @@ void Voice::initializeProcessors() if ((processorIsActive[i] && processorType[i] != dsp::processor::proct_none) || (processorType[i] == dsp::processor::proct_none && !processorIsActive[i])) { + // this init code is partly copied above in the voice state toggle processors[i] = dsp::processor::spawnProcessorInPlace( processorType[i], zone->getEngine()->getMemoryPool().get(), processorPlacementStorage[i], dsp::processor::processorMemoryBufferSize,