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;
|
ModMatrix& mm = resources.modMatrix;
|
||||||
|
mm.beginCycle(numFrames);
|
||||||
|
|
||||||
activeVoices = 0;
|
activeVoices = 0;
|
||||||
{ // Main render block
|
{ // Main render block
|
||||||
|
|
@ -731,8 +732,6 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
||||||
tempMixSpan->fill(0.0f);
|
tempMixSpan->fill(0.0f);
|
||||||
resources.filePool.cleanupPromises();
|
resources.filePool.cleanupPromises();
|
||||||
|
|
||||||
mm.beginCycle(numFrames);
|
|
||||||
|
|
||||||
// Ramp out whatever is in the buffer at this point; should only be killed voice data
|
// 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));
|
linearRamp<float>(*rampSpan, 1.0f, -1.0f / static_cast<float>(numFrames));
|
||||||
for (size_t i = 0, n = effectBuses.size(); i < n; ++i) {
|
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.filters += voice->getLastFilterDuration();
|
||||||
callbackBreakdown.panning += voice->getLastPanningDuration();
|
callbackBreakdown.panning += voice->getLastPanningDuration();
|
||||||
|
|
||||||
|
mm.endVoice();
|
||||||
|
|
||||||
if (voice->toBeCleanedUp())
|
if (voice->toBeCleanedUp())
|
||||||
voice->reset();
|
voice->reset();
|
||||||
}
|
}
|
||||||
|
|
@ -781,6 +782,9 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
||||||
// Apply the master volume
|
// Apply the master volume
|
||||||
buffer.applyGain(db2mag(volume));
|
buffer.applyGain(db2mag(volume));
|
||||||
|
|
||||||
|
// Perform any remaining modulators
|
||||||
|
mm.endCycle();
|
||||||
|
|
||||||
{ // Clear events and advance midi time
|
{ // Clear events and advance midi time
|
||||||
ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration };
|
ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration };
|
||||||
resources.midiState.advanceTime(buffer.getNumFrames());
|
resources.midiState.advanceTime(buffer.getNumFrames());
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,20 @@ public:
|
||||||
* @param buffer output buffer
|
* @param buffer output buffer
|
||||||
*/
|
*/
|
||||||
virtual void generate(const ModKey& sourceKey, NumericId<Voice> voiceNum, absl::Span<float> buffer) = 0;
|
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
|
} // namespace sfz
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,22 @@ void ModMatrix::beginCycle(unsigned numFrames)
|
||||||
target.bufferReady = false;
|
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)
|
void ModMatrix::beginVoice(NumericId<Voice> voiceId)
|
||||||
{
|
{
|
||||||
Impl& impl = *impl_;
|
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)
|
float* ModMatrix::getModulation(TargetId targetId)
|
||||||
{
|
{
|
||||||
if (!validTarget(targetId))
|
if (!validTarget(targetId))
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void beginCycle(unsigned numFrames);
|
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.
|
* @brief Start modulation processing for a given voice.
|
||||||
* This clears all the buffers which are per-voice.
|
* This clears all the buffers which are per-voice.
|
||||||
|
|
@ -121,6 +127,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void beginVoice(NumericId<Voice> voiceId);
|
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.
|
* @brief Get the modulation buffer for the given target.
|
||||||
* If the target does not exist, the result is null.
|
* If the target does not exist, the result is null.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue