/[svn]/linuxsampler/trunk/src/lfo.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/lfo.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (show annotations) (download) (as text)
Wed Mar 31 10:28:42 2004 UTC (20 years ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 13030 byte(s)
removed unnecessary dependencies

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #ifndef __LFO_H__
24 #define __LFO_H__
25
26 #include "global.h"
27 #include "rtmath.h"
28 #include "modulationsystem.h"
29
30 /**
31 * Low Frequency Oscillator
32 *
33 * Synthesizes a triangular wave for arbitrary usage. This LFO class is a
34 * generalization; it takes a class as template parameter (T_Manipulator)
35 * which is actually responsible to do something with the wave levels of the
36 * oscillator. The class given with T_Manipulator has to provide a
37 *
38 * void ApplyLevel(float Level, int iSample);
39 *
40 * method. This method will be called by the LFO whenever the level of the
41 * oscillator wave changes, where parameter 'Level' is the new level of the
42 * wave and 'iSample' is the index of the corresponding sample point in the
43 * current audio fragment.
44 */
45 template<class T_Manipulator>
46 class LFO {
47 public:
48
49 // *************** types ***************
50 // *
51
52 /**
53 * Defines the position of the LFO wave within the given value range
54 * and from which value to start when the LFO is triggered.
55 */
56 enum propagation_t {
57 propagation_top_down, ///< Wave level starts from given max. and grows down with growing oscillator depth.
58 propagation_middle_balanced, ///< Wave level starts from the middle of the given value range and grows in both directions with growing oscillator depth.
59 propagation_bottom_up ///< Wave level starts from given min. and grows up with growing oscillator depth.
60 };
61
62
63 // *************** attributes ***************
64 // *
65
66 T_Manipulator Manipulator; ///< Instance of the specific manipulator class given by template parameter T_Manipulator.
67 uint8_t ExtController; ///< MIDI control change controller number if the LFO is controlled by an external controller, 0 otherwise.
68
69
70 // *************** methods ***************
71 // *
72
73 /**
74 * Constructor
75 *
76 * @param Min - minimum value of the output level
77 * @param Max - maximum value of the output level
78 * @param Propagation - defines from which level the wave starts and which direction it grows with growing oscillator depth
79 * @param pEventPool - reference to an event pool which will be used to allocate Event objects
80 */
81 LFO(float Min, float Max, propagation_t Propagation, RTELMemoryPool<ModulationSystem::Event>* pEventPool) {
82 this->Propagation = Propagation;
83 this->pEvents = new RTEList<ModulationSystem::Event>(pEventPool);
84 this->ExtController = 0;
85 this->Min = Min;
86 this->Max = Max;
87 this->Range = Max - Min;
88 }
89
90 ~LFO() {
91 if (pEvents) delete pEvents;
92 }
93
94 /**
95 * Will be called by the voice for every audio fragment to let the LFO write it's modulation changes to the synthesis parameter matrix for the current audio fragment.
96 *
97 * @param Samples - total number of sample points to be rendered in
98 * this audio fragment cycle by the audio engine
99 */
100 void Process(uint Samples) {
101 ModulationSystem::Event* pCtrlEvent = pEvents->first();
102 int iSample = TriggerDelay;
103 while (iSample < Samples) {
104 int process_break = Samples;
105 if (pCtrlEvent && pCtrlEvent->FragmentPos() <= process_break) process_break = pCtrlEvent->FragmentPos();
106
107 if (Coeff > 0.0f) { // level going up
108 while (iSample < process_break && Level <= CurrentMax) {
109 Manipulator.ApplyLevel(Level, iSample);
110 iSample++;
111 Level += Coeff;
112 }
113 if (Level > CurrentMax) {
114 Coeff = -Coeff; // invert direction
115 Level += 2.0f * Coeff;
116 }
117 }
118 else if (Coeff < 0.0f) { // level going down
119 while (iSample < process_break && Level >= CurrentMin) {
120 Manipulator.ApplyLevel(Level, iSample);
121 iSample++;
122 Level += Coeff;
123 }
124 if (Level < CurrentMin) {
125 Coeff = -Coeff; // invert direction
126 Level += 2.0f * Coeff;
127 }
128 }
129 else { // no modulation at all (Coeff = 0.0)
130 switch (Propagation) {
131 case propagation_top_down:
132 Level = Max;
133 break;
134 case propagation_middle_balanced:
135 Level = Min + 0.5f * Range;
136 break;
137 case propagation_bottom_up:
138 Level = Min;
139 break;
140 }
141 while (iSample < process_break) {
142 Manipulator.ApplyLevel(Level, iSample);
143 iSample++;
144 }
145 }
146
147 if (pCtrlEvent) {
148 RecalculateCoeff(pCtrlEvent->Value);
149 pCtrlEvent = pEvents->next();
150 }
151 }
152 TriggerDelay = 0;
153 pEvents->clear();
154 }
155
156 /**
157 * Will be called by the voice when the key / voice was triggered.
158 *
159 * @param Frequency - frequency of the oscillator in Hz
160 * @param InternalDepth - firm, internal oscillator amplitude
161 * @param ExtControlDepth - defines how strong the external MIDI
162 * controller has influence on the
163 * oscillator amplitude
164 * @param ExtControlValue - current MIDI value of the external
165 * controller for the time when the voice
166 * was triggered
167 * @param FlipPhase - inverts the oscillator wave
168 * @param Delay - number of sample points triggering should
169 * be delayed
170 */
171 void Trigger(float Frequency, uint16_t InternalDepth, uint16_t ExtControlDepth, uint16_t ExtControlValue, bool FlipPhase, uint Delay) {
172 this->Coeff = 0.0f;
173 this->InternalDepth = (InternalDepth / 1200.0f) * Range;
174 this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * Range;
175 this->TriggerDelay = Delay;
176 this->FrequencyCoeff = (2.0f * Frequency) / (float) ModulationSystem::SampleRate();
177
178 if (ExtController) RecalculateCoeff(ExtControlValue);
179 else RecalculateCoeff(0);
180
181 switch (Propagation) {
182 case propagation_top_down: {
183 if (FlipPhase) {
184 Level = CurrentMin;
185 }
186 else { // normal case
187 Level = Max;
188 Coeff = -Coeff; // level starts at max. thus has to go down now
189 }
190 break;
191 }
192 case propagation_middle_balanced: {
193 Level = Min + 0.5f * Range;
194 if (FlipPhase) Coeff = -Coeff; // invert direction (going down)
195 break;
196 }
197 case propagation_bottom_up: {
198 if (FlipPhase) {
199 Level = CurrentMax;
200 Coeff = -Coeff; // level starts at max. thus has to go down now
201 }
202 else { // normal case
203 Level = Min;
204 }
205 break;
206 }
207 }
208 }
209
210 /**
211 * Will be called by the voice to inform the LFO about a change of
212 * the external controller's value.
213 *
214 * @param pEvent - control change event of external controller
215 */
216 inline void SendEvent(ModulationSystem::Event* pEvent) {
217 if (ExtController && pEvent->FragmentPos() >= this->TriggerDelay) pEvents->alloc_assign(*pEvent);
218 }
219
220 /**
221 * Should always be called when the voice was killed.
222 */
223 void Reset() {
224 pEvents->clear();
225 }
226
227 protected:
228 RTEList<ModulationSystem::Event>* pEvents;
229 propagation_t Propagation;
230 int TriggerDelay;
231 float Min;
232 float Max;
233 float CurrentMin;
234 float CurrentMax;
235 float FrequencyCoeff;
236 float ExtControlDepthCoeff;
237 float InternalDepth;
238 float Range;
239 float Coeff;
240 float Level;
241
242 inline void RecalculateCoeff(uint16_t ExtControlValue) {
243 float currentrange = InternalDepth + ExtControlValue * ExtControlDepthCoeff;
244 if (currentrange > Range) currentrange = Range;
245 Coeff = (Coeff < 0) ? -(currentrange * FrequencyCoeff)
246 : currentrange * FrequencyCoeff;
247 switch (Propagation) {
248 case propagation_top_down: {
249 CurrentMax = Max;
250 CurrentMin = Max - currentrange;
251 break;
252 }
253 case propagation_middle_balanced: {
254 float rangediff = (Range - currentrange) * 0.5f;
255 CurrentMax = Max - rangediff;
256 CurrentMin = Min + rangediff;
257 break;
258 }
259 case propagation_bottom_up: {
260 CurrentMax = Max - currentrange;
261 CurrentMin = Min;
262 break;
263 }
264 }
265 }
266 };
267
268 /** Amplification Manipulator
269 *
270 * Specialized manipulator for writing volume parameters to the synthesis
271 * parameter matrix.
272 */
273 class VCAManipulator {
274 public:
275 inline void ApplyLevel(float& Level, int& iSample) {
276 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample] *= Level;
277 }
278 };
279
280 /** Filter Cutoff Frequency Manipulator
281 *
282 * Specialized manipulator for writing filter cutoff frequency parameters to
283 * the synthesis parameter matrix.
284 */
285 class VCFCManipulator {
286 public:
287 inline void ApplyLevel(float& Level, int& iSample) {
288 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][iSample] *= Level;
289 }
290 };
291
292 /** Pitch Manipulator
293 *
294 * Specialized manipulator for writing pitch parameters to the synthesis
295 * parameter matrix.
296 */
297 class VCOManipulator {
298 public:
299 inline void ApplyLevel(float& Level, int& iSample) {
300 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][iSample] *= RTMath::CentsToFreqRatio(Level);
301 }
302 };
303
304 #endif // __LFO_H__

  ViewVC Help
Powered by ViewVC