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

Annotation of /linuxsampler/trunk/src/engines/common/LFO.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 53 - (hide annotations) (download) (as text)
Mon Apr 26 17:15:51 2004 UTC (19 years, 11 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 12872 byte(s)
* completely restructured source tree
* implemented multi channel support
* implemented instrument manager, which controls sharing of instruments
  between multiple sampler engines / sampler channels
* created abstract classes 'AudioOutputDevice' and 'MidiInputDevice' for
  convenient implementation of further audio output driver and MIDI input
  driver for LinuxSampler
* implemented following LSCP commands: 'SET CHANNEL MIDI INPUT TYPE',
  'LOAD ENGINE', 'GET CHANNELS', 'ADD CHANNEL', 'REMOVE CHANNEL',
  'SET CHANNEL AUDIO OUTPUT TYPE'
* temporarily removed all command line options
* LSCP server is now launched by default

1 schoenebeck 53 /***************************************************************************
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 __LS_LFO_H__
24     #define __LS_LFO_H__
25    
26     #include "../../common/global.h"
27    
28     #if DEBUG_HEADERS
29     # warning LFO.h included
30     #endif // DEBUG_HEADERS
31    
32     #include "../../common/RTMath.h"
33     #include "Event.h"
34    
35     namespace LinuxSampler {
36    
37     /**
38     * Low Frequency Oscillator
39     *
40     * Synthesizes a triangular wave for arbitrary usage. This LFO class is a
41     * generalization; it takes a class as template parameter (T_Manipulator)
42     * which is actually responsible to do something with the wave levels of the
43     * oscillator. The class given with T_Manipulator has to provide a
44     *
45     * void ApplyLevel(float Level, int iSample);
46     *
47     * method. This method will be called by the LFO whenever the level of the
48     * oscillator wave changes, where parameter 'Level' is the new level of the
49     * wave and 'iSample' is the index of the corresponding sample point in the
50     * current audio fragment.
51     */
52     template<class T_Manipulator>
53     class LFO {
54     public:
55    
56     // *************** types ***************
57     // *
58    
59     /**
60     * Defines the position of the LFO wave within the given value range
61     * and from which value to start when the LFO is triggered.
62     */
63     enum propagation_t {
64     propagation_top_down, ///< Wave level starts from given max. and grows down with growing oscillator depth.
65     propagation_middle_balanced, ///< Wave level starts from the middle of the given value range and grows in both directions with growing oscillator depth.
66     propagation_bottom_up ///< Wave level starts from given min. and grows up with growing oscillator depth.
67     };
68    
69    
70     // *************** attributes ***************
71     // *
72    
73     T_Manipulator* pManipulator; ///< Instance of the specific manipulator class given by template parameter T_Manipulator.
74     uint8_t ExtController; ///< MIDI control change controller number if the LFO is controlled by an external controller, 0 otherwise.
75    
76    
77     // *************** methods ***************
78     // *
79    
80     /**
81     * Constructor
82     *
83     * @param Min - minimum value of the output level
84     * @param Max - maximum value of the output level
85     * @param Propagation - defines from which level the wave starts and which direction it grows with growing oscillator depth
86     * @param pEventPool - reference to an event pool which will be used to allocate Event objects
87     */
88     LFO(float Min, float Max, propagation_t Propagation, T_Manipulator* pManipulator, RTELMemoryPool<Event>* pEventPool) {
89     this->Propagation = Propagation;
90     this->pEvents = new RTEList<Event>(pEventPool);
91     this->ExtController = 0;
92     this->Min = Min;
93     this->Max = Max;
94     this->Range = Max - Min;
95     this->pManipulator = pManipulator;
96     }
97    
98     ~LFO() {
99     if (pEvents) delete pEvents;
100     }
101    
102     /**
103     * 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.
104     *
105     * @param Samples - total number of sample points to be rendered in
106     * this audio fragment cycle by the audio engine
107     */
108     void Process(uint Samples) {
109     Event* pCtrlEvent = pEvents->first();
110     int iSample = TriggerDelay;
111     while (iSample < Samples) {
112     int process_break = Samples;
113     if (pCtrlEvent && pCtrlEvent->FragmentPos() <= process_break) process_break = pCtrlEvent->FragmentPos();
114    
115     if (Coeff > 0.0f) { // level going up
116     while (iSample < process_break && Level <= CurrentMax) {
117     pManipulator->ApplyLevel(Level, iSample);
118     iSample++;
119     Level += Coeff;
120     }
121     if (Level > CurrentMax) {
122     Coeff = -Coeff; // invert direction
123     Level += 2.0f * Coeff;
124     }
125     }
126     else if (Coeff < 0.0f) { // level going down
127     while (iSample < process_break && Level >= CurrentMin) {
128     pManipulator->ApplyLevel(Level, iSample);
129     iSample++;
130     Level += Coeff;
131     }
132     if (Level < CurrentMin) {
133     Coeff = -Coeff; // invert direction
134     Level += 2.0f * Coeff;
135     }
136     }
137     else { // no modulation at all (Coeff = 0.0)
138     switch (Propagation) {
139     case propagation_top_down:
140     Level = Max;
141     break;
142     case propagation_middle_balanced:
143     Level = Min + 0.5f * Range;
144     break;
145     case propagation_bottom_up:
146     Level = Min;
147     break;
148     }
149     while (iSample < process_break) {
150     pManipulator->ApplyLevel(Level, iSample);
151     iSample++;
152     }
153     }
154    
155     if (pCtrlEvent) {
156     RecalculateCoeff(pCtrlEvent->Value);
157     pCtrlEvent = pEvents->next();
158     }
159     }
160     TriggerDelay = 0;
161     pEvents->clear();
162     }
163    
164     /**
165     * Will be called by the voice when the key / voice was triggered.
166     *
167     * @param Frequency - frequency of the oscillator in Hz
168     * @param InternalDepth - firm, internal oscillator amplitude
169     * @param ExtControlDepth - defines how strong the external MIDI
170     * controller has influence on the
171     * oscillator amplitude
172     * @param ExtControlValue - current MIDI value of the external
173     * controller for the time when the
174     * voice was triggered
175     * @param FlipPhase - inverts the oscillator wave
176     * @param SampleRate - current sample rate of the engines
177     * audio output signal
178     * @param Delay - number of sample points triggering
179     * should be delayed
180     */
181     void Trigger(float Frequency, uint16_t InternalDepth, uint16_t ExtControlDepth, uint16_t ExtControlValue, bool FlipPhase, uint SampleRate, uint Delay) {
182     this->Coeff = 0.0f;
183     this->InternalDepth = (InternalDepth / 1200.0f) * Range;
184     this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * Range;
185     this->TriggerDelay = Delay;
186     this->FrequencyCoeff = (2.0f * Frequency) / (float) SampleRate;
187    
188     if (ExtController) RecalculateCoeff(ExtControlValue);
189     else RecalculateCoeff(0);
190    
191     switch (Propagation) {
192     case propagation_top_down: {
193     if (FlipPhase) {
194     Level = CurrentMin;
195     }
196     else { // normal case
197     Level = Max;
198     Coeff = -Coeff; // level starts at max. thus has to go down now
199     }
200     break;
201     }
202     case propagation_middle_balanced: {
203     Level = Min + 0.5f * Range;
204     if (FlipPhase) Coeff = -Coeff; // invert direction (going down)
205     break;
206     }
207     case propagation_bottom_up: {
208     if (FlipPhase) {
209     Level = CurrentMax;
210     Coeff = -Coeff; // level starts at max. thus has to go down now
211     }
212     else { // normal case
213     Level = Min;
214     }
215     break;
216     }
217     }
218     }
219    
220     /**
221     * Will be called by the voice to inform the LFO about a change of
222     * the external controller's value.
223     *
224     * @param pEvent - control change event of external controller
225     */
226     inline void SendEvent(Event* pEvent) {
227     if (ExtController && pEvent->FragmentPos() >= this->TriggerDelay) pEvents->alloc_assign(*pEvent);
228     }
229    
230     /**
231     * Should always be called when the voice was killed.
232     */
233     void Reset() {
234     pEvents->clear();
235     }
236    
237     protected:
238     RTEList<Event>* pEvents;
239     propagation_t Propagation;
240     int TriggerDelay;
241     float Min;
242     float Max;
243     float CurrentMin;
244     float CurrentMax;
245     float FrequencyCoeff;
246     float ExtControlDepthCoeff;
247     float InternalDepth;
248     float Range;
249     float Coeff;
250     float Level;
251    
252     inline void RecalculateCoeff(uint16_t ExtControlValue) {
253     float currentrange = InternalDepth + ExtControlValue * ExtControlDepthCoeff;
254     if (currentrange > Range) currentrange = Range;
255     Coeff = (Coeff < 0) ? -(currentrange * FrequencyCoeff)
256     : currentrange * FrequencyCoeff;
257     switch (Propagation) {
258     case propagation_top_down: {
259     CurrentMax = Max;
260     CurrentMin = Max - currentrange;
261     break;
262     }
263     case propagation_middle_balanced: {
264     float rangediff = (Range - currentrange) * 0.5f;
265     CurrentMax = Max - rangediff;
266     CurrentMin = Min + rangediff;
267     break;
268     }
269     case propagation_bottom_up: {
270     CurrentMax = Max - currentrange;
271     CurrentMin = Min;
272     break;
273     }
274     }
275     }
276     };
277    
278     } // namespace LinuxSampler
279    
280     #endif // __LS_LFO_H__

  ViewVC Help
Powered by ViewVC