18#include "Oscillator.h"
22#define LFO_TEMPODIV_VALIST "1/64", "1/32", "1/16T", "1/16", "1/16D", "1/8T", "1/8", "1/8D", "1/4", "1/4D", "1/2", "1/1", "2/1", "4/1", "8/1"
24#define LFO_SHAPE_VALIST "Triangle", "Square", "Ramp Up", "Ramp Down", "Sine"
26template<
typename T =
double>
75 static constexpr T scalars[kNumDivisions] = {
93 return scalars[division];
99 static const char* displays[kNumDivisions] = { LFO_TEMPODIV_VALIST };
100 return displays[division];
113 void ProcessBlock(T* pOutput,
int nFrames,
double qnPos = 0.,
bool transportIsRunning =
false,
double tempo = 120.)
115 T oneOverQNScalar = 1./mQNScalar;
118 if(mRateMode == ERateMode::kBPM && !transportIsRunning)
125 for (
int s=0; s<nFrames; s++)
127 double sampleAccurateQnPos = qnPos + ((double) s / samplesPerBeat);
129 if(mRateMode == ERateMode::kBPM)
131 if(transportIsRunning)
132 phase = std::fmod(sampleAccurateQnPos, oneOverQNScalar) / oneOverQNScalar;
134 phase = WrapPhase(phase + (phaseIncr * mQNScalar));
137 phase = WrapPhase(phase + phaseIncr);
139 pOutput[s] = DoProcess(phase);
145 void SetShape(
int lfoShape)
147 mShape = (EShape)
Clip(lfoShape, 0, kNumShapes-1);
150 void SetPolarity(
bool bipolar)
152 mPolarity = bipolar ? EPolarity::kBipolar : EPolarity::kUnipolar;
155 void SetScalar(T scalar)
157 mLevelScalar = scalar;
160 void SetQNScalar(T scalar)
165 void SetQNScalarFromDivision(
int division)
167 mQNScalar =
GetQNScalar(
static_cast<ETempoDivison
>(
Clip(division, 0, (
int) kNumDivisions)));
170 void SetRateMode(
bool sync)
172 mRateMode = sync ? ERateMode::kBPM : ERateMode::kHz;
175 T GetLastOutput()
const
181 static inline T WrapPhase (T x, T lo = 0., T hi = 1.)
190 inline T DoProcess(T phase)
192 auto triangle = [](T x){
return (2. * (1. - std::abs((WrapPhase(x + 0.25) * 2.) -1.))) - 1.; };
193 auto triangleUnipolar = [](T x){
return 1. - std::abs((x * 2.) - 1. ); };
194 auto square = [](T x){
return std::copysign(1., x - 0.5); };
195 auto squareUnipolar = [](T x){
return std::copysign(0.5, x - 0.5) + 0.5; };
196 auto rampup = [](T x){
return (x * 2.) - 1.; };
197 auto rampupUnipolar = [](T x){
return x; };
198 auto rampdown = [](T x){
return ((1. - x) * 2.) - 1.; };
199 auto rampdownUnipolar = [](T x){
return 1. - x; };
203 if(mPolarity == EPolarity::kUnipolar)
206 case kTriangle: output = triangleUnipolar(phase);
break;
207 case kSquare: output = squareUnipolar(phase);
break;
208 case kRampUp: output = rampupUnipolar(phase);
break;
209 case kRampDown: output = rampdownUnipolar(phase);
break;
210 case kSine: output = (std::sin(phase * 6.283185307179586) * 0.5) + 0.5;
break;
217 case kTriangle: output = triangle(phase);
break;
218 case kSquare: output = square(phase);
break;
219 case kRampUp: output = rampup(phase);
break;
220 case kRampDown: output = rampdown(phase);
break;
221 case kSine: output = std::sin(phase * 6.283185307179586);
break;
226 mLastOutput = output * mLevelScalar;
235 EShape mShape = EShape::kTriangle;
236 EPolarity mPolarity = EPolarity::kUnipolar;
237 ERateMode mRateMode = ERateMode::kHz;
static const char * GetQNDisplay(ETempoDivison division)
Get a CString to display the divisor as text.
static T GetQNScalar(ETempoDivison division)
Get the scalar factor to convert a ramp at the host BPM to tempo division value.
T Process(double freqHz) override
Per sample process function, updating frequency per sample.
BEGIN_IPLUG_NAMESPACE T Clip(T x, T lo, T hi)
Clips the value x between lo and hi.