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

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

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

revision 2012 by iliev, Fri Oct 23 17:53:17 2009 UTC revision 2645 by schoenebeck, Wed Jun 18 00:14:57 2014 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6   *   Copyright (C) 2005-2009 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009 Grigor Iliev                                       *   *   Copyright (C) 2009-2010 Christian Schoenebeck and Grigor Iliev        *
8   *                                                                         *   *                                                                         *
9   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
10   *   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 23  Line 23 
23   ***************************************************************************/   ***************************************************************************/
24    
25  #ifndef __LS_MIDIKEYBOARDMANAGER_H__  #ifndef __LS_MIDIKEYBOARDMANAGER_H__
26  #define __LS_MIDIKEYBOARDMANAGER_H__  #define __LS_MIDIKEYBOARDMANAGER_H__
27    
28  #include "Event.h"  #include "Event.h"
29  #include "Stream.h"  #include "Stream.h"
# Line 97  namespace LinuxSampler { Line 97  namespace LinuxSampler {
97              virtual void PostProcessSostenutoPedalDown() { }              virtual void PostProcessSostenutoPedalDown() { }
98      };      };
99    
100        /**
101         * This is the base class for class MidiKeyboardManager::MidiKey. It is
102         * not intended to be instantiated directly. Instead it just defines
103         * the part of class MidiKey which is not dependant on a C++ template
104         * parameter.
105         *
106         * There are also ScriptEvent lists maintained for each key, which are not
107         * stored here though, but on the InstrumentScript structure. Simply because
108         * RTLists are tied to one Pool instance, and it would be error prone to
109         * maintain @c Pool<ScriptEvent> and @c RTList<ScriptEvent> separately,
110         * since one would need to be very careful to reallocate the lists when the
111         * script was changed or when the Engine instance changed, etc.
112         *
113         * @see InstrumentScript::pKeyEvents
114         */
115        class MidiKeyBase {
116            public:
117                bool            KeyPressed;     ///< Is true if the respective MIDI key is currently pressed.
118                bool            Active;         ///< If the key contains active voices.
119                bool            ReleaseTrigger; ///< If we have to launch release triggered voice(s) when the key is released
120                Pool<uint>::Iterator itSelf;    ///< hack to allow fast deallocation of the key from the list of active keys
121                RTList<Event>*  pEvents;        ///< Key specific events (only Note-on, Note-off and sustain pedal currently)
122                int             VoiceTheftsQueued; ///< Amount of voices postponed due to shortage of voices.
123                uint32_t*       pRoundRobinIndex; ///< For the round robin dimension: current articulation for this key, will be incremented for each note on
124                uint8_t         Velocity;       ///< Latest Note-on velocity for this key
125                unsigned long   NoteOnTime;     ///< Time for latest Note-on event for this key
126                float           Volume;         ///< Individual volume level for this MIDI key (usually 1.0f unless Roland GS NRPN 0x1Ann was received, nn reflecting the note number, see EngineBase::ProcessHardcodedControllers())
127                float           PanLeft;        ///< Individual volume balance (left channel coefficient) for this MIDI key (usually 1.0f unless Roland GS NRPN 0x1Cnn was received, nn reflecting the note number, see EngineBase::ProcessHardcodedControllers())
128                float           PanRight;       ///< Individual volume balance (right channel coefficient) for this MIDI key (usually 1.0f unless Roland GS NRPN 0x1Cnn was received, nn reflecting the note number, see EngineBase::ProcessHardcodedControllers())
129                optional<float> ReverbSend;     ///< Optional individual reverb send level for this MIDI key (usually not set, unless Roland GS NRPN 0x1Dnn was received, nn reflecting the note number, see EngineBase::ProcessHardcodedControllers())
130                optional<float> ChorusSend;     ///< Optional individual chorus send level for this MIDI key (usually not set, unless Roland GS NRPN 0x1Enn was received, nn reflecting the note number, see EngineBase::ProcessHardcodedControllers())
131        };
132    
133        class MidiKeyboardManagerBase {
134        public:
135            Pool<uint>*           pActiveKeys;  ///< Holds all keys in it's allocation list with active voices.
136            bool                  SoloMode;                 ///< in Solo Mode we only play one voice (group) at a time
137            int                   SoloKey;                  ///< Currently 'active' solo key, that is the key to which the currently sounding voice belongs to (only if SoloMode is enabled)
138            bool                  SustainPedal;             ///< true if sustain pedal is down
139            bool                  SostenutoPedal;           ///< true if sostenuto pedal is down
140            int                   SostenutoKeys[128];
141            int                   SostenutoKeyCount;
142            uint32_t              RoundRobinIndexes[128];
143            int8_t                KeyDown[128]; ///< True if the respective key is currently pressed down. Currently only used as built-in instrument script array variable %KEY_DOWN. It is currently not used by the sampler for any other purpose.
144        };
145    
146      template <class V>      template <class V>
147      class MidiKeyboardManager {      class MidiKeyboardManager : public MidiKeyboardManagerBase {
148          public:          public:
149              /** @brief Voice Stealing Algorithms              /** @brief Voice Stealing Algorithms
150               *               *
# Line 109  namespace LinuxSampler { Line 155  namespace LinuxSampler {
155                  voice_steal_algo_oldestvoiceonkey,  ///< Try to kill the oldest voice from same key where the new voice should be spawned.                  voice_steal_algo_oldestvoiceonkey,  ///< Try to kill the oldest voice from same key where the new voice should be spawned.
156                  voice_steal_algo_oldestkey          ///< Try to kill the oldest voice from the oldest active key.                  voice_steal_algo_oldestkey          ///< Try to kill the oldest voice from the oldest active key.
157              };              };
158            
159    
160              /** @brief MIDI key runtime informations              /** @brief MIDI key runtime informations
161               *               *
162               * Reflects runtime informations for one MIDI key.               * Reflects runtime informations for one MIDI key.
163               */               */
164              class MidiKey {              class MidiKey : public MidiKeyBase {
165              public:              public:
166                  RTList<V>*      pActiveVoices;  ///< Contains the active voices associated with the MIDI key.                  RTList<V>* pActiveVoices;  ///< Contains the active voices associated with the MIDI key.
                 bool            KeyPressed;     ///< Is true if the respective MIDI key is currently pressed.  
                 bool            Active;         ///< If the key contains active voices.  
                 bool            ReleaseTrigger; ///< If we have to launch release triggered voice(s) when the key is released  
                 Pool<uint>::Iterator itSelf;    ///< hack to allow fast deallocation of the key from the list of active keys  
                 RTList<Event>*  pEvents;        ///< Key specific events (only Note-on, Note-off and sustain pedal currently)  
                 int             VoiceTheftsQueued; ///< Amount of voices postponed due to shortage of voices.  
                 uint8_t         RoundRobinIndex; ///< For the round robin dimension: current articulation for this key, will be incremented for each note on  
                 uint8_t         Velocity;       ///< Latest Note-on velocity for this key  
                 unsigned long   NoteOnTime;     ///< Time for latest Note-on event for this key  
167    
168                  MidiKey() {                  MidiKey() {
169                      pActiveVoices  = NULL;                      pActiveVoices  = NULL;
# Line 135  namespace LinuxSampler { Line 172  namespace LinuxSampler {
172                      ReleaseTrigger = false;                      ReleaseTrigger = false;
173                      pEvents        = NULL;                      pEvents        = NULL;
174                      VoiceTheftsQueued = 0;                      VoiceTheftsQueued = 0;
175                      RoundRobinIndex = 0;                      Volume = 1.0f;
176                        PanLeft = 1.0f;
177                        PanRight = 1.0f;
178                  }                  }
179    
180                  void Reset() {                  void Reset() {
181                      if (pActiveVoices) pActiveVoices->clear();                      if (pActiveVoices) {
182                            RTListVoiceIterator itVoice = pActiveVoices->first();
183                            RTListVoiceIterator itVoicesEnd = pActiveVoices->end();
184                            for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
185                                itVoice->VoiceFreed();
186                            }
187                            pActiveVoices->clear();
188                        }
189                      if (pEvents) pEvents->clear();                      if (pEvents) pEvents->clear();
190                      KeyPressed        = false;                      KeyPressed        = false;
191                      Active            = false;                      Active            = false;
192                      ReleaseTrigger    = false;                      ReleaseTrigger    = false;
193                      itSelf            = Pool<uint>::Iterator();                      itSelf            = Pool<uint>::Iterator();
194                      VoiceTheftsQueued = 0;                      VoiceTheftsQueued = 0;
195                        Volume = 1.0f;
196                        PanLeft = 1.0f;
197                        PanRight = 1.0f;
198                        ReverbSend = optional<float>::nothing;
199                        ChorusSend = optional<float>::nothing;
200                  }                  }
201              };              };
202    
# Line 175  namespace LinuxSampler { Line 226  namespace LinuxSampler {
226              };              };
227    
228              MidiKey*              pMIDIKeyInfo; ///< Contains all active voices sorted by MIDI key number and other informations to the respective MIDI key              MidiKey*              pMIDIKeyInfo; ///< Contains all active voices sorted by MIDI key number and other informations to the respective MIDI key
             Pool<uint>*           pActiveKeys;  ///< Holds all keys in it's allocation list with active voices.  
             std::map<uint,uint*>  ActiveKeyGroups;  ///< Contains active keys (in case they belong to a key group) ordered by key group ID.  
             bool                  SoloMode;                 ///< in Solo Mode we only play one voice (group) at a time  
             int                   SoloKey;                  ///< Currently 'active' solo key, that is the key to which the currently sounding voice belongs to (only if SoloMode is enabled)  
             bool                  SustainPedal;             ///< true if sustain pedal is down  
             bool                  SostenutoPedal;           ///< true if sostenuto pedal is down  
             int                   SostenutoKeys[128];  
             int                   SostenutoKeyCount;  
229    
230              MidiKeyboardManager() {              MidiKeyboardManager(AbstractEngineChannel* pEngineChannel) {
231                  pMIDIKeyInfo = new MidiKey[128];                  pMIDIKeyInfo = new MidiKey[128];
232                  pActiveKeys  = new Pool<uint>(128);                  pActiveKeys  = new Pool<uint>(128);
233                  SoloMode     = false;                  SoloMode     = false;
234                  SustainPedal   = false;                  SustainPedal   = false;
235                  SostenutoPedal = false;                  SostenutoPedal = false;
236                    for (int i = 0 ; i < 128 ; i++) {
237                        RoundRobinIndexes[i] = 0;
238                        KeyDown[i] = false;
239    
240                        // by default use one counter for each key (the
241                        // gig engine will change this to one counter per
242                        // region)
243                        pMIDIKeyInfo[i].pRoundRobinIndex = &RoundRobinIndexes[i];
244                    }
245                    m_engineChannel = pEngineChannel;
246              }              }
247    
248              virtual ~MidiKeyboardManager() {              virtual ~MidiKeyboardManager() {
# Line 198  namespace LinuxSampler { Line 251  namespace LinuxSampler {
251                  if (pMIDIKeyInfo) delete[] pMIDIKeyInfo;                  if (pMIDIKeyInfo) delete[] pMIDIKeyInfo;
252              }              }
253    
254              void Reset(){              void Reset() {
255                  SoloKey = -1;    // no solo key active yet                  SoloKey = -1;    // no solo key active yet
256    
                 // reset all key groups  
                 std::map<uint,uint*>::iterator iter = ActiveKeyGroups.begin();  
                 for (; iter != ActiveKeyGroups.end(); iter++) iter->second = NULL;  
   
257                  // reset key info                  // reset key info
258                  for (uint i = 0; i < 128; i++) pMIDIKeyInfo[i].Reset();                  for (uint i = 0; i < 128; i++) {
259                        pMIDIKeyInfo[i].Reset();
260                        KeyDown[i] = false;
261                        if (m_engineChannel->pScript)
262                            m_engineChannel->pScript->pKeyEvents[i]->clear();
263                    }
264    
265                  // free all active keys                  // free all active keys
266                  pActiveKeys->clear();                  pActiveKeys->clear();
# Line 246  namespace LinuxSampler { Line 300  namespace LinuxSampler {
300                  }                  }
301              }              }
302    
303              void ClearAllActiveKeyEvents() {              /*void ClearAllActiveKeyEvents() {
304                  RTList<uint>::Iterator iuiKey = pActiveKeys->first();                  RTList<uint>::Iterator iuiKey = pActiveKeys->first();
305                  RTList<uint>::Iterator end    = pActiveKeys->end();                  RTList<uint>::Iterator end    = pActiveKeys->end();
306                  for(; iuiKey != end; ++iuiKey) {                  for(; iuiKey != end; ++iuiKey) {
307                      pMIDIKeyInfo[*iuiKey].pEvents->clear(); // free all events on the key                      pMIDIKeyInfo[*iuiKey].pEvents->clear(); // free all events on the key
308                  }                  }
309              }              }*/
310    
311              /**              /**
312               *  Removes the given voice from the MIDI key's list of active voices.               *  Removes the given voice from the MIDI key's list of active voices.
# Line 266  namespace LinuxSampler { Line 320  namespace LinuxSampler {
320                  if (itVoice) {                  if (itVoice) {
321                      MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey];                      MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey];
322    
                     uint keygroup = itVoice->KeyGroup;  
   
323                      // if the sample and dimension region belong to an                      // if the sample and dimension region belong to an
324                      // instrument that is unloaded, tell the disk thread to                      // instrument that is unloaded, tell the disk thread to
325                      // release them                      // release them
# Line 279  namespace LinuxSampler { Line 331  namespace LinuxSampler {
331    
332                      // free the voice object                      // free the voice object
333                      pKey->pActiveVoices->free(itVoice);                      pKey->pActiveVoices->free(itVoice);
   
                     // if no other voices left and member of a key group, remove from key group  
                     if (pKey->pActiveVoices->isEmpty() && keygroup) {  
                         uint** ppKeyGroup = &ActiveKeyGroups[keygroup];  
                         if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group  
                     }  
334                  }                  }
335                  else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;                  else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;
336              }              }
# Line 298  namespace LinuxSampler { Line 344  namespace LinuxSampler {
344               */               */
345              void FreeKey(MidiKey* pKey) {              void FreeKey(MidiKey* pKey) {
346                  if (pKey->pActiveVoices->isEmpty()) {                  if (pKey->pActiveVoices->isEmpty()) {
347                        if (m_engineChannel->pScript)
348                            m_engineChannel->pScript->pKeyEvents[pKey->itSelf]->clear();
349                      pKey->Active = false;                      pKey->Active = false;
350                      pActiveKeys->free(pKey->itSelf); // remove key from list of active keys                      pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
351                      pKey->itSelf = RTList<uint>::Iterator();                      pKey->itSelf = RTList<uint>::Iterator();
# Line 315  namespace LinuxSampler { Line 363  namespace LinuxSampler {
363                  RTList<uint>::Iterator iuiKey = pActiveKeys->first();                  RTList<uint>::Iterator iuiKey = pActiveKeys->first();
364                  RTList<uint>::Iterator end    = pActiveKeys->end();                  RTList<uint>::Iterator end    = pActiveKeys->end();
365                  while (iuiKey != end) { // iterate through all active keys                  while (iuiKey != end) { // iterate through all active keys
366                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];                      MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
367                      ++iuiKey;                      ++iuiKey;
368                      if (pKey->pActiveVoices->isEmpty()) FreeKey(pKey);                      if (pKey->pActiveVoices->isEmpty()) FreeKey(pKey);
369                      #if CONFIG_DEVMODE                      #if CONFIG_DEVMODE
# Line 477  namespace LinuxSampler { Line 525  namespace LinuxSampler {
525                              iPendingStreamDeletions++;                              iPendingStreamDeletions++;
526                          }                          }
527                          // free the voice to the voice pool and update key info                          // free the voice to the voice pool and update key info
528                            itVoice->VoiceFreed();
529                          FreeVoice(itVoice);                          FreeVoice(itVoice);
530                      }                      }
531                  }                  }
# Line 517  namespace LinuxSampler { Line 566  namespace LinuxSampler {
566                      }                      }
567                  }                  }
568              }              }
569                
570                /**
571                 * Recalculate the pitch of all active voices.
572                 */
573                void OnScaleTuningChanged() {
574                    RTList<uint>::Iterator iuiKey = pActiveKeys->first();
575                    for (; iuiKey; ++iuiKey) {
576                        MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
577                        RTListVoiceIterator itVoice = pKey->pActiveVoices->first();
578                        for (; itVoice; ++itVoice) {
579                            itVoice->onScaleTuningChanged();
580                        }
581                    }
582                }
583                
584              void ProcessSustainPedalDown(Pool<Event>::Iterator& itEvent) {              void ProcessSustainPedalDown(Pool<Event>::Iterator& itEvent) {
585                  // Cancel release process of all voices                  // Cancel release process of all voices
586                  RTList<uint>::Iterator iuiKey = pActiveKeys->first();                  RTList<uint>::Iterator iuiKey = pActiveKeys->first();
# Line 598  namespace LinuxSampler { Line 661  namespace LinuxSampler {
661              void RemoveMidiKeyboardListener(MidiKeyboardListener* l) { listeners.RemoveListener(l); }              void RemoveMidiKeyboardListener(MidiKeyboardListener* l) { listeners.RemoveListener(l); }
662    
663          protected:          protected:
664                AbstractEngineChannel* m_engineChannel;
665    
666              class Listeners : public MidiKeyboardListener, public ListenerList<MidiKeyboardListener*> {              class Listeners : public MidiKeyboardListener, public ListenerList<MidiKeyboardListener*> {
667              public:              public:
668                  REGISTER_FIRE_EVENT_METHOD_ARG2(PreProcessNoteOn, uint8_t, uint8_t)                  REGISTER_FIRE_EVENT_METHOD_ARG2(PreProcessNoteOn, uint8_t, uint8_t)
# Line 616  namespace LinuxSampler { Line 681  namespace LinuxSampler {
681      };      };
682  } // namespace LinuxSampler  } // namespace LinuxSampler
683    
684  #endif  /* __LS_MIDIKEYBOARDMANAGER_H__ */  #endif  /* __LS_MIDIKEYBOARDMANAGER_H__ */
   

Legend:
Removed from v.2012  
changed lines
  Added in v.2645

  ViewVC Help
Powered by ViewVC