/[svn]/linuxsampler/trunk/src/engines/AbstractEngine.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/AbstractEngine.cpp

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

revision 2298 by iliev, Fri Dec 9 17:04:24 2011 UTC revision 3707 by schoenebeck, Wed Jan 8 21:21:58 2020 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-2008 Christian Schoenebeck                         *   *   Copyright (C) 2005-2020 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2010 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2012 Grigor Iliev                                  *
8     *   Copyright (C) 2013-2016 Andreas Persson                               *
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   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 60  namespace LinuxSampler { Line 61  namespace LinuxSampler {
61          } else { // create a new engine (and disk thread) instance for the given audio output device          } else { // create a new engine (and disk thread) instance for the given audio output device
62              dmsg(4,("Creating new Engine.\n"));              dmsg(4,("Creating new Engine.\n"));
63              pEngine = (AbstractEngine*) EngineFactory::Create(pChannel->EngineName());              pEngine = (AbstractEngine*) EngineFactory::Create(pChannel->EngineName());
64                pEngine->CreateInstrumentScriptVM();
65              pEngine->Connect(pDevice);              pEngine->Connect(pDevice);
66              engines[pChannel->GetEngineFormat()][pDevice] = pEngine;              engines[pChannel->GetEngineFormat()][pDevice] = pEngine;
67          }          }
# Line 67  namespace LinuxSampler { Line 69  namespace LinuxSampler {
69          pEngine->engineChannels.add(pChannel);          pEngine->engineChannels.add(pChannel);
70          // remember index in the ArrayList          // remember index in the ArrayList
71          pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;          pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
72          dmsg(4,("This Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));          dmsg(4,("This Engine has now %" PRId64 " EngineChannels.\n", (int64_t)pEngine->engineChannels.size()));
73          return pEngine;          return pEngine;
74      }      }
75    
76      AbstractEngine::AbstractEngine() {      AbstractEngine::AbstractEngine() {
77          pAudioOutputDevice = NULL;          pAudioOutputDevice = NULL;
78          pEventGenerator    = NULL;          pEventGenerator    = new EventGenerator(44100);
79          pSysexBuffer       = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);          pSysexBuffer       = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);
80          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
81          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
82            pEventPool->setPoolElementIDsReservedBits(INSTR_SCRIPT_EVENT_ID_RESERVED_BITS);
83          pGlobalEvents      = new RTList<Event>(pEventPool);          pGlobalEvents      = new RTList<Event>(pEventPool);
84          FrameTime          = 0;          FrameTime          = 0;
85          RandomSeed         = 0;          RandomSeed         = 0;
86          pDedicatedVoiceChannelLeft = pDedicatedVoiceChannelRight = NULL;          pDedicatedVoiceChannelLeft = pDedicatedVoiceChannelRight = NULL;
87            pScriptVM          = NULL;
88      }      }
89    
90      AbstractEngine::~AbstractEngine() {      AbstractEngine::~AbstractEngine() {
# Line 91  namespace LinuxSampler { Line 95  namespace LinuxSampler {
95          if (pSysexBuffer) delete pSysexBuffer;          if (pSysexBuffer) delete pSysexBuffer;
96          if (pDedicatedVoiceChannelLeft) delete pDedicatedVoiceChannelLeft;          if (pDedicatedVoiceChannelLeft) delete pDedicatedVoiceChannelLeft;
97          if (pDedicatedVoiceChannelRight) delete pDedicatedVoiceChannelRight;          if (pDedicatedVoiceChannelRight) delete pDedicatedVoiceChannelRight;
98            if (pScriptVM) delete pScriptVM;
99          Unregister();          Unregister();
100      }      }
101    
102        void AbstractEngine::CreateInstrumentScriptVM() {
103            dmsg(2,("Created sampler format independent instrument script VM.\n"));
104            if (pScriptVM) return;
105            pScriptVM = new InstrumentScriptVM; // format independent script runner
106        }
107    
108      /**      /**
109       * Once an engine channel is disconnected from an audio output device,       * Once an engine channel is disconnected from an audio output device,
110       * it will immediately call this method to unregister itself from the       * it will immediately call this method to unregister itself from the
# Line 116  namespace LinuxSampler { Line 127  namespace LinuxSampler {
127              delete pEngine;              delete pEngine;
128              dmsg(4,("Destroying Engine.\n"));              dmsg(4,("Destroying Engine.\n"));
129          }          }
130          else dmsg(4,("This Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));          else dmsg(4,("This Engine has now %" PRId64 " EngineChannels.\n", (int64_t)pEngine->engineChannels.size()));
131      }      }
132    
133      void AbstractEngine::Enable() {      void AbstractEngine::Enable() {
# Line 165  namespace LinuxSampler { Line 176  namespace LinuxSampler {
176       */       */
177      void AbstractEngine::ResetScaleTuning() {      void AbstractEngine::ResetScaleTuning() {
178          memset(&ScaleTuning[0], 0x00, 12);          memset(&ScaleTuning[0], 0x00, 12);
179            ScaleTuningChanged.raise();
180      }      }
181    
182      /**      /**
# Line 302  namespace LinuxSampler { Line 314  namespace LinuxSampler {
314          for (int iChan = 0; iChan < 2; ++iChan) {          for (int iChan = 0; iChan < 2; ++iChan) {
315              const int iDstChan = pFxSend->DestinationChannel(iChan);              const int iDstChan = pFxSend->DestinationChannel(iChan);
316              if (iDstChan < 0) {              if (iDstChan < 0) {
317                  dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));                  dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)\n",
318                            ((iChan) ? "R" : "L"), iChan, iDstChan));
319                  return false; // error                  return false; // error
320              }              }
321              AudioChannel* pDstChan = NULL;              AudioChannel* pDstChan = NULL;
322                Effect* pEffect = NULL;
323              if (pFxSend->DestinationEffectChain() >= 0) { // fx send routed to an internal send effect              if (pFxSend->DestinationEffectChain() >= 0) { // fx send routed to an internal send effect
324                  EffectChain* pEffectChain =                  EffectChain* pEffectChain =
325                      pAudioOutputDevice->SendEffectChainByID(                      pAudioOutputDevice->SendEffectChainByID(
326                          pFxSend->DestinationEffectChain()                          pFxSend->DestinationEffectChain()
327                      );                      );
328                  if (!pEffectChain) {                  if (!pEffectChain) {
329                      dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChain()));                      dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d\n",
330                                ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChain()));
331                      return false; // error                      return false; // error
332                  }                  }
333                  Effect* pEffect =                  pEffect =
334                      pEffectChain->GetEffect(                      pEffectChain->GetEffect(
335                          pFxSend->DestinationEffectChainPosition()                          pFxSend->DestinationEffectChainPosition()
336                      );                      );
337                  if (!pEffect) {                  if (!pEffect) {
338                      dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChainPosition(), pFxSend->DestinationEffectChain()));                      dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d\n",
339                                ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChainPosition(), pFxSend->DestinationEffectChain()));
340                      return false; // error                      return false; // error
341                  }                  }
342                  pDstChan = pEffect->InputChannel(iDstChan);                  pDstChan = pEffect->InputChannel(iDstChan);
343              } else { // FX send routed directly to an audio output channel              } else { // FX send routed directly to audio output device channel(s)
344                  pDstChan = pAudioOutputDevice->Channel(iDstChan);                  pDstChan = pAudioOutputDevice->Channel(iDstChan);
345              }              }
346              if (!pDstChan) {              if (!pDstChan) {
347                  dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));                  if (pFxSend->DestinationEffectChain() >= 0) { // fx send routed to an internal send effect
348                        const int iEffectChannels = pEffect ? pEffect->InputChannelCount() : 0;
349                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d): "
350                                "FX send is routed to effect %d of effect chain %d and that effect has %d input channels\n",
351                                ((iChan) ? "R" : "L"), iChan, iDstChan,
352                                pFxSend->DestinationEffectChainPosition(),
353                                pFxSend->DestinationEffectChain(), iEffectChannels));
354                    } else { // FX send routed directly to audio output device channel(s)
355                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d): "
356                                "FX send is directly routed to audio output device which has %d output channels\n",
357                                ((iChan) ? "R" : "L"), iChan, iDstChan,
358                                (pAudioOutputDevice ? pAudioOutputDevice->ChannelCount() : 0)));
359                    }
360                  return false; // error                  return false; // error
361              }              }
362              ppSource[iChan]->MixTo(pDstChan, Samples, FxSendLevel);              ppSource[iChan]->MixTo(pDstChan, Samples, FxSendLevel);
# Line 346  namespace LinuxSampler { Line 374  namespace LinuxSampler {
374       */       */
375      uint8_t AbstractEngine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {      uint8_t AbstractEngine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {
376          RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;          RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
377          uint bytes = 3 /*addr*/ + DataSize;          uint bytes = 3 /*addr*/ + DataSize;        
         uint8_t addr_and_data[bytes];  
         reader.read(&addr_and_data[0], bytes);  
378          uint8_t sum = 0;          uint8_t sum = 0;
379          for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];          uint8_t c;
380            for (uint i = 0; i < bytes; ++i) {
381                if (!reader.pop(&c)) break;
382                sum += c;
383            }
384          return 128 - sum % 128;          return 128 - sum % 128;
385      }      }
386    
# Line 359  namespace LinuxSampler { Line 389  namespace LinuxSampler {
389       *       *
390       * @param ScaleTunes - detuning of all twelve semitones (in cents)       * @param ScaleTunes - detuning of all twelve semitones (in cents)
391       */       */
392      void AbstractEngine::AdjustScale(int8_t ScaleTunes[12]) {      void AbstractEngine::AdjustScaleTuning(const int8_t ScaleTunes[12]) {
393          memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate          memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12);
394            ScaleTuningChanged.raise();
395        }
396        
397        void AbstractEngine::GetScaleTuning(int8_t* pScaleTunes) {
398            memcpy(pScaleTunes, &this->ScaleTuning[0], 12);
399      }      }
400    
401      uint AbstractEngine::VoiceCount() {      uint AbstractEngine::VoiceCount() {
# Line 376  namespace LinuxSampler { Line 411  namespace LinuxSampler {
411      }      }
412    
413      /**      /**
414       *  Moves pitchbend event from the general (input) event list to the engine       *  Stores the latest pitchbend event as current pitchbend scalar value.
      *  channel's event list. It will actually processed later by the  
      *  respective voice.  
415       *       *
416       *  @param pEngineChannel - engine channel on which this event occured on       *  @param pEngineChannel - engine channel on which this event occured on
417       *  @param itPitchbendEvent - absolute pitch value and time stamp of the event       *  @param itPitchbendEvent - absolute pitch value and time stamp of the event
# Line 499  namespace LinuxSampler { Line 532  namespace LinuxSampler {
532    
533                  // command address                  // command address
534                  uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)                  uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
535                  const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later                  //const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
536                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
537                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
538                      dmsg(3,("\tSystem Parameter\n"));                      dmsg(3,("\tSystem Parameter\n"));
# Line 507  namespace LinuxSampler { Line 540  namespace LinuxSampler {
540                          for (int i = 0; i < engineChannels.size(); ++i) {                          for (int i = 0; i < engineChannels.size(); ++i) {
541                              AbstractEngineChannel* pEngineChannel                              AbstractEngineChannel* pEngineChannel
542                                  = static_cast<AbstractEngineChannel*>(engineChannels[i]);                                  = static_cast<AbstractEngineChannel*>(engineChannels[i]);
543                              if (pEngineChannel->GetMidiInputPort() == itSysexEvent->pMidiInputPort) {                              Sync< ArrayList<MidiInputPort*> > midiInputs = pEngineChannel->midiInputs.front();
544                                  KillAllVoices(pEngineChannel, itSysexEvent);                              for (int k = 0; k < midiInputs->size(); ++k) {
545                                  pEngineChannel->ResetControllers();                                  if ((*midiInputs)[k] == itSysexEvent->pMidiInputPort) {
546                                        KillAllVoices(pEngineChannel, itSysexEvent);
547                                        pEngineChannel->ResetControllers();
548                                        break;
549                                    }
550                              }                              }
551                          }                          }
552                      }                      }
# Line 530  namespace LinuxSampler { Line 567  namespace LinuxSampler {
567                              if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;                              if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
568                              #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM                              #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
569                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
570                              AdjustScale((int8_t*) scale_tunes);                              AdjustScaleTuning((int8_t*) scale_tunes);
571                              dmsg(3,("\t\t\tNew scale applied.\n"));                              dmsg(3,("\t\t\tNew scale applied.\n"));
572                              break;                              break;
573                          }                          }
# Line 542  namespace LinuxSampler { Line 579  namespace LinuxSampler {
579                              for (int i = 0; i < engineChannels.size(); ++i) {                              for (int i = 0; i < engineChannels.size(); ++i) {
580                                  AbstractEngineChannel* pEngineChannel                                  AbstractEngineChannel* pEngineChannel
581                                      = static_cast<AbstractEngineChannel*>(engineChannels[i]);                                      = static_cast<AbstractEngineChannel*>(engineChannels[i]);
582                                  if (                                  if (pEngineChannel->midiChannel == part ||
583                                      (pEngineChannel->midiChannel == part ||                                      pEngineChannel->midiChannel == midi_chan_all)
584                                       pEngineChannel->midiChannel == midi_chan_all) &&                                  {  
585                                       pEngineChannel->GetMidiInputPort() == itSysexEvent->pMidiInputPort                                      Sync< ArrayList<MidiInputPort*> > midiInputs = pEngineChannel->midiInputs.front();
586                                  ) {                                      for (int k = 0; k < midiInputs->size(); ++k) {
587                                      try {                                          if ((*midiInputs)[k] == itSysexEvent->pMidiInputPort) {
588                                          pEngineChannel->SetMidiInstrumentMap(map);                                              try {
589                                      } catch (Exception e) {                                                  pEngineChannel->SetMidiInstrumentMap(map);
590                                          dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d: %s\n", map, part, e.Message().c_str()));                                              } catch (Exception e) {
591                                          goto free_sysex_data;                                                  dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d: %s\n", map, part, e.Message().c_str()));
592                                      } catch (...) {                                                  goto free_sysex_data;
593                                          dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part));                                              } catch (...) {
594                                          goto free_sysex_data;                                                  dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part));
595                                                    goto free_sysex_data;
596                                                }
597                                                break;
598                                            }
599                                      }                                      }
600                                  }                                  }
601                              }                              }
# Line 630  namespace LinuxSampler { Line 671  namespace LinuxSampler {
671          return y;          return y;
672      }      }
673    
674        /**
675         * Returns the volume factor to be used for the requested signed,
676         * normalized @a pan value and audio @a channel index.
677         *
678         * @param pan - between -1.0 (most left) and +1.0 (most right)
679         * @param channel - 0: return value for left channel, 1: return value for right channel
680         * @returns final volume factor for the requested audio channel to be applied
681         */
682        float AbstractEngine::PanCurveValueNorm(float pan, int channel) {
683            float pan128 = (pan + 1.f) / 2.f * 128.f;
684            if (channel == 0) pan128 = 128 - pan128;
685            return PanCurve[pan128]; //TODO: interpolation should be done here (float type "pan" argument here allows a much more fine graded result value than those 129 steps of the PanCurve)
686        }
687    
688  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC