/[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 2298 by iliev, Fri Dec 9 17:04:24 2011 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-2011 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 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();
# 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() { return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0; }
254              virtual uint DiskStreamCountMax() { return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0; }              virtual uint DiskStreamCountMax() { return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0; }
# 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->pEG1->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              /**              /**
# Line 530  namespace LinuxSampler { Line 558  namespace LinuxSampler {
558    
559              //friend class EngineChannelBase<V, R, I>;              //friend class EngineChannelBase<V, R, I>;
560    
561                static IM instruments;
562    
563          protected:          protected:
564              class SuspensionVoiceHandler : public MidiKeyboardManager<V>::VoiceHandler {              class SuspensionVoiceHandler : public MidiKeyboardManager<V>::VoiceHandler {
565              public:              public:
# Line 558  namespace LinuxSampler { Line 588  namespace LinuxSampler {
588                  }                  }
589              };              };
590    
             static IM instruments;  
   
591              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.
592              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.
593              D*        pDiskThread;              D*        pDiskThread;
# Line 765  namespace LinuxSampler { Line 793  namespace LinuxSampler {
793                      //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
794                      ResetSuspendedRegions();                      ResetSuspendedRegions();
795                  }                  }
   
                 for (int i = 0; i < engineChannels.size(); i++) {  
                     EngineChannelBase<V, R, I>* channel =  
                         static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);  
                     channel->InstrumentChangeCommandReader.Unlock();  
                 }  
796              }              }
797    
798              /**              /**
# Line 857  namespace LinuxSampler { Line 879  namespace LinuxSampler {
879                  pChannel->ClearEventLists();                  pChannel->ClearEventLists();
880              }              }
881    
882                /**
883                 * Process MIDI control change events with hard coded behavior,
884                 * that is controllers whose behavior is defined independently
885                 * of the actual sampler engine type and instrument.
886                 *
887                 * @param pEngineChannel - engine channel on which the MIDI CC event was received
888                 * @param itControlChangeEvent - the actual MIDI CC event
889                 */
890              void ProcessHardcodedControllers (              void ProcessHardcodedControllers (
891                  EngineChannel*          pEngineChannel,                  EngineChannel*          pEngineChannel,
892                  Pool<Event>::Iterator&  itControlChangeEvent                  Pool<Event>::Iterator&  itControlChangeEvent
# Line 869  namespace LinuxSampler { Line 899  namespace LinuxSampler {
899                          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;
900                          break;                          break;
901                      }                      }
902                      case 6: { // data entry (currently only used for RPN controllers)                      case 6: { // data entry (currently only used for RPN and NRPN controllers)
903                          if (pChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones                          //dmsg(1,("DATA ENTRY %d\n", itControlChangeEvent->Param.CC.Value));
904                              int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;                          if (pChannel->GetMidiRpnController() >= 0) { // RPN controller number was sent previously ...
905                              // limit to +- two octaves for now                              dmsg(4,("Guess it's an RPN ...\n"));
906                              transpose = RTMath::Min(transpose,  24);                              if (pChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
907                              transpose = RTMath::Max(transpose, -24);                                  int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
908                              pChannel->GlobalTranspose = transpose;                                  // limit to +- two octaves for now
909                              // workaround, so we won't have hanging notes                                  transpose = RTMath::Min(transpose,  24);
910                              pChannel->ReleaseAllVoices(itControlChangeEvent);                                  transpose = RTMath::Max(transpose, -24);
911                                    pChannel->GlobalTranspose = transpose;
912                                    // workaround, so we won't have hanging notes
913                                    pChannel->ReleaseAllVoices(itControlChangeEvent);
914                                }
915                                // to prevent other MIDI CC #6 messages to be misenterpreted as RPN controller data
916                                pChannel->ResetMidiRpnController();
917                            } else if (pChannel->GetMidiNrpnController() >= 0) { // NRPN controller number was sent previously ...
918                                dmsg(4,("Guess it's an NRPN ...\n"));
919                                const int NrpnCtrlMSB = pChannel->GetMidiNrpnController() >> 8;
920                                const int NrpnCtrlLSB = pChannel->GetMidiNrpnController() & 0xff;
921                                dmsg(4,("NRPN MSB=%d LSB=%d Data=%d\n", NrpnCtrlMSB, NrpnCtrlLSB, itControlChangeEvent->Param.CC.Value));
922                                switch (NrpnCtrlMSB) {
923                                    case 0x1a: { // volume level of note (Roland GS NRPN)
924                                        const uint note = NrpnCtrlLSB;
925                                        const uint vol  = itControlChangeEvent->Param.CC.Value;
926                                        dmsg(4,("Note Volume NRPN received (note=%d,vol=%d).\n", note, vol));
927                                        if (note < 128 && vol < 128)
928                                            pChannel->pMIDIKeyInfo[note].Volume = VolumeCurve[vol];
929                                        break;
930                                    }
931                                    case 0x1c: { // panpot of note (Roland GS NRPN)
932                                        const uint note = NrpnCtrlLSB;
933                                        const uint pan  = itControlChangeEvent->Param.CC.Value;
934                                        dmsg(4,("Note Pan NRPN received (note=%d,pan=%d).\n", note, pan));
935                                        if (note < 128 && pan < 128) {
936                                            pChannel->pMIDIKeyInfo[note].PanLeft  = PanCurve[128 - pan];
937                                            pChannel->pMIDIKeyInfo[note].PanRight = PanCurve[pan];
938                                        }
939                                        break;
940                                    }
941                                    case 0x1d: { // reverb send of note (Roland GS NRPN)
942                                        const uint note = NrpnCtrlLSB;
943                                        const float reverb = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
944                                        dmsg(4,("Note Reverb Send NRPN received (note=%d,send=%d).\n", note, reverb));
945                                        if (note < 128)
946                                            pChannel->pMIDIKeyInfo[note].ReverbSend = reverb;
947                                        break;
948                                    }
949                                    case 0x1e: { // chorus send of note (Roland GS NRPN)
950                                        const uint note = NrpnCtrlLSB;
951                                        const float chorus = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
952                                        dmsg(4,("Note Chorus Send NRPN received (note=%d,send=%d).\n", note, chorus));
953                                        if (note < 128)
954                                            pChannel->pMIDIKeyInfo[note].ChorusSend = chorus;
955                                        break;
956                                    }
957                                }
958                                // to prevent other MIDI CC #6 messages to be misenterpreted as NRPN controller data
959                                pChannel->ResetMidiNrpnController();
960                          }                          }
                         // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data  
                         pChannel->ResetMidiRpnController();  
961                          break;                          break;
962                      }                      }
963                      case 7: { // volume                      case 7: { // volume
# Line 969  namespace LinuxSampler { Line 1046  namespace LinuxSampler {
1046                          }                          }
1047                          break;                          break;
1048                      }                      }
1049                        case 98: { // NRPN controller LSB
1050                            dmsg(4,("NRPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1051                            pEngineChannel->SetMidiNrpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1052                            break;
1053                        }
1054                        case 99: { // NRPN controller MSB
1055                            dmsg(4,("NRPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1056                            pEngineChannel->SetMidiNrpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1057                            break;
1058                        }
1059                      case 100: { // RPN controller LSB                      case 100: { // RPN controller LSB
1060                            dmsg(4,("RPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1061                          pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);                          pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1062                          break;                          break;
1063                      }                      }
1064                      case 101: { // RPN controller MSB                      case 101: { // RPN controller MSB
1065                            dmsg(4,("RPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1066                          pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);                          pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1067                          break;                          break;
1068                      }                      }
# Line 1064  namespace LinuxSampler { Line 1153  namespace LinuxSampler {
1153                              VoiceIterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();                              VoiceIterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
1154                              VoiceIterator end               = pOtherKey->pActiveVoices->end();                              VoiceIterator end               = pOtherKey->pActiveVoices->end();
1155                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1156                                  if (itVoiceToBeKilled->Type != Voice::type_release_trigger)                                  if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1157                                      itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);                                      itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
1158                              }                              }
1159                          }                          }
# Line 1096  namespace LinuxSampler { Line 1185  namespace LinuxSampler {
1185                      pKey->pEvents->free(itNoteOnEventOnKeyList);                      pKey->pEvents->free(itNoteOnEventOnKeyList);
1186    
1187                  if (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f) pChannel->PortamentoPos = (float) key;                  if (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f) pChannel->PortamentoPos = (float) key;
1188                  pKey->RoundRobinIndex++;                  if (pKey->pRoundRobinIndex) {
1189                        (*pKey->pRoundRobinIndex)++; // counter specific for the key or region
1190                        pChannel->RoundRobinIndex++; // common counter for the channel
1191                    }
1192                  pChannel->listeners.PostProcessNoteOn(key, vel);                  pChannel->listeners.PostProcessNoteOn(key, vel);
1193              }              }
1194    
# Line 1198  namespace LinuxSampler { Line 1290  namespace LinuxSampler {
1290                              VoiceIterator itVoiceToBeKilled = pKey->pActiveVoices->first();                              VoiceIterator itVoiceToBeKilled = pKey->pActiveVoices->first();
1291                              VoiceIterator end               = pKey->pActiveVoices->end();                              VoiceIterator end               = pKey->pActiveVoices->end();
1292                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1293                                  if (itVoiceToBeKilled->Type != Voice::type_release_trigger)                                  if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1294                                      itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);                                      itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1295                              }                              }
1296                          }                          }
# Line 1331  namespace LinuxSampler { Line 1423  namespace LinuxSampler {
1423                              pKey->itSelf = pChannel->pActiveKeys->allocAppend();                              pKey->itSelf = pChannel->pActiveKeys->allocAppend();
1424                              *pKey->itSelf = itNoteOnEvent->Param.Note.Key;                              *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
1425                          }                          }
1426                          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)  
1427                          return 0; // success                          return 0; // success
1428                      }                      }
1429                  }                  }

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

  ViewVC Help
Powered by ViewVC