Precompute targets for the modulation on voice start
This commit is contained in:
parent
60eecba226
commit
11d5abe435
2 changed files with 32 additions and 14 deletions
|
|
@ -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);
|
egEnvelope.reset(region->amplitudeEG, *region, resources.midiState, delay, triggerEvent.value, sampleRate);
|
||||||
|
|
||||||
resources.modMatrix.initVoice(id, region->getId(), delay);
|
resources.modMatrix.initVoice(id, region->getId(), delay);
|
||||||
|
saveModulationTargets(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sfz::Voice::getCurrentSampleQuality() const noexcept
|
int sfz::Voice::getCurrentSampleQuality() const noexcept
|
||||||
|
|
@ -370,22 +371,20 @@ void sfz::Voice::amplitudeEnvelope(absl::Span<float> modulationSpan) noexcept
|
||||||
const auto numSamples = modulationSpan.size();
|
const auto numSamples = modulationSpan.size();
|
||||||
|
|
||||||
ModMatrix& mm = resources.modMatrix;
|
ModMatrix& mm = resources.modMatrix;
|
||||||
const ModKey volumeKey = ModKey::createNXYZ(ModId::Volume, region->getId());
|
|
||||||
const ModKey amplitudeKey = ModKey::createNXYZ(ModId::Amplitude, region->getId());
|
|
||||||
|
|
||||||
// AmpEG envelope
|
// AmpEG envelope
|
||||||
egEnvelope.getBlock(modulationSpan);
|
egEnvelope.getBlock(modulationSpan);
|
||||||
|
|
||||||
// Amplitude envelope
|
// Amplitude envelope
|
||||||
applyGain1<float>(baseGain, modulationSpan);
|
applyGain1<float>(baseGain, modulationSpan);
|
||||||
if (float* mod = mm.getModulationByKey(amplitudeKey)) {
|
if (float* mod = mm.getModulation(amplitudeTarget)) {
|
||||||
for (size_t i = 0; i < numSamples; ++i)
|
for (size_t i = 0; i < numSamples; ++i)
|
||||||
modulationSpan[i] *= normalizePercents(mod[i]);
|
modulationSpan[i] *= normalizePercents(mod[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Volume envelope
|
// Volume envelope
|
||||||
applyGain1<float>(db2mag(baseVolumedB), modulationSpan);
|
applyGain1<float>(db2mag(baseVolumedB), modulationSpan);
|
||||||
if (float* mod = mm.getModulationByKey(volumeKey)) {
|
if (float* mod = mm.getModulation(volumeTarget)) {
|
||||||
for (size_t i = 0; i < numSamples; ++i)
|
for (size_t i = 0; i < numSamples; ++i)
|
||||||
modulationSpan[i] *= db2mag(mod[i]);
|
modulationSpan[i] *= db2mag(mod[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -437,14 +436,13 @@ void sfz::Voice::panStageMono(AudioSpan<float> buffer) noexcept
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ModMatrix& mm = resources.modMatrix;
|
ModMatrix& mm = resources.modMatrix;
|
||||||
const ModKey panKey = ModKey::createNXYZ(ModId::Pan, region->getId());
|
|
||||||
|
|
||||||
// Prepare for stereo output
|
// Prepare for stereo output
|
||||||
copy<float>(leftBuffer, rightBuffer);
|
copy<float>(leftBuffer, rightBuffer);
|
||||||
|
|
||||||
// Apply panning
|
// Apply panning
|
||||||
fill(*modulationSpan, region->pan);
|
fill(*modulationSpan, region->pan);
|
||||||
if (float* mod = mm.getModulationByKey(panKey)) {
|
if (float* mod = mm.getModulation(panTarget)) {
|
||||||
for (size_t i = 0; i < numSamples; ++i)
|
for (size_t i = 0; i < numSamples; ++i)
|
||||||
(*modulationSpan)[i] += normalizePercents(mod[i]);
|
(*modulationSpan)[i] += normalizePercents(mod[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -463,13 +461,10 @@ void sfz::Voice::panStageStereo(AudioSpan<float> buffer) noexcept
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ModMatrix& mm = resources.modMatrix;
|
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
|
// Apply panning
|
||||||
fill(*modulationSpan, region->pan);
|
fill(*modulationSpan, region->pan);
|
||||||
if (float* mod = mm.getModulationByKey(panKey)) {
|
if (float* mod = mm.getModulation(panTarget)) {
|
||||||
for (size_t i = 0; i < numSamples; ++i)
|
for (size_t i = 0; i < numSamples; ++i)
|
||||||
(*modulationSpan)[i] += normalizePercents(mod[i]);
|
(*modulationSpan)[i] += normalizePercents(mod[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -477,14 +472,14 @@ void sfz::Voice::panStageStereo(AudioSpan<float> buffer) noexcept
|
||||||
|
|
||||||
// Apply the width/position process
|
// Apply the width/position process
|
||||||
fill(*modulationSpan, region->width);
|
fill(*modulationSpan, region->width);
|
||||||
if (float* mod = mm.getModulationByKey(widthKey)) {
|
if (float* mod = mm.getModulation(widthTarget)) {
|
||||||
for (size_t i = 0; i < numSamples; ++i)
|
for (size_t i = 0; i < numSamples; ++i)
|
||||||
(*modulationSpan)[i] += normalizePercents(mod[i]);
|
(*modulationSpan)[i] += normalizePercents(mod[i]);
|
||||||
}
|
}
|
||||||
width(*modulationSpan, leftBuffer, rightBuffer);
|
width(*modulationSpan, leftBuffer, rightBuffer);
|
||||||
|
|
||||||
fill(*modulationSpan, region->position);
|
fill(*modulationSpan, region->position);
|
||||||
if (float* mod = mm.getModulationByKey(positionKey)) {
|
if (float* mod = mm.getModulation(positionTarget)) {
|
||||||
for (size_t i = 0; i < numSamples; ++i)
|
for (size_t i = 0; i < numSamples; ++i)
|
||||||
(*modulationSpan)[i] += normalizePercents(mod[i]);
|
(*modulationSpan)[i] += normalizePercents(mod[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -889,9 +884,8 @@ void sfz::Voice::pitchEnvelope(absl::Span<float> pitchSpan) noexcept
|
||||||
applyGain<float>(*bends, pitchSpan);
|
applyGain<float>(*bends, pitchSpan);
|
||||||
|
|
||||||
ModMatrix& mm = resources.modMatrix;
|
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)
|
for (size_t i = 0; i < numFrames; ++i)
|
||||||
pitchSpan[i] *= centsFactor(mod[i]);
|
pitchSpan[i] *= centsFactor(mod[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -902,3 +896,14 @@ void sfz::Voice::resetSmoothers() noexcept
|
||||||
bendSmoother.reset(1.0f);
|
bendSmoother.reset(1.0f);
|
||||||
gainSmoother.reset(0.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()));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -406,6 +406,12 @@ private:
|
||||||
*/
|
*/
|
||||||
void switchState(State s);
|
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<Voice> id;
|
const NumericId<Voice> id;
|
||||||
StateListener* stateListener = nullptr;
|
StateListener* stateListener = nullptr;
|
||||||
|
|
||||||
|
|
@ -466,6 +472,13 @@ private:
|
||||||
Smoother xfadeSmoother;
|
Smoother xfadeSmoother;
|
||||||
void resetSmoothers() noexcept;
|
void resetSmoothers() noexcept;
|
||||||
|
|
||||||
|
ModMatrix::TargetId amplitudeTarget;
|
||||||
|
ModMatrix::TargetId volumeTarget;
|
||||||
|
ModMatrix::TargetId panTarget;
|
||||||
|
ModMatrix::TargetId positionTarget;
|
||||||
|
ModMatrix::TargetId widthTarget;
|
||||||
|
ModMatrix::TargetId pitchTarget;
|
||||||
|
|
||||||
PowerFollower powerFollower;
|
PowerFollower powerFollower;
|
||||||
|
|
||||||
LEAK_DETECTOR(Voice);
|
LEAK_DETECTOR(Voice);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue