Add lfoN_fade_oncc, lfoN_delay_oncc, lfoN_phase_oncc
The phase modifier is actually an "audio rate" modifier with curve, step and smoothcc options. The v2 spec only had oncc, which would limit it to a set value with the LFO starts, but having it at audio rate makes sense if you want to tweak the phase while the LFO is running.
This commit is contained in:
parent
9e5d27af3c
commit
a4dbf89766
11 changed files with 87 additions and 47 deletions
|
|
@ -119,8 +119,11 @@ FloatSpec lfoFreqMod { 0.0f, {-100.0f, 100.0f}, kPermissiveBounds };
|
||||||
FloatSpec lfoBeats { 0.0f, {0.0f, 1000.0f}, kPermissiveBounds };
|
FloatSpec lfoBeats { 0.0f, {0.0f, 1000.0f}, kPermissiveBounds };
|
||||||
FloatSpec lfoBeatsMod { 0.0f, {-1000.0f, 1000.0f}, kPermissiveBounds };
|
FloatSpec lfoBeatsMod { 0.0f, {-1000.0f, 1000.0f}, kPermissiveBounds };
|
||||||
FloatSpec lfoPhase { 0.0f, {0.0f, 1.0f}, kWrapPhase|kPermissiveBounds };
|
FloatSpec lfoPhase { 0.0f, {0.0f, 1.0f}, kWrapPhase|kPermissiveBounds };
|
||||||
|
FloatSpec lfoPhaseMod { 0.0f, {0.0f, 1.0f}, kPermissiveBounds };
|
||||||
FloatSpec lfoDelay { 0.0f, {0.0f, 30.0f}, kPermissiveBounds };
|
FloatSpec lfoDelay { 0.0f, {0.0f, 30.0f}, kPermissiveBounds };
|
||||||
|
FloatSpec lfoDelayMod { 0.0f, {0.0f, 30.0f}, kPermissiveBounds };
|
||||||
FloatSpec lfoFade { 0.0f, {0.0f, 30.0f}, kPermissiveBounds };
|
FloatSpec lfoFade { 0.0f, {0.0f, 30.0f}, kPermissiveBounds };
|
||||||
|
FloatSpec lfoFadeMod { 0.0f, {0.0f, 30.0f}, kPermissiveBounds };
|
||||||
UInt32Spec lfoCount { 0, {0, 1000}, kEnforceLowerBound|kPermissiveUpperBound };
|
UInt32Spec lfoCount { 0, {0, 1000}, kEnforceLowerBound|kPermissiveUpperBound };
|
||||||
UInt32Spec lfoSteps { 0, {0, static_cast<unsigned>(config::maxLFOSteps)}, kEnforceBounds };
|
UInt32Spec lfoSteps { 0, {0, static_cast<unsigned>(config::maxLFOSteps)}, kEnforceBounds };
|
||||||
FloatSpec lfoStepX { 0.0f, {-100.0f, 100.0f}, kNormalizePercent|kPermissiveBounds };
|
FloatSpec lfoStepX { 0.0f, {-100.0f, 100.0f}, kNormalizePercent|kPermissiveBounds };
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,12 @@ struct OpcodeSpec
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
typename bool normalizeInput(bool input) const
|
||||||
|
{
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
operator T() const { return normalizeInput(defaultInputValue); }
|
operator T() const { return normalizeInput(defaultInputValue); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -219,8 +225,11 @@ namespace Default
|
||||||
extern const OpcodeSpec<float> lfoBeats;
|
extern const OpcodeSpec<float> lfoBeats;
|
||||||
extern const OpcodeSpec<float> lfoBeatsMod;
|
extern const OpcodeSpec<float> lfoBeatsMod;
|
||||||
extern const OpcodeSpec<float> lfoPhase;
|
extern const OpcodeSpec<float> lfoPhase;
|
||||||
|
extern const OpcodeSpec<float> lfoPhaseMod;
|
||||||
extern const OpcodeSpec<float> lfoDelay;
|
extern const OpcodeSpec<float> lfoDelay;
|
||||||
|
extern const OpcodeSpec<float> lfoDelayMod;
|
||||||
extern const OpcodeSpec<float> lfoFade;
|
extern const OpcodeSpec<float> lfoFade;
|
||||||
|
extern const OpcodeSpec<float> lfoFadeMod;
|
||||||
extern const OpcodeSpec<uint32_t> lfoCount;
|
extern const OpcodeSpec<uint32_t> lfoCount;
|
||||||
extern const OpcodeSpec<uint32_t> lfoSteps;
|
extern const OpcodeSpec<uint32_t> lfoSteps;
|
||||||
extern const OpcodeSpec<float> lfoStepX;
|
extern const OpcodeSpec<float> lfoStepX;
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,10 @@
|
||||||
|
|
||||||
#include "LFO.h"
|
#include "LFO.h"
|
||||||
#include "LFODescription.h"
|
#include "LFODescription.h"
|
||||||
#include "BeatClock.h"
|
|
||||||
#include "BufferPool.h"
|
|
||||||
#include "MathHelpers.h"
|
#include "MathHelpers.h"
|
||||||
#include "SIMDHelpers.h"
|
#include "SIMDHelpers.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "modulations/ModMatrix.h"
|
#include "Resources.h"
|
||||||
#include "modulations/ModKey.h"
|
#include "modulations/ModKey.h"
|
||||||
#include "modulations/ModId.h"
|
#include "modulations/ModId.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
@ -21,18 +19,14 @@
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
|
|
||||||
struct LFO::Impl {
|
struct LFO::Impl {
|
||||||
explicit Impl(BufferPool& bufferPool, BeatClock* beatClock, ModMatrix* modMatrix)
|
explicit Impl(Resources& resources)
|
||||||
: bufferPool_(bufferPool),
|
: resources_(resources),
|
||||||
beatClock_(beatClock),
|
|
||||||
modMatrix_(modMatrix),
|
|
||||||
sampleRate_(config::defaultSampleRate),
|
sampleRate_(config::defaultSampleRate),
|
||||||
desc_(&LFODescription::getDefault())
|
desc_(&LFODescription::getDefault())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferPool& bufferPool_;
|
Resources& resources_;
|
||||||
BeatClock* beatClock_ = nullptr;
|
|
||||||
ModMatrix* modMatrix_ = nullptr;
|
|
||||||
float sampleRate_ = 0;
|
float sampleRate_ = 0;
|
||||||
|
|
||||||
// control
|
// control
|
||||||
|
|
@ -40,14 +34,15 @@ struct LFO::Impl {
|
||||||
|
|
||||||
// state
|
// state
|
||||||
size_t delayFramesLeft_ = 0;
|
size_t delayFramesLeft_ = 0;
|
||||||
|
float fadeTime_ = 0;
|
||||||
float fadePosition_ = 0;
|
float fadePosition_ = 0;
|
||||||
std::array<float, config::maxLFOSubs> subPhases_ {{}};
|
std::array<float, config::maxLFOSubs> subPhases_ {{}};
|
||||||
std::array<float, config::maxLFOSubs> sampleHoldMem_ {{}};
|
std::array<float, config::maxLFOSubs> sampleHoldMem_ {{}};
|
||||||
std::array<int, config::maxLFOSubs> sampleHoldState_ {{}};
|
std::array<int, config::maxLFOSubs> sampleHoldState_ {{}};
|
||||||
};
|
};
|
||||||
|
|
||||||
LFO::LFO(BufferPool& bufferPool, BeatClock* beatClock, ModMatrix* modMatrix)
|
LFO::LFO(Resources& resources)
|
||||||
: impl_(new Impl(bufferPool, beatClock, modMatrix))
|
: impl_(new Impl(resources))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,16 +65,25 @@ void LFO::start(unsigned triggerDelay)
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
const LFODescription& desc = *impl.desc_;
|
const LFODescription& desc = *impl.desc_;
|
||||||
const float sampleRate = impl.sampleRate_;
|
const float sampleRate = impl.sampleRate_;
|
||||||
|
const MidiState& state = impl.resources_.midiState;
|
||||||
|
|
||||||
impl.subPhases_.fill(0.0f);
|
impl.subPhases_.fill(0.0f);
|
||||||
impl.sampleHoldMem_.fill(0.0f);
|
impl.sampleHoldMem_.fill(0.0f);
|
||||||
impl.sampleHoldState_.fill(0);
|
impl.sampleHoldState_.fill(0);
|
||||||
|
|
||||||
const float delay = desc.delay;
|
float delay = desc.delay;
|
||||||
|
for (const auto& mod: desc.delayCC)
|
||||||
|
delay += mod.data * state.getCCValue(mod.cc);
|
||||||
|
|
||||||
size_t delayFrames = (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.delayFramesLeft_ = triggerDelay + delayFrames;
|
||||||
|
|
||||||
impl.fadePosition_ = (desc.fade > 0) ? 0.0f : 1.0f;
|
float fade = desc.fade;
|
||||||
|
for (const auto& mod: desc.fadeCC)
|
||||||
|
fade += mod.data * state.getCCValue(mod.cc);
|
||||||
|
|
||||||
|
impl.fadeTime_ = fade;
|
||||||
|
impl.fadePosition_ = (fade > 0) ? 0.0f : 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
@ -218,6 +222,7 @@ void LFO::process(absl::Span<float> out)
|
||||||
{
|
{
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
const LFODescription& desc = *impl.desc_;
|
const LFODescription& desc = *impl.desc_;
|
||||||
|
BufferPool& pool = impl.resources_.bufferPool;
|
||||||
size_t numFrames = out.size();
|
size_t numFrames = out.size();
|
||||||
|
|
||||||
fill(out, 0.0f);
|
fill(out, 0.0f);
|
||||||
|
|
@ -235,7 +240,7 @@ void LFO::process(absl::Span<float> out)
|
||||||
if (countSubs < 1)
|
if (countSubs < 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto phasesTemp = impl.bufferPool_.getBuffer(numFrames);
|
auto phasesTemp = pool.getBuffer(numFrames);
|
||||||
if (!phasesTemp) {
|
if (!phasesTemp) {
|
||||||
ASSERTFALSE;
|
ASSERTFALSE;
|
||||||
fill(out, 0.0f);
|
fill(out, 0.0f);
|
||||||
|
|
@ -289,7 +294,6 @@ void LFO::process(absl::Span<float> out)
|
||||||
void LFO::processFadeIn(absl::Span<float> out)
|
void LFO::processFadeIn(absl::Span<float> out)
|
||||||
{
|
{
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
const LFODescription& desc = *impl.desc_;
|
|
||||||
const float samplePeriod = 1.0f / impl.sampleRate_;
|
const float samplePeriod = 1.0f / impl.sampleRate_;
|
||||||
size_t numFrames = out.size();
|
size_t numFrames = out.size();
|
||||||
|
|
||||||
|
|
@ -297,7 +301,7 @@ void LFO::processFadeIn(absl::Span<float> out)
|
||||||
if (fadePosition >= 1.0f)
|
if (fadePosition >= 1.0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const float fadeTime = desc.fade;
|
const float fadeTime = impl.fadeTime_;
|
||||||
const float fadeStep = samplePeriod / fadeTime;
|
const float fadeStep = samplePeriod / fadeTime;
|
||||||
|
|
||||||
for (size_t i = 0; i < numFrames && fadePosition < 1; ++i) {
|
for (size_t i = 0; i < numFrames && fadePosition < 1; ++i) {
|
||||||
|
|
@ -311,9 +315,9 @@ void LFO::processFadeIn(absl::Span<float> out)
|
||||||
void LFO::generatePhase(unsigned nth, absl::Span<float> phases)
|
void LFO::generatePhase(unsigned nth, absl::Span<float> phases)
|
||||||
{
|
{
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
BufferPool& bufferPool = impl.bufferPool_;
|
BufferPool& bufferPool = impl.resources_.bufferPool;
|
||||||
BeatClock* beatClock = impl.beatClock_;
|
BeatClock& beatClock = impl.resources_.beatClock;
|
||||||
ModMatrix* modMatrix = impl.modMatrix_;
|
ModMatrix& modMatrix = impl.resources_.modMatrix;
|
||||||
const LFODescription& desc = *impl.desc_;
|
const LFODescription& desc = *impl.desc_;
|
||||||
const LFODescription::Sub& sub = desc.sub[nth];
|
const LFODescription::Sub& sub = desc.sub[nth];
|
||||||
const float samplePeriod = 1.0f / impl.sampleRate_;
|
const float samplePeriod = 1.0f / impl.sampleRate_;
|
||||||
|
|
@ -329,39 +333,39 @@ void LFO::generatePhase(unsigned nth, absl::Span<float> phases)
|
||||||
// modulations
|
// modulations
|
||||||
const float* beatsMod = nullptr;
|
const float* beatsMod = nullptr;
|
||||||
const float* freqMod = nullptr;
|
const float* freqMod = nullptr;
|
||||||
if (modMatrix) {
|
const float* phaseMod = nullptr;
|
||||||
// Note(jpc) we might switch between beats and frequency, if host
|
// Note(jpc) we might switch between beats and frequency, if host
|
||||||
// switches play state on and off; continually generate both.
|
// switches play state on and off; continually generate both.
|
||||||
beatsMod = modMatrix->getModulationByKey(desc.beatsKey);
|
beatsMod = modMatrix.getModulationByKey(desc.beatsKey);
|
||||||
freqMod = modMatrix->getModulationByKey(desc.freqKey);
|
freqMod = modMatrix.getModulationByKey(desc.freqKey);
|
||||||
}
|
phaseMod = modMatrix.getModulationByKey(desc.phaseKey);
|
||||||
|
|
||||||
if (beatClock && beatClock->isPlaying() && beats > 0) {
|
if (beatClock.isPlaying() && beats > 0) {
|
||||||
// generate using the beat clock
|
// generate using the beat clock
|
||||||
float beatRatio = (ratio > 0) ? (1.0f / ratio) : 0.0f;
|
float beatRatio = (ratio > 0) ? (1.0f / ratio) : 0.0f;
|
||||||
|
|
||||||
if (!beatsMod)
|
if (!beatsMod)
|
||||||
beatClock->calculatePhase(beats * beatRatio, phases.data());
|
beatClock.calculatePhase(beats * beatRatio, phases.data());
|
||||||
else {
|
else {
|
||||||
auto temp = bufferPool.getBuffer(numFrames);
|
auto temp = bufferPool.getBuffer(numFrames);
|
||||||
if (!temp) {
|
if (!temp) {
|
||||||
ASSERTFALSE;
|
ASSERTFALSE;
|
||||||
beatClock->calculatePhase(beats * beatRatio, phases.data());
|
beatClock.calculatePhase(beats * beatRatio, phases.data());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fill(*temp, beats);
|
fill(*temp, beats);
|
||||||
add(absl::MakeConstSpan(beatsMod, numFrames), *temp);
|
add(absl::MakeConstSpan(beatsMod, numFrames), *temp);
|
||||||
applyGain1(beatRatio, *temp);
|
applyGain1(beatRatio, *temp);
|
||||||
beatClock->calculatePhaseModulated(temp->data(), phases.data());
|
beatClock.calculatePhaseModulated(temp->data(), phases.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// generate using the frequency
|
// generate using the frequency
|
||||||
if (!freqMod) {
|
if (!freqMod) {
|
||||||
|
float incr = ratio * samplePeriod * baseFreq;
|
||||||
for (size_t i = 0; i < numFrames; ++i) {
|
for (size_t i = 0; i < numFrames; ++i) {
|
||||||
phases[i] = phase;
|
phases[i] = phase;
|
||||||
float incr = ratio * samplePeriod * baseFreq;
|
|
||||||
phase = wrapPhase(phase + incr);
|
phase = wrapPhase(phase + incr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -372,13 +376,16 @@ void LFO::generatePhase(unsigned nth, absl::Span<float> phases)
|
||||||
phase = wrapPhase(phase + incr);
|
phase = wrapPhase(phase + incr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply phase offsets
|
// apply phase offsets
|
||||||
for (size_t i = 0; i < numFrames; ++i) {
|
if (!phaseMod) {
|
||||||
float withOffset = phases[i] + phaseOffset;
|
for (size_t i = 0; i < numFrames; ++i)
|
||||||
withOffset -= (int)withOffset;
|
phases[i] = wrapPhase(phases[i] + phaseOffset);
|
||||||
phases[i] = withOffset;
|
} else {
|
||||||
|
for (size_t i = 0; i < numFrames; ++i)
|
||||||
|
phases[i] = wrapPhase(phases[i] + phaseOffset + phaseMod[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl.subPhases_[nth] = phase;
|
impl.subPhases_[nth] = phase;
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
class BufferPool;
|
class Resources;
|
||||||
class BeatClock;
|
|
||||||
class ModMatrix;
|
|
||||||
struct Region;
|
struct Region;
|
||||||
|
|
||||||
enum class LFOWave : int;
|
enum class LFOWave : int;
|
||||||
|
|
@ -54,10 +52,7 @@ struct LFODescription;
|
||||||
|
|
||||||
class LFO {
|
class LFO {
|
||||||
public:
|
public:
|
||||||
explicit LFO(
|
explicit LFO(Resources& resources);
|
||||||
BufferPool& bufferPool,
|
|
||||||
BeatClock* beatClock = nullptr,
|
|
||||||
ModMatrix* modMatrix = nullptr);
|
|
||||||
~LFO();
|
~LFO();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Defaults.h"
|
#include "Defaults.h"
|
||||||
|
#include "CCMap.h"
|
||||||
#include "modulations/ModKey.h"
|
#include "modulations/ModKey.h"
|
||||||
#include <absl/types/optional.h>
|
#include <absl/types/optional.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -19,8 +20,11 @@ struct LFODescription {
|
||||||
float freq { Default::lfoFreq }; // lfoN_freq
|
float freq { Default::lfoFreq }; // lfoN_freq
|
||||||
float beats { Default::lfoBeats }; // lfoN_beats
|
float beats { Default::lfoBeats }; // lfoN_beats
|
||||||
float phase0 { Default::lfoPhase }; // lfoN_phase
|
float phase0 { Default::lfoPhase }; // lfoN_phase
|
||||||
|
CCMap<float> phaseCC { Default::lfoPhaseMod }; // lfoN_phase_cc
|
||||||
float delay { Default::lfoDelay }; // lfoN_delay
|
float delay { Default::lfoDelay }; // lfoN_delay
|
||||||
|
CCMap<float> delayCC { Default::lfoDelayMod }; // lfoN_phase_cc
|
||||||
float fade { Default::lfoFade }; // lfoN_fade
|
float fade { Default::lfoFade }; // lfoN_fade
|
||||||
|
CCMap<float> fadeCC { Default::lfoFadeMod }; // lfoN_phase_cc
|
||||||
unsigned count { Default::lfoCount }; // lfoN_count
|
unsigned count { Default::lfoCount }; // lfoN_count
|
||||||
struct Sub {
|
struct Sub {
|
||||||
LFOWave wave { Default::lfoWave }; // lfoN_wave[X]
|
LFOWave wave { Default::lfoWave }; // lfoN_wave[X]
|
||||||
|
|
@ -37,6 +41,7 @@ struct LFODescription {
|
||||||
// modulations
|
// modulations
|
||||||
ModKey beatsKey;
|
ModKey beatsKey;
|
||||||
ModKey freqKey;
|
ModKey freqKey;
|
||||||
|
ModKey phaseKey;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sfz
|
} // namespace sfz
|
||||||
|
|
|
||||||
|
|
@ -1123,6 +1123,7 @@ bool sfz::Region::parseLFOOpcodeV2(const Opcode& opcode)
|
||||||
//
|
//
|
||||||
lfo.beatsKey = ModKey::createNXYZ(ModId::LFOBeats, id, lfoNumber);
|
lfo.beatsKey = ModKey::createNXYZ(ModId::LFOBeats, id, lfoNumber);
|
||||||
lfo.freqKey = ModKey::createNXYZ(ModId::LFOFrequency, id, lfoNumber);
|
lfo.freqKey = ModKey::createNXYZ(ModId::LFOFrequency, id, lfoNumber);
|
||||||
|
lfo.phaseKey = ModKey::createNXYZ(ModId::LFOPhase, id, lfoNumber);
|
||||||
|
|
||||||
//
|
//
|
||||||
auto getOrCreateLFOStep = [&opcode, &lfo]() -> float* {
|
auto getOrCreateLFOStep = [&opcode, &lfo]() -> float* {
|
||||||
|
|
@ -1172,12 +1173,27 @@ bool sfz::Region::parseLFOOpcodeV2(const Opcode& opcode)
|
||||||
case hash("lfo&_phase"):
|
case hash("lfo&_phase"):
|
||||||
lfo.phase0 = opcode.read(Default::lfoPhase);
|
lfo.phase0 = opcode.read(Default::lfoPhase);
|
||||||
break;
|
break;
|
||||||
|
case_any_ccN("lfo&_phase"):
|
||||||
|
processGenericCc(opcode, Default::lfoPhaseMod, ModKey::createNXYZ(ModId::LFOPhase, id, lfoNumber));
|
||||||
|
break;
|
||||||
case hash("lfo&_delay"):
|
case hash("lfo&_delay"):
|
||||||
lfo.delay = opcode.read(Default::lfoDelay);
|
lfo.delay = opcode.read(Default::lfoDelay);
|
||||||
break;
|
break;
|
||||||
|
case hash("lfo&_delay_oncc&"):
|
||||||
|
if (opcode.parameters.back() > config::numCCs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
lfo.delayCC[opcode.parameters.back()] = opcode.read(Default::lfoDelayMod);
|
||||||
|
break;
|
||||||
case hash("lfo&_fade"):
|
case hash("lfo&_fade"):
|
||||||
lfo.fade = opcode.read(Default::lfoFade);
|
lfo.fade = opcode.read(Default::lfoFade);
|
||||||
break;
|
break;
|
||||||
|
case hash("lfo&_fade_oncc&"):
|
||||||
|
if (opcode.parameters.back() > config::numCCs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
lfo.fadeCC[opcode.parameters.back()] = opcode.read(Default::lfoFadeMod);
|
||||||
|
break;
|
||||||
case hash("lfo&_count"):
|
case hash("lfo&_count"):
|
||||||
lfo.count = opcode.read(Default::lfoCount);
|
lfo.count = opcode.read(Default::lfoCount);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1671,7 +1671,7 @@ void Voice::setMaxLFOsPerVoice(size_t numLFOs)
|
||||||
impl.lfos_.resize(numLFOs);
|
impl.lfos_.resize(numLFOs);
|
||||||
|
|
||||||
for (size_t i = 0; i < numLFOs; ++i) {
|
for (size_t i = 0; i < numLFOs; ++i) {
|
||||||
auto lfo = absl::make_unique<LFO>(resources.bufferPool, &resources.beatClock, &resources.modMatrix);
|
auto lfo = absl::make_unique<LFO>(resources);
|
||||||
lfo->setSampleRate(impl.sampleRate_);
|
lfo->setSampleRate(impl.sampleRate_);
|
||||||
impl.lfos_[i] = std::move(lfo);
|
impl.lfos_[i] = std::move(lfo);
|
||||||
}
|
}
|
||||||
|
|
@ -1712,7 +1712,7 @@ void Voice::setAmplitudeLFOEnabledPerVoice(bool haveAmplitudeLFO)
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
Resources& res = impl.resources_;
|
Resources& res = impl.resources_;
|
||||||
if (haveAmplitudeLFO) {
|
if (haveAmplitudeLFO) {
|
||||||
LFO* lfo = new LFO(res.bufferPool, &res.beatClock, &res.modMatrix);
|
LFO* lfo = new LFO(res);
|
||||||
impl.lfoAmplitude_.reset(lfo);
|
impl.lfoAmplitude_.reset(lfo);
|
||||||
lfo->setSampleRate(impl.sampleRate_);
|
lfo->setSampleRate(impl.sampleRate_);
|
||||||
}
|
}
|
||||||
|
|
@ -1725,7 +1725,7 @@ void Voice::setPitchLFOEnabledPerVoice(bool havePitchLFO)
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
Resources& res = impl.resources_;
|
Resources& res = impl.resources_;
|
||||||
if (havePitchLFO) {
|
if (havePitchLFO) {
|
||||||
LFO* lfo = new LFO(res.bufferPool, &res.beatClock, &res.modMatrix);
|
LFO* lfo = new LFO(res);
|
||||||
impl.lfoPitch_.reset(lfo);
|
impl.lfoPitch_.reset(lfo);
|
||||||
lfo->setSampleRate(impl.sampleRate_);
|
lfo->setSampleRate(impl.sampleRate_);
|
||||||
}
|
}
|
||||||
|
|
@ -1738,7 +1738,7 @@ void Voice::setFilterLFOEnabledPerVoice(bool haveFilterLFO)
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
Resources& res = impl.resources_;
|
Resources& res = impl.resources_;
|
||||||
if (haveFilterLFO) {
|
if (haveFilterLFO) {
|
||||||
LFO* lfo = new LFO(res.bufferPool, &res.beatClock, &res.modMatrix);
|
LFO* lfo = new LFO(res);
|
||||||
impl.lfoFilter_.reset(lfo);
|
impl.lfoFilter_.reset(lfo);
|
||||||
lfo->setSampleRate(impl.sampleRate_);
|
lfo->setSampleRate(impl.sampleRate_);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,8 @@ int ModIds::flags(ModId id) noexcept
|
||||||
return kModIsPerVoice|kModIsAdditive;
|
return kModIsPerVoice|kModIsAdditive;
|
||||||
case ModId::LFOBeats:
|
case ModId::LFOBeats:
|
||||||
return kModIsPerVoice|kModIsAdditive;
|
return kModIsPerVoice|kModIsAdditive;
|
||||||
|
case ModId::LFOPhase:
|
||||||
|
return kModIsPerVoice|kModIsAdditive;
|
||||||
|
|
||||||
// unknown
|
// unknown
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ enum class ModId : int {
|
||||||
FilLFOFrequency,
|
FilLFOFrequency,
|
||||||
LFOFrequency,
|
LFOFrequency,
|
||||||
LFOBeats,
|
LFOBeats,
|
||||||
|
LFOPhase,
|
||||||
|
|
||||||
_TargetsEnd,
|
_TargetsEnd,
|
||||||
// [/targets] --------------------------------------------------------------
|
// [/targets] --------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,8 @@ std::string ModKey::toString() const
|
||||||
return absl::StrCat("LFOFrequency {", region_.number(), ", N=", 1 + params_.N, "}");
|
return absl::StrCat("LFOFrequency {", region_.number(), ", N=", 1 + params_.N, "}");
|
||||||
case ModId::LFOBeats:
|
case ModId::LFOBeats:
|
||||||
return absl::StrCat("LFOBeats {", region_.number(), ", N=", 1 + params_.N, "}");
|
return absl::StrCat("LFOBeats {", region_.number(), ", N=", 1 + params_.N, "}");
|
||||||
|
case ModId::LFOPhase:
|
||||||
|
return absl::StrCat("LFOPhase {", region_.number(), ", N=", 1 + params_.N, "}");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ static bool computeLFO(DataPoints& dp, const fs::path& sfzPath, double sampleRat
|
||||||
std::vector<std::unique_ptr<sfz::LFO>> lfos(numLfos);
|
std::vector<std::unique_ptr<sfz::LFO>> lfos(numLfos);
|
||||||
|
|
||||||
for (size_t l = 0; l < numLfos; ++l) {
|
for (size_t l = 0; l < numLfos; ++l) {
|
||||||
sfz::LFO* lfo = new sfz::LFO(resources.bufferPool);
|
sfz::LFO* lfo = new sfz::LFO(resources);
|
||||||
lfos[l].reset(lfo);
|
lfos[l].reset(lfo);
|
||||||
lfo->setSampleRate(sampleRate);
|
lfo->setSampleRate(sampleRate);
|
||||||
lfo->configure(&desc[l]);
|
lfo->configure(&desc[l]);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue