/[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 2091 by persson, Sat May 15 09:02:31 2010 UTC revision 2879 by schoenebeck, Tue Apr 19 14:07:53 2016 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-2012 Christian Schoenebeck and Grigor Iliev        *
8     *   Copyright (C) 2013-2014 Christian Schoenebeck and 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 26  Line 27 
27  #include "AbstractEngineChannel.h"  #include "AbstractEngineChannel.h"
28  #include "EngineFactory.h"  #include "EngineFactory.h"
29  #include "../common/global_private.h"  #include "../common/global_private.h"
30    #include "../effects/EffectFactory.h"
31    
32  namespace LinuxSampler {  namespace LinuxSampler {
33    
# Line 59  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 76  namespace LinuxSampler { Line 79  namespace LinuxSampler {
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;
87            pScriptVM          = NULL;
88      }      }
89    
90      AbstractEngine::~AbstractEngine() {      AbstractEngine::~AbstractEngine() {
# Line 87  namespace LinuxSampler { Line 93  namespace LinuxSampler {
93          if (pEventGenerator) delete pEventGenerator;          if (pEventGenerator) delete pEventGenerator;
94          if (pGlobalEvents) delete pGlobalEvents;          if (pGlobalEvents) delete pGlobalEvents;
95          if (pSysexBuffer) delete pSysexBuffer;          if (pSysexBuffer) delete pSysexBuffer;
96            if (pDedicatedVoiceChannelLeft) delete pDedicatedVoiceChannelLeft;
97            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 161  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 221  namespace LinuxSampler { Line 237  namespace LinuxSampler {
237       */       */
238      void AbstractEngine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {      void AbstractEngine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
239          AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);          AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
240            AudioChannel* ppSource[2] = {
241                pChannel->pChannelLeft,
242                pChannel->pChannelRight
243            };
244          // route dry signal          // route dry signal
245          {          {
246              AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);              AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);
247              AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);              AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);
248              pChannel->pChannelLeft->MixTo(pDstL, Samples);              ppSource[0]->MixTo(pDstL, Samples);
249              pChannel->pChannelRight->MixTo(pDstR, Samples);              ppSource[1]->MixTo(pDstR, Samples);
250          }          }
251          // route FX send signal          // route FX send signal (wet)
252          {          {
253              for (int iFxSend = 0; iFxSend < pChannel->GetFxSendCount(); iFxSend++) {              for (int iFxSend = 0; iFxSend < pChannel->GetFxSendCount(); iFxSend++) {
254                  FxSend* pFxSend = pChannel->GetFxSend(iFxSend);                  FxSend* pFxSend = pChannel->GetFxSend(iFxSend);
255                  for (int iChan = 0; iChan < 2; ++iChan) {                  const bool success = RouteFxSend(pFxSend, ppSource, pFxSend->Level(), Samples);
256                      AudioChannel* pSource =                  if (!success) goto channel_cleanup;
                         (iChan)  
                             ? pChannel->pChannelRight  
                             : pChannel->pChannelLeft;  
                     const int iDstChan = pFxSend->DestinationChannel(iChan);  
                     if (iDstChan < 0) {  
                         dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));  
                         goto channel_cleanup;  
                     }  
                     AudioChannel* pDstChan = NULL;  
                     if (pFxSend->DestinationMasterEffectChain() >= 0) { // fx send routed to an internal master effect  
                         EffectChain* pEffectChain =  
                             pAudioOutputDevice->MasterEffectChain(  
                                 pFxSend->DestinationMasterEffectChain()  
                             );  
                         if (!pEffectChain) {  
                             dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationMasterEffectChain()));  
                             goto channel_cleanup;  
                         }  
                         Effect* pEffect =  
                             pEffectChain->GetEffect(  
                                 pFxSend->DestinationMasterEffect()  
                             );  
                         if (!pEffect) {  
                             dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationMasterEffect(), pFxSend->DestinationMasterEffectChain()));  
                             goto channel_cleanup;  
                         }  
                         pDstChan = pEffect->InputChannel(iDstChan);  
                     } else { // FX send routed directly to an audio output channel  
                         pDstChan = pAudioOutputDevice->Channel(iDstChan);  
                     }  
                     if (!pDstChan) {  
                         dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));  
                         goto channel_cleanup;  
                     }  
                     pSource->MixTo(pDstChan, Samples, pFxSend->Level());  
                 }  
257              }              }
258          }          }
259          channel_cleanup:          channel_cleanup:
260          // reset buffers with silence (zero out) for the next audio cycle          // reset buffers with silence (zero out) for the next audio cycle
261          pChannel->pChannelLeft->Clear();          ppSource[0]->Clear();
262          pChannel->pChannelRight->Clear();          ppSource[1]->Clear();
263        }
264        
265        /**
266         * Similar to RouteAudio(), but this method is even more special. It is
267         * only called by voices which have dedicated effect send(s) level(s). So
268         * such voices have to be routed separately apart from the other voices
269         * which can just be mixed together and routed afterwards in one turn.
270         */
271        void AbstractEngine::RouteDedicatedVoiceChannels(EngineChannel* pEngineChannel, optional<float> FxSendLevels[2], uint Samples) {
272            AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
273            AudioChannel* ppSource[2] = {
274                pDedicatedVoiceChannelLeft,
275                pDedicatedVoiceChannelRight
276            };
277            // route dry signal
278            {
279                AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);
280                AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);
281                ppSource[0]->MixTo(pDstL, Samples);
282                ppSource[1]->MixTo(pDstR, Samples);
283            }
284            // route FX send signals (wet)
285            // (we simply hard code the voices 'reverb send' to the 1st effect
286            // send bus, and the voioces 'chorus send' to the 2nd effect send bus)
287            {
288                for (int iFxSend = 0; iFxSend < 2 && iFxSend < pChannel->GetFxSendCount(); iFxSend++) {
289                    // no voice specific FX send level defined for this effect?
290                    if (!FxSendLevels[iFxSend]) continue; // ignore this effect then
291                    
292                    FxSend* pFxSend = pChannel->GetFxSend(iFxSend);
293                    const bool success = RouteFxSend(pFxSend, ppSource, *FxSendLevels[iFxSend], Samples);
294                    if (!success) goto channel_cleanup;
295                }
296            }
297            channel_cleanup:
298            // reset buffers with silence (zero out) for the next dedicated voice rendering/routing process
299            ppSource[0]->Clear();
300            ppSource[1]->Clear();
301        }
302        
303        /**
304         * Route the audio signal given by @a ppSource to the effect send bus
305         * defined by @a pFxSend (wet signal only).
306         *
307         * @param pFxSend - definition of effect send bus
308         * @param ppSource - the 2 channels of the audio signal to be routed
309         * @param FxSendLevel - the effect send level to by applied
310         * @param Samples - amount of sample points to be processed
311         * @returns true if signal was routed successfully, false on error
312         */
313        bool AbstractEngine::RouteFxSend(FxSend* pFxSend, AudioChannel* ppSource[2], float FxSendLevel, uint Samples) {
314            for (int iChan = 0; iChan < 2; ++iChan) {
315                const int iDstChan = pFxSend->DestinationChannel(iChan);
316                if (iDstChan < 0) {
317                    dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
318                    return false; // error
319                }
320                AudioChannel* pDstChan = NULL;
321                if (pFxSend->DestinationEffectChain() >= 0) { // fx send routed to an internal send effect
322                    EffectChain* pEffectChain =
323                        pAudioOutputDevice->SendEffectChainByID(
324                            pFxSend->DestinationEffectChain()
325                        );
326                    if (!pEffectChain) {
327                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChain()));
328                        return false; // error
329                    }
330                    Effect* pEffect =
331                        pEffectChain->GetEffect(
332                            pFxSend->DestinationEffectChainPosition()
333                        );
334                    if (!pEffect) {
335                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChainPosition(), pFxSend->DestinationEffectChain()));
336                        return false; // error
337                    }
338                    pDstChan = pEffect->InputChannel(iDstChan);
339                } else { // FX send routed directly to an audio output channel
340                    pDstChan = pAudioOutputDevice->Channel(iDstChan);
341                }
342                if (!pDstChan) {
343                    dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
344                    return false; // error
345                }
346                ppSource[iChan]->MixTo(pDstChan, Samples, FxSendLevel);
347            }
348            return true; // success
349      }      }
350    
351      /**      /**
# Line 288  namespace LinuxSampler { Line 358  namespace LinuxSampler {
358       */       */
359      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) {
360          RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;          RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
361          uint bytes = 3 /*addr*/ + DataSize;          uint bytes = 3 /*addr*/ + DataSize;        
         uint8_t addr_and_data[bytes];  
         reader.read(&addr_and_data[0], bytes);  
362          uint8_t sum = 0;          uint8_t sum = 0;
363          for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];          uint8_t c;
364            for (uint i = 0; i < bytes; ++i) {
365                if (!reader.pop(&c)) break;
366                sum += c;
367            }
368          return 128 - sum % 128;          return 128 - sum % 128;
369      }      }
370    
# Line 301  namespace LinuxSampler { Line 373  namespace LinuxSampler {
373       *       *
374       * @param ScaleTunes - detuning of all twelve semitones (in cents)       * @param ScaleTunes - detuning of all twelve semitones (in cents)
375       */       */
376      void AbstractEngine::AdjustScale(int8_t ScaleTunes[12]) {      void AbstractEngine::AdjustScaleTuning(const int8_t ScaleTunes[12]) {
377          memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate          memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12);
378            ScaleTuningChanged.raise();
379        }
380        
381        void AbstractEngine::GetScaleTuning(int8_t* pScaleTunes) {
382            memcpy(pScaleTunes, &this->ScaleTuning[0], 12);
383      }      }
384    
385      uint AbstractEngine::VoiceCount() {      uint AbstractEngine::VoiceCount() {
# Line 318  namespace LinuxSampler { Line 395  namespace LinuxSampler {
395      }      }
396    
397      /**      /**
398       *  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.  
399       *       *
400       *  @param pEngineChannel - engine channel on which this event occured on       *  @param pEngineChannel - engine channel on which this event occured on
401       *  @param itPitchbendEvent - absolute pitch value and time stamp of the event       *  @param itPitchbendEvent - absolute pitch value and time stamp of the event
# Line 449  namespace LinuxSampler { Line 524  namespace LinuxSampler {
524                          for (int i = 0; i < engineChannels.size(); ++i) {                          for (int i = 0; i < engineChannels.size(); ++i) {
525                              AbstractEngineChannel* pEngineChannel                              AbstractEngineChannel* pEngineChannel
526                                  = static_cast<AbstractEngineChannel*>(engineChannels[i]);                                  = static_cast<AbstractEngineChannel*>(engineChannels[i]);
527                              if (pEngineChannel->GetMidiInputPort() == itSysexEvent->pMidiInputPort) {                              Sync< ArrayList<MidiInputPort*> > midiInputs = pEngineChannel->midiInputs.front();
528                                  KillAllVoices(pEngineChannel, itSysexEvent);                              for (int k = 0; k < midiInputs->size(); ++k) {
529                                  pEngineChannel->ResetControllers();                                  if ((*midiInputs)[k] == itSysexEvent->pMidiInputPort) {
530                                        KillAllVoices(pEngineChannel, itSysexEvent);
531                                        pEngineChannel->ResetControllers();
532                                        break;
533                                    }
534                              }                              }
535                          }                          }
536                      }                      }
# Line 472  namespace LinuxSampler { Line 551  namespace LinuxSampler {
551                              if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;                              if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
552                              #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM                              #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
553                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
554                              AdjustScale((int8_t*) scale_tunes);                              AdjustScaleTuning((int8_t*) scale_tunes);
555                              dmsg(3,("\t\t\tNew scale applied.\n"));                              dmsg(3,("\t\t\tNew scale applied.\n"));
556                              break;                              break;
557                          }                          }
# Line 484  namespace LinuxSampler { Line 563  namespace LinuxSampler {
563                              for (int i = 0; i < engineChannels.size(); ++i) {                              for (int i = 0; i < engineChannels.size(); ++i) {
564                                  AbstractEngineChannel* pEngineChannel                                  AbstractEngineChannel* pEngineChannel
565                                      = static_cast<AbstractEngineChannel*>(engineChannels[i]);                                      = static_cast<AbstractEngineChannel*>(engineChannels[i]);
566                                  if (                                  if (pEngineChannel->midiChannel == part ||
567                                      (pEngineChannel->midiChannel == part ||                                      pEngineChannel->midiChannel == midi_chan_all)
568                                       pEngineChannel->midiChannel == midi_chan_all) &&                                  {  
569                                       pEngineChannel->GetMidiInputPort() == itSysexEvent->pMidiInputPort                                      Sync< ArrayList<MidiInputPort*> > midiInputs = pEngineChannel->midiInputs.front();
570                                  ) {                                      for (int k = 0; k < midiInputs->size(); ++k) {
571                                      try {                                          if ((*midiInputs)[k] == itSysexEvent->pMidiInputPort) {
572                                          pEngineChannel->SetMidiInstrumentMap(map);                                              try {
573                                      } catch (Exception e) {                                                  pEngineChannel->SetMidiInstrumentMap(map);
574                                          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) {
575                                          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()));
576                                      } catch (...) {                                                  goto free_sysex_data;
577                                          dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part));                                              } catch (...) {
578                                          goto free_sysex_data;                                                  dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part));
579                                                    goto free_sysex_data;
580                                                }
581                                                break;
582                                            }
583                                      }                                      }
584                                  }                                  }
585                              }                              }

Legend:
Removed from v.2091  
changed lines
  Added in v.2879

  ViewVC Help
Powered by ViewVC