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

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

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

revision 2027 by iliev, Tue Nov 3 19:27:42 2009 UTC revision 2434 by schoenebeck, Thu Mar 7 19:23:24 2013 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 104  namespace LinuxSampler { Line 104  namespace LinuxSampler {
104               *  @param Samples - number of sample points to be rendered               *  @param Samples - number of sample points to be rendered
105               *  @returns       0 on success               *  @returns       0 on success
106               */               */
107              virtual int RenderAudio(uint Samples) {              virtual int RenderAudio(uint Samples) OVERRIDE {
108                  dmsg(8,("RenderAudio(Samples=%d)\n", Samples));                  dmsg(8,("RenderAudio(Samples=%d)\n", Samples));
109    
110                  // return if engine disabled                  // return if engine disabled
# Line 190  namespace LinuxSampler { Line 190  namespace LinuxSampler {
190                  // been deleted by the disk thread                  // been deleted by the disk thread
191                  if (iPendingStreamDeletions) ProcessPendingStreamDeletions();                  if (iPendingStreamDeletions) ProcessPendingStreamDeletions();
192    
193                    // Release the instrument change command. (This has to
194                    // be done after all voices have been rendered and not
195                    // in HandleInstrumentChanges, as the RegionsInUse
196                    // list has been built up by the voice renderers.)
197                    for (int i = 0; i < engineChannels.size(); i++) {
198                        EngineChannelBase<V, R, I>* channel =
199                            static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
200                        channel->InstrumentChangeCommandReader.Unlock();
201                    }
202                  FrameTime += Samples;                  FrameTime += Samples;
203    
204                  EngineDisabled.RttDone();                  EngineDisabled.RttDone();
205                  return 0;                  return 0;
206              }              }
207    
208              virtual int MaxVoices() { return pVoicePool->poolSize(); }              virtual int MaxVoices() OVERRIDE { return pVoicePool->poolSize(); }
209    
210              virtual void SetMaxVoices(int iVoices) throw (Exception) {              virtual void SetMaxVoices(int iVoices) throw (Exception) OVERRIDE {
211                  if (iVoices < 1)                  if (iVoices < 1)
212                      throw Exception("Maximum voices for an engine cannot be set lower than 1");                      throw Exception("Maximum voices for an engine cannot be set lower than 1");
213    
# Line 234  namespace LinuxSampler { Line 243  namespace LinuxSampler {
243                  }                  }
244                  pVoicePool->clear();                  pVoicePool->clear();
245    
246                    PostSetMaxVoices(iVoices);
247                  ResumeAll();                  ResumeAll();
248              }              }
249                
250                /** Called after the new max number of voices is set and before resuming the engine. */
251                virtual void PostSetMaxVoices(int iVoices) { }
252    
253              virtual uint DiskStreamCount() { return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0; }              virtual uint DiskStreamCount() OVERRIDE { return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0; }
254              virtual uint DiskStreamCountMax() { return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0; }              virtual uint DiskStreamCountMax() OVERRIDE { return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0; }
255              virtual int  MaxDiskStreams() { return iMaxDiskStreams; }              virtual int  MaxDiskStreams() OVERRIDE { return iMaxDiskStreams; }
256    
257              virtual void SetMaxDiskStreams(int iStreams) throw (Exception) {              virtual void SetMaxDiskStreams(int iStreams) throw (Exception) OVERRIDE {
258                  if (iStreams < 0)                  if (iStreams < 0)
259                      throw Exception("Maximum disk streams for an engine cannot be set lower than 0");                      throw Exception("Maximum disk streams for an engine cannot be set lower than 0");
260    
# Line 256  namespace LinuxSampler { Line 269  namespace LinuxSampler {
269                  ResumeAll();                  ResumeAll();
270              }              }
271    
272              virtual String DiskStreamBufferFillBytes() { return (pDiskThread) ? pDiskThread->GetBufferFillBytes() : ""; }              virtual String DiskStreamBufferFillBytes() OVERRIDE { return (pDiskThread) ? pDiskThread->GetBufferFillBytes() : ""; }
273              virtual String DiskStreamBufferFillPercentage() { return (pDiskThread) ? pDiskThread->GetBufferFillPercentage() : ""; }              virtual String DiskStreamBufferFillPercentage() OVERRIDE { return (pDiskThread) ? pDiskThread->GetBufferFillPercentage() : ""; }
274              virtual InstrumentManager* GetInstrumentManager() { return &instruments; }              virtual InstrumentManager* GetInstrumentManager() OVERRIDE { return &instruments; }
275    
276              /**              /**
277               * Connect this engine instance with the given audio output device.               * Connect this engine instance with the given audio output device.
# Line 269  namespace LinuxSampler { Line 282  namespace LinuxSampler {
282               *               *
283               * @param pAudioOut - audio output device to connect to               * @param pAudioOut - audio output device to connect to
284               */               */
285              virtual void Connect(AudioOutputDevice* pAudioOut) {              virtual void Connect(AudioOutputDevice* pAudioOut) OVERRIDE {
286                  // caution: don't ignore if connecting to the same device here,                  // caution: don't ignore if connecting to the same device here,
287                  // because otherwise SetMaxDiskStreams() implementation won't work anymore!                  // because otherwise SetMaxDiskStreams() implementation won't work anymore!
288    
# Line 299  namespace LinuxSampler { Line 312  namespace LinuxSampler {
312                      // lower minimum release time                      // lower minimum release time
313                      const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;                      const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
314                      for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {                      for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
315                          iterVoice->EG1.CalculateFadeOutCoeff(minReleaseTime, SampleRate);                          iterVoice->CalculateFadeOutCoeff(minReleaseTime, SampleRate);
316                      }                      }
317                      pVoicePool->clear();                      pVoicePool->clear();
318                  }                  }
# Line 332  namespace LinuxSampler { Line 345  namespace LinuxSampler {
345                  pDiskThread->StartThread();                  pDiskThread->StartThread();
346                  dmsg(1,("OK\n"));                  dmsg(1,("OK\n"));
347    
348                    bool printEqInfo = true;
349                  for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {                  for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
350                      if (!iterVoice->pDiskThread) {                      if (!iterVoice->pDiskThread) {
351                          dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));                          dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
352                          exit(EXIT_FAILURE);                          exit(EXIT_FAILURE);
353                      }                      }
354                        
355                        iterVoice->CreateEq();
356                        
357                        if(printEqInfo) {
358                            iterVoice->PrintEqInfo();
359                            printEqInfo = false;
360                        }
361                  }                  }
362                  pVoicePool->clear();                  pVoicePool->clear();
363                    
364                    // (re)create dedicated voice audio buffers
365                    //TODO: we could optimize resource usage a bit by just allocating these dedicated voice buffers when there is at least one engine channel with FX sends, because only in this case those special buffers are used actually, but since it would usually only save couple bytes in total, its probably not worth it
366                    if (pDedicatedVoiceChannelLeft)  delete pDedicatedVoiceChannelLeft;
367                    if (pDedicatedVoiceChannelRight) delete pDedicatedVoiceChannelRight;
368                    pDedicatedVoiceChannelLeft  = new AudioChannel(0, MaxSamplesPerCycle);
369                    pDedicatedVoiceChannelRight = new AudioChannel(1, MaxSamplesPerCycle);
370                }
371            
372                // Implementattion for abstract method derived from Engine.
373                virtual void ReconnectAudioOutputDevice() OVERRIDE {
374                    SuspendAll();
375                    if (pAudioOutputDevice) Connect(pAudioOutputDevice);
376                    ResumeAll();
377              }              }
378    
379              /**              /**
# Line 394  namespace LinuxSampler { Line 429  namespace LinuxSampler {
429               */               */
430              virtual void Suspend(RR* pRegion) {              virtual void Suspend(RR* pRegion) {
431                  dmsg(2,("EngineBase: Suspending Region %x ...\n",pRegion));                  dmsg(2,("EngineBase: Suspending Region %x ...\n",pRegion));
432                  SuspendedRegionsMutex.Lock();                  {
433                  SuspensionChangeOngoing.Set(true);                      LockGuard lock(SuspendedRegionsMutex);
434                  pPendingRegionSuspension = pRegion;                      SuspensionChangeOngoing.Set(true);
435                  SuspensionChangeOngoing.WaitAndUnlockIf(true);                      pPendingRegionSuspension = pRegion;
436                  SuspendedRegionsMutex.Unlock();                      SuspensionChangeOngoing.WaitAndUnlockIf(true);
437                    }
438                  dmsg(2,("EngineBase: Region %x suspended.",pRegion));                  dmsg(2,("EngineBase: Region %x suspended.",pRegion));
439              }              }
440    
# Line 410  namespace LinuxSampler { Line 446  namespace LinuxSampler {
446               */               */
447              virtual void Resume(RR* pRegion) {              virtual void Resume(RR* pRegion) {
448                  dmsg(2,("EngineBase: Resuming Region %x ...\n",pRegion));                  dmsg(2,("EngineBase: Resuming Region %x ...\n",pRegion));
449                  SuspendedRegionsMutex.Lock();                  {
450                  SuspensionChangeOngoing.Set(true);                      LockGuard lock(SuspendedRegionsMutex);
451                  pPendingRegionResumption = pRegion;                      SuspensionChangeOngoing.Set(true);
452                  SuspensionChangeOngoing.WaitAndUnlockIf(true);                      pPendingRegionResumption = pRegion;
453                  SuspendedRegionsMutex.Unlock();                      SuspensionChangeOngoing.WaitAndUnlockIf(true);
454                    }
455                  dmsg(2,("EngineBase: Region %x resumed.\n",pRegion));                  dmsg(2,("EngineBase: Region %x resumed.\n",pRegion));
456              }              }
457    
# Line 530  namespace LinuxSampler { Line 567  namespace LinuxSampler {
567    
568              //friend class EngineChannelBase<V, R, I>;              //friend class EngineChannelBase<V, R, I>;
569    
570                static IM instruments;
571    
572          protected:          protected:
573              class SuspensionVoiceHandler : public MidiKeyboardManager<V>::VoiceHandler {              class SuspensionVoiceHandler : public MidiKeyboardManager<V>::VoiceHandler {
574              public:              public:
575                  int PendingStreamDeletions;                  int PendingStreamDeletions;
576                  RR* pPendingRegionSuspension;                  RR* pPendingRegionSuspension;
577    
578                  SuspensionVoiceHandler(RR* pPendingRegionSuspension) {                  SuspensionVoiceHandler(RR* pPendingRegionSuspension) {
579                      PendingStreamDeletions = 0;                      PendingStreamDeletions = 0;
580                      this->pPendingRegionSuspension = pPendingRegionSuspension;                      this->pPendingRegionSuspension = pPendingRegionSuspension;
581                  }                  }
582    
583                  virtual bool Process(MidiKey* pMidiKey) {                  virtual bool Process(MidiKey* pMidiKey) OVERRIDE {
584                      VoiceIterator itVoice = pMidiKey->pActiveVoices->first();                      VoiceIterator itVoice = pMidiKey->pActiveVoices->first();
585                      // if current key is not associated with this region, skip this key                      // if current key is not associated with this region, skip this key
586                      if (itVoice->GetRegion()->GetParent() != pPendingRegionSuspension) return false;                      if (itVoice->GetRegion()->GetParent() != pPendingRegionSuspension) return false;
# Line 548  namespace LinuxSampler { Line 588  namespace LinuxSampler {
588                      return true;                      return true;
589                  }                  }
590    
591                  virtual void Process(VoiceIterator& itVoice) {                  virtual void Process(VoiceIterator& itVoice) OVERRIDE {
592                      // request a notification from disk thread side for stream deletion                      // request a notification from disk thread side for stream deletion
593                      const Stream::Handle hStream = itVoice->KillImmediately(true);                      const Stream::Handle hStream = itVoice->KillImmediately(true);
594                      if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream                      if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream
# Line 558  namespace LinuxSampler { Line 598  namespace LinuxSampler {
598                  }                  }
599              };              };
600    
             static IM instruments;  
   
601              Pool<R*>* pRegionPool[2]; ///< Double buffered pool, used by the engine channels to keep track of regions in use.              Pool<R*>* pRegionPool[2]; ///< Double buffered pool, used by the engine channels to keep track of regions in use.
602              int       MinFadeOutSamples;     ///< The number of samples needed to make an instant fade out (e.g. for voice stealing) without leading to clicks.              int       MinFadeOutSamples;     ///< The number of samples needed to make an instant fade out (e.g. for voice stealing) without leading to clicks.
603              D*        pDiskThread;              D*        pDiskThread;
# Line 765  namespace LinuxSampler { Line 803  namespace LinuxSampler {
803                      //TODO: this is a lazy solution ATM and not safe in case somebody is currently editing the instrument we're currently switching to (we should store all suspended regions on instrument manager side and when switching to another instrument copy that list to the engine's local list of suspensions                      //TODO: this is a lazy solution ATM and not safe in case somebody is currently editing the instrument we're currently switching to (we should store all suspended regions on instrument manager side and when switching to another instrument copy that list to the engine's local list of suspensions
804                      ResetSuspendedRegions();                      ResetSuspendedRegions();
805                  }                  }
   
                 for (int i = 0; i < engineChannels.size(); i++) {  
                     EngineChannelBase<V, R, I>* channel =  
                         static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);  
                     channel->InstrumentChangeCommandReader.Unlock();  
                 }  
806              }              }
807    
808              /**              /**
# Line 857  namespace LinuxSampler { Line 889  namespace LinuxSampler {
889                  pChannel->ClearEventLists();                  pChannel->ClearEventLists();
890              }              }
891    
892                /**
893                 * Process MIDI control change events with hard coded behavior,
894                 * that is controllers whose behavior is defined independently
895                 * of the actual sampler engine type and instrument.
896                 *
897                 * @param pEngineChannel - engine channel on which the MIDI CC event was received
898                 * @param itControlChangeEvent - the actual MIDI CC event
899                 */
900              void ProcessHardcodedControllers (              void ProcessHardcodedControllers (
901                  EngineChannel*          pEngineChannel,                  EngineChannel*          pEngineChannel,
902                  Pool<Event>::Iterator&  itControlChangeEvent                  Pool<Event>::Iterator&  itControlChangeEvent
# Line 869  namespace LinuxSampler { Line 909  namespace LinuxSampler {
909                          pChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;                          pChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
910                          break;                          break;
911                      }                      }
912                      case 6: { // data entry (currently only used for RPN controllers)                      case 6: { // data entry (currently only used for RPN and NRPN controllers)
913                          if (pChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones                          //dmsg(1,("DATA ENTRY %d\n", itControlChangeEvent->Param.CC.Value));
914                              int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;                          if (pChannel->GetMidiRpnController() >= 0) { // RPN controller number was sent previously ...
915                              // limit to +- two octaves for now                              dmsg(4,("Guess it's an RPN ...\n"));
916                              transpose = RTMath::Min(transpose,  24);                              if (pChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
917                              transpose = RTMath::Max(transpose, -24);                                  int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
918                              pChannel->GlobalTranspose = transpose;                                  // limit to +- two octaves for now
919                              // workaround, so we won't have hanging notes                                  transpose = RTMath::Min(transpose,  24);
920                              pChannel->ReleaseAllVoices(itControlChangeEvent);                                  transpose = RTMath::Max(transpose, -24);
921                                    pChannel->GlobalTranspose = transpose;
922                                    // workaround, so we won't have hanging notes
923                                    pChannel->ReleaseAllVoices(itControlChangeEvent);
924                                }
925                                // to prevent other MIDI CC #6 messages to be misenterpreted as RPN controller data
926                                pChannel->ResetMidiRpnController();
927                            } else if (pChannel->GetMidiNrpnController() >= 0) { // NRPN controller number was sent previously ...
928                                dmsg(4,("Guess it's an NRPN ...\n"));
929                                const int NrpnCtrlMSB = pChannel->GetMidiNrpnController() >> 8;
930                                const int NrpnCtrlLSB = pChannel->GetMidiNrpnController() & 0xff;
931                                dmsg(4,("NRPN MSB=%d LSB=%d Data=%d\n", NrpnCtrlMSB, NrpnCtrlLSB, itControlChangeEvent->Param.CC.Value));
932                                switch (NrpnCtrlMSB) {
933                                    case 0x1a: { // volume level of note (Roland GS NRPN)
934                                        const uint note = NrpnCtrlLSB;
935                                        const uint vol  = itControlChangeEvent->Param.CC.Value;
936                                        dmsg(4,("Note Volume NRPN received (note=%d,vol=%d).\n", note, vol));
937                                        if (note < 128 && vol < 128)
938                                            pChannel->pMIDIKeyInfo[note].Volume = VolumeCurve[vol];
939                                        break;
940                                    }
941                                    case 0x1c: { // panpot of note (Roland GS NRPN)
942                                        const uint note = NrpnCtrlLSB;
943                                        const uint pan  = itControlChangeEvent->Param.CC.Value;
944                                        dmsg(4,("Note Pan NRPN received (note=%d,pan=%d).\n", note, pan));
945                                        if (note < 128 && pan < 128) {
946                                            pChannel->pMIDIKeyInfo[note].PanLeft  = PanCurve[128 - pan];
947                                            pChannel->pMIDIKeyInfo[note].PanRight = PanCurve[pan];
948                                        }
949                                        break;
950                                    }
951                                    case 0x1d: { // reverb send of note (Roland GS NRPN)
952                                        const uint note = NrpnCtrlLSB;
953                                        const float reverb = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
954                                        dmsg(4,("Note Reverb Send NRPN received (note=%d,send=%d).\n", note, reverb));
955                                        if (note < 128)
956                                            pChannel->pMIDIKeyInfo[note].ReverbSend = reverb;
957                                        break;
958                                    }
959                                    case 0x1e: { // chorus send of note (Roland GS NRPN)
960                                        const uint note = NrpnCtrlLSB;
961                                        const float chorus = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
962                                        dmsg(4,("Note Chorus Send NRPN received (note=%d,send=%d).\n", note, chorus));
963                                        if (note < 128)
964                                            pChannel->pMIDIKeyInfo[note].ChorusSend = chorus;
965                                        break;
966                                    }
967                                }
968                                // to prevent other MIDI CC #6 messages to be misenterpreted as NRPN controller data
969                                pChannel->ResetMidiNrpnController();
970                          }                          }
                         // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data  
                         pChannel->ResetMidiRpnController();  
971                          break;                          break;
972                      }                      }
973                      case 7: { // volume                      case 7: { // volume
# Line 891  namespace LinuxSampler { Line 978  namespace LinuxSampler {
978                      }                      }
979                      case 10: { // panpot                      case 10: { // panpot
980                          //TODO: not sample accurate yet                          //TODO: not sample accurate yet
                         pChannel->GlobalPanLeft  = PanCurve[128 - itControlChangeEvent->Param.CC.Value];  
                         pChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value];  
981                          pChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;                          pChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;
982                          break;                          break;
983                      }                      }
# Line 969  namespace LinuxSampler { Line 1054  namespace LinuxSampler {
1054                          }                          }
1055                          break;                          break;
1056                      }                      }
1057                        case 98: { // NRPN controller LSB
1058                            dmsg(4,("NRPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1059                            pEngineChannel->SetMidiNrpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1060                            break;
1061                        }
1062                        case 99: { // NRPN controller MSB
1063                            dmsg(4,("NRPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1064                            pEngineChannel->SetMidiNrpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1065                            break;
1066                        }
1067                      case 100: { // RPN controller LSB                      case 100: { // RPN controller LSB
1068                            dmsg(4,("RPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1069                          pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);                          pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1070                          break;                          break;
1071                      }                      }
1072                      case 101: { // RPN controller MSB                      case 101: { // RPN controller MSB
1073                            dmsg(4,("RPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1074                          pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);                          pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1075                          break;                          break;
1076                      }                      }
# Line 1064  namespace LinuxSampler { Line 1161  namespace LinuxSampler {
1161                              VoiceIterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();                              VoiceIterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
1162                              VoiceIterator end               = pOtherKey->pActiveVoices->end();                              VoiceIterator end               = pOtherKey->pActiveVoices->end();
1163                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1164                                  if (itVoiceToBeKilled->Type != Voice::type_release_trigger)                                  if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1165                                      itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);                                      itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
1166                              }                              }
1167                          }                          }
# Line 1096  namespace LinuxSampler { Line 1193  namespace LinuxSampler {
1193                      pKey->pEvents->free(itNoteOnEventOnKeyList);                      pKey->pEvents->free(itNoteOnEventOnKeyList);
1194    
1195                  if (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f) pChannel->PortamentoPos = (float) key;                  if (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f) pChannel->PortamentoPos = (float) key;
1196                  pKey->RoundRobinIndex++;                  if (pKey->pRoundRobinIndex) {
1197                        (*pKey->pRoundRobinIndex)++; // counter specific for the key or region
1198                        pChannel->RoundRobinIndex++; // common counter for the channel
1199                    }
1200                  pChannel->listeners.PostProcessNoteOn(key, vel);                  pChannel->listeners.PostProcessNoteOn(key, vel);
1201              }              }
1202    
# Line 1198  namespace LinuxSampler { Line 1298  namespace LinuxSampler {
1298                              VoiceIterator itVoiceToBeKilled = pKey->pActiveVoices->first();                              VoiceIterator itVoiceToBeKilled = pKey->pActiveVoices->first();
1299                              VoiceIterator end               = pKey->pActiveVoices->end();                              VoiceIterator end               = pKey->pActiveVoices->end();
1300                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1301                                  if (itVoiceToBeKilled->Type != Voice::type_release_trigger)                                  if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1302                                      itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);                                      itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1303                              }                              }
1304                          }                          }
# Line 1228  namespace LinuxSampler { Line 1328  namespace LinuxSampler {
1328               *  control and status variables. This method is protected by a mutex.               *  control and status variables. This method is protected by a mutex.
1329               */               */
1330              virtual void ResetInternal() {              virtual void ResetInternal() {
1331                  ResetInternalMutex.Lock();                  LockGuard lock(ResetInternalMutex);
1332    
1333                  // make sure that the engine does not get any sysex messages                  // make sure that the engine does not get any sysex messages
1334                  // while it's reseting                  // while it's reseting
# Line 1257  namespace LinuxSampler { Line 1357  namespace LinuxSampler {
1357                  pEventQueue->init();                  pEventQueue->init();
1358                  pSysexBuffer->init();                  pSysexBuffer->init();
1359                  if (sysexDisabled) MidiInputPort::AddSysexListener(this);                  if (sysexDisabled) MidiInputPort::AddSysexListener(this);
                 ResetInternalMutex.Unlock();  
1360              }              }
1361    
1362              /**              /**
# Line 1331  namespace LinuxSampler { Line 1430  namespace LinuxSampler {
1430                              pKey->itSelf = pChannel->pActiveKeys->allocAppend();                              pKey->itSelf = pChannel->pActiveKeys->allocAppend();
1431                              *pKey->itSelf = itNoteOnEvent->Param.Note.Key;                              *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
1432                          }                          }
1433                          if (itNewVoice->KeyGroup) {                          if (itNewVoice->Type & Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
                             uint** ppKeyGroup = &pChannel->ActiveKeyGroups[itNewVoice->KeyGroup];  
                             *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group  
                         }  
                         if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)  
1434                          return 0; // success                          return 0; // success
1435                      }                      }
1436                  }                  }

Legend:
Removed from v.2027  
changed lines
  Added in v.2434

  ViewVC Help
Powered by ViewVC