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

Diff of /linuxsampler/trunk/src/engines/common/SignalUnit.h

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

revision 2205 by iliev, Mon Jul 11 17:52:01 2011 UTC revision 2217 by iliev, Tue Jul 26 15:51:30 2011 UTC
# Line 28  Line 28 
28    
29  namespace LinuxSampler {  namespace LinuxSampler {
30    
31        class SignalUnitRack;
32    
33      /**      /**
34       * A signal unit consist of internal signal generator (like envelope generator,       * A signal unit consist of internal signal generator (like envelope generator,
35       * low frequency oscillator, etc) with a number of generator parameters which       * low frequency oscillator, etc) with a number of generator parameters which
36       * influence/modulate/dynamically change the generator's signal in some manner.       * influence/modulate/dynamically change the generator's signal in some manner.
37       * The generators' parameters (also called signal unit parameters) can receive       * Each generator parameter (also called signal unit parameter) can receive
38       * the signal of one or more signal units (through modulators if need)       * signal from another signal unit and use this signal to dynamically change the
39       * and use the (modulated) signals of those units to dynamically change the       * behavior of the signal generator. In turn, the signal of this unit can be fed
      * behavior of the signal generator. In turn, the signal of those unit can be fed  
40       * to another unit(s) and influence its parameters.       * to another unit(s) and influence its parameters.
41       */       */
42      class SignalUnit {      class SignalUnit {
43          public:          public:
44    
45          /**          /**
          * Used as an intermediate link between a source signal unit and  
          * a destination unit parameter. Modulates the received signal from the  
          * source unit and feed it to the unit parameter to which it is connected.  
          */  
         class Modulator {  
             public:  
                 SignalUnit* pUnit; /* The signal source which will be used for modulation.  
                                     * If pUnit is NULL the level is considered to be 1!  
                                     */  
                 float Coeff; // The modulation coefficient  
                   
                 Modulator() : pUnit(NULL) { }  
                 Modulator(SignalUnit* Unit) { pUnit = Unit; }  
                 Modulator(const Modulator& Mod) { Copy(Mod); }  
                 void operator=(const Modulator& Mod) { Copy(Mod); }  
               
                 virtual void Copy(const Modulator& Mod) {  
                     if (this == &Mod) return;  
   
                     pUnit = Mod.pUnit;  
                     Coeff = Mod.Coeff;  
                 }  
                   
                 /**  
                  * Gets the normalized level of the signal source for the current  
                  * time step (sample point). Returns 1 if source unit is NULL or  
                  * if the source unit is inactive.  
                  */  
                 virtual float GetLevel() {  
                     if (pUnit == NULL) return 1.0f;  
                     return pUnit->Active() ? pUnit->GetLevel() : 1.0f;  
                 }  
                   
                 /**  
                  * Gets the modulated level of the source signal  
                  * for the current time step (sample point).  
                  */  
                 virtual float GetValue() {  
                     return Transform(GetLevel());  
                 }  
                   
                 /**  
                  * Calculates the transformation that should be applied  
                  * to the signal of the source unit and multiplies by Coeff.  
                  * This implementation of the method just multiplies by Coeff,  
                  * or returns 1 if the source unit is inactive.  
                  */  
                 virtual float Transform(float val) {  
                     if (pUnit != NULL && !pUnit->Active()) return 1;  
                     return val * Coeff;  
                 }  
         };  
           
         /**  
46           * This class represents a parameter which will influence the signal           * This class represents a parameter which will influence the signal
47           * unit to which it belongs in certain way.           * unit to which it belongs in certain way.
48           * For example, let's say the signal unit is a low frequency oscillator           * For example, let's say the signal unit is a low frequency oscillator
49           * with frequency 1Hz. If we want to modulate the LFO to start with 1Hz           * with frequency 1Hz. If we want to modulate the LFO to start with 1Hz
50           * and increment its frequency to 5Hz in 1 second, we can add           * and increment its frequency to 5Hz in 1 second, we can add
51           * a parameter with one modulator which signal source is an envelope           * a parameter which signal source is an envelope
52           * generator with attack time of 1 second and coefficient 4. Thus, the           * generator with attack time of 1 second and coefficient 4. Thus, the
53           * normalized level of the EG will move from 0 to 1 in one second.           * normalized level of the EG will move from 0 to 1 in one second.
54           * On every time step (sample point) the normalized level           * On every time step (sample point) the normalized level
# Line 113  namespace LinuxSampler { Line 60  namespace LinuxSampler {
60           */           */
61          class Parameter {          class Parameter {
62              public:              public:
63                  ArrayList<Modulator> Modulators; // A list of signal units which will modulate this parameter                  SignalUnit* pUnit; /* The source unit whose output signal
64                                                        * will modulate the parameter.
                 SignalUnit* pUnit; /* If pUnit is not NULL, the modulators are ignored and  
                                     * this unit is used as only source.  
                                     * This is done for efficiency reasons.  
65                                      */                                      */
66                                    
67                  float Coeff; // The global modulation coefficient                  float Coeff; // The modulation coefficient
68                                    
69                                    
70                  Parameter() : Coeff(1), pUnit(NULL) { }                  Parameter() : Coeff(1), pUnit(NULL) { }
71    
72                  /**                  /**
                  * Most often we just need to directly feed the signal of single unit  
                  * to a unit parameter without any additional modulation.  
                  * This constructor creates a parameter with only a single source  
                  * unit without additional modulation, optimized for efficiency.  
73                   * @param unit The source unit used to influence this parameter.                   * @param unit The source unit used to influence this parameter.
74                   * @param coeff The coefficient by which the normalized signal                   * @param coeff The coefficient by which the normalized signal
75                   * received from the source unit should be multiplied when a                   * received from the source unit should be multiplied when a
# Line 146  namespace LinuxSampler { Line 86  namespace LinuxSampler {
86                  virtual void Copy(const Parameter& Prm) {                  virtual void Copy(const Parameter& Prm) {
87                      if (this == &Prm) return;                      if (this == &Prm) return;
88    
                     Modulators = Prm.Modulators;  
89                      pUnit = Prm.pUnit;                      pUnit = Prm.pUnit;
90                      Coeff = Prm.Coeff;                      Coeff = Prm.Coeff;
91                  }                  }
92                                    
93                                    
94                  /**                  /**
95                   * Calculates the global transformation for this parameter                   * Calculates the transformation for this parameter
96                   * which should be applied to the parameter's value                   * which should be applied to the parameter's value
97                   * and multiplies by Coeff.                   * and multiplies by Coeff.
98                   * This implementation of the method just multiplies by Coeff.                   * This implementation of the method just multiplies by Coeff.
# Line 163  namespace LinuxSampler { Line 102  namespace LinuxSampler {
102                  }                  }
103                                    
104                  /**                  /**
105                   * Gets the current value of the parameter (without transformation).                   * Gets the current value of the parameter.
106                   * This implementation just sum the modulators values.                   * This implementation returns the current signal level of the
107                   * If only a single unit is used without additional modulation                   * source unit with applied transformation if the source unit is
108                   * returns the source unit's level or 1 if the unit is not active.                   * active, otherwise returns 1.
109                     * Note that this method assume that pUnit is not NULL.
110                   */                   */
111                  virtual float GetValue() {                  virtual float GetValue() {
112                      if (pUnit != NULL) {                      return pUnit->Active() ? Transform(pUnit->GetLevel()) : 1.0f;
                         return pUnit->Active() ? pUnit->GetLevel() : 1.0f;  
                     }  
   
                     float val = 0;  
                     for(int i = 0; i < Modulators.size(); i++) {  
                         val += Modulators[i].GetValue();  
                     }  
                       
                     return val;  
                 }  
                   
                 /** Gets the final value - with applied transformation. */  
                 virtual float GetFinalValue() {  
                     return Transform(GetValue());  
113                  }                  }
114          };          };
115    
# Line 191  namespace LinuxSampler { Line 117  namespace LinuxSampler {
117          public:          public:
118              ArrayList<SignalUnit::Parameter> Params; // The list of parameters which are modulating the signal unit              ArrayList<SignalUnit::Parameter> Params; // The list of parameters which are modulating the signal unit
119                            
120              SignalUnit() : bActive(false), Level(0.0f), bCalculating(false), uiDelayTrigger(0) { }              SignalUnit(SignalUnitRack* rack): pRack(rack), bActive(false), Level(0.0f), bCalculating(false), uiDelayTrigger(0) { }
121              SignalUnit(const SignalUnit& Unit) { Copy(Unit); }              SignalUnit(const SignalUnit& Unit): pRack(Unit.pRack) { Copy(Unit); }
122              void operator=(const SignalUnit& Unit) { Copy(Unit); }              void operator=(const SignalUnit& Unit) { Copy(Unit); }
123                            
124              virtual void Copy(const SignalUnit& Unit) {              virtual void Copy(const SignalUnit& Unit) {
# Line 258  namespace LinuxSampler { Line 184  namespace LinuxSampler {
184               */               */
185              virtual void Increment() { bRecalculate = true; }              virtual void Increment() { bRecalculate = true; }
186    
187              /** Initializes and triggers the unit. */              /**
188                 * Initializes and triggers the unit.
189                 * Note that when a voice is the owner of a unit rack, all settings
190                 * should be reset when this method is called, because the sampler
191                 * is reusing the voice objects.
192                 */
193              virtual void Trigger() = 0;              virtual void Trigger() = 0;
194                            
195              /**              /**
# Line 271  namespace LinuxSampler { Line 202  namespace LinuxSampler {
202               */               */
203              virtual uint DelayTrigger() { return uiDelayTrigger; }              virtual uint DelayTrigger() { return uiDelayTrigger; }
204                            
205                /**
206                 * A helper method which checks whether the delay
207                 * stage is finished.
208                 */
209                bool DelayStage();
210                
211          protected:          protected:
212                SignalUnitRack* const pRack;
213    
214              bool   bActive; /* Don't use it to check the active state of the unit!!!              bool   bActive; /* Don't use it to check the active state of the unit!!!
215                               * Use Active() instead! */                               * Use Active() instead! */
216              float  Level;              float  Level;
# Line 284  namespace LinuxSampler { Line 223  namespace LinuxSampler {
223                    
224      };      };
225            
226      class EndpointSignalUnit: virtual public SignalUnit {      class EndpointSignalUnit: public SignalUnit {
227          public:          public:
228                EndpointSignalUnit(SignalUnitRack* rack): SignalUnit(rack) { }
229    
230              /**              /**
231               * Gets the volume modulation value               * Gets the volume modulation value
232               * for the current time step (sample point).               * for the current time step (sample point).
# Line 310  namespace LinuxSampler { Line 251  namespace LinuxSampler {
251               */               */
252              virtual float GetResonance() = 0;              virtual float GetResonance() = 0;
253                            
254              virtual float CalculateFilterCutoff(float cutoff) = 0;              virtual float CalculateFilterCutoff(float cutoff) {
255                                cutoff *= GetFilterCutoff();
256              virtual float CalculatePitch(float pitch) = 0;                  return cutoff > 13500 ? 13500 : cutoff;
               
             virtual float CalculateResonance(float res) = 0;  
     };  
       
   
     class SignalUnitRack;  
   
     template <class O /* The signal unit's owner */>  
     class SignalUnitBase: virtual public SignalUnit {  
         public:  
             SignalUnitBase() : pOwner(NULL) { }  
             SignalUnitBase(const SignalUnitBase& Unit) { Copy(Unit); }  
             void operator=(const SignalUnitBase& Unit) { Copy(Unit); }  
               
             virtual void Copy(const SignalUnitBase& Unit) {  
                 if (this == &Unit) return;  
   
                 pOwner = Unit.pOwner;  
                 SignalUnit::Copy(Unit);  
257              }              }
   
         protected:  
             O* pOwner; // The owner to which this rack belongs.  
               
             SignalUnitRack* GetSignalUnitRack() { return pOwner->GetSignalUnitRack(); }  
           
         public:  
               
258                            
259              /**              virtual float CalculatePitch(float pitch) {
260               * The owner of the unit is set by the rack                  return GetPitch() * pitch;
261               * just before the call to the unit's trigger method.              }
              */  
             void SetOwner(O* Owner) { pOwner = Owner; }  
262                            
263              /**              virtual float CalculateResonance(float res) {
264               * A helper method which checks whether the delay                  return GetResonance() * res;
              * stage is finished.  
              */  
             bool DelayStage() {  
                 return (DelayTrigger() >= GetSignalUnitRack()->GetCurrentStep());  
265              }              }
266      };      };
267            
# Line 362  namespace LinuxSampler { Line 270  namespace LinuxSampler {
270       * The level of this unit corresponds to the controller changes       * The level of this unit corresponds to the controller changes
271       * and is normalized to be in the range from -1 to +1.       * and is normalized to be in the range from -1 to +1.
272       */       */
273      template<class O>      class CCSignalUnit: public SignalUnit {
     class CCSignalUnit: public SignalUnitBase<O> {  
274          private:          private:
275              uint8_t Ctrl; // The number of the MIDI controller which modulates this signal unit.              uint8_t Ctrl; // The number of the MIDI controller which modulates this signal unit.
276    
277          public:          public:
278              CCSignalUnit(uint8_t Controller) {              CCSignalUnit(SignalUnitRack* rack, uint8_t Controller): SignalUnit(rack) {
279                  Ctrl = Controller;                  Ctrl = Controller;
280              }              }
281                            
282              CCSignalUnit(const CCSignalUnit& Unit) { Copy(Unit); }              CCSignalUnit(const CCSignalUnit& Unit): SignalUnit(Unit) { Copy(Unit); }
283              void operator=(const CCSignalUnit& Unit) { Copy(Unit); }              void operator=(const CCSignalUnit& Unit) { SignalUnit::Copy(Unit); Copy(Unit); }
284                            
285              virtual void Copy(const CCSignalUnit& Unit) {              virtual void Copy(const CCSignalUnit& Unit) {
                 SignalUnitBase<O>::Copy(Unit);  
286                  Ctrl = Unit.Ctrl;                  Ctrl = Unit.Ctrl;
287              }              }
288                            
# Line 386  namespace LinuxSampler { Line 292  namespace LinuxSampler {
292                  if (Controller != Ctrl) return;                  if (Controller != Ctrl) return;
293                                    
294                  // Normalize the value so it belongs to the interval [-1, +1]                  // Normalize the value so it belongs to the interval [-1, +1]
295                  SignalUnitBase<O>::Level = 2 * Value;                  Level = 2 * Value;
296                  SignalUnitBase<O>::Level = SignalUnitBase<O>::Level/127.0f - 1.0f;                  Level = Level/127.0f - 1.0f;
297                                    
298                  if (!SignalUnitBase<O>::bActive) SignalUnitBase<O>::bActive = true;                  if (!bActive) bActive = true;
             }  
     };  
   
     /**  
      * Endpoint signal unit.  
      */  
     template<class O>  
     class EndpointSignalUnitBase : public SignalUnitBase<O>, public EndpointSignalUnit {  
         public:  
   
             virtual float CalculateFilterCutoff(float cutoff) {  
                 return GetFilterCutoff() * cutoff;  
             }  
               
             virtual float CalculatePitch(float pitch) {  
                 return GetPitch() * pitch;  
             }  
               
             virtual float CalculateResonance(float res) {  
                 return GetResonance() * res;  
299              }              }
300      };      };
301            

Legend:
Removed from v.2205  
changed lines
  Added in v.2217

  ViewVC Help
Powered by ViewVC