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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 39 by schoenebeck, Sun Mar 21 16:09:43 2004 UTC revision 40 by schoenebeck, Tue Mar 30 13:14:58 2004 UTC
# Line 24  Line 24 
24  #define __LFO_H__  #define __LFO_H__
25    
26  #include "global.h"  #include "global.h"
27    #include "rtmath.h"
28  #include "rtelmemorypool.h"  #include "rtelmemorypool.h"
29  #include "modulationsystem.h"  #include "modulationsystem.h"
30  #include "gig.h"  #include "gig.h"
# Line 31  Line 32 
32  /**  /**
33   * Low Frequency Oscillator   * Low Frequency Oscillator
34   *   *
35   * Synthesizes a triangular wave for modulating arbitrary synthesis   * Synthesizes a triangular wave for arbitrary usage. This LFO class is a
36   * parameters.   * generalization; it takes a class as template parameter (T_Manipulator)
37     * which is actually responsible to do something with the wave levels of the
38     * oscillator. The class given with T_Manipulator has to provide a
39     *
40     *      void ApplyLevel(float Level, int iSample);
41     *
42     * method. This method will be called by the LFO whenever the level of the
43     * oscillator wave changes, where parameter 'Level' is the new level of the
44     * wave and 'iSample' is the index of the corresponding sample point in the
45     * current audio fragment.
46   */   */
47    template<class T_Manipulator>
48  class LFO {  class LFO {
49      public:      public:
50          /**  
51           * Defines how the LFO applies it's values to the synthesis          // *************** types ***************
52           * parameter matrix.          // *
53           */  
         enum manipulation_type_t {  
             manipulation_type_add,      ///< Add LFO's values to the synthesis paramter matrix.  
             manipulation_type_multiply  ///< Multiply LFO's values with the ones from the synthesis parameter matrix.  
         };  
54          /**          /**
55           * Defines the position of the LFO wave within the given value range           * Defines the position of the LFO wave within the given value range
56           * and from which value to start when the LFO is triggered.           * and from which value to start when the LFO is triggered.
# Line 54  class LFO { Line 61  class LFO {
61              propagation_bottom_up        ///< Wave level starts from given min. and grows up with growing oscillator depth.              propagation_bottom_up        ///< Wave level starts from given min. and grows up with growing oscillator depth.
62          };          };
63    
         uint8_t ExtController; ///< MIDI control change controller number if the LFO is controlled by an external controller, 0 otherwise.  
64    
65          LFO(ModulationSystem::destination_t ModulationDestination, manipulation_type_t ManipulationType, float Min, float Max, propagation_t Propagation, RTELMemoryPool<ModulationSystem::Event>* pEventPool);          // *************** attributes ***************
66          void Process(uint Samples);          // *
67          void Trigger(float Frequency, uint16_t InternalDepth, uint16_t ExtControlDepth, uint16_t ExtControlValue, bool FlipPhase, uint Delay);  
68          void Reset();          T_Manipulator Manipulator;   ///< Instance of the specific manipulator class given by template parameter T_Manipulator.
69            uint8_t       ExtController; ///< MIDI control change controller number if the LFO is controlled by an external controller, 0 otherwise.
70    
71    
72            // *************** methods ***************
73            // *
74    
75            /**
76             * Constructor
77             *
78             * @param Min         - minimum value of the output level
79             * @param Max         - maximum value of the output level
80             * @param Propagation - defines from which level the wave starts and which direction it grows with growing oscillator depth
81             * @param pEventPool  - reference to an event pool which will be used to allocate Event objects
82             */
83            LFO(float Min, float Max, propagation_t Propagation, RTELMemoryPool<ModulationSystem::Event>* pEventPool) {
84                this->Propagation   = Propagation;
85                this->pEvents       = new RTEList<ModulationSystem::Event>(pEventPool);
86                this->ExtController = 0;
87                this->Min           = Min;
88                this->Max           = Max;
89                this->Range         = Max - Min;
90            }
91    
92            ~LFO() {
93                if (pEvents) delete pEvents;
94            }
95    
96            /**
97             * 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.
98             *
99             * @param Samples - total number of sample points to be rendered in
100             *                  this audio fragment cycle by the audio engine
101             */
102            void Process(uint Samples) {
103                ModulationSystem::Event* pCtrlEvent = pEvents->first();
104                int iSample = TriggerDelay;
105                while (iSample < Samples) {
106                    int process_break = Samples;
107                    if (pCtrlEvent && pCtrlEvent->FragmentPos() <= process_break) process_break = pCtrlEvent->FragmentPos();
108    
109                    if (Coeff > 0.0f) { // level going up
110                        while (iSample < process_break && Level <= CurrentMax) {
111                            Manipulator.ApplyLevel(Level, iSample);
112                            iSample++;
113                            Level += Coeff;
114                        }
115                        if (Level > CurrentMax) {
116                            Coeff = -Coeff; // invert direction
117                            Level += 2.0f * Coeff;
118                        }
119                    }
120                    else if (Coeff < 0.0f) { // level going down
121                        while (iSample < process_break && Level >= CurrentMin) {
122                            Manipulator.ApplyLevel(Level, iSample);
123                            iSample++;
124                            Level += Coeff;
125                        }
126                        if (Level < CurrentMin) {
127                            Coeff = -Coeff; // invert direction
128                            Level += 2.0f * Coeff;
129                        }
130                    }
131                    else { // no modulation at all (Coeff = 0.0)
132                        switch (Propagation) {
133                            case propagation_top_down:
134                                Level = Max;
135                                break;
136                            case propagation_middle_balanced:
137                                Level = Min + 0.5f * Range;
138                                break;
139                            case propagation_bottom_up:
140                                Level = Min;
141                                break;
142                        }
143                        while (iSample < process_break) {
144                            Manipulator.ApplyLevel(Level, iSample);
145                            iSample++;
146                        }
147                    }
148    
149                    if (pCtrlEvent) {
150                        RecalculateCoeff(pCtrlEvent->Value);
151                        pCtrlEvent = pEvents->next();
152                    }
153                }
154                TriggerDelay = 0;
155                pEvents->clear();
156            }
157    
158            /**
159             * Will be called by the voice when the key / voice was triggered.
160             *
161             * @param Frequency       - frequency of the oscillator in Hz
162             * @param InternalDepth   - firm, internal oscillator amplitude
163             * @param ExtControlDepth - defines how strong the external MIDI
164             *                          controller has influence on the
165             *                          oscillator amplitude
166             * @param ExtControlValue - current MIDI value of the external
167             *                          controller for the time when the voice
168             *                          was triggered
169             * @param FlipPhase       - inverts the oscillator wave
170             * @param Delay           - number of sample points triggering should
171             *                          be delayed
172             */
173            void Trigger(float Frequency, uint16_t InternalDepth, uint16_t ExtControlDepth, uint16_t ExtControlValue, bool FlipPhase, uint Delay) {
174                this->Coeff                = 0.0f;
175                this->InternalDepth        = (InternalDepth / 1200.0f) * Range;
176                this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * Range;
177                this->TriggerDelay         = Delay;
178                this->FrequencyCoeff       = (2.0f * Frequency) / (float) ModulationSystem::SampleRate();
179    
180                if (ExtController) RecalculateCoeff(ExtControlValue);
181                else               RecalculateCoeff(0);
182    
183                switch (Propagation) {
184                    case propagation_top_down: {
185                        if (FlipPhase) {
186                            Level = CurrentMin;
187                        }
188                        else { // normal case
189                            Level = Max;
190                            Coeff = -Coeff; // level starts at max. thus has to go down now
191                        }
192                        break;
193                    }
194                    case propagation_middle_balanced: {
195                        Level = Min + 0.5f * Range;
196                        if (FlipPhase) Coeff = -Coeff; // invert direction (going down)
197                        break;
198                    }
199                    case propagation_bottom_up: {
200                        if (FlipPhase) {
201                            Level = CurrentMax;
202                            Coeff = -Coeff; // level starts at max. thus has to go down now
203                        }
204                        else { // normal case
205                            Level = Min;
206                        }
207                        break;
208                    }
209                }
210            }
211    
212          /**          /**
213           * Will be called by the voice to inform the LFO about a change of           * Will be called by the voice to inform the LFO about a change of
214           * the external controller's value.           * the external controller's value.
# Line 69  class LFO { Line 218  class LFO {
218          inline void SendEvent(ModulationSystem::Event* pEvent) {          inline void SendEvent(ModulationSystem::Event* pEvent) {
219              if (ExtController && pEvent->FragmentPos() >= this->TriggerDelay) pEvents->alloc_assign(*pEvent);              if (ExtController && pEvent->FragmentPos() >= this->TriggerDelay) pEvents->alloc_assign(*pEvent);
220          }          }
221          ~LFO();  
222            /**
223             * Should always be called when the voice was killed.
224             */
225            void Reset() {
226                pEvents->clear();
227            }
228    
229      protected:      protected:
230          RTEList<ModulationSystem::Event>* pEvents;          RTEList<ModulationSystem::Event>* pEvents;
         ModulationSystem::destination_t   ModulationDestination;  
         manipulation_type_t               ManipulationType;  
231          propagation_t                     Propagation;          propagation_t                     Propagation;
232          int                               TriggerDelay;          int                               TriggerDelay;
233          float                             Min;          float                             Min;
# Line 113  class LFO { Line 267  class LFO {
267          }          }
268  };  };
269    
270    /** Amplification Manipulator
271     *
272     * Specialized manipulator for writing volume parameters to the synthesis
273     * parameter matrix.
274     */
275    class VCAManipulator {
276         public:
277            inline void ApplyLevel(float& Level, int& iSample) {
278                ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample] *= Level;
279            }
280    };
281    
282    /** Filter Cutoff Frequency Manipulator
283     *
284     * Specialized manipulator for writing filter cutoff frequency parameters to
285     * the synthesis parameter matrix.
286     */
287    class VCFCManipulator {
288         public:
289            inline void ApplyLevel(float& Level, int& iSample) {
290                ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][iSample] *= Level;
291            }
292    };
293    
294    /** Pitch Manipulator
295     *
296     * Specialized manipulator for writing pitch parameters to the synthesis
297     * parameter matrix.
298     */
299    class VCOManipulator {
300         public:
301            inline void ApplyLevel(float& Level, int& iSample) {
302                ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][iSample] *= RTMath::CentsToFreqRatio(Level);
303            }
304    };
305    
306  #endif // __LFO_H__  #endif // __LFO_H__

Legend:
Removed from v.39  
changed lines
  Added in v.40

  ViewVC Help
Powered by ViewVC