/[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 2012 by iliev, Fri Oct 23 17:53:17 2009 UTC revision 2448 by schoenebeck, Fri May 3 14:26:32 2013 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6   *   Copyright (C) 2005-2009 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009 Grigor Iliev                                       *   *   Copyright (C) 2009-2010 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 26  Line 26 
26  #include "AbstractEngineChannel.h"  #include "AbstractEngineChannel.h"
27  #include "EngineFactory.h"  #include "EngineFactory.h"
28  #include "../common/global_private.h"  #include "../common/global_private.h"
29    #include "../effects/EffectFactory.h"
30    
31  namespace LinuxSampler {  namespace LinuxSampler {
32    
# Line 78  namespace LinuxSampler { Line 79  namespace LinuxSampler {
79          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
80          pGlobalEvents      = new RTList<Event>(pEventPool);          pGlobalEvents      = new RTList<Event>(pEventPool);
81          FrameTime          = 0;          FrameTime          = 0;
82            RandomSeed         = 0;
83            pDedicatedVoiceChannelLeft = pDedicatedVoiceChannelRight = NULL;
84      }      }
85    
86      AbstractEngine::~AbstractEngine() {      AbstractEngine::~AbstractEngine() {
# Line 86  namespace LinuxSampler { Line 89  namespace LinuxSampler {
89          if (pEventGenerator) delete pEventGenerator;          if (pEventGenerator) delete pEventGenerator;
90          if (pGlobalEvents) delete pGlobalEvents;          if (pGlobalEvents) delete pGlobalEvents;
91          if (pSysexBuffer) delete pSysexBuffer;          if (pSysexBuffer) delete pSysexBuffer;
92            if (pDedicatedVoiceChannelLeft) delete pDedicatedVoiceChannelLeft;
93            if (pDedicatedVoiceChannelRight) delete pDedicatedVoiceChannelRight;
94          Unregister();          Unregister();
95      }      }
96    
# Line 160  namespace LinuxSampler { Line 165  namespace LinuxSampler {
165       */       */
166      void AbstractEngine::ResetScaleTuning() {      void AbstractEngine::ResetScaleTuning() {
167          memset(&ScaleTuning[0], 0x00, 12);          memset(&ScaleTuning[0], 0x00, 12);
168            ScaleTuningChanged.raise();
169      }      }
170    
171      /**      /**
# Line 220  namespace LinuxSampler { Line 226  namespace LinuxSampler {
226       */       */
227      void AbstractEngine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {      void AbstractEngine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
228          AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);          AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
229            AudioChannel* ppSource[2] = {
230                pChannel->pChannelLeft,
231                pChannel->pChannelRight
232            };
233          // route dry signal          // route dry signal
234          {          {
235              AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);              AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);
236              AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);              AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);
237              pChannel->pChannelLeft->MixTo(pDstL, Samples);              ppSource[0]->MixTo(pDstL, Samples);
238              pChannel->pChannelRight->MixTo(pDstR, Samples);              ppSource[1]->MixTo(pDstR, Samples);
239          }          }
240          // route FX send signal          // route FX send signal (wet)
241          {          {
242              for (int iFxSend = 0; iFxSend < pChannel->GetFxSendCount(); iFxSend++) {              for (int iFxSend = 0; iFxSend < pChannel->GetFxSendCount(); iFxSend++) {
243                  FxSend* pFxSend = pChannel->GetFxSend(iFxSend);                  FxSend* pFxSend = pChannel->GetFxSend(iFxSend);
244                  for (int iChan = 0; iChan < 2; ++iChan) {                  const bool success = RouteFxSend(pFxSend, ppSource, pFxSend->Level(), Samples);
245                      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());  
                 }  
246              }              }
247          }          }
248          channel_cleanup:          channel_cleanup:
249          // reset buffers with silence (zero out) for the next audio cycle          // reset buffers with silence (zero out) for the next audio cycle
250          pChannel->pChannelLeft->Clear();          ppSource[0]->Clear();
251          pChannel->pChannelRight->Clear();          ppSource[1]->Clear();
252        }
253        
254        /**
255         * Similar to RouteAudio(), but this method is even more special. It is
256         * only called by voices which have dedicated effect send(s) level(s). So
257         * such voices have to be routed separately apart from the other voices
258         * which can just be mixed together and routed afterwards in one turn.
259         */
260        void AbstractEngine::RouteDedicatedVoiceChannels(EngineChannel* pEngineChannel, optional<float> FxSendLevels[2], uint Samples) {
261            AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
262            AudioChannel* ppSource[2] = {
263                pDedicatedVoiceChannelLeft,
264                pDedicatedVoiceChannelRight
265            };
266            // route dry signal
267            {
268                AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);
269                AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);
270                ppSource[0]->MixTo(pDstL, Samples);
271                ppSource[1]->MixTo(pDstR, Samples);
272            }
273            // route FX send signals (wet)
274            // (we simply hard code the voices 'reverb send' to the 1st effect
275            // send bus, and the voioces 'chorus send' to the 2nd effect send bus)
276            {
277                for (int iFxSend = 0; iFxSend < 2 && iFxSend < pChannel->GetFxSendCount(); iFxSend++) {
278                    // no voice specific FX send level defined for this effect?
279                    if (!FxSendLevels[iFxSend]) continue; // ignore this effect then
280                    
281                    FxSend* pFxSend = pChannel->GetFxSend(iFxSend);
282                    const bool success = RouteFxSend(pFxSend, ppSource, *FxSendLevels[iFxSend], Samples);
283                    if (!success) goto channel_cleanup;
284                }
285            }
286            channel_cleanup:
287            // reset buffers with silence (zero out) for the next dedicated voice rendering/routing process
288            ppSource[0]->Clear();
289            ppSource[1]->Clear();
290        }
291        
292        /**
293         * Route the audio signal given by @a ppSource to the effect send bus
294         * defined by @a pFxSend (wet signal only).
295         *
296         * @param pFxSend - definition of effect send bus
297         * @param ppSource - the 2 channels of the audio signal to be routed
298         * @param FxSendLevel - the effect send level to by applied
299         * @param Samples - amount of sample points to be processed
300         * @returns true if signal was routed successfully, false on error
301         */
302        bool AbstractEngine::RouteFxSend(FxSend* pFxSend, AudioChannel* ppSource[2], float FxSendLevel, uint Samples) {
303            for (int iChan = 0; iChan < 2; ++iChan) {
304                const int iDstChan = pFxSend->DestinationChannel(iChan);
305                if (iDstChan < 0) {
306                    dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
307                    return false; // error
308                }
309                AudioChannel* pDstChan = NULL;
310                if (pFxSend->DestinationEffectChain() >= 0) { // fx send routed to an internal send effect
311                    EffectChain* pEffectChain =
312                        pAudioOutputDevice->SendEffectChainByID(
313                            pFxSend->DestinationEffectChain()
314                        );
315                    if (!pEffectChain) {
316                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChain()));
317                        return false; // error
318                    }
319                    Effect* pEffect =
320                        pEffectChain->GetEffect(
321                            pFxSend->DestinationEffectChainPosition()
322                        );
323                    if (!pEffect) {
324                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChainPosition(), pFxSend->DestinationEffectChain()));
325                        return false; // error
326                    }
327                    pDstChan = pEffect->InputChannel(iDstChan);
328                } else { // FX send routed directly to an audio output channel
329                    pDstChan = pAudioOutputDevice->Channel(iDstChan);
330                }
331                if (!pDstChan) {
332                    dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
333                    return false; // error
334                }
335                ppSource[iChan]->MixTo(pDstChan, Samples, FxSendLevel);
336            }
337            return true; // success
338      }      }
339    
340      /**      /**
# Line 300  namespace LinuxSampler { Line 360  namespace LinuxSampler {
360       *       *
361       * @param ScaleTunes - detuning of all twelve semitones (in cents)       * @param ScaleTunes - detuning of all twelve semitones (in cents)
362       */       */
363      void AbstractEngine::AdjustScale(int8_t ScaleTunes[12]) {      void AbstractEngine::AdjustScaleTuning(const int8_t ScaleTunes[12]) {
364          memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate          memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12);
365            ScaleTuningChanged.raise();
366        }
367        
368        void AbstractEngine::GetScaleTuning(int8_t* pScaleTunes) {
369            memcpy(pScaleTunes, &this->ScaleTuning[0], 12);
370      }      }
371    
372      uint AbstractEngine::VoiceCount() {      uint AbstractEngine::VoiceCount() {
# Line 471  namespace LinuxSampler { Line 536  namespace LinuxSampler {
536                              if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;                              if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
537                              #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM                              #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
538                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
539                              AdjustScale((int8_t*) scale_tunes);                              AdjustScaleTuning((int8_t*) scale_tunes);
540                              dmsg(3,("\t\t\tNew scale applied.\n"));                              dmsg(3,("\t\t\tNew scale applied.\n"));
541                              break;                              break;
542                          }                          }

Legend:
Removed from v.2012  
changed lines
  Added in v.2448

  ViewVC Help
Powered by ViewVC