/[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 2217 by iliev, Tue Jul 26 15:51:30 2011 UTC revision 3034 by schoenebeck, Mon Oct 31 00:05:00 2016 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2011 Grigor Iliev                                       *   *   Copyright (C) 2011 - 2012 Grigor Iliev                                *
6   *                                                                         *   *                                                                         *
7   *   This program is free software; you can redistribute it and/or modify  *   *   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  *   *   it under the terms of the GNU General Public License as published by  *
# Line 24  Line 24 
24  #define __LS_SIGNALUNIT_H__  #define __LS_SIGNALUNIT_H__
25    
26  #include "../../common/ArrayList.h"  #include "../../common/ArrayList.h"
27    #include "../../common/Pool.h"
28    
29    
30  namespace LinuxSampler {  namespace LinuxSampler {
31    
32        template<typename T>
33        class FixedArray {
34            public:
35                FixedArray(int capacity) {
36                    iSize = 0;
37                    iCapacity = capacity;
38                    pData = new T[iCapacity];
39                }
40                
41                ~FixedArray() {
42                    delete[] pData;
43                    pData = NULL;
44                }
45                
46                inline int size() const { return iSize; }
47                inline int capacity() { return iCapacity; }
48                
49                void add(T element) {
50                    if (iSize >= iCapacity) throw Exception("Array out of bounds");
51                    pData[iSize++] = element;
52                }
53                
54                
55                T& increment() {
56                    if (iSize >= iCapacity) throw Exception("Array out of bounds");
57                    return pData[iSize++];
58                }
59                
60                void clear() { iSize = 0; }
61                
62                void copy(const FixedArray<T>& array) {
63                    if(array.size() >= capacity()) throw Exception("Not enough space to copy array");
64                    for (int i = 0; i < array.size(); i++) pData[i] = array[i];
65                    iSize = array.size();
66                }
67                
68                inline T& operator[](int idx) const {
69                    return pData[idx];
70                }
71                
72            private:
73                T*   pData;
74                int  iSize;
75                int  iCapacity;
76        };
77        
78      class SignalUnitRack;      class SignalUnitRack;
79    
80      /**      /**
# Line 67  namespace LinuxSampler { Line 114  namespace LinuxSampler {
114                  float Coeff; // The modulation coefficient                  float Coeff; // The modulation coefficient
115                                    
116                                    
117                  Parameter() : Coeff(1), pUnit(NULL) { }                  Parameter() : pUnit(NULL), Coeff(1) { }
118    
119                  /**                  /**
120                   * @param unit The source unit used to influence this parameter.                   * @param unit The source unit used to influence this parameter.
# Line 83  namespace LinuxSampler { Line 130  namespace LinuxSampler {
130                  Parameter(const Parameter& Prm) { Copy(Prm); }                  Parameter(const Parameter& Prm) { Copy(Prm); }
131                  void operator=(const Parameter& Prm) { Copy(Prm); }                  void operator=(const Parameter& Prm) { Copy(Prm); }
132                            
133                  virtual void Copy(const Parameter& Prm) {                  void Copy(const Parameter& Prm) {
134                      if (this == &Prm) return;                      if (this == &Prm) return;
135    
136                      pUnit = Prm.pUnit;                      pUnit = Prm.pUnit;
# Line 117  namespace LinuxSampler { Line 164  namespace LinuxSampler {
164          public:          public:
165              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
166                            
167              SignalUnit(SignalUnitRack* rack): pRack(rack), bActive(false), Level(0.0f), bCalculating(false), uiDelayTrigger(0) { }              SignalUnit(SignalUnitRack* rack): pRack(rack), bActive(false), Level(0.0f), bRecalculate(true), bCalculating(false), uiDelayTrigger(0) { }
168              SignalUnit(const SignalUnit& Unit): pRack(Unit.pRack) { Copy(Unit); }              SignalUnit(const SignalUnit& Unit): pRack(Unit.pRack) { Copy(Unit); }
169              void operator=(const SignalUnit& Unit) { Copy(Unit); }              void operator=(const SignalUnit& Unit) { Copy(Unit); }
170                virtual ~SignalUnit() { }
171                            
172              virtual void Copy(const SignalUnit& Unit) {              void Copy(const SignalUnit& Unit) {
173                  if (this == &Unit) return;                  if (this == &Unit) return;
174    
175                  bActive = Unit.bActive;                  bActive = Unit.bActive;
# Line 156  namespace LinuxSampler { Line 204  namespace LinuxSampler {
204               * the parameters, their levels are calculated too.               * the parameters, their levels are calculated too.
205               */               */
206              virtual float GetLevel() {              virtual float GetLevel() {
207                  if (!bRecalculate) return Level;                  if (Params.empty() || !bRecalculate) return Level;
208    
209                  if (bCalculating) {                  if (bCalculating) {
210                      std::cerr << "SignalUnit: Loop detected. Aborted!";                      std::cerr << "SignalUnit: Loop detected. Aborted!";
# Line 251  namespace LinuxSampler { Line 299  namespace LinuxSampler {
299               */               */
300              virtual float GetResonance() = 0;              virtual float GetResonance() = 0;
301                            
302                /** Should return value in the range [-100, 100] (L <-> R) */
303                virtual float GetPan() = 0;
304                
305              virtual float CalculateFilterCutoff(float cutoff) {              virtual float CalculateFilterCutoff(float cutoff) {
306                  cutoff *= GetFilterCutoff();                  cutoff *= GetFilterCutoff();
307                  return cutoff > 13500 ? 13500 : cutoff;                  return cutoff > 13500 ? 13500 : cutoff;
# Line 263  namespace LinuxSampler { Line 314  namespace LinuxSampler {
314              virtual float CalculateResonance(float res) {              virtual float CalculateResonance(float res) {
315                  return GetResonance() * res;                  return GetResonance() * res;
316              }              }
317                
318                /** Should return value in the range [0, 127] (L <-> R) */
319                virtual uint8_t CalculatePan(int pan) {
320                    int p = pan + GetPan() * 0.63;
321                    if (p < 0) return 0;
322                    if (p > 127) return 127;
323                    return p;
324                }
325                
326                /**
327                 * Decreases the delay by Sample time steps.
328                 * This method is used to delay the sample playback.
329                 * While the endpoint unit is in delay stage the rack is not incremented.
330                 */
331                void DecreaseDelay(uint Samples) {
332                    uiDelayTrigger -= Samples;
333                }
334        };
335        
336        /**
337         * Used to smooth out the parameter changes.
338         */
339        class Smoother {
340            protected:
341                uint  timeSteps; // The number of time steps to reach the goal
342                uint  currentTimeStep;
343                float goal;
344                float prev;
345                
346            public:
347                /**
348                 *
349                 * @param time The time (in seconds) to reach the goal
350                 * @param sampleRate
351                 * @param val The initial value
352                 */
353                void trigger(float time, float sampleRate, float val = 0) {
354                    currentTimeStep = timeSteps = time * sampleRate;
355                    prev = goal = val;
356                }
357                
358                /**
359                 * Set the current value, which the smoother will not smooth out.
360                 * If you want the value to be smoothen out, use update() instead.
361                 */
362                void setValue( float val) {
363                    currentTimeStep = timeSteps;
364                    prev = goal = val;
365                }
366                
367                /**
368                 * Sets a new value. The render function will return
369                 * values gradually approaching this value.
370                 */
371                void update(float val) {
372                    if (val == goal) return;
373                    
374                    prev = prev + (goal - prev) * (currentTimeStep / (float)timeSteps);
375                    goal = val;
376                    currentTimeStep = 0;
377                }
378                
379                float render() {
380                    if (currentTimeStep >= timeSteps) return goal;
381                    return prev + (goal - prev) * (currentTimeStep++ / (float)timeSteps);
382                }
383                
384                bool isSmoothingOut() { return currentTimeStep < timeSteps; }
385                
386                float getGoal() { return goal; }
387      };      };
388            
389      /**      /**
390       * Continuous controller signal unit.       * Continuous controller signal unit.
391       * The level of this unit corresponds to the controller changes       * The level of this unit corresponds to the controllers changes
392       * and is normalized to be in the range from -1 to +1.       * and their influences.
393       */       */
394      class CCSignalUnit: public SignalUnit {      class CCSignalUnit: public SignalUnit {
395          private:          public:
396              uint8_t Ctrl; // The number of the MIDI controller which modulates this signal unit.              /** Listener which will be notified when the level of the unit is changed. */
397                class Listener {
398                    public:
399                        virtual void ValueChanged(CCSignalUnit* pUnit) = 0;
400                };
401                
402                class CC {
403                    public:
404                        uint8_t   Controller;  ///< MIDI controller number.
405                        uint8_t   Value;       ///< Controller Value.
406                        short int Curve;       ///< specifies the curve type
407                        float     Influence;
408                        float     Step;
409                        
410                        Smoother* pSmoother;
411                        
412                        CC (
413                            uint8_t   Controller = 0,
414                            float     Influence  = 0.0f,
415                            short int Curve      = -1,
416                            Smoother* pSmoother  = NULL,
417                            float     Step       = 0
418                        ) {
419                            this->Controller = Controller;
420                            this->Value = 0;
421                            this->Curve = Curve;
422                            this->Influence = Influence;
423                            this->pSmoother = pSmoother;
424                            this->Step  = Step;
425                        }
426                        
427                        CC(const CC& cc) { Copy(cc); }
428                        void operator=(const CC& cc) { Copy(cc); }
429                        
430                        void Copy(const CC& cc) {
431                            Controller = cc.Controller;
432                            Value      = cc.Value;
433                            Influence  = cc.Influence;
434                            Curve      = cc.Curve;
435                            pSmoother  = cc.pSmoother;
436                            Step       = cc.Step;
437                        }
438                };
439                
440            protected:
441                RTList<CC>* pCtrls; // The MIDI controllers which modulates this signal unit.
442                Listener* pListener;
443                bool hasSmoothCtrls; // determines whether there are smooth controllers (used for optimization)
444                bool isSmoothingOut; // determines whether there is a CC which is in process of smoothing out (used for optimization)
445    
446          public:          public:
447              CCSignalUnit(SignalUnitRack* rack, uint8_t Controller): SignalUnit(rack) {              
448                  Ctrl = Controller;              CCSignalUnit(SignalUnitRack* rack, Listener* l = NULL): SignalUnit(rack), pCtrls(NULL) {
449                    pListener = l;
450                    hasSmoothCtrls = isSmoothingOut = false;
451              }              }
452                            
453              CCSignalUnit(const CCSignalUnit& Unit): SignalUnit(Unit) { Copy(Unit); }              CCSignalUnit(const CCSignalUnit& Unit): SignalUnit(Unit.pRack), pCtrls(NULL) { Copy(Unit); }
454              void operator=(const CCSignalUnit& Unit) { SignalUnit::Copy(Unit); Copy(Unit); }              void operator=(const CCSignalUnit& Unit) { Copy(Unit); }
455                            
456              virtual void Copy(const CCSignalUnit& Unit) {              virtual ~CCSignalUnit() {
457                  Ctrl = Unit.Ctrl;                  if (pCtrls != NULL) delete pCtrls;
458              }              }
459                            
460              virtual void Increment() { }              void Copy(const CCSignalUnit& Unit) {
461                    if (pCtrls != NULL) delete pCtrls;
462                    pCtrls = new RTList<CC>(*(Unit.pCtrls));
463                    if (pCtrls->poolIsEmpty() && pCtrls->count() < Unit.pCtrls->count()) {
464                        std::cerr << "Maximum number of CC reached!" << std::endl;
465                    }
466                    
467                    pListener = Unit.pListener;
468                    hasSmoothCtrls = Unit.hasSmoothCtrls;
469                    isSmoothingOut = Unit.isSmoothingOut;
470                    SignalUnit::Copy(Unit);
471                }
472                
473                virtual void InitCCList(Pool<CC>* pCCPool, Pool<Smoother>* pSmootherPool) {
474                    if (pCtrls != NULL) delete pCtrls;
475                    pCtrls = new RTList<CC>(pCCPool);
476                }
477                
478                void AddCC(uint8_t Controller, float Influence, short int Curve = -1, Smoother* pSmoother = NULL, float Step = 0) {
479                    if(pCtrls->poolIsEmpty()) {
480                        std::cerr << "Maximum number of CC reached!" << std::endl;
481                        return;
482                    }
483                    *(pCtrls->allocAppend()) = CC(Controller, Influence, Curve, pSmoother, Step);
484                    if (pSmoother != NULL) hasSmoothCtrls = true;
485                }
486                
487                virtual void RemoveAllCCs() { pCtrls->clear(); }
488                
489                int GetCCCount() { return pCtrls->count(); }
490                
491                bool HasCCs() { return GetCCCount() > 0; }
492                
493                virtual void Increment() {
494                    if (hasSmoothCtrls && isSmoothingOut) Calculate();
495                }
496                
497                virtual void Trigger() {
498                    Calculate();
499                    bActive = Level != 0;
500                }
501                            
502              virtual void ProcessCCEvent(uint8_t Controller, uint8_t Value) {              virtual void ProcessCCEvent(uint8_t Controller, uint8_t Value) {
503                  if (Controller != Ctrl) return;                  bool recalculate = false;
504                                    
505                  // Normalize the value so it belongs to the interval [-1, +1]                  RTList<CC>::Iterator ctrl = pCtrls->first();
506                  Level = 2 * Value;                  RTList<CC>::Iterator end  = pCtrls->end();
507                  Level = Level/127.0f - 1.0f;                  for(; ctrl != end; ++ctrl) {
508                        if (Controller != (*ctrl).Controller) continue;
509                        if ((*ctrl).Value == Value) continue;
510                        
511                        (*ctrl).Value = Value;
512                        
513                        if ((*ctrl).Step > 0 && (*ctrl).pSmoother != NULL) {
514                            float oldGoal = (*ctrl).pSmoother->getGoal();
515                            float newGoal = Normalize(Value, (*ctrl).Curve) * (*ctrl).Influence;
516                            newGoal = ((int) (newGoal / (*ctrl).Step)) * (*ctrl).Step;
517                            if (oldGoal != newGoal) (*ctrl).pSmoother->update(newGoal);
518                        }
519                        
520                        if ((*ctrl).pSmoother != NULL && (*ctrl).Step <= 0) (*ctrl).pSmoother->update(Value);
521                        if (!bActive) bActive = true;
522                        recalculate = true;
523                    }
524                                    
525                  if (!bActive) bActive = true;                  if (!(hasSmoothCtrls && isSmoothingOut) && recalculate) Calculate();
526                }
527                
528                virtual void Calculate() {
529                    float l = 0;
530                    isSmoothingOut = false;
531                    RTList<CC>::Iterator ctrl = pCtrls->first();
532                    RTList<CC>::Iterator end  = pCtrls->end();
533                    for(; ctrl != end; ++ctrl) {
534                        if ((*ctrl).pSmoother == NULL) {
535                            float val = Normalize((*ctrl).Value, (*ctrl).Curve) * (*ctrl).Influence;
536                            if ((*ctrl).Step > 0) val = ( (int)(val / (*ctrl).Step) ) * (*ctrl).Step;
537                            l += val;
538                        } else {
539                            if ((*ctrl).pSmoother->isSmoothingOut()) isSmoothingOut = true;
540                            
541                            if ((*ctrl).Step > 0) {
542                                l += (*ctrl).pSmoother->render();
543                            } else {
544                                l += Normalize((*ctrl).pSmoother->render(), (*ctrl).Curve) * (*ctrl).Influence;
545                            }
546                        }
547                    }
548                    if (Level != l) {
549                        Level = l;
550                        if (pListener != NULL) pListener->ValueChanged(this);
551                    }
552                }
553                
554                virtual float Normalize(uint8_t val, short int curve = -1) {
555                    return val / 127.0f;
556              }              }
557      };      };
558            

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

  ViewVC Help
Powered by ViewVC