Implement lfoN_beats
This commit is contained in:
parent
c1306f8a71
commit
d8dcb2e56f
6 changed files with 54 additions and 14 deletions
|
|
@ -222,6 +222,7 @@ namespace Default
|
||||||
constexpr int numLFOSubs { 2 };
|
constexpr int numLFOSubs { 2 };
|
||||||
constexpr int numLFOSteps { 8 };
|
constexpr int numLFOSteps { 8 };
|
||||||
constexpr Range<float> lfoFreqRange { 0.0, 100.0 };
|
constexpr Range<float> lfoFreqRange { 0.0, 100.0 };
|
||||||
|
constexpr Range<float> lfoBeatsRange { 0.0, 1000.0 };
|
||||||
constexpr Range<float> lfoPhaseRange { 0.0, 1.0 };
|
constexpr Range<float> lfoPhaseRange { 0.0, 1.0 };
|
||||||
constexpr Range<float> lfoDelayRange { 0.0, 30.0 };
|
constexpr Range<float> lfoDelayRange { 0.0, 30.0 };
|
||||||
constexpr Range<float> lfoFadeRange { 0.0, 30.0 };
|
constexpr Range<float> lfoFadeRange { 0.0, 30.0 };
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "LFO.h"
|
#include "LFO.h"
|
||||||
#include "LFODescription.h"
|
#include "LFODescription.h"
|
||||||
|
#include "BeatClock.h"
|
||||||
#include "BufferPool.h"
|
#include "BufferPool.h"
|
||||||
#include "MathHelpers.h"
|
#include "MathHelpers.h"
|
||||||
#include "SIMDHelpers.h"
|
#include "SIMDHelpers.h"
|
||||||
|
|
@ -17,14 +18,16 @@
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
|
|
||||||
struct LFO::Impl {
|
struct LFO::Impl {
|
||||||
explicit Impl(BufferPool& bufferPool)
|
explicit Impl(BufferPool& bufferPool, BeatClock* beatClock)
|
||||||
: bufferPool_(bufferPool),
|
: bufferPool_(bufferPool),
|
||||||
|
beatClock_(beatClock),
|
||||||
sampleRate_(config::defaultSampleRate),
|
sampleRate_(config::defaultSampleRate),
|
||||||
desc_(&LFODescription::getDefault())
|
desc_(&LFODescription::getDefault())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferPool& bufferPool_;
|
BufferPool& bufferPool_;
|
||||||
|
BeatClock* beatClock_ = nullptr;
|
||||||
float sampleRate_ = 0;
|
float sampleRate_ = 0;
|
||||||
|
|
||||||
// control
|
// control
|
||||||
|
|
@ -38,8 +41,8 @@ struct LFO::Impl {
|
||||||
std::array<int, config::maxLFOSubs> sampleHoldState_ {{}};
|
std::array<int, config::maxLFOSubs> sampleHoldState_ {{}};
|
||||||
};
|
};
|
||||||
|
|
||||||
LFO::LFO(BufferPool& bufferPool)
|
LFO::LFO(BufferPool& bufferPool, BeatClock* beatClock)
|
||||||
: impl_(new Impl(bufferPool))
|
: impl_(new Impl(bufferPool, beatClock))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -299,26 +302,46 @@ 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_;
|
||||||
|
BeatClock* beatClock = impl.beatClock_;
|
||||||
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_;
|
||||||
const float baseFreq = desc.freq;
|
const float baseFreq = desc.freq;
|
||||||
|
const float beats = desc.beats;
|
||||||
const float phaseOffset = desc.phase0;
|
const float phaseOffset = desc.phase0;
|
||||||
const float ratio = sub.ratio;
|
const float ratio = sub.ratio;
|
||||||
float phase = impl.subPhases_[nth];
|
float phase = impl.subPhases_[nth];
|
||||||
|
const size_t numFrames = phases.size();
|
||||||
|
|
||||||
for (size_t i = 0, n = phases.size(); i < n; ++i) {
|
if (beatClock && beatClock->isPlaying() && beats > 0) {
|
||||||
float withOffset = phase + phaseOffset;
|
// generate using the beat clock
|
||||||
withOffset -= (int)withOffset;
|
float beatRatio = (ratio > 0) ? (1.0f / ratio) : 0.0f;
|
||||||
|
beatClock->calculatePhase(beats * beatRatio, phases.data());
|
||||||
|
|
||||||
phases[i] = withOffset;
|
for (size_t i = 0; i < numFrames; ++i) {
|
||||||
|
float withOffset = phase + phaseOffset;
|
||||||
|
withOffset -= (int)withOffset;
|
||||||
|
|
||||||
// TODO(jpc) lfoN_count: number of repetitions
|
phases[i] = withOffset;
|
||||||
|
|
||||||
float incr = ratio * samplePeriod * baseFreq;
|
// TODO(jpc) lfoN_count: number of repetitions
|
||||||
phase += incr;
|
}
|
||||||
int numWraps = (int)phase;
|
}
|
||||||
phase -= numWraps;
|
else {
|
||||||
|
// generate using the frequency
|
||||||
|
for (size_t i = 0; i < numFrames; ++i) {
|
||||||
|
float withOffset = phase + phaseOffset;
|
||||||
|
withOffset -= (int)withOffset;
|
||||||
|
|
||||||
|
phases[i] = withOffset;
|
||||||
|
|
||||||
|
// TODO(jpc) lfoN_count: number of repetitions
|
||||||
|
|
||||||
|
float incr = ratio * samplePeriod * baseFreq;
|
||||||
|
phase += incr;
|
||||||
|
int numWraps = (int)phase;
|
||||||
|
phase -= numWraps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl.subPhases_[nth] = phase;
|
impl.subPhases_[nth] = phase;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
class BufferPool;
|
class BufferPool;
|
||||||
|
class BeatClock;
|
||||||
|
|
||||||
enum class LFOWave : int;
|
enum class LFOWave : int;
|
||||||
struct LFODescription;
|
struct LFODescription;
|
||||||
|
|
@ -50,7 +51,9 @@ struct LFODescription;
|
||||||
|
|
||||||
class LFO {
|
class LFO {
|
||||||
public:
|
public:
|
||||||
explicit LFO(BufferPool& bufferPool);
|
explicit LFO(
|
||||||
|
BufferPool& bufferPool,
|
||||||
|
BeatClock* beatClock = nullptr);
|
||||||
~LFO();
|
~LFO();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ struct LFODescription {
|
||||||
~LFODescription();
|
~LFODescription();
|
||||||
static const LFODescription& getDefault();
|
static const LFODescription& getDefault();
|
||||||
float freq = 0; // lfoN_freq
|
float freq = 0; // lfoN_freq
|
||||||
|
float beats = 0; // lfoN_beats
|
||||||
float phase0 = 0; // lfoN_phase
|
float phase0 = 0; // lfoN_phase
|
||||||
float delay = 0; // lfoN_delay
|
float delay = 0; // lfoN_delay
|
||||||
float fade = 0; // lfoN_fade
|
float fade = 0; // lfoN_fade
|
||||||
|
|
|
||||||
|
|
@ -866,6 +866,16 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
|
||||||
setValueFromOpcode(opcode, lfos[lfoNumber - 1].freq, Default::lfoFreqRange);
|
setValueFromOpcode(opcode, lfos[lfoNumber - 1].freq, Default::lfoFreqRange);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case hash("lfo&_beats"):
|
||||||
|
{
|
||||||
|
const auto lfoNumber = opcode.parameters.front();
|
||||||
|
if (lfoNumber == 0)
|
||||||
|
return false;
|
||||||
|
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
|
||||||
|
return false;
|
||||||
|
setValueFromOpcode(opcode, lfos[lfoNumber - 1].beats, Default::lfoBeatsRange);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case hash("lfo&_phase"):
|
case hash("lfo&_phase"):
|
||||||
{
|
{
|
||||||
const auto lfoNumber = opcode.parameters.front();
|
const auto lfoNumber = opcode.parameters.front();
|
||||||
|
|
|
||||||
|
|
@ -1475,10 +1475,12 @@ void Voice::setMaxEQsPerVoice(size_t numFilters)
|
||||||
void Voice::setMaxLFOsPerVoice(size_t numLFOs)
|
void Voice::setMaxLFOsPerVoice(size_t numLFOs)
|
||||||
{
|
{
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
|
Resources& resources = impl.resources_;
|
||||||
|
|
||||||
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>(impl.resources_.bufferPool);
|
auto lfo = absl::make_unique<LFO>(resources.bufferPool, &resources.beatClock);
|
||||||
lfo->setSampleRate(impl.sampleRate_);
|
lfo->setSampleRate(impl.sampleRate_);
|
||||||
impl.lfos_[i] = std::move(lfo);
|
impl.lfos_[i] = std::move(lfo);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue