392 |
// now that all ordinary voices on ALL engine channels are rendered, render new stolen voices |
// now that all ordinary voices on ALL engine channels are rendered, render new stolen voices |
393 |
RenderStolenVoices(Samples); |
RenderStolenVoices(Samples); |
394 |
|
|
395 |
|
// handle audio routing for engine channels with FX sends |
396 |
|
for (int i = 0; i < engineChannels.size(); i++) { |
397 |
|
if (engineChannels[i]->fxSends.empty()) continue; // ignore if no FX sends |
398 |
|
RouteAudio(engineChannels[i], Samples); |
399 |
|
} |
400 |
|
|
401 |
// handle cleanup on all engine channels for the next audio fragment |
// handle cleanup on all engine channels for the next audio fragment |
402 |
for (int i = 0; i < engineChannels.size(); i++) { |
for (int i = 0; i < engineChannels.size(); i++) { |
403 |
if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded |
if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded |
538 |
} |
} |
539 |
|
|
540 |
/** |
/** |
541 |
|
* Will be called in case the respective engine channel sports FX send |
542 |
|
* channels. In this particular case, engine channel local buffers are |
543 |
|
* used to render and mix all voices to. This method is responsible for |
544 |
|
* copying the audio data from those local buffers to the master audio |
545 |
|
* output channels as well as to the FX send audio output channels with |
546 |
|
* their respective FX send levels. |
547 |
|
* |
548 |
|
* @param pEngineChannel - engine channel from which audio should be |
549 |
|
* routed |
550 |
|
* @param Samples - amount of sample points to be routed in |
551 |
|
* this audio fragment cycle |
552 |
|
*/ |
553 |
|
void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) { |
554 |
|
// route master signal |
555 |
|
{ |
556 |
|
AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft); |
557 |
|
AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight); |
558 |
|
pEngineChannel->pChannelLeft->CopyTo(pDstL, Samples); |
559 |
|
pEngineChannel->pChannelRight->CopyTo(pDstR, Samples); |
560 |
|
} |
561 |
|
// route FX send signal |
562 |
|
{ |
563 |
|
for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) { |
564 |
|
FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend); |
565 |
|
// left channel |
566 |
|
const int iDstL = pFxSend->DestinationChannel(0); |
567 |
|
if (iDstL < 0) { |
568 |
|
dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel")); |
569 |
|
} else { |
570 |
|
AudioChannel* pDstL = pAudioOutputDevice->Channel(iDstL); |
571 |
|
if (!pDstL) { |
572 |
|
dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel")); |
573 |
|
} else pEngineChannel->pChannelLeft->CopyTo(pDstL, Samples, pFxSend->Level()); |
574 |
|
} |
575 |
|
// right channel |
576 |
|
const int iDstR = pFxSend->DestinationChannel(1); |
577 |
|
if (iDstR < 0) { |
578 |
|
dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel")); |
579 |
|
} else { |
580 |
|
AudioChannel* pDstR = pAudioOutputDevice->Channel(iDstR); |
581 |
|
if (!pDstR) { |
582 |
|
dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel")); |
583 |
|
} else pEngineChannel->pChannelRight->CopyTo(pDstR, Samples, pFxSend->Level()); |
584 |
|
} |
585 |
|
} |
586 |
|
} |
587 |
|
// reset buffers with silence (zero out) for the next audio cycle |
588 |
|
pEngineChannel->pChannelLeft->Clear(); |
589 |
|
pEngineChannel->pChannelRight->Clear(); |
590 |
|
} |
591 |
|
|
592 |
|
/** |
593 |
* Free all keys which have turned inactive in this audio fragment, from |
* Free all keys which have turned inactive in this audio fragment, from |
594 |
* the list of active keys and clear all event lists on that engine |
* the list of active keys and clear all event lists on that engine |
595 |
* channel. |
* channel. |
1294 |
// update controller value in the engine channel's controller table |
// update controller value in the engine channel's controller table |
1295 |
pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value; |
pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value; |
1296 |
|
|
1297 |
|
// handle hard coded MIDI controllers |
1298 |
switch (itControlChangeEvent->Param.CC.Controller) { |
switch (itControlChangeEvent->Param.CC.Controller) { |
1299 |
case 5: { // portamento time |
case 5: { // portamento time |
1300 |
pEngineChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN; |
pEngineChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN; |
1433 |
break; |
break; |
1434 |
} |
} |
1435 |
} |
} |
1436 |
|
|
1437 |
|
// handle FX send controllers |
1438 |
|
if (!pEngineChannel->fxSends.empty()) { |
1439 |
|
for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) { |
1440 |
|
FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend); |
1441 |
|
if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller) |
1442 |
|
pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value); |
1443 |
|
} |
1444 |
|
} |
1445 |
} |
} |
1446 |
|
|
1447 |
/** |
/** |
1636 |
} |
} |
1637 |
|
|
1638 |
String Engine::Version() { |
String Engine::Version() { |
1639 |
String s = "$Revision: 1.67 $"; |
String s = "$Revision: 1.68 $"; |
1640 |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
1641 |
} |
} |
1642 |
|
|