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

Diff of /linuxsampler/trunk/src/engines/EngineChannelBase.h

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

revision 2063 by persson, Sun Feb 28 07:28:56 2010 UTC revision 2611 by schoenebeck, Mon Jun 9 19:20:37 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-2013 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 39  namespace LinuxSampler { Line 39  namespace LinuxSampler {
39              bool bChangeInstrument;       ///< Set to true by the loader when the channel should change instrument.              bool bChangeInstrument;       ///< Set to true by the loader when the channel should change instrument.
40              I* pInstrument;               ///< The new instrument. Also used by the loader to read the previously loaded instrument.              I* pInstrument;               ///< The new instrument. Also used by the loader to read the previously loaded instrument.
41              RTList<R*>* pRegionsInUse; ///< List of dimension regions in use by the currently loaded instrument. Continuously updated by the audio thread.              RTList<R*>* pRegionsInUse; ///< List of dimension regions in use by the currently loaded instrument. Continuously updated by the audio thread.
42                InstrumentScript* pScript; ///< Instrument script to be executed for this instrument, or NULL if instrument does not have a script.
43      };      };
44    
45      template<class R>      template<class R>
# Line 68  namespace LinuxSampler { Line 69  namespace LinuxSampler {
69              virtual void ClearRegionsInUse() {              virtual void ClearRegionsInUse() {
70                  {                  {
71                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
72                      if(cmd.pRegionsInUse != NULL) cmd.pRegionsInUse->clear();                      if (cmd.pRegionsInUse) cmd.pRegionsInUse->clear();
73                        cmd.bChangeInstrument = false;
74                  }                  }
75                  {                  {
76                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
77                      if(cmd.pRegionsInUse != NULL) cmd.pRegionsInUse->clear();                      if (cmd.pRegionsInUse) cmd.pRegionsInUse->clear();
78                        cmd.bChangeInstrument = false;
79                  }                  }
80              }              }
81    
# Line 84  namespace LinuxSampler { Line 87  namespace LinuxSampler {
87              virtual void DeleteRegionsInUse() {              virtual void DeleteRegionsInUse() {
88                  {                  {
89                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
90                      if(cmd.pRegionsInUse != NULL) {                      if (cmd.pRegionsInUse) {
91                          delete cmd.pRegionsInUse;                          delete cmd.pRegionsInUse;
92                          cmd.pRegionsInUse = NULL;                          cmd.pRegionsInUse = NULL;
93                      }                      }
94                        cmd.bChangeInstrument = false;
95                  }                  }
96                  {                  {
97                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
98                      if(cmd.pRegionsInUse != NULL) {                      if (cmd.pRegionsInUse) {
99                          delete cmd.pRegionsInUse;                          delete cmd.pRegionsInUse;
100                          cmd.pRegionsInUse = NULL;                          cmd.pRegionsInUse = NULL;
101                      }                      }
102                        cmd.bChangeInstrument = false;
103                  }                  }
104              }              }
105    
# Line 102  namespace LinuxSampler { Line 107  namespace LinuxSampler {
107                  {                  {
108                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
109                      cmd.pRegionsInUse = new RTList<R*>(pRegionPool[0]);                      cmd.pRegionsInUse = new RTList<R*>(pRegionPool[0]);
110                        cmd.bChangeInstrument = false;
111                  }                  }
112                  {                  {
113                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
114                      cmd.pRegionsInUse = new RTList<R*>(pRegionPool[1]);                      cmd.pRegionsInUse = new RTList<R*>(pRegionPool[1]);
115                        cmd.bChangeInstrument = false;
116                  }                  }
117              }              }
118    
# Line 114  namespace LinuxSampler { Line 121  namespace LinuxSampler {
121                      if (pEngine->pAudioOutputDevice == pAudioOut) return;                      if (pEngine->pAudioOutputDevice == pAudioOut) return;
122                      DisconnectAudioOutputDevice();                      DisconnectAudioOutputDevice();
123                  }                  }
124                  pEngine = AbstractEngine::AcquireEngine(this, pAudioOut);                  AbstractEngine* newEngine = AbstractEngine::AcquireEngine(this, pAudioOut);
125                    {
126                        LockGuard lock(EngineMutex);
127                        pEngine = newEngine;
128                    }
129                  ResetInternal();                  ResetInternal();
130                  pEvents = new RTList<Event>(pEngine->pEventPool);                  pEvents = new RTList<Event>(pEngine->pEventPool);
131    
# Line 183  namespace LinuxSampler { Line 194  namespace LinuxSampler {
194    
195                      MidiKeyboardManager<V>::DeleteActiveVoices();                      MidiKeyboardManager<V>::DeleteActiveVoices();
196                      MidiKeyboardManager<V>::DeleteEvents();                      MidiKeyboardManager<V>::DeleteEvents();
197                        DeleteGroupEventLists();
198    
199                      AudioOutputDevice* oldAudioDevice = pEngine->pAudioOutputDevice;                      AudioOutputDevice* oldAudioDevice = pEngine->pAudioOutputDevice;
200                      pEngine = NULL;                      {
201                            LockGuard lock(EngineMutex);
202                            pEngine = NULL;
203                        }
204                      AbstractEngine::FreeEngine(this, oldAudioDevice);                      AbstractEngine::FreeEngine(this, oldAudioDevice);
205                      AudioDeviceChannelLeft  = -1;                      AudioDeviceChannelLeft  = -1;
206                      AudioDeviceChannelRight = -1;                      AudioDeviceChannelRight = -1;
# Line 207  namespace LinuxSampler { Line 222  namespace LinuxSampler {
222                  pEvents->clear();                  pEvents->clear();
223                  // empty MIDI key specific event lists                  // empty MIDI key specific event lists
224                  ClearEventListsHandler handler;                  ClearEventListsHandler handler;
225                  ProcessActiveVoices(&handler);                  this->ProcessActiveVoices(&handler);
226    
227                    // empty exclusive group specific event lists
228                    // (pInstrument == 0 could mean that LoadInstrument is
229                    // building new group event lists, so we must check
230                    // for that)
231                    if (pInstrument) ClearGroupEventLists();
232              }              }
233    
234              // implementation of abstract methods derived from interface class 'InstrumentConsumer'              // implementation of abstract methods derived from interface class 'InstrumentConsumer'
# Line 217  namespace LinuxSampler { Line 238  namespace LinuxSampler {
238               * we are currently using on this EngineChannel is going to be updated,               * we are currently using on this EngineChannel is going to be updated,
239               * so we can stop playback before that happens.               * so we can stop playback before that happens.
240               */               */
241              virtual void ResourceToBeUpdated(I* pResource, void*& pUpdateArg) {              virtual void ResourceToBeUpdated(I* pResource, void*& pUpdateArg) OVERRIDE {
242                  dmsg(3,("EngineChannelBase: Received instrument update message.\n"));                  dmsg(3,("EngineChannelBase: Received instrument update message.\n"));
243                  if (pEngine) pEngine->DisableAndLock();                  if (pEngine) pEngine->DisableAndLock();
244                  ResetInternal();                  ResetInternal();
# Line 228  namespace LinuxSampler { Line 249  namespace LinuxSampler {
249               * Will be called by the InstrumentResourceManager when the instrument               * Will be called by the InstrumentResourceManager when the instrument
250               * update process was completed, so we can continue with playback.               * update process was completed, so we can continue with playback.
251               */               */
252              virtual void ResourceUpdated(I* pOldResource, I* pNewResource, void* pUpdateArg) {              virtual void ResourceUpdated(I* pOldResource, I* pNewResource, void* pUpdateArg) OVERRIDE {
253                  this->pInstrument = pNewResource; //TODO: there are couple of engine parameters we should update here as well if the instrument was updated (see LoadInstrument())                  this->pInstrument = pNewResource; //TODO: there are couple of engine parameters we should update here as well if the instrument was updated (see LoadInstrument())
254                  if (pEngine) pEngine->Enable();                  if (pEngine) pEngine->Enable();
255                  bStatusChanged = true; // status of engine has changed, so set notify flag                  bStatusChanged = true; // status of engine has changed, so set notify flag
# Line 240  namespace LinuxSampler { Line 261  namespace LinuxSampler {
261               *               *
262               * @param fProgress - current progress as value between 0.0 and 1.0               * @param fProgress - current progress as value between 0.0 and 1.0
263               */               */
264              virtual void OnResourceProgress(float fProgress) {              virtual void OnResourceProgress(float fProgress) OVERRIDE {
265                  this->InstrumentStat = int(fProgress * 100.0f);                  this->InstrumentStat = int(fProgress * 100.0f);
266                  dmsg(7,("EngineChannelBase: progress %d%", InstrumentStat));                  dmsg(7,("EngineChannelBase: progress %d%", InstrumentStat));
267                  bStatusChanged = true; // status of engine has changed, so set notify flag                  bStatusChanged = true; // status of engine has changed, so set notify flag
# Line 248  namespace LinuxSampler { Line 269  namespace LinuxSampler {
269    
270              void RenderActiveVoices(uint Samples) {              void RenderActiveVoices(uint Samples) {
271                  RenderVoicesHandler handler(this, Samples);                  RenderVoicesHandler handler(this, Samples);
272                  ProcessActiveVoices(&handler);                  this->ProcessActiveVoices(&handler);
273    
274                  SetVoiceCount(handler.VoiceCount);                  SetVoiceCount(handler.VoiceCount);
275                  SetDiskStreamCount(handler.StreamCount);                  SetDiskStreamCount(handler.StreamCount);
# Line 269  namespace LinuxSampler { Line 290  namespace LinuxSampler {
290                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
291                      cmd.pRegionsInUse = NULL;                      cmd.pRegionsInUse = NULL;
292                      cmd.pInstrument = NULL;                      cmd.pInstrument = NULL;
293                        cmd.pScript = new InstrumentScript(this);
294                      cmd.bChangeInstrument = false;                      cmd.bChangeInstrument = false;
295                  }                  }
296                  {                  {
297                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
298                      cmd.pRegionsInUse = NULL;                      cmd.pRegionsInUse = NULL;
299                      cmd.pInstrument = NULL;                      cmd.pInstrument = NULL;
300                        cmd.pScript = new InstrumentScript(this);
301                      cmd.bChangeInstrument = false;                      cmd.bChangeInstrument = false;
302                  }                  }
303              }              }
304    
305              virtual ~EngineChannelBase() { }              virtual ~EngineChannelBase() {
306                    {
307                        InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
308                        if (cmd.pScript) delete cmd.pScript;
309                    }
310                    {
311                        InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
312                        if (cmd.pScript) delete cmd.pScript;
313                    }
314                }
315    
316              typedef typename RTList<V>::Iterator RTListVoiceIterator;              typedef typename RTList<V>::Iterator RTListVoiceIterator;
317    
# Line 306  namespace LinuxSampler { Line 338  namespace LinuxSampler {
338                                  if ((itVoice->DiskStreamRef).State != Stream::state_unused) StreamCount++;                                  if ((itVoice->DiskStreamRef).State != Stream::state_unused) StreamCount++;
339                              }                              }
340                          }  else { // voice reached end, is now inactive                          }  else { // voice reached end, is now inactive
341                                itVoice->VoiceFreed();
342                              pChannel->FreeVoice(itVoice); // remove voice from the list of active voices                              pChannel->FreeVoice(itVoice); // remove voice from the list of active voices
343                          }                          }
344                      }                      }
# Line 331  namespace LinuxSampler { Line 364  namespace LinuxSampler {
364              }              }
365    
366              /**              /**
367                 * Load real-time instrument script and all its resources required
368                 * for the upcoming instrument change.
369                 *
370                 * @param text - source code of script
371                 */
372                void LoadInstrumentScript(const String& text) {
373                    InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
374                    // unload *PRE*-previous script
375                    cmd.pScript->reset(); //TODO: previous script should be freed as soon as the EngineBase switched the instrument, right now 2 scripts are kept in memory all the time, even though the old one is not used anymore
376                    // load the new script
377                    cmd.pScript->load(text);
378                }
379    
380                /**
381               * Changes the instrument for an engine channel.               * Changes the instrument for an engine channel.
382               *               *
383               * @param pInstrument - new instrument               * @param pInstrument - new instrument
# Line 347  namespace LinuxSampler { Line 394  namespace LinuxSampler {
394              }              }
395    
396              virtual void ProcessKeySwitchChange(int key) = 0;              virtual void ProcessKeySwitchChange(int key) = 0;
   
             /**  
              * Handle key group (a.k.a. exclusive group) conflicts  
              */  
         void HandleKeyGroupConflicts(uint KeyGroup, Pool<Event>::Iterator& itNoteOnEvent, bool UseRelease = false) {  
                 if (KeyGroup) { // if this voice / key belongs to a key group  
                     uint* pKeyGroup = MidiKeyboardManager<V>::ActiveKeyGroups[KeyGroup];  
                     if (pKeyGroup) { // if there's already an active key in that key group  
                         MidiKey* pOtherKey = &MidiKeyboardManager<V>::pMIDIKeyInfo[*pKeyGroup];  
   
                         if (UseRelease) {  
                             // send a note off to the other key  
                             if (pOtherKey->KeyPressed && itNoteOnEvent->Param.Note.Key != *pKeyGroup) {  
                                 RTList<Event>::Iterator itNewEvent = pEngine->pGlobalEvents->allocAppend();  
                                 if (itNewEvent) {  
                                     pOtherKey->ReleaseTrigger = false;  
                                     *itNewEvent = *itNoteOnEvent;  
                                     itNewEvent->Type = Event::type_note_off;  
                                     itNewEvent->Param.Note.Key = *pKeyGroup;  
                                     pEngine->ProcessNoteOff(this, itNewEvent);  
                                 }  
                             }  
                         } else {  
                             // kill all voices on the (other) key  
                             typename RTList<V>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();  
                             typename RTList<V>::Iterator end               = pOtherKey->pActiveVoices->end();  
                             for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {  
                                 if (itVoiceToBeKilled->Type != Voice::type_release_trigger) {  
                                     itVoiceToBeKilled->Kill(itNoteOnEvent);  
                                     --pEngine->VoiceSpawnsLeft; //FIXME: just a hack, we should better check in StealVoice() if the voice was killed due to key conflict  
                                 }  
                             }  
                         }  
                     }  
                 }  
             }  
397      };      };
398    
399  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2063  
changed lines
  Added in v.2611

  ViewVC Help
Powered by ViewVC