/[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 2219 by iliev, Thu Jul 28 12:35:49 2011 UTC revision 2238 by iliev, Fri Aug 12 17:30:47 2011 UTC
# Line 28  Line 28 
28    
29  namespace LinuxSampler {  namespace LinuxSampler {
30    
31        template<typename T>
32        class FixedArray {
33            public:
34                FixedArray(int capacity) {
35                    iSize = 0;
36                    iCapacity = capacity;
37                    pData = new T[iCapacity];
38                }
39                
40                ~FixedArray() {
41                    delete[] pData;
42                    pData = NULL;
43                }
44                
45                inline int size() const { return iSize; }
46                inline int capacity() { return iCapacity; }
47                
48                void add(T element) {
49                    if (iSize >= iCapacity) throw Exception("Array out of bounds");
50                    pData[iSize++] = element;
51                }
52                
53                
54                T& increment() {
55                    if (iSize >= iCapacity) throw Exception("Array out of bounds");
56                    return pData[iSize++];
57                }
58                
59                void clear() { iSize = 0; }
60                
61                void copy(const FixedArray<T>& array) {
62                    if(array.size() >= capacity()) throw Exception("Not enough space to copy array");
63                    for (int i = 0; i < array.size(); i++) pData[i] = array[i];
64                    iSize = array.size();
65                }
66                
67                inline T& operator[](int idx) const {
68                    return pData[idx];
69                }
70                
71            private:
72                T*   pData;
73                int  iSize;
74                int  iCapacity;
75        };
76        
77      class SignalUnitRack;      class SignalUnitRack;
78    
79      /**      /**
# Line 277  namespace LinuxSampler { Line 323  namespace LinuxSampler {
323      };      };
324            
325      /**      /**
326         * Used to smooth out the parameter changes.
327         */
328        class Smoother {
329            protected:
330                uint    timeSteps; // The number of time steps to reach the goal
331                uint    currentTimeStep;
332                uint8_t goal; // 0 - 127
333                uint8_t prev; // 0 - 127
334                
335            public:
336                /**
337                 *
338                 * @param time The time (in seconds) to reach the goal
339                 * @param sampleRate
340                 * @param val The initial value
341                 */
342                void trigger(float time, float sampleRate, uint8_t val = 0) {
343                    currentTimeStep = timeSteps = time * sampleRate;
344                    prev = goal = val;
345                }
346                
347                /**
348                 * Set the current value, which the smoother will not smooth out.
349                 * If you want the value to be smoothen out, use update() instead.
350                 */
351                void setValue( uint8_t val) {
352                    currentTimeStep = timeSteps;
353                    prev = goal = val;
354                }
355                
356                /**
357                 * Sets a new value. The render function will return
358                 * values gradually approaching this value.
359                 */
360                void update(uint8_t val) {
361                    if (val == goal) return;
362                    
363                    prev = prev + (goal - prev) * (currentTimeStep / (float)timeSteps);
364                    goal = val;
365                    currentTimeStep = 0;
366                }
367                
368                uint8_t render() {
369                    if (currentTimeStep >= timeSteps) return goal;
370                    return prev + (goal - prev) * (currentTimeStep++ / (float)timeSteps);
371                }
372                
373                bool isSmoothingOut() { return currentTimeStep < timeSteps; }
374        };
375        
376        
377        const int MaxCCs = 10;
378        
379        /**
380       * Continuous controller signal unit.       * Continuous controller signal unit.
381       * The level of this unit corresponds to the controller changes       * The level of this unit corresponds to the controllers changes
382       * and is normalized to be in the range from -1 to +1.       * and their influences.
383       */       */
384      class CCSignalUnit: public SignalUnit {      class CCSignalUnit: public SignalUnit {
385          private:          public:
386              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. */
387                class Listener {
388                    public:
389                        virtual void ValueChanged(CCSignalUnit* pUnit) = 0;
390                };
391                
392            protected:
393                class CC {
394                    public:
395                        uint8_t   Controller;  ///< MIDI controller number.
396                        uint8_t   Value;       ///< Controller Value.
397                        short int Curve;       ///< specifies the curve type
398                        float     Influence;
399                        
400                        Smoother* pSmoother;
401                        
402                        CC(uint8_t Controller = 0, float Influence = 0.0f, short int Curve = -1, Smoother* pSmoother = NULL) {
403                            this->Controller = Controller;
404                            this->Value = 0;
405                            this->Curve = Curve;
406                            this->Influence = Influence;
407                            this->pSmoother = pSmoother;
408                        }
409                        
410                        CC(const CC& cc) { Copy(cc); }
411                        void operator=(const CC& cc) { Copy(cc); }
412                        
413                        void Copy(const CC& cc) {
414                            Controller = cc.Controller;
415                            Value = cc.Value;
416                            Influence = cc.Influence;
417                            Curve = cc.Curve;
418                            pSmoother = cc.pSmoother;
419                        }
420                };
421                
422                FixedArray<CC> Ctrls; // The MIDI controllers which modulates this signal unit.
423                Listener* pListener;
424                bool hasSmoothCtrls; // determines whether there are smooth controllers (used for optimization)
425                bool isSmoothingOut; // determines whether there is a CC which is in process of smoothing out (used for optimization)
426    
427          public:          public:
428              CCSignalUnit(SignalUnitRack* rack, uint8_t Controller): SignalUnit(rack) {              
429                  Ctrl = Controller;              CCSignalUnit(SignalUnitRack* rack, Listener* l = NULL): SignalUnit(rack), Ctrls(MaxCCs) {
430                    pListener = l;
431                    hasSmoothCtrls = isSmoothingOut = false;
432              }              }
433                            
434              CCSignalUnit(const CCSignalUnit& Unit): SignalUnit(Unit.pRack) { Copy(Unit); }              CCSignalUnit(const CCSignalUnit& Unit): SignalUnit(Unit.pRack), Ctrls(MaxCCs) { Copy(Unit); }
435              void operator=(const CCSignalUnit& Unit) { Copy(Unit); }              void operator=(const CCSignalUnit& Unit) { Copy(Unit); }
436                            
437              void Copy(const CCSignalUnit& Unit) {              void Copy(const CCSignalUnit& Unit) {
438                  Ctrl = Unit.Ctrl;                  Ctrls.copy(Unit.Ctrls);
439                    pListener = Unit.pListener;
440                    hasSmoothCtrls = Unit.hasSmoothCtrls;
441                    isSmoothingOut = Unit.isSmoothingOut;
442                  SignalUnit::Copy(Unit);                  SignalUnit::Copy(Unit);
443              }              }
444                            
445              virtual void Increment() { }              void AddCC(uint8_t Controller, float Influence, short int Curve = -1, Smoother* pSmoother = NULL) {
446                    if(Ctrls.size() >= Ctrls.capacity()) {
447                        std::cerr << "Maximum number of CC reached" << std::endl;
448                        return;
449                    }
450                    Ctrls.add(CC(Controller, Influence, Curve, pSmoother));
451                    if (pSmoother != NULL) hasSmoothCtrls = true;
452                }
453                
454                virtual void RemoveAllCCs() { Ctrls.clear(); }
455                
456                int GetCCCount() { return Ctrls.size(); }
457                
458                virtual void Increment() {
459                    if (hasSmoothCtrls && isSmoothingOut) Calculate();
460                }
461                
462                virtual void Trigger() {
463                    Calculate();
464                    bActive = Level != 0;
465                }
466                            
467              virtual void ProcessCCEvent(uint8_t Controller, uint8_t Value) {              virtual void ProcessCCEvent(uint8_t Controller, uint8_t Value) {
468                  if (Controller != Ctrl) return;                  bool recalculate = false;
469                                    
470                  // Normalize the value so it belongs to the interval [-1, +1]                  for (int i = 0; i < Ctrls.size(); i++) {
471                  Level = 2 * Value;                      if (Controller != Ctrls[i].Controller) continue;
472                  Level = Level/127.0f - 1.0f;                      if (Ctrls[i].Value == Value) continue;
473                        Ctrls[i].Value = Value;
474                        if (Ctrls[i].pSmoother != NULL) Ctrls[i].pSmoother->update(Value);
475                        if (!bActive) bActive = true;
476                        recalculate = true;
477                    }
478                                    
479                  if (!bActive) bActive = true;                  if (!(hasSmoothCtrls && isSmoothingOut) && recalculate) Calculate();
480                }
481                
482                virtual void Calculate() {
483                    float l = 0;
484                    isSmoothingOut = false;
485                    for (int i = 0; i < Ctrls.size(); i++) {
486                        if (Ctrls[i].pSmoother == NULL) {
487                            l += Normalize(Ctrls[i].Value, Ctrls[i].Curve) * Ctrls[i].Influence;
488                        } else {
489                            if (Ctrls[i].pSmoother->isSmoothingOut()) isSmoothingOut = true;
490                            l += Normalize(Ctrls[i].pSmoother->render(), Ctrls[i].Curve) * Ctrls[i].Influence;
491                        }
492                    }
493                    if (Level != l) {
494                        Level = l;
495                        if (pListener != NULL) pListener->ValueChanged(this);
496                    }
497                }
498                
499                virtual float Normalize(uint8_t val, short int curve = -1) {
500                    return val / 127.0f;
501              }              }
502      };      };
503            

Legend:
Removed from v.2219  
changed lines
  Added in v.2238

  ViewVC Help
Powered by ViewVC