/[svn]/linuxsampler/trunk/src/engines/common/LFOCluster.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/common/LFOCluster.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3625 - (show annotations) (download) (as text)
Thu Oct 3 13:37:25 2019 UTC (4 years, 6 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 8441 byte(s)
* gig format extension: Added support for different LFO wave forms
  (currently either sine [default], triangle, saw or square).

* gig format extension: Added support for LFO phase displacement
  (0°..360°).

* gig format extension: Added support for flipping LFO polarity on LFO 3
  (in the original gig format this was only available for LFO 1 and LFO 2).

* Bumped version (2.1.1.svn22).

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 #ifndef LS_LFO_CLUSTER_H
11 #define LS_LFO_CLUSTER_H
12
13 #include "LFOAll.h"
14 #include <type_traits> // for std::conditional
15
16 namespace LinuxSampler {
17
18 /** @brief Low Frequency Oscillator (sampler internal template class).
19 *
20 * This is a generalized cluster class providing all our LFO implementations
21 * encapsulated as one single class. This is thus a C++ template variant of the
22 * similar public API C++ class LFO. Even though LFOCluster and LFO serve a
23 * similar purpose, you should however always use this template variant instead
24 * of the public API LFO class for sampler internal code. LFOCluster has a
25 * higher potential for the compiler to optimize the finally emitted
26 * instructions, however it requires direct access to our individual LFO
27 * implementations' code (which are subject to change at any time for
28 * performance reasons). Hence this template class is not suitable for public
29 * API purposes (that is for third party apps), hence the reason for the
30 + existence of the separate public API LFO class. The latter has the priority
31 * for API & ABI stability for the price of slightly reduced runtime efficiency
32 * though.
33 */
34 template<LFO::range_type_t RANGE>
35 class LFOCluster {
36 public:
37 uint8_t& ExtController = sine.ExtController; /// redirect to union
38
39 /**
40 * Constructor
41 *
42 * @param Max - maximum value of the output levels
43 */
44 LFOCluster(float Max) :
45 wave(LFO::wave_sine),
46 sine(Max) // union-like class: use any union member's constructor (one for all, all for one)
47 {
48 }
49
50 /**
51 * Calculates exactly one sample point of the LFO wave.
52 *
53 * @returns next LFO level
54 */
55 inline float render() {
56 switch (wave) {
57 case LFO::wave_sine: return sine.render();
58 case LFO::wave_triangle: return triangle.render();
59 case LFO::wave_saw: return saw.render();
60 case LFO::wave_square: return square.render();
61 }
62 return 0.f;
63 }
64
65 /**
66 * Will be called by the voice when the key / voice was triggered.
67 *
68 * @param Wave - wave form to be used (e.g. sine, saw, square)
69 * @param Frequency - frequency of the oscillator in Hz
70 * @param Phase - phase displacement of wave form's start level
71 * (0��..360��)
72 * @param StartLevel - on which level the wave should start
73 * @param InternalDepth - firm, internal oscillator amplitude
74 * @param ExtControlDepth - defines how strong the external MIDI
75 * controller has influence on the
76 * oscillator amplitude
77 * @param FlipPhase - inverts the oscillator wave against
78 * a horizontal axis
79 * @param SampleRate - current sample rate of the engines
80 * audio output signal
81 */
82 void trigger(LFO::wave_t Wave, float Frequency, float Phase, LFO::start_level_t StartLevel, uint16_t InternalDepth, uint16_t ExtControlDepth, bool FlipPhase, unsigned int SampleRate) {
83 wave = Wave;
84 switch (Wave) {
85 case LFO::wave_sine:
86 sine.trigger(Frequency, StartLevel, InternalDepth, ExtControlDepth, FlipPhase, SampleRate);
87 sine.setPhase(Phase);
88 break;
89 case LFO::wave_triangle:
90 triangle.trigger(Frequency, StartLevel, InternalDepth, ExtControlDepth, FlipPhase, SampleRate);
91 triangle.setPhase(Phase);
92 break;
93 case LFO::wave_saw:
94 saw.trigger(Frequency, StartLevel, InternalDepth, ExtControlDepth, FlipPhase, SampleRate);
95 saw.setPhase(Phase);
96 break;
97 case LFO::wave_square:
98 square.trigger(Frequency, StartLevel, InternalDepth, ExtControlDepth, FlipPhase, SampleRate);
99 square.setPhase(Phase);
100 break;
101 }
102 }
103
104 /**
105 * Update LFO depth with a new external controller value.
106 *
107 * @param ExtControlValue - new external controller value
108 */
109 void updateByMIDICtrlValue(const uint16_t& ExtControlValue) {
110 switch (wave) {
111 case LFO::wave_sine:
112 sine.updateByMIDICtrlValue(ExtControlValue);
113 break;
114 case LFO::wave_triangle:
115 triangle.updateByMIDICtrlValue(ExtControlValue);
116 break;
117 case LFO::wave_saw:
118 saw.updateByMIDICtrlValue(ExtControlValue);
119 break;
120 case LFO::wave_square:
121 square.updateByMIDICtrlValue(ExtControlValue);
122 break;
123 }
124 }
125
126 /**
127 * Should be invoked after the LFO is triggered.
128 * @param phase From 0 to 360 degrees.
129 */
130 void setPhase(float phase) {
131 switch (wave) {
132 case LFO::wave_sine:
133 sine.setPhase(phase);
134 break;
135 case LFO::wave_triangle:
136 triangle.setPhase(phase);
137 break;
138 case LFO::wave_saw:
139 saw.setPhase(phase);
140 break;
141 case LFO::wave_square:
142 square.setPhase(phase);
143 break;
144 }
145 }
146
147 void setFrequency(float Frequency, unsigned int SampleRate) {
148 switch (wave) {
149 case LFO::wave_sine:
150 sine.setFrequency(Frequency, SampleRate);
151 break;
152 case LFO::wave_triangle:
153 triangle.setFrequency(Frequency, SampleRate);
154 break;
155 case LFO::wave_saw:
156 saw.setFrequency(Frequency, SampleRate);
157 break;
158 case LFO::wave_square:
159 square.setFrequency(Frequency, SampleRate);
160 break;
161 }
162 }
163
164 void setScriptDepthFactor(float factor, bool isFinal) {
165 switch (wave) {
166 case LFO::wave_sine:
167 sine.setScriptDepthFactor(factor, isFinal);
168 break;
169 case LFO::wave_triangle:
170 triangle.setScriptDepthFactor(factor, isFinal);
171 break;
172 case LFO::wave_saw:
173 saw.setScriptDepthFactor(factor, isFinal);
174 break;
175 case LFO::wave_square:
176 square.setScriptDepthFactor(factor, isFinal);
177 break;
178 }
179 }
180
181 void setScriptFrequencyFactor(float factor, unsigned int samplerate) {
182 switch (wave) {
183 case LFO::wave_sine:
184 sine.setScriptFrequencyFactor(factor, samplerate);
185 break;
186 case LFO::wave_triangle:
187 triangle.setScriptFrequencyFactor(factor, samplerate);
188 break;
189 case LFO::wave_saw:
190 saw.setScriptFrequencyFactor(factor, samplerate);
191 break;
192 case LFO::wave_square:
193 square.setScriptFrequencyFactor(factor, samplerate);
194 break;
195 }
196 }
197
198 void setScriptFrequencyFinal(float hz, unsigned int samplerate) {
199 switch (wave) {
200 case LFO::wave_sine:
201 sine.setScriptFrequencyFinal(hz, samplerate);
202 break;
203 case LFO::wave_triangle:
204 triangle.setScriptFrequencyFinal(hz, samplerate);
205 break;
206 case LFO::wave_saw:
207 saw.setScriptFrequencyFinal(hz, samplerate);
208 break;
209 case LFO::wave_square:
210 square.setScriptFrequencyFinal(hz, samplerate);
211 break;
212 }
213 }
214
215 protected:
216 typedef LFOSineNumericComplexNr<RANGE> Sine;
217 typedef typename std::conditional<RANGE == LFO::range_signed, LFOTriangleSigned, LFOTriangleUnsigned>::type Triangle;
218 typedef LFOSawIntMathNew<RANGE> Saw;
219 typedef LFOSquareIntMath<RANGE> Square;
220
221 private:
222 LFO::wave_t wave;
223 union {
224 Sine sine;
225 Triangle triangle;
226 Saw saw;
227 Square square;
228 };
229 };
230
231 typedef LFOCluster<LFO::range_signed> LFOClusterSigned;
232 typedef LFOCluster<LFO::range_unsigned> LFOClusterUnsigned;
233
234 } // namespace LinuxSampler
235
236 #endif // LS_LFO_CLUSTER_H

  ViewVC Help
Powered by ViewVC