1 |
/* |
2 |
* Copyright (c) 2019 Christian Schoenebeck |
3 |
* |
4 |
* http://www.linuxsampler.org |
5 |
* |
6 |
* This file is part of LinuxSampler and released under the same terms. |
7 |
* See README file for details. |
8 |
*/ |
9 |
|
10 |
#include "LFO.h" |
11 |
#include "common/LFOAll.h" |
12 |
#include <type_traits> // for std::is_same |
13 |
|
14 |
namespace LinuxSampler { |
15 |
|
16 |
enum lfo_class_t { |
17 |
lfo_class_sine_signed, |
18 |
lfo_class_sine_unsigned, |
19 |
lfo_class_triangle_signed, |
20 |
lfo_class_triangle_unsigned, |
21 |
lfo_class_saw_signed, |
22 |
lfo_class_saw_unsigned, |
23 |
lfo_class_square_signed, |
24 |
lfo_class_square_unsigned, |
25 |
}; |
26 |
|
27 |
struct LFOPriv { |
28 |
LFOPOD* lfo = NULL; |
29 |
lfo_class_t lfoClass = (lfo_class_t) -1; // some invalid value |
30 |
|
31 |
virtual ~LFOPriv() { |
32 |
if (lfo) delete lfo; |
33 |
} |
34 |
}; |
35 |
|
36 |
LFO::LFO() { |
37 |
SELF = new LFOPriv; |
38 |
} |
39 |
|
40 |
LFO::~LFO() { |
41 |
if (SELF) delete SELF; |
42 |
} |
43 |
|
44 |
template<class T> |
45 |
static T* createLFO(LFOPriv* SELF, const LFO::SetupOpt& opt) { |
46 |
if (SELF->lfo) { |
47 |
delete SELF->lfo; |
48 |
SELF->lfo = NULL; |
49 |
} |
50 |
|
51 |
const bool flipPolarity = (opt.flipPolarity) ? *opt.flipPolarity : false; |
52 |
const float maxValue = (opt.maxValue) ? *opt.maxValue : 1.0; |
53 |
const float frequency = (opt.frequency) ? *opt.frequency : 1.0; |
54 |
const LFO::start_level_t startLevel = (opt.startLevel) ? *opt.startLevel : LFO::start_level_mid; |
55 |
const uint16_t internalDepth = (opt.internalDepth) ? *opt.internalDepth : 0; |
56 |
const uint16_t midiCtrlDepth = (opt.midiControllerDepth) ? *opt.midiControllerDepth : 0; |
57 |
const float samplerate = (opt.samplerate) ? *opt.samplerate : 44100; |
58 |
|
59 |
T* lfo = new T(maxValue); |
60 |
SELF->lfo = lfo; |
61 |
|
62 |
lfo->trigger(frequency, startLevel, internalDepth, midiCtrlDepth, flipPolarity, samplerate); |
63 |
if (opt.phase) |
64 |
lfo->setPhase( *opt.phase ); |
65 |
lfo->updateByMIDICtrlValue(0); |
66 |
|
67 |
if (std::is_same<T,LFOSineSigned>::value) |
68 |
SELF->lfoClass = lfo_class_sine_signed; |
69 |
else if (std::is_same<T,LFOSineUnsigned>::value) |
70 |
SELF->lfoClass = lfo_class_sine_unsigned; |
71 |
else if (std::is_same<T,LFOTriangleSigned>::value) |
72 |
SELF->lfoClass = lfo_class_triangle_signed; |
73 |
else if (std::is_same<T,LFOTriangleUnsigned>::value) |
74 |
SELF->lfoClass = lfo_class_triangle_unsigned; |
75 |
else if (std::is_same<T,LFOSawSigned>::value) |
76 |
SELF->lfoClass = lfo_class_saw_signed; |
77 |
else if (std::is_same<T,LFOSawUnsigned>::value) |
78 |
SELF->lfoClass = lfo_class_saw_unsigned; |
79 |
else if (std::is_same<T,LFOSquareSigned>::value) |
80 |
SELF->lfoClass = lfo_class_square_signed; |
81 |
else if (std::is_same<T,LFOSquareUnsigned>::value) |
82 |
SELF->lfoClass = lfo_class_square_unsigned; |
83 |
else |
84 |
assert(false); |
85 |
|
86 |
return lfo; |
87 |
} |
88 |
|
89 |
void LFO::setup(const SetupOpt& opt) { |
90 |
const wave_t wave = (opt.waveType) ? *opt.waveType : wave_sine; |
91 |
const bool isSigned = (opt.rangeType) ? (*opt.rangeType == range_signed) : false; |
92 |
|
93 |
switch (wave) { |
94 |
case wave_sine: |
95 |
if (isSigned) |
96 |
createLFO<LFOSineSigned>(SELF, opt); |
97 |
else |
98 |
createLFO<LFOSineUnsigned>(SELF, opt); |
99 |
break; |
100 |
case wave_triangle: |
101 |
if (isSigned) |
102 |
createLFO<LFOTriangleSigned>(SELF, opt); |
103 |
else |
104 |
createLFO<LFOTriangleUnsigned>(SELF, opt); |
105 |
break; |
106 |
case wave_saw: |
107 |
if (isSigned) |
108 |
createLFO<LFOSawSigned>(SELF, opt); |
109 |
else |
110 |
createLFO<LFOSawUnsigned>(SELF, opt); |
111 |
break; |
112 |
case wave_square: |
113 |
if (isSigned) |
114 |
createLFO<LFOSquareSigned>(SELF, opt); |
115 |
else |
116 |
createLFO<LFOSquareUnsigned>(SELF, opt); |
117 |
break; |
118 |
default: |
119 |
assert(false); |
120 |
} |
121 |
} |
122 |
|
123 |
template<class T> |
124 |
inline float renderLFO(LFOPriv* SELF) { |
125 |
return static_cast<T*>(SELF->lfo)->render(); |
126 |
} |
127 |
|
128 |
float LFO::render() { |
129 |
switch (SELF->lfoClass) { |
130 |
case lfo_class_sine_signed: |
131 |
return renderLFO<LFOSineSigned>(SELF); |
132 |
case lfo_class_sine_unsigned: |
133 |
return renderLFO<LFOSineUnsigned>(SELF); |
134 |
case lfo_class_triangle_signed: |
135 |
return renderLFO<LFOTriangleSigned>(SELF); |
136 |
case lfo_class_triangle_unsigned: |
137 |
return renderLFO<LFOTriangleUnsigned>(SELF); |
138 |
case lfo_class_saw_signed: |
139 |
return renderLFO<LFOSawSigned>(SELF); |
140 |
case lfo_class_saw_unsigned: |
141 |
return renderLFO<LFOSawUnsigned>(SELF); |
142 |
case lfo_class_square_signed: |
143 |
return renderLFO<LFOSquareSigned>(SELF); |
144 |
case lfo_class_square_unsigned: |
145 |
return renderLFO<LFOSquareUnsigned>(SELF); |
146 |
} |
147 |
return 0; |
148 |
} |
149 |
|
150 |
template<class T> |
151 |
inline void setLFOMidiCtrlValue(LFOPriv* SELF, uint16_t value) { |
152 |
return static_cast<T*>(SELF->lfo)->updateByMIDICtrlValue(value); |
153 |
} |
154 |
|
155 |
void LFO::setMIDICtrlValue(uint8_t midiCCValue) { |
156 |
switch (SELF->lfoClass) { |
157 |
case lfo_class_sine_signed: |
158 |
return setLFOMidiCtrlValue<LFOSineSigned>(SELF, midiCCValue); |
159 |
case lfo_class_sine_unsigned: |
160 |
return setLFOMidiCtrlValue<LFOSineUnsigned>(SELF, midiCCValue); |
161 |
case lfo_class_triangle_signed: |
162 |
return setLFOMidiCtrlValue<LFOTriangleSigned>(SELF, midiCCValue); |
163 |
case lfo_class_triangle_unsigned: |
164 |
return setLFOMidiCtrlValue<LFOTriangleUnsigned>(SELF, midiCCValue); |
165 |
case lfo_class_saw_signed: |
166 |
return setLFOMidiCtrlValue<LFOSawSigned>(SELF, midiCCValue); |
167 |
case lfo_class_saw_unsigned: |
168 |
return setLFOMidiCtrlValue<LFOSawUnsigned>(SELF, midiCCValue); |
169 |
case lfo_class_square_signed: |
170 |
return setLFOMidiCtrlValue<LFOSquareSigned>(SELF, midiCCValue); |
171 |
case lfo_class_square_unsigned: |
172 |
return setLFOMidiCtrlValue<LFOSquareUnsigned>(SELF, midiCCValue); |
173 |
} |
174 |
} |
175 |
|
176 |
} // namespace LinuxSampler |