Advance the generator when not used
This commit is contained in:
parent
6bb4b7c83e
commit
97702e4308
4 changed files with 65 additions and 2 deletions
|
|
@ -723,6 +723,7 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
|||
}
|
||||
|
||||
ModMatrix& mm = resources.modMatrix;
|
||||
mm.beginCycle(numFrames);
|
||||
|
||||
activeVoices = 0;
|
||||
{ // Main render block
|
||||
|
|
@ -731,8 +732,6 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
|||
tempMixSpan->fill(0.0f);
|
||||
resources.filePool.cleanupPromises();
|
||||
|
||||
mm.beginCycle(numFrames);
|
||||
|
||||
// Ramp out whatever is in the buffer at this point; should only be killed voice data
|
||||
linearRamp<float>(*rampSpan, 1.0f, -1.0f / static_cast<float>(numFrames));
|
||||
for (size_t i = 0, n = effectBuses.size(); i < n; ++i) {
|
||||
|
|
@ -754,6 +753,8 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
|||
callbackBreakdown.filters += voice->getLastFilterDuration();
|
||||
callbackBreakdown.panning += voice->getLastPanningDuration();
|
||||
|
||||
mm.endVoice();
|
||||
|
||||
if (voice->toBeCleanedUp())
|
||||
voice->reset();
|
||||
}
|
||||
|
|
@ -781,6 +782,9 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
|||
// Apply the master volume
|
||||
buffer.applyGain(db2mag(volume));
|
||||
|
||||
// Perform any remaining modulators
|
||||
mm.endCycle();
|
||||
|
||||
{ // Clear events and advance midi time
|
||||
ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration };
|
||||
resources.midiState.advanceTime(buffer.getNumFrames());
|
||||
|
|
|
|||
|
|
@ -47,6 +47,20 @@ public:
|
|||
* @param buffer output buffer
|
||||
*/
|
||||
virtual void generate(const ModKey& sourceKey, NumericId<Voice> voiceNum, absl::Span<float> buffer) = 0;
|
||||
|
||||
/**
|
||||
* @brief Advance the generator by a number of frames
|
||||
* This is called instead of `generate` in case the output is discarded.
|
||||
* It can be overriden with a faster implementation if wanted.
|
||||
*
|
||||
* @param sourceKey source key
|
||||
* @param voiceNum voice number if the generator is per-voice, otherwise undefined
|
||||
* @param buffer writable spare buffer, contents will be discarded
|
||||
*/
|
||||
virtual void generateDiscarded(const ModKey& sourceKey, NumericId<Voice> voiceNum, absl::Span<float> buffer)
|
||||
{
|
||||
generate(sourceKey, voiceNum, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sfz
|
||||
|
|
|
|||
|
|
@ -224,6 +224,22 @@ void ModMatrix::beginCycle(unsigned numFrames)
|
|||
target.bufferReady = false;
|
||||
}
|
||||
|
||||
void ModMatrix::endCycle()
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
const uint32_t numFrames = impl.numFrames_;
|
||||
|
||||
for (Impl::Source &source : impl.sources_) {
|
||||
if (!source.bufferReady) {
|
||||
int flags = source.key.flags();
|
||||
if (flags & kModIsPerCycle) {
|
||||
absl::Span<float> buffer(source.buffer.data(), numFrames);
|
||||
source.gen->generateDiscarded(source.key, {}, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModMatrix::beginVoice(NumericId<Voice> voiceId)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
|
|
@ -242,6 +258,23 @@ void ModMatrix::beginVoice(NumericId<Voice> voiceId)
|
|||
}
|
||||
}
|
||||
|
||||
void ModMatrix::endVoice()
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
const uint32_t numFrames = impl.numFrames_;
|
||||
const NumericId<Voice> voiceId = impl.voiceId_;
|
||||
|
||||
for (Impl::Source &source : impl.sources_) {
|
||||
if (!source.bufferReady) {
|
||||
int flags = source.key.flags();
|
||||
if (flags & kModIsPerVoice) {
|
||||
absl::Span<float> buffer(source.buffer.data(), numFrames);
|
||||
source.gen->generateDiscarded(source.key, voiceId, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float* ModMatrix::getModulation(TargetId targetId)
|
||||
{
|
||||
if (!validTarget(targetId))
|
||||
|
|
|
|||
|
|
@ -113,6 +113,12 @@ public:
|
|||
*/
|
||||
void beginCycle(unsigned numFrames);
|
||||
|
||||
/**
|
||||
* @brief End modulation processing for the entire cycle.
|
||||
* This performs a dummy run of any unused modulations.
|
||||
*/
|
||||
void endCycle();
|
||||
|
||||
/**
|
||||
* @brief Start modulation processing for a given voice.
|
||||
* This clears all the buffers which are per-voice.
|
||||
|
|
@ -121,6 +127,12 @@ public:
|
|||
*/
|
||||
void beginVoice(NumericId<Voice> voiceId);
|
||||
|
||||
/**
|
||||
* @brief End modulation processing for a given voice.
|
||||
* This performs a dummy run of any unused modulations which are per-cycle.
|
||||
*/
|
||||
void endVoice();
|
||||
|
||||
/**
|
||||
* @brief Get the modulation buffer for the given target.
|
||||
* If the target does not exist, the result is null.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue