51 |
if (engines.count(pDevice)) { |
if (engines.count(pDevice)) { |
52 |
dmsg(4,("Using existing gig::Engine.\n")); |
dmsg(4,("Using existing gig::Engine.\n")); |
53 |
pEngine = engines[pDevice]; |
pEngine = engines[pDevice]; |
54 |
|
|
55 |
|
// Disable the engine while the new engine channel is |
56 |
|
// added and initialized. The engine will be enabled again |
57 |
|
// in EngineChannel::Connect. |
58 |
|
pEngine->DisableAndLock(); |
59 |
} 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 |
60 |
dmsg(4,("Creating new gig::Engine.\n")); |
dmsg(4,("Creating new gig::Engine.\n")); |
61 |
pEngine = (Engine*) EngineFactory::Create("gig"); |
pEngine = (Engine*) EngineFactory::Create("gig"); |
62 |
pEngine->Connect(pDevice); |
pEngine->Connect(pDevice); |
63 |
engines[pDevice] = pEngine; |
engines[pDevice] = pEngine; |
64 |
} |
} |
|
|
|
65 |
// register engine channel to the engine instance |
// register engine channel to the engine instance |
|
|
|
|
// Disable the engine while the new engine channel is added |
|
|
// and initialized. The engine will be enabled again in |
|
|
// EngineChannel::Connect. |
|
|
pEngine->DisableAndLock(); |
|
|
|
|
66 |
pEngine->engineChannels.add(pChannel); |
pEngine->engineChannels.add(pChannel); |
67 |
// remember index in the ArrayList |
// remember index in the ArrayList |
68 |
pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1; |
pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1; |
141 |
if (pEventGenerator) delete pEventGenerator; |
if (pEventGenerator) delete pEventGenerator; |
142 |
if (pVoiceStealingQueue) delete pVoiceStealingQueue; |
if (pVoiceStealingQueue) delete pVoiceStealingQueue; |
143 |
if (pSysexBuffer) delete pSysexBuffer; |
if (pSysexBuffer) delete pSysexBuffer; |
144 |
|
if (pGlobalEvents) delete pGlobalEvents; |
145 |
|
if (InstrumentChangeQueue) delete InstrumentChangeQueue; |
146 |
|
if (InstrumentChangeReplyQueue) delete InstrumentChangeReplyQueue; |
147 |
|
if (pDimRegionsInUse) delete[] pDimRegionsInUse; |
148 |
Unregister(); |
Unregister(); |
149 |
} |
} |
150 |
|
|
526 |
if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted |
if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted |
527 |
#endif |
#endif |
528 |
|
|
529 |
|
uint voiceCount = 0; |
530 |
|
uint streamCount = 0; |
531 |
RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first(); |
532 |
RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end(); |
RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end(); |
533 |
while (iuiKey != end) { // iterate through all active keys |
while (iuiKey != end) { // iterate through all active keys |
539 |
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
540 |
// now render current voice |
// now render current voice |
541 |
itVoice->Render(Samples); |
itVoice->Render(Samples); |
542 |
if (itVoice->IsActive()) ActiveVoiceCountTemp++; // still active |
if (itVoice->IsActive()) { // still active |
543 |
else { // voice reached end, is now inactive |
ActiveVoiceCountTemp++; |
544 |
|
voiceCount++; |
545 |
|
|
546 |
|
if (itVoice->PlaybackState == Voice::playback_state_disk) { |
547 |
|
if ((itVoice->DiskStreamRef).State == Stream::state_active) streamCount++; |
548 |
|
} |
549 |
|
} else { // voice reached end, is now inactive |
550 |
FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices |
FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices |
551 |
} |
} |
552 |
} |
} |
553 |
} |
} |
554 |
|
|
555 |
|
pEngineChannel->SetVoiceCount(voiceCount); |
556 |
|
pEngineChannel->SetDiskStreamCount(streamCount); |
557 |
} |
} |
558 |
|
|
559 |
/** |
/** |
579 |
LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false); |
LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false); |
580 |
if (itNewVoice) { |
if (itNewVoice) { |
581 |
itNewVoice->Render(Samples); |
itNewVoice->Render(Samples); |
582 |
if (itNewVoice->IsActive()) ActiveVoiceCountTemp++; // still active |
if (itNewVoice->IsActive()) { // still active |
583 |
else { // voice reached end, is now inactive |
ActiveVoiceCountTemp++; |
584 |
|
pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1); |
585 |
|
|
586 |
|
if (itNewVoice->PlaybackState == Voice::playback_state_disk) { |
587 |
|
if (itNewVoice->DiskStreamRef.State == Stream::state_active) { |
588 |
|
pEngineChannel->SetDiskStreamCount(pEngineChannel->GetDiskStreamCount() + 1); |
589 |
|
} |
590 |
|
} |
591 |
|
} else { // voice reached end, is now inactive |
592 |
FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices |
FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices |
593 |
} |
} |
594 |
} |
} |
732 |
|
|
733 |
if (!pEngineChannel->pInstrument) return; // ignore if no instrument loaded |
if (!pEngineChannel->pInstrument) return; // ignore if no instrument loaded |
734 |
|
|
735 |
|
//HACK: we should better add the transpose value only to the most mandatory places (like for retrieving the region and calculating the tuning), because otherwise voices will unintendedly survive when changing transpose while playing |
736 |
|
itNoteOnEvent->Param.Note.Key += pEngineChannel->GlobalTranspose; |
737 |
|
|
738 |
const int key = itNoteOnEvent->Param.Note.Key; |
const int key = itNoteOnEvent->Param.Note.Key; |
739 |
midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key]; |
midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key]; |
740 |
|
|
822 |
if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted |
if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted |
823 |
#endif |
#endif |
824 |
|
|
825 |
|
//HACK: we should better add the transpose value only to the most mandatory places (like for retrieving the region and calculating the tuning), because otherwise voices will unintendedly survive when changing transpose while playing |
826 |
|
itNoteOffEvent->Param.Note.Key += pEngineChannel->GlobalTranspose; |
827 |
|
|
828 |
const int iKey = itNoteOffEvent->Param.Note.Key; |
const int iKey = itNoteOffEvent->Param.Note.Key; |
829 |
midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[iKey]; |
midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[iKey]; |
830 |
pKey->KeyPressed = false; // the MIDI key was now released |
pKey->KeyPressed = false; // the MIDI key was now released |
1385 |
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; |
1386 |
break; |
break; |
1387 |
} |
} |
1388 |
|
case 6: { // data entry (currently only used for RPN controllers) |
1389 |
|
if (pEngineChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones |
1390 |
|
int transpose = (int) itControlChangeEvent->Param.CC.Value - 64; |
1391 |
|
// limit to +- two octaves for now |
1392 |
|
transpose = RTMath::Min(transpose, 24); |
1393 |
|
transpose = RTMath::Max(transpose, -24); |
1394 |
|
pEngineChannel->GlobalTranspose = transpose; |
1395 |
|
// workaround, so we won't have hanging notes |
1396 |
|
ReleaseAllVoices(pEngineChannel, itControlChangeEvent); |
1397 |
|
} |
1398 |
|
// to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data |
1399 |
|
pEngineChannel->ResetMidiRpnController(); |
1400 |
|
break; |
1401 |
|
} |
1402 |
case 7: { // volume |
case 7: { // volume |
1403 |
//TODO: not sample accurate yet |
//TODO: not sample accurate yet |
1404 |
pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value]; |
pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value]; |
1503 |
} |
} |
1504 |
break; |
break; |
1505 |
} |
} |
1506 |
|
case 100: { // RPN controller LSB |
1507 |
|
pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value); |
1508 |
|
break; |
1509 |
|
} |
1510 |
|
case 101: { // RPN controller MSB |
1511 |
|
pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value); |
1512 |
|
break; |
1513 |
|
} |
1514 |
|
|
1515 |
|
|
1516 |
// Channel Mode Messages |
// Channel Mode Messages |
1547 |
FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend); |
FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend); |
1548 |
if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller) |
if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller) |
1549 |
pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value); |
pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value); |
1550 |
|
pFxSend->SetInfoChanged(true); |
1551 |
} |
} |
1552 |
} |
} |
1553 |
} |
} |
1744 |
} |
} |
1745 |
|
|
1746 |
String Engine::Version() { |
String Engine::Version() { |
1747 |
String s = "$Revision: 1.71 $"; |
String s = "$Revision: 1.79 $"; |
1748 |
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 |
1749 |
} |
} |
1750 |
|
|