/[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 2298 by iliev, Fri Dec 9 17:04:24 2011 UTC
# 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 79  namespace LinuxSampler { Line 80  namespace LinuxSampler {
80          pGlobalEvents      = new RTList<Event>(pEventPool);          pGlobalEvents      = new RTList<Event>(pEventPool);
81          FrameTime          = 0;          FrameTime          = 0;
82          RandomSeed         = 0;          RandomSeed         = 0;
83            pDedicatedVoiceChannelLeft = pDedicatedVoiceChannelRight = NULL;
84      }      }
85    
86      AbstractEngine::~AbstractEngine() {      AbstractEngine::~AbstractEngine() {
# Line 87  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 221  namespace LinuxSampler { Line 225  namespace LinuxSampler {
225       */       */
226      void AbstractEngine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {      void AbstractEngine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
227          AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);          AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
228            AudioChannel* ppSource[2] = {
229                pChannel->pChannelLeft,
230                pChannel->pChannelRight
231            };
232          // route dry signal          // route dry signal
233          {          {
234              AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);              AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);
235              AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);              AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);
236              pChannel->pChannelLeft->MixTo(pDstL, Samples);              ppSource[0]->MixTo(pDstL, Samples);
237              pChannel->pChannelRight->MixTo(pDstR, Samples);              ppSource[1]->MixTo(pDstR, Samples);
238          }          }
239          // route FX send signal          // route FX send signal (wet)
240          {          {
241              for (int iFxSend = 0; iFxSend < pChannel->GetFxSendCount(); iFxSend++) {              for (int iFxSend = 0; iFxSend < pChannel->GetFxSendCount(); iFxSend++) {
242                  FxSend* pFxSend = pChannel->GetFxSend(iFxSend);                  FxSend* pFxSend = pChannel->GetFxSend(iFxSend);
243                  for (int iChan = 0; iChan < 2; ++iChan) {                  const bool success = RouteFxSend(pFxSend, ppSource, pFxSend->Level(), Samples);
244                      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());  
                 }  
245              }              }
246          }          }
247          channel_cleanup:          channel_cleanup:
248          // reset buffers with silence (zero out) for the next audio cycle          // reset buffers with silence (zero out) for the next audio cycle
249          pChannel->pChannelLeft->Clear();          ppSource[0]->Clear();
250          pChannel->pChannelRight->Clear();          ppSource[1]->Clear();
251        }
252        
253        /**
254         * Similar to RouteAudio(), but this method is even more special. It is
255         * only called by voices which have dedicated effect send(s) level(s). So
256         * such voices have to be routed separately apart from the other voices
257         * which can just be mixed together and routed afterwards in one turn.
258         */
259        void AbstractEngine::RouteDedicatedVoiceChannels(EngineChannel* pEngineChannel, optional<float> FxSendLevels[2], uint Samples) {
260            AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
261            AudioChannel* ppSource[2] = {
262                pDedicatedVoiceChannelLeft,
263                pDedicatedVoiceChannelRight
264            };
265            // route dry signal
266            {
267                AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);
268                AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);
269                ppSource[0]->MixTo(pDstL, Samples);
270                ppSource[1]->MixTo(pDstR, Samples);
271            }
272            // route FX send signals (wet)
273            // (we simply hard code the voices 'reverb send' to the 1st effect
274            // send bus, and the voioces 'chorus send' to the 2nd effect send bus)
275            {
276                for (int iFxSend = 0; iFxSend < 2 && iFxSend < pChannel->GetFxSendCount(); iFxSend++) {
277                    // no voice specific FX send level defined for this effect?
278                    if (!FxSendLevels[iFxSend]) continue; // ignore this effect then
279                    
280                    FxSend* pFxSend = pChannel->GetFxSend(iFxSend);
281                    const bool success = RouteFxSend(pFxSend, ppSource, *FxSendLevels[iFxSend], Samples);
282                    if (!success) goto channel_cleanup;
283                }
284            }
285            channel_cleanup:
286            // reset buffers with silence (zero out) for the next dedicated voice rendering/routing process
287            ppSource[0]->Clear();
288            ppSource[1]->Clear();
289        }
290        
291        /**
292         * Route the audio signal given by @a ppSource to the effect send bus
293         * defined by @a pFxSend (wet signal only).
294         *
295         * @param pFxSend - definition of effect send bus
296         * @param ppSource - the 2 channels of the audio signal to be routed
297         * @param FxSendLevel - the effect send level to by applied
298         * @param Samples - amount of sample points to be processed
299         * @returns true if signal was routed successfully, false on error
300         */
301        bool AbstractEngine::RouteFxSend(FxSend* pFxSend, AudioChannel* ppSource[2], float FxSendLevel, uint Samples) {
302            for (int iChan = 0; iChan < 2; ++iChan) {
303                const int iDstChan = pFxSend->DestinationChannel(iChan);
304                if (iDstChan < 0) {
305                    dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
306                    return false; // error
307                }
308                AudioChannel* pDstChan = NULL;
309                if (pFxSend->DestinationEffectChain() >= 0) { // fx send routed to an internal send effect
310                    EffectChain* pEffectChain =
311                        pAudioOutputDevice->SendEffectChainByID(
312                            pFxSend->DestinationEffectChain()
313                        );
314                    if (!pEffectChain) {
315                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChain()));
316                        return false; // error
317                    }
318                    Effect* pEffect =
319                        pEffectChain->GetEffect(
320                            pFxSend->DestinationEffectChainPosition()
321                        );
322                    if (!pEffect) {
323                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChainPosition(), pFxSend->DestinationEffectChain()));
324                        return false; // error
325                    }
326                    pDstChan = pEffect->InputChannel(iDstChan);
327                } else { // FX send routed directly to an audio output channel
328                    pDstChan = pAudioOutputDevice->Channel(iDstChan);
329                }
330                if (!pDstChan) {
331                    dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
332                    return false; // error
333                }
334                ppSource[iChan]->MixTo(pDstChan, Samples, FxSendLevel);
335            }
336            return true; // success
337      }      }
338    
339      /**      /**

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

  ViewVC Help
Powered by ViewVC