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

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

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 19  Line 19 
19   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
20   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
21   ***************************************************************************/   ***************************************************************************/
   
 #include "lfo.h"  
   
 LFO::LFO(ModulationSystem::destination_t ModulationDestination, manipulation_type_t ManipulationType, float Min, float Max, propagation_t Propagation, RTELMemoryPool<ModulationSystem::Event>* pEventPool) {  
     this->ModulationDestination = ModulationDestination;  
     this->ManipulationType      = ManipulationType;  
     this->Propagation           = Propagation;  
     this->pEvents               = new RTEList<ModulationSystem::Event>(pEventPool);  
     this->ExtController         = 0;  
     this->Min                   = Min;  
     this->Max                   = Max;  
     this->Range                 = Max - Min;  
 }  
   
 LFO::~LFO() {  
     if (pEvents) delete pEvents;  
 }  
   
 /**  
  * 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.  
  *  
  * @param Samples - total number of sample points to be rendered in this  
  *                  audio fragment cycle by the audio engine  
  */  
 void LFO::Process(uint Samples) {  
     ModulationSystem::Event* pCtrlEvent = pEvents->first();  
   
     int iSample = TriggerDelay;  
     switch (ManipulationType) {  
         case manipulation_type_add: {  
             while (iSample < Samples) {  
                 int process_break = Samples;  
                 if (pCtrlEvent && pCtrlEvent->FragmentPos() <= process_break) process_break = pCtrlEvent->FragmentPos();  
   
                 if (Coeff > 0.0f) { // level going up  
                     while (iSample < process_break && Level <= CurrentMax) {  
                         ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] += Level;  
                         Level += Coeff;  
                     }  
                     if (Level > CurrentMax) {  
                         Coeff = -Coeff; // invert direction  
                         Level += 2.0f * Coeff;  
                     }  
                 }  
                 else if (Coeff < 0.0f) { // level going down  
                     while (iSample < process_break && Level >= CurrentMin) {  
                         ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] += Level;  
                         Level += Coeff;  
                     }  
                     if (Level < CurrentMin) {  
                         Coeff = -Coeff; // invert direction  
                         Level += 2.0f * Coeff;  
                     }  
                 }  
                 else { // no modulation at all (Coeff = 0.0)  
                     switch (Propagation) {  
                         case propagation_top_down:  
                             Level = Max;  
                             break;  
                         case propagation_middle_balanced:  
                             Level = Min + 0.5f * Range;  
                             break;  
                         case propagation_bottom_up:  
                             Level = Min;  
                             break;  
                     }  
                     while (iSample < process_break) {  
                         ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] += Level;  
                     }  
                 }  
   
                 if (pCtrlEvent) {  
                     RecalculateCoeff(pCtrlEvent->Value);  
                     pCtrlEvent = pEvents->next();  
                 }  
             }  
             break;  
         }  
         case manipulation_type_multiply: {  
             while (iSample < Samples) {  
                 int process_break = Samples;  
                 if (pCtrlEvent && pCtrlEvent->FragmentPos() <= process_break) process_break = pCtrlEvent->FragmentPos();  
   
                 if (Coeff > 0.0f) { // level going up  
                     while (iSample < process_break && Level <= CurrentMax) {  
                         ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] *= Level;  
                         Level += Coeff;  
                     }  
                     if (Level > CurrentMax) {  
                         Coeff = -Coeff; // invert direction  
                         Level += 2.0f * Coeff;  
                     }  
                 }  
                 else if (Coeff < 0.0f) { // level going down  
                     while (iSample < process_break && Level >= CurrentMin) {  
                         ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] *= Level;  
                         Level += Coeff;  
                     }  
                     if (Level < CurrentMin) {  
                         Coeff = -Coeff; // invert direction  
                         Level += 2.0f * Coeff;  
                     }  
                 }  
                 else { // no modulation at all (Coeff = 0.0)  
                     switch (Propagation) {  
                         case propagation_top_down:  
                             Level = Max;  
                             break;  
                         case propagation_middle_balanced:  
                             Level = Min + 0.5f * Range;  
                             break;  
                         case propagation_bottom_up:  
                             Level = Min;  
                             break;  
                     }  
                     while (iSample < process_break) {  
                         ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] *= Level;  
                     }  
                 }  
   
                 if (pCtrlEvent) {  
                     RecalculateCoeff(pCtrlEvent->Value);  
                     pCtrlEvent = pEvents->next();  
                 }  
             }  
             break;  
         }  
     }  
     TriggerDelay = 0;  
     pEvents->clear();  
 }  
   
 /**  
  * Will be called by the voice when the key / voice was triggered.  
  *  
  * @param Frequency       - frequency of the oscillator in Hz  
  * @param InternalDepth   - firm, internal oscillator amplitude  
  * @param ExtControlDepth - defines how strong the external MIDI controller  
  *                          has influence on the oscillator amplitude  
  * @param ExtControlValue - current MIDI value of the external controller  
  *                          for the time when the voice was triggered  
  * @param FlipPhase       - inverts the oscillator wave  
  * @param Delay           - number of sample points triggering should be  
  *                          delayed  
  */  
 void LFO::Trigger(float Frequency, uint16_t InternalDepth, uint16_t ExtControlDepth, uint16_t ExtControlValue, bool FlipPhase, uint Delay) {  
     this->Coeff                = 0.0f;  
     this->InternalDepth        = (InternalDepth / 1200.0f) * Range;  
     this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * Range;  
     this->TriggerDelay         = Delay;  
     this->FrequencyCoeff       = (2.0f * Frequency) / (float) ModulationSystem::SampleRate();  
   
     if (ExtController) RecalculateCoeff(ExtControlValue);  
     else               RecalculateCoeff(0);  
   
     switch (Propagation) {  
         case propagation_top_down: {  
             if (FlipPhase) {  
                 Level = CurrentMin;  
             }  
             else { // normal case  
                 Level = Max;  
                 Coeff = -Coeff; // level starts at max. thus has to go down now  
             }  
             break;  
         }  
         case propagation_middle_balanced: {  
             Level = Min + 0.5f * Range;  
             if (FlipPhase) Coeff = -Coeff; // invert direction (going down)  
             break;  
         }  
         case propagation_bottom_up: {  
             if (FlipPhase) {  
                 Level = CurrentMax;  
                 Coeff = -Coeff; // level starts at max. thus has to go down now  
             }  
             else { // normal case  
                 Level = Min;  
             }  
             break;  
         }  
     }  
 }  
   
 /**  
  * Should always be called when the voice was killed.  
  */  
 void LFO::Reset() {  
     pEvents->clear();  
 }  

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

  ViewVC Help
Powered by ViewVC