diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 8647de86..b19c6cb5 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -144,6 +144,7 @@ void sfz::Voice::startVoice(Region* region, int delay, const TriggerEvent& event egEnvelope.reset(region->amplitudeEG, *region, resources.midiState, delay, triggerEvent.value, sampleRate); resources.modMatrix.initVoice(id, region->getId(), delay); + saveModulationTargets(region); } int sfz::Voice::getCurrentSampleQuality() const noexcept @@ -370,22 +371,20 @@ void sfz::Voice::amplitudeEnvelope(absl::Span modulationSpan) noexcept const auto numSamples = modulationSpan.size(); ModMatrix& mm = resources.modMatrix; - const ModKey volumeKey = ModKey::createNXYZ(ModId::Volume, region->getId()); - const ModKey amplitudeKey = ModKey::createNXYZ(ModId::Amplitude, region->getId()); // AmpEG envelope egEnvelope.getBlock(modulationSpan); // Amplitude envelope applyGain1(baseGain, modulationSpan); - if (float* mod = mm.getModulationByKey(amplitudeKey)) { + if (float* mod = mm.getModulation(amplitudeTarget)) { for (size_t i = 0; i < numSamples; ++i) modulationSpan[i] *= normalizePercents(mod[i]); } // Volume envelope applyGain1(db2mag(baseVolumedB), modulationSpan); - if (float* mod = mm.getModulationByKey(volumeKey)) { + if (float* mod = mm.getModulation(volumeTarget)) { for (size_t i = 0; i < numSamples; ++i) modulationSpan[i] *= db2mag(mod[i]); } @@ -437,14 +436,13 @@ void sfz::Voice::panStageMono(AudioSpan buffer) noexcept return; ModMatrix& mm = resources.modMatrix; - const ModKey panKey = ModKey::createNXYZ(ModId::Pan, region->getId()); // Prepare for stereo output copy(leftBuffer, rightBuffer); // Apply panning fill(*modulationSpan, region->pan); - if (float* mod = mm.getModulationByKey(panKey)) { + if (float* mod = mm.getModulation(panTarget)) { for (size_t i = 0; i < numSamples; ++i) (*modulationSpan)[i] += normalizePercents(mod[i]); } @@ -463,13 +461,10 @@ void sfz::Voice::panStageStereo(AudioSpan buffer) noexcept return; ModMatrix& mm = resources.modMatrix; - const ModKey panKey = ModKey::createNXYZ(ModId::Pan, region->getId()); - const ModKey widthKey = ModKey::createNXYZ(ModId::Width, region->getId()); - const ModKey positionKey = ModKey::createNXYZ(ModId::Position, region->getId()); // Apply panning fill(*modulationSpan, region->pan); - if (float* mod = mm.getModulationByKey(panKey)) { + if (float* mod = mm.getModulation(panTarget)) { for (size_t i = 0; i < numSamples; ++i) (*modulationSpan)[i] += normalizePercents(mod[i]); } @@ -477,14 +472,14 @@ void sfz::Voice::panStageStereo(AudioSpan buffer) noexcept // Apply the width/position process fill(*modulationSpan, region->width); - if (float* mod = mm.getModulationByKey(widthKey)) { + if (float* mod = mm.getModulation(widthTarget)) { for (size_t i = 0; i < numSamples; ++i) (*modulationSpan)[i] += normalizePercents(mod[i]); } width(*modulationSpan, leftBuffer, rightBuffer); fill(*modulationSpan, region->position); - if (float* mod = mm.getModulationByKey(positionKey)) { + if (float* mod = mm.getModulation(positionTarget)) { for (size_t i = 0; i < numSamples; ++i) (*modulationSpan)[i] += normalizePercents(mod[i]); } @@ -889,9 +884,8 @@ void sfz::Voice::pitchEnvelope(absl::Span pitchSpan) noexcept applyGain(*bends, pitchSpan); ModMatrix& mm = resources.modMatrix; - const ModKey pitchKey = ModKey::createNXYZ(ModId::Pitch, region->getId()); - if (float* mod = mm.getModulationByKey(pitchKey)) { + if (float* mod = mm.getModulation(pitchTarget)) { for (size_t i = 0; i < numFrames; ++i) pitchSpan[i] *= centsFactor(mod[i]); } @@ -902,3 +896,14 @@ void sfz::Voice::resetSmoothers() noexcept bendSmoother.reset(1.0f); gainSmoother.reset(0.0f); } + +void sfz::Voice::saveModulationTargets(const Region* region) noexcept +{ + ModMatrix& mm = resources.modMatrix; + amplitudeTarget = mm.findTarget(ModKey::createNXYZ(ModId::Amplitude, region->getId())); + volumeTarget = mm.findTarget(ModKey::createNXYZ(ModId::Volume, region->getId())); + panTarget = mm.findTarget(ModKey::createNXYZ(ModId::Pan, region->getId())); + positionTarget = mm.findTarget(ModKey::createNXYZ(ModId::Position, region->getId())); + widthTarget = mm.findTarget(ModKey::createNXYZ(ModId::Width, region->getId())); + pitchTarget = mm.findTarget(ModKey::createNXYZ(ModId::Pitch, region->getId())); +} diff --git a/src/sfizz/Voice.h b/src/sfizz/Voice.h index c8ebb0c8..10e0df2a 100644 --- a/src/sfizz/Voice.h +++ b/src/sfizz/Voice.h @@ -406,6 +406,12 @@ private: */ void switchState(State s); + /** + * @brief Save the modulation targets to avoid recomputing them in every callback. + * Must be called during startVoice() ideally. + */ + void saveModulationTargets(const Region* region) noexcept; + const NumericId id; StateListener* stateListener = nullptr; @@ -466,6 +472,13 @@ private: Smoother xfadeSmoother; void resetSmoothers() noexcept; + ModMatrix::TargetId amplitudeTarget; + ModMatrix::TargetId volumeTarget; + ModMatrix::TargetId panTarget; + ModMatrix::TargetId positionTarget; + ModMatrix::TargetId widthTarget; + ModMatrix::TargetId pitchTarget; + PowerFollower powerFollower; LEAK_DETECTOR(Voice);