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