Allow modulations to trigger at a frame-accurate instant (LFO)
This commit is contained in:
parent
68712140d6
commit
a71c1eb0f3
12 changed files with 19 additions and 16 deletions
|
|
@ -49,7 +49,7 @@ void LFO::configure(const LFODescription* desc)
|
|||
impl_->desc_ = desc ? desc : &LFODescription::getDefault();
|
||||
}
|
||||
|
||||
void LFO::start()
|
||||
void LFO::start(unsigned triggerDelay)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
const LFODescription& desc = *impl.desc_;
|
||||
|
|
@ -59,7 +59,8 @@ void LFO::start()
|
|||
impl.sampleHoldMem_.fill(0.0f);
|
||||
|
||||
const float delay = desc.delay;
|
||||
impl.delayFramesLeft_ = (delay > 0) ? static_cast<size_t>(std::ceil(sampleRate * delay)) : 0u;
|
||||
size_t delayFrames = (delay > 0) ? static_cast<size_t>(std::ceil(sampleRate * delay)) : 0u;
|
||||
impl.delayFramesLeft_ = triggerDelay + delayFrames;
|
||||
|
||||
impl.fadePosition_ = (desc.fade > 0) ? 0.0f : 1.0f;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public:
|
|||
Start processing a LFO as a region is triggered.
|
||||
Prepares the delay, phases, fade-in, etc..
|
||||
*/
|
||||
void start();
|
||||
void start(unsigned triggerDelay);
|
||||
|
||||
/**
|
||||
Process a cycle of the oscillator.
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value,
|
|||
bendSmoother.reset(centsFactor(region->getBendInCents(resources.midiState.getPitchBend())));
|
||||
egEnvelope.reset(region->amplitudeEG, *region, resources.midiState, delay, value, sampleRate);
|
||||
|
||||
resources.modMatrix.initVoice(id, region->getId());
|
||||
resources.modMatrix.initVoice(id, region->getId(), delay);
|
||||
}
|
||||
|
||||
int sfz::Voice::getCurrentSampleQuality() const noexcept
|
||||
|
|
|
|||
|
|
@ -36,8 +36,9 @@ public:
|
|||
*
|
||||
* @param sourceKey identifier of the source to initialize
|
||||
* @param voiceId the particular voice to initialize, if per-voice
|
||||
* @param delay the frame time when it happens
|
||||
*/
|
||||
virtual void init(const ModKey& sourceKey, NumericId<Voice> voiceId) = 0;
|
||||
virtual void init(const ModKey& sourceKey, NumericId<Voice> voiceId, unsigned delay) = 0;
|
||||
|
||||
/**
|
||||
* @brief Generate a cycle of the modulator
|
||||
|
|
|
|||
|
|
@ -196,18 +196,18 @@ void ModMatrix::init()
|
|||
for (Impl::Source &source : impl.sources_) {
|
||||
const int flags = source.key.flags();
|
||||
if (flags & kModIsPerCycle)
|
||||
source.gen->init(source.key, {});
|
||||
source.gen->init(source.key, {}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ModMatrix::initVoice(NumericId<Voice> voiceId, NumericId<Region> regionId)
|
||||
void ModMatrix::initVoice(NumericId<Voice> voiceId, NumericId<Region> regionId, unsigned delay)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
|
||||
for (Impl::Source &source : impl.sources_) {
|
||||
const int flags = source.key.flags();
|
||||
if ((flags & kModIsPerVoice) && source.key.region() == regionId)
|
||||
source.gen->init(source.key, voiceId);
|
||||
source.gen->init(source.key, voiceId, delay);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ public:
|
|||
* @brief Reinitialize modulation source for a given voice.
|
||||
* This must be called first after a voice enters active state.
|
||||
*/
|
||||
void initVoice(NumericId<Voice> voiceId, NumericId<Region> regionId);
|
||||
void initVoice(NumericId<Voice> voiceId, NumericId<Region> regionId, unsigned delay);
|
||||
|
||||
/**
|
||||
* @brief Start modulation processing for the entire cycle.
|
||||
|
|
|
|||
|
|
@ -49,9 +49,10 @@ void ControllerSource::setSamplesPerBlock(unsigned count)
|
|||
(void)count;
|
||||
}
|
||||
|
||||
void ControllerSource::init(const ModKey& sourceKey, NumericId<Voice> voiceId)
|
||||
void ControllerSource::init(const ModKey& sourceKey, NumericId<Voice> voiceId, unsigned delay)
|
||||
{
|
||||
(void)voiceId;
|
||||
(void)delay;
|
||||
|
||||
const ModKey::Parameters p = sourceKey.parameters();
|
||||
if (p.smooth > 0) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public:
|
|||
~ControllerSource();
|
||||
void setSampleRate(double sampleRate) override;
|
||||
void setSamplesPerBlock(unsigned count) override;
|
||||
void init(const ModKey& sourceKey, NumericId<Voice> voiceId) override;
|
||||
void init(const ModKey& sourceKey, NumericId<Voice> voiceId, unsigned delay) override;
|
||||
void generate(const ModKey& sourceKey, NumericId<Voice> voiceId, absl::Span<float> buffer) override;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ LFOSource::LFOSource(Synth &synth)
|
|||
{
|
||||
}
|
||||
|
||||
void LFOSource::init(const ModKey& sourceKey, NumericId<Voice> voiceId)
|
||||
void LFOSource::init(const ModKey& sourceKey, NumericId<Voice> voiceId, unsigned delay)
|
||||
{
|
||||
Synth& synth = *synth_;
|
||||
unsigned lfoIndex = sourceKey.parameters().N;
|
||||
|
|
@ -38,7 +38,7 @@ void LFOSource::init(const ModKey& sourceKey, NumericId<Voice> voiceId)
|
|||
|
||||
LFO* lfo = voice->getLFO(lfoIndex);
|
||||
lfo->configure(®ion->lfos[lfoIndex]);
|
||||
lfo->start();
|
||||
lfo->start(delay);
|
||||
}
|
||||
|
||||
void LFOSource::generate(const ModKey& sourceKey, NumericId<Voice> voiceId, absl::Span<float> buffer)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class Synth;
|
|||
class LFOSource : public ModGenerator {
|
||||
public:
|
||||
explicit LFOSource(Synth &synth);
|
||||
void init(const ModKey& sourceKey, NumericId<Voice> voiceId) override;
|
||||
void init(const ModKey& sourceKey, NumericId<Voice> voiceId, unsigned delay) override;
|
||||
void generate(const ModKey& sourceKey, NumericId<Voice> voiceId, absl::Span<float> buffer) override;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ static bool computeLFO(DataPoints& dp, const fs::path& sfzPath, double sampleRat
|
|||
std::vector<float> outputMemory(numLfos * numFrames);
|
||||
|
||||
for (size_t l = 0; l < numLfos; ++l) {
|
||||
lfos[l].start();
|
||||
lfos[l].start(0);
|
||||
}
|
||||
|
||||
std::vector<absl::Span<float>> lfoOutputs(numLfos);
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ int main(int argc, char* argv[])
|
|||
std::vector<float> outputMemory(numLfos * numFrames);
|
||||
|
||||
for (size_t l = 0; l < numLfos; ++l) {
|
||||
lfos[l].start();
|
||||
lfos[l].start(0);
|
||||
}
|
||||
|
||||
std::vector<absl::Span<float>> lfoOutputs(numLfos);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue