/[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 2121 by schoenebeck, Tue Sep 14 17:09:08 2010 UTC revision 2559 by schoenebeck, Sun May 18 17:38:25 2014 UTC
# Line 4  Line 4 
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-2008 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2010 Christian Schoenebeck and 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 143  namespace LinuxSampler { Line 143  namespace LinuxSampler {
143                          }                          }
144                      }                      }
145                  }                  }
146                    
147                    // In case scale tuning has been changed, recalculate pitch for
148                    // all active voices.
149                    ProcessScaleTuningChange();
150    
151                  // reset internal voice counter (just for statistic of active voices)                  // reset internal voice counter (just for statistic of active voices)
152                  ActiveVoiceCountTemp = 0;                  ActiveVoiceCountTemp = 0;
# Line 190  namespace LinuxSampler { Line 194  namespace LinuxSampler {
194                  // been deleted by the disk thread                  // been deleted by the disk thread
195                  if (iPendingStreamDeletions) ProcessPendingStreamDeletions();                  if (iPendingStreamDeletions) ProcessPendingStreamDeletions();
196    
197                    // Release the instrument change command. (This has to
198                    // be done after all voices have been rendered and not
199                    // in HandleInstrumentChanges, as the RegionsInUse
200                    // list has been built up by the voice renderers.)
201                    for (int i = 0; i < engineChannels.size(); i++) {
202                        EngineChannelBase<V, R, I>* channel =
203                            static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
204                        channel->InstrumentChangeCommandReader.Unlock();
205                    }
206                  FrameTime += Samples;                  FrameTime += Samples;
207    
208                  EngineDisabled.RttDone();                  EngineDisabled.RttDone();
209                  return 0;                  return 0;
210              }              }
211    
212              virtual int MaxVoices() { return pVoicePool->poolSize(); }              virtual int MaxVoices() OVERRIDE { return pVoicePool->poolSize(); }
213    
214              virtual void SetMaxVoices(int iVoices) throw (Exception) {              virtual void SetMaxVoices(int iVoices) throw (Exception) OVERRIDE {
215                  if (iVoices < 1)                  if (iVoices < 1)
216                      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");
217    
# Line 234  namespace LinuxSampler { Line 247  namespace LinuxSampler {
247                  }                  }
248                  pVoicePool->clear();                  pVoicePool->clear();
249    
250                    PostSetMaxVoices(iVoices);
251                  ResumeAll();                  ResumeAll();
252              }              }
253                
254                /** Called after the new max number of voices is set and before resuming the engine. */
255                virtual void PostSetMaxVoices(int iVoices) { }
256    
257              virtual uint DiskStreamCount() { return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0; }              virtual uint DiskStreamCount() OVERRIDE { return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0; }
258              virtual uint DiskStreamCountMax() { return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0; }              virtual uint DiskStreamCountMax() OVERRIDE { return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0; }
259              virtual int  MaxDiskStreams() { return iMaxDiskStreams; }              virtual int  MaxDiskStreams() OVERRIDE { return iMaxDiskStreams; }
260    
261              virtual void SetMaxDiskStreams(int iStreams) throw (Exception) {              virtual void SetMaxDiskStreams(int iStreams) throw (Exception) OVERRIDE {
262                  if (iStreams < 0)                  if (iStreams < 0)
263                      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");
264    
# Line 256  namespace LinuxSampler { Line 273  namespace LinuxSampler {
273                  ResumeAll();                  ResumeAll();
274              }              }
275    
276              virtual String DiskStreamBufferFillBytes() { return (pDiskThread) ? pDiskThread->GetBufferFillBytes() : ""; }              virtual String DiskStreamBufferFillBytes() OVERRIDE { return (pDiskThread) ? pDiskThread->GetBufferFillBytes() : ""; }
277              virtual String DiskStreamBufferFillPercentage() { return (pDiskThread) ? pDiskThread->GetBufferFillPercentage() : ""; }              virtual String DiskStreamBufferFillPercentage() OVERRIDE { return (pDiskThread) ? pDiskThread->GetBufferFillPercentage() : ""; }
278              virtual InstrumentManager* GetInstrumentManager() { return &instruments; }              virtual InstrumentManager* GetInstrumentManager() OVERRIDE { return &instruments; }
279    
280              /**              /**
281               * 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 286  namespace LinuxSampler {
286               *               *
287               * @param pAudioOut - audio output device to connect to               * @param pAudioOut - audio output device to connect to
288               */               */
289              virtual void Connect(AudioOutputDevice* pAudioOut) {              virtual void Connect(AudioOutputDevice* pAudioOut) OVERRIDE {
290                  // caution: don't ignore if connecting to the same device here,                  // caution: don't ignore if connecting to the same device here,
291                  // because otherwise SetMaxDiskStreams() implementation won't work anymore!                  // because otherwise SetMaxDiskStreams() implementation won't work anymore!
292    
# Line 299  namespace LinuxSampler { Line 316  namespace LinuxSampler {
316                      // lower minimum release time                      // lower minimum release time
317                      const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;                      const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
318                      for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {                      for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
319                          iterVoice->pEG1->CalculateFadeOutCoeff(minReleaseTime, SampleRate);                          iterVoice->CalculateFadeOutCoeff(minReleaseTime, SampleRate);
320                      }                      }
321                      pVoicePool->clear();                      pVoicePool->clear();
322                  }                  }
# Line 332  namespace LinuxSampler { Line 349  namespace LinuxSampler {
349                  pDiskThread->StartThread();                  pDiskThread->StartThread();
350                  dmsg(1,("OK\n"));                  dmsg(1,("OK\n"));
351    
352                    bool printEqInfo = true;
353                  for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {                  for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
354                      if (!iterVoice->pDiskThread) {                      if (!iterVoice->pDiskThread) {
355                          dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));                          dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
356                          exit(EXIT_FAILURE);                          exit(EXIT_FAILURE);
357                      }                      }
358                        
359                        iterVoice->CreateEq();
360                        
361                        if(printEqInfo) {
362                            iterVoice->PrintEqInfo();
363                            printEqInfo = false;
364                        }
365                  }                  }
366                  pVoicePool->clear();                  pVoicePool->clear();
367                                    
# Line 347  namespace LinuxSampler { Line 372  namespace LinuxSampler {
372                  pDedicatedVoiceChannelLeft  = new AudioChannel(0, MaxSamplesPerCycle);                  pDedicatedVoiceChannelLeft  = new AudioChannel(0, MaxSamplesPerCycle);
373                  pDedicatedVoiceChannelRight = new AudioChannel(1, MaxSamplesPerCycle);                  pDedicatedVoiceChannelRight = new AudioChannel(1, MaxSamplesPerCycle);
374              }              }
375            
376                // Implementattion for abstract method derived from Engine.
377                virtual void ReconnectAudioOutputDevice() OVERRIDE {
378                    SuspendAll();
379                    if (pAudioOutputDevice) Connect(pAudioOutputDevice);
380                    ResumeAll();
381                }
382    
383              /**              /**
384               * Similar to @c Disable() but this method additionally kills all voices               * Similar to @c Disable() but this method additionally kills all voices
# Line 401  namespace LinuxSampler { Line 433  namespace LinuxSampler {
433               */               */
434              virtual void Suspend(RR* pRegion) {              virtual void Suspend(RR* pRegion) {
435                  dmsg(2,("EngineBase: Suspending Region %x ...\n",pRegion));                  dmsg(2,("EngineBase: Suspending Region %x ...\n",pRegion));
436                  SuspendedRegionsMutex.Lock();                  {
437                  SuspensionChangeOngoing.Set(true);                      LockGuard lock(SuspendedRegionsMutex);
438                  pPendingRegionSuspension = pRegion;                      SuspensionChangeOngoing.Set(true);
439                  SuspensionChangeOngoing.WaitAndUnlockIf(true);                      pPendingRegionSuspension = pRegion;
440                  SuspendedRegionsMutex.Unlock();                      SuspensionChangeOngoing.WaitAndUnlockIf(true);
441                    }
442                  dmsg(2,("EngineBase: Region %x suspended.",pRegion));                  dmsg(2,("EngineBase: Region %x suspended.",pRegion));
443              }              }
444    
# Line 417  namespace LinuxSampler { Line 450  namespace LinuxSampler {
450               */               */
451              virtual void Resume(RR* pRegion) {              virtual void Resume(RR* pRegion) {
452                  dmsg(2,("EngineBase: Resuming Region %x ...\n",pRegion));                  dmsg(2,("EngineBase: Resuming Region %x ...\n",pRegion));
453                  SuspendedRegionsMutex.Lock();                  {
454                  SuspensionChangeOngoing.Set(true);                      LockGuard lock(SuspendedRegionsMutex);
455                  pPendingRegionResumption = pRegion;                      SuspensionChangeOngoing.Set(true);
456                  SuspensionChangeOngoing.WaitAndUnlockIf(true);                      pPendingRegionResumption = pRegion;
457                  SuspendedRegionsMutex.Unlock();                      SuspensionChangeOngoing.WaitAndUnlockIf(true);
458                    }
459                  dmsg(2,("EngineBase: Region %x resumed.\n",pRegion));                  dmsg(2,("EngineBase: Region %x resumed.\n",pRegion));
460              }              }
461    
# Line 537  namespace LinuxSampler { Line 571  namespace LinuxSampler {
571    
572              //friend class EngineChannelBase<V, R, I>;              //friend class EngineChannelBase<V, R, I>;
573    
574                static IM instruments;
575    
576          protected:          protected:
577              class SuspensionVoiceHandler : public MidiKeyboardManager<V>::VoiceHandler {              class SuspensionVoiceHandler : public MidiKeyboardManager<V>::VoiceHandler {
578              public:              public:
579                  int PendingStreamDeletions;                  int PendingStreamDeletions;
580                  RR* pPendingRegionSuspension;                  RR* pPendingRegionSuspension;
581    
582                  SuspensionVoiceHandler(RR* pPendingRegionSuspension) {                  SuspensionVoiceHandler(RR* pPendingRegionSuspension) {
583                      PendingStreamDeletions = 0;                      PendingStreamDeletions = 0;
584                      this->pPendingRegionSuspension = pPendingRegionSuspension;                      this->pPendingRegionSuspension = pPendingRegionSuspension;
585                  }                  }
586    
587                  virtual bool Process(MidiKey* pMidiKey) {                  virtual bool Process(MidiKey* pMidiKey) OVERRIDE {
588                      VoiceIterator itVoice = pMidiKey->pActiveVoices->first();                      VoiceIterator itVoice = pMidiKey->pActiveVoices->first();
589                      // if current key is not associated with this region, skip this key                      // if current key is not associated with this region, skip this key
590                      if (itVoice->GetRegion()->GetParent() != pPendingRegionSuspension) return false;                      if (itVoice->GetRegion()->GetParent() != pPendingRegionSuspension) return false;
# Line 555  namespace LinuxSampler { Line 592  namespace LinuxSampler {
592                      return true;                      return true;
593                  }                  }
594    
595                  virtual void Process(VoiceIterator& itVoice) {                  virtual void Process(VoiceIterator& itVoice) OVERRIDE {
596                      // request a notification from disk thread side for stream deletion                      // request a notification from disk thread side for stream deletion
597                      const Stream::Handle hStream = itVoice->KillImmediately(true);                      const Stream::Handle hStream = itVoice->KillImmediately(true);
598                      if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream                      if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream
# Line 565  namespace LinuxSampler { Line 602  namespace LinuxSampler {
602                  }                  }
603              };              };
604    
             static IM instruments;  
   
605              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.
606              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.
607              D*        pDiskThread;              D*        pDiskThread;
# Line 614  namespace LinuxSampler { Line 649  namespace LinuxSampler {
649                                  dmsg(5,("Engine: MIDI CC received\n"));                                  dmsg(5,("Engine: MIDI CC received\n"));
650                                  ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);                                  ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
651                                  break;                                  break;
652                                case Event::type_channel_pressure:
653                                    dmsg(5,("Engine: MIDI Chan. Pressure received\n"));
654                                    ProcessChannelPressure((EngineChannel*)itEvent->pEngineChannel, itEvent);
655                                    break;
656                                case Event::type_note_pressure:
657                                    dmsg(5,("Engine: MIDI Note Pressure received\n"));
658                                    ProcessPolyphonicKeyPressure((EngineChannel*)itEvent->pEngineChannel, itEvent);
659                                    break;
660                              case Event::type_pitchbend:                              case Event::type_pitchbend:
661                                  dmsg(5,("Engine: Pitchbend received\n"));                                  dmsg(5,("Engine: Pitchbend received\n"));
662                                  ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);                                  ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);
# Line 772  namespace LinuxSampler { Line 815  namespace LinuxSampler {
815                      //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
816                      ResetSuspendedRegions();                      ResetSuspendedRegions();
817                  }                  }
   
                 for (int i = 0; i < engineChannels.size(); i++) {  
                     EngineChannelBase<V, R, I>* channel =  
                         static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);  
                     channel->InstrumentChangeCommandReader.Unlock();  
                 }  
818              }              }
819    
820              /**              /**
# Line 953  namespace LinuxSampler { Line 990  namespace LinuxSampler {
990                      }                      }
991                      case 10: { // panpot                      case 10: { // panpot
992                          //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];  
993                          pChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;                          pChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;
994                          break;                          break;
995                      }                      }
# Line 1305  namespace LinuxSampler { Line 1340  namespace LinuxSampler {
1340               *  control and status variables. This method is protected by a mutex.               *  control and status variables. This method is protected by a mutex.
1341               */               */
1342              virtual void ResetInternal() {              virtual void ResetInternal() {
1343                  ResetInternalMutex.Lock();                  LockGuard lock(ResetInternalMutex);
1344    
1345                  // make sure that the engine does not get any sysex messages                  // make sure that the engine does not get any sysex messages
1346                  // while it's reseting                  // while it's reseting
# Line 1334  namespace LinuxSampler { Line 1369  namespace LinuxSampler {
1369                  pEventQueue->init();                  pEventQueue->init();
1370                  pSysexBuffer->init();                  pSysexBuffer->init();
1371                  if (sysexDisabled) MidiInputPort::AddSysexListener(this);                  if (sysexDisabled) MidiInputPort::AddSysexListener(this);
                 ResetInternalMutex.Unlock();  
1372              }              }
1373    
1374              /**              /**
# Line 1430  namespace LinuxSampler { Line 1464  namespace LinuxSampler {
1464    
1465                  return -1;                  return -1;
1466              }              }
1467                
1468                /**
1469                 * Checks whether scale tuning setting has been changed since last
1470                 * time this method was called, if yes, it recalculates the pitch
1471                 * for all active voices.
1472                 */
1473                void ProcessScaleTuningChange() {
1474                    const bool changed = ScaleTuningChanged.readAndReset();
1475                    if (!changed) return;
1476                    
1477                    for (int i = 0; i < engineChannels.size(); i++) {
1478                        EngineChannelBase<V, R, I>* channel =
1479                            static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
1480                        channel->OnScaleTuningChanged();
1481                    }
1482                }
1483    
1484          private:          private:
1485              Pool<V>*    pVoicePool;            ///< Contains all voices that can be activated.              Pool<V>*    pVoicePool;            ///< Contains all voices that can be activated.

Legend:
Removed from v.2121  
changed lines
  Added in v.2559

  ViewVC Help
Powered by ViewVC