30 |
#include "../../EventListeners.h" |
#include "../../EventListeners.h" |
31 |
#include "../../common/Pool.h" |
#include "../../common/Pool.h" |
32 |
#include "../../common/global_private.h" |
#include "../../common/global_private.h" |
33 |
|
#include "Note.h" |
34 |
|
|
35 |
namespace LinuxSampler { |
namespace LinuxSampler { |
36 |
|
|
164 |
*/ |
*/ |
165 |
class MidiKey : public MidiKeyBase { |
class MidiKey : public MidiKeyBase { |
166 |
public: |
public: |
167 |
RTList<V>* pActiveVoices; ///< Contains the active voices associated with the MIDI key. |
RTList< Note<V> >* pActiveNotes; ///< Contains the active notes associated with the MIDI key. |
168 |
|
|
169 |
MidiKey() { |
MidiKey() { |
170 |
pActiveVoices = NULL; |
pActiveNotes = NULL; |
171 |
KeyPressed = false; |
KeyPressed = false; |
172 |
Active = false; |
Active = false; |
173 |
ReleaseTrigger = false; |
ReleaseTrigger = false; |
179 |
} |
} |
180 |
|
|
181 |
void Reset() { |
void Reset() { |
182 |
if (pActiveVoices) { |
if (pActiveNotes) { |
183 |
RTListVoiceIterator itVoice = pActiveVoices->first(); |
RTListNoteIterator itNote = pActiveNotes->first(); |
184 |
RTListVoiceIterator itVoicesEnd = pActiveVoices->end(); |
RTListNoteIterator itNotesEnd = pActiveNotes->end(); |
185 |
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
for (; itNote != itNotesEnd; ++itNote) { // iterate through all active notes on this key |
186 |
itVoice->VoiceFreed(); |
itNote->reset(); |
187 |
} |
} |
188 |
pActiveVoices->clear(); |
pActiveNotes->clear(); |
189 |
} |
} |
190 |
if (pEvents) pEvents->clear(); |
if (pEvents) pEvents->clear(); |
191 |
KeyPressed = false; |
KeyPressed = false; |
201 |
} |
} |
202 |
}; |
}; |
203 |
|
|
204 |
|
typedef typename RTList< Note<V> >::Iterator RTListNoteIterator; |
205 |
typedef typename RTList<V>::Iterator RTListVoiceIterator; |
typedef typename RTList<V>::Iterator RTListVoiceIterator; |
206 |
typedef typename Pool<V>::Iterator PoolVoiceIterator; |
typedef typename Pool<V>::Iterator PoolVoiceIterator; |
207 |
|
|
245 |
pMIDIKeyInfo[i].pRoundRobinIndex = &RoundRobinIndexes[i]; |
pMIDIKeyInfo[i].pRoundRobinIndex = &RoundRobinIndexes[i]; |
246 |
} |
} |
247 |
m_engineChannel = pEngineChannel; |
m_engineChannel = pEngineChannel; |
248 |
|
m_voicePool = NULL; |
249 |
} |
} |
250 |
|
|
251 |
virtual ~MidiKeyboardManager() { |
virtual ~MidiKeyboardManager() { |
269 |
pActiveKeys->clear(); |
pActiveKeys->clear(); |
270 |
} |
} |
271 |
|
|
272 |
void AllocateActiveVoices(Pool<V>* pVoicePool) { |
void AllocateActiveNotesLists(Pool< Note<V> >* pNotePool, Pool<V>* pVoicePool) { |
273 |
DeleteActiveVoices(); |
DeleteActiveNotesLists(); |
274 |
|
|
275 |
|
m_voicePool = pVoicePool; |
276 |
|
|
277 |
for (uint i = 0; i < 128; i++) { |
for (uint i = 0; i < 128; i++) { |
278 |
pMIDIKeyInfo[i].pActiveVoices = new RTList<V>(pVoicePool); |
pMIDIKeyInfo[i].pActiveNotes = new RTList< Note<V> >(pNotePool); |
279 |
} |
} |
280 |
} |
} |
281 |
|
|
282 |
void DeleteActiveVoices() { |
void DeleteActiveNotesLists() { |
283 |
for (uint i = 0; i < 128; i++) { |
for (uint i = 0; i < 128; i++) { |
284 |
if (pMIDIKeyInfo[i].pActiveVoices) { |
if (pMIDIKeyInfo[i].pActiveNotes) { |
285 |
delete pMIDIKeyInfo[i].pActiveVoices; |
delete pMIDIKeyInfo[i].pActiveNotes; |
286 |
pMIDIKeyInfo[i].pActiveVoices = NULL; |
pMIDIKeyInfo[i].pActiveNotes = NULL; |
287 |
} |
} |
288 |
} |
} |
289 |
|
m_voicePool = NULL; |
290 |
} |
} |
291 |
|
|
292 |
void AllocateEvents(Pool<Event>* pEventPool) { |
void AllocateEventsLists(Pool<Event>* pEventPool) { |
293 |
DeleteEvents(); |
DeleteEventsLists(); |
294 |
|
|
295 |
for (uint i = 0; i < 128; i++) { |
for (uint i = 0; i < 128; i++) { |
296 |
pMIDIKeyInfo[i].pEvents = new RTList<Event>(pEventPool); |
pMIDIKeyInfo[i].pEvents = new RTList<Event>(pEventPool); |
297 |
} |
} |
298 |
} |
} |
299 |
|
|
300 |
void DeleteEvents() { |
void DeleteEventsLists() { |
301 |
for (uint i = 0; i < 128; i++) { |
for (uint i = 0; i < 128; i++) { |
302 |
if (pMIDIKeyInfo[i].pEvents) { |
if (pMIDIKeyInfo[i].pEvents) { |
303 |
delete pMIDIKeyInfo[i].pEvents; |
delete pMIDIKeyInfo[i].pEvents; |
324 |
*/ |
*/ |
325 |
void FreeVoice(PoolVoiceIterator& itVoice) { |
void FreeVoice(PoolVoiceIterator& itVoice) { |
326 |
if (itVoice) { |
if (itVoice) { |
327 |
MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey]; |
//MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey]; |
328 |
|
|
329 |
// if the sample and dimension region belong to an |
// if the sample and dimension region belong to an |
330 |
// instrument that is unloaded, tell the disk thread to |
// instrument that is unloaded, tell the disk thread to |
336 |
} |
} |
337 |
|
|
338 |
// free the voice object |
// free the voice object |
339 |
pKey->pActiveVoices->free(itVoice); |
m_voicePool->free(itVoice); |
340 |
} |
} |
341 |
else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush; |
else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush; |
342 |
} |
} |
349 |
* @param pKey - key which is now inactive |
* @param pKey - key which is now inactive |
350 |
*/ |
*/ |
351 |
void FreeKey(MidiKey* pKey) { |
void FreeKey(MidiKey* pKey) { |
352 |
if (pKey->pActiveVoices->isEmpty()) { |
if (pKey->pActiveNotes->isEmpty()) { |
353 |
if (m_engineChannel->pScript) |
if (m_engineChannel->pScript) |
354 |
m_engineChannel->pScript->pKeyEvents[pKey->itSelf]->clear(); |
m_engineChannel->pScript->pKeyEvents[pKey->itSelf]->clear(); |
355 |
pKey->Active = false; |
pKey->Active = false; |
371 |
while (iuiKey != end) { // iterate through all active keys |
while (iuiKey != end) { // iterate through all active keys |
372 |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
373 |
++iuiKey; |
++iuiKey; |
374 |
if (pKey->pActiveVoices->isEmpty()) FreeKey(pKey); |
for (RTListNoteIterator itNote = pKey->pActiveNotes->first(), |
375 |
#if CONFIG_DEVMODE |
itNotesEnd = pKey->pActiveNotes->end(); |
376 |
else { // just a sanity check for debugging |
itNote != itNotesEnd; ++itNote) |
377 |
RTListVoiceIterator itVoice = pKey->pActiveVoices->first(); |
{ // iterate over all active notes on that key ... |
378 |
RTListVoiceIterator = pKey->pActiveVoices->end(); |
if (itNote->pActiveVoices->isEmpty()) { // free note ... |
379 |
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
itNote->reset(); |
380 |
if (itVoice->itKillEvent) { |
pKey->pActiveNotes->free(itNote); |
381 |
dmsg(1,("gig::Engine: ERROR, killed voice survived !!!\n")); |
} |
382 |
|
#if CONFIG_DEVMODE |
383 |
|
else { // just a sanity check for debugging |
384 |
|
RTListVoiceIterator itVoice = itNote->pActiveVoices->first(); |
385 |
|
RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end(); |
386 |
|
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
387 |
|
if (itVoice->itKillEvent) { |
388 |
|
dmsg(1,("gig::Engine: ERROR, killed voice survived !!!\n")); |
389 |
|
} |
390 |
} |
} |
391 |
} |
} |
392 |
|
#endif // CONFIG_DEVMODE |
393 |
} |
} |
394 |
#endif // CONFIG_DEVMODE |
if (pKey->pActiveNotes->isEmpty()) FreeKey(pKey); |
395 |
} |
} |
396 |
} |
} |
397 |
|
|
398 |
int StealVoice ( |
int StealVoice ( |
399 |
Pool<Event>::Iterator& itNoteOnEvent, |
Pool<Event>::Iterator& itNoteOnEvent, |
400 |
RTListVoiceIterator* LastStolenVoice, |
RTListVoiceIterator* LastStolenVoice, |
401 |
|
RTListNoteIterator* LastStolenNote, |
402 |
RTList<uint>::Iterator* LastStolenKey |
RTList<uint>::Iterator* LastStolenKey |
403 |
) { |
) { |
404 |
RTListVoiceIterator itSelectedVoice; |
RTListVoiceIterator itSelectedVoice; |
412 |
// 'oldestkey' algorithm |
// 'oldestkey' algorithm |
413 |
case voice_steal_algo_oldestvoiceonkey: { |
case voice_steal_algo_oldestvoiceonkey: { |
414 |
MidiKey* pSelectedKey = &pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key]; |
MidiKey* pSelectedKey = &pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key]; |
415 |
itSelectedVoice = pSelectedKey->pActiveVoices->first(); |
for (RTListNoteIterator itNote = pSelectedKey->pActiveNotes->first(), |
416 |
// proceed iterating if voice was created in this fragment cycle |
itNotesEnd = pSelectedKey->pActiveNotes->end(); |
417 |
while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice; |
itNote != itNotesEnd; ++itNote) |
418 |
// if we haven't found a voice then proceed with algorithm 'oldestkey' |
{ |
419 |
if (itSelectedVoice && itSelectedVoice->IsStealable()) break; |
for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice) |
420 |
|
if (itSelectedVoice->IsStealable()) // proceed iterating if voice was created in this audio fragment cycle |
421 |
|
goto voiceFound; // selection succeeded |
422 |
|
} |
423 |
|
// if we haven't found a voice then proceed with algorithm 'oldestkey' ... |
424 |
} // no break - intentional ! |
} // no break - intentional ! |
425 |
|
|
426 |
// try to pick the oldest voice on the oldest active key |
// try to pick the oldest voice on the oldest active key |
427 |
// from the same engine channel |
// from the same engine channel |
428 |
// (caution: must stay after 'oldestvoiceonkey' algorithm !) |
// (caution: must stay after 'oldestvoiceonkey' algorithm !) |
429 |
case voice_steal_algo_oldestkey: { |
case voice_steal_algo_oldestkey: { |
430 |
// if we already stole in this fragment, try to proceed on same key |
// if we already stole in this fragment, try to proceed to steal on same note |
431 |
if (*LastStolenVoice) { |
if (*LastStolenVoice) { |
432 |
itSelectedVoice = *LastStolenVoice; |
itSelectedVoice = *LastStolenVoice; |
433 |
do { |
do { |
440 |
break; // selection succeeded |
break; // selection succeeded |
441 |
} |
} |
442 |
} |
} |
443 |
|
|
444 |
|
// get (next) oldest note |
445 |
|
if (*LastStolenNote) { |
446 |
|
for (RTListNoteIterator itNote = ++(*LastStolenNote); |
447 |
|
itNote; ++itNote) |
448 |
|
{ |
449 |
|
for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice) { |
450 |
|
// proceed iterating if voice was created in this audio fragment cycle |
451 |
|
if (itSelectedVoice->IsStealable()) { |
452 |
|
// remember which voice on which note we stole, so we can simply proceed on next voice stealing |
453 |
|
*LastStolenNote = itNote; |
454 |
|
*LastStolenVoice = itSelectedVoice; |
455 |
|
goto voiceFound; // selection succeeded |
456 |
|
} |
457 |
|
} |
458 |
|
} |
459 |
|
} |
460 |
|
|
461 |
// get (next) oldest key |
// get (next) oldest key |
462 |
RTList<uint>::Iterator iuiSelectedKey = (*LastStolenKey) ? ++(*LastStolenKey) : pActiveKeys->first(); |
RTList<uint>::Iterator iuiSelectedKey = (*LastStolenKey) ? ++(*LastStolenKey) : pActiveKeys->first(); |
463 |
while (iuiSelectedKey) { |
for (; iuiSelectedKey; ++iuiSelectedKey) { |
464 |
MidiKey* pSelectedKey = &pMIDIKeyInfo[*iuiSelectedKey]; |
MidiKey* pSelectedKey = &pMIDIKeyInfo[*iuiSelectedKey]; |
465 |
itSelectedVoice = pSelectedKey->pActiveVoices->first(); |
|
466 |
// proceed iterating if voice was created in this fragment cycle |
for (RTListNoteIterator itNote = pSelectedKey->pActiveNotes->first(), |
467 |
while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice; |
itNotesEnd = pSelectedKey->pActiveNotes->end(); |
468 |
// found a "stealable" voice ? |
itNote != itNotesEnd; ++itNote) |
469 |
if (itSelectedVoice && itSelectedVoice->IsStealable()) { |
{ |
470 |
// remember which voice on which key we stole, so we can simply proceed on next voice stealing |
for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice) { |
471 |
*LastStolenKey = iuiSelectedKey; |
// proceed iterating if voice was created in this audio fragment cycle |
472 |
*LastStolenVoice = itSelectedVoice; |
if (itSelectedVoice->IsStealable()) { |
473 |
break; // selection succeeded |
// remember which voice on which key we stole, so we can simply proceed on next voice stealing |
474 |
|
*LastStolenKey = iuiSelectedKey; |
475 |
|
*LastStolenNote = itNote; |
476 |
|
*LastStolenVoice = itSelectedVoice; |
477 |
|
goto voiceFound; // selection succeeded |
478 |
|
} |
479 |
|
} |
480 |
} |
} |
|
++iuiSelectedKey; // get next oldest key |
|
481 |
} |
} |
482 |
break; |
break; |
483 |
} |
} |
489 |
return -1; |
return -1; |
490 |
} |
} |
491 |
} |
} |
492 |
|
|
493 |
|
voiceFound: |
494 |
|
|
495 |
if (!itSelectedVoice || !itSelectedVoice->IsStealable()) return -1; |
if (!itSelectedVoice || !itSelectedVoice->IsStealable()) return -1; |
496 |
|
|
528 |
else dmsg(1,("Event pool emtpy!\n")); |
else dmsg(1,("Event pool emtpy!\n")); |
529 |
} |
} |
530 |
} |
} |
531 |
|
|
532 |
/** |
/** |
533 |
* Kill all active voices. |
* Kill all active voices. |
534 |
* @returns The number of voices. |
* @returns The number of voices. |
536 |
int KillAllVoices(Pool<Event>::Iterator& itKillEvent) { |
int KillAllVoices(Pool<Event>::Iterator& itKillEvent) { |
537 |
int count = 0; |
int count = 0; |
538 |
|
|
539 |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
540 |
RTList<uint>::Iterator end = pActiveKeys->end(); |
RTList<uint>::Iterator end = pActiveKeys->end(); |
541 |
for (; iuiKey != end; ++iuiKey) { // iterate through all active keys |
for (; iuiKey != end; ++iuiKey) { // iterate through all active keys |
542 |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
543 |
RTListVoiceIterator itVoice = pKey->pActiveVoices->first(); |
|
544 |
RTListVoiceIterator itVoicesEnd = pKey->pActiveVoices->end(); |
for (RTListNoteIterator itNote = pKey->pActiveNotes->first(), |
545 |
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
itNotesEnd = pKey->pActiveNotes->end(); |
546 |
itVoice->Kill(itKillEvent); |
itNote != itNotesEnd; ++itNote) |
547 |
count++; |
{ |
548 |
|
RTListVoiceIterator itVoice = itNote->pActiveVoices->first(); |
549 |
|
RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end(); |
550 |
|
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
551 |
|
itVoice->Kill(itKillEvent); |
552 |
|
count++; |
553 |
|
} |
554 |
} |
} |
555 |
} |
} |
556 |
|
|
564 |
int KillAllVoicesImmediately() { |
int KillAllVoicesImmediately() { |
565 |
int iPendingStreamDeletions = 0; |
int iPendingStreamDeletions = 0; |
566 |
|
|
567 |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
568 |
RTList<uint>::Iterator end = pActiveKeys->end(); |
RTList<uint>::Iterator end = pActiveKeys->end(); |
569 |
for (; iuiKey != end; ++iuiKey) { // iterate through all active keys |
for (; iuiKey != end; ++iuiKey) { // iterate through all active keys |
570 |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
571 |
RTListVoiceIterator itVoice = pKey->pActiveVoices->first(); |
|
572 |
RTListVoiceIterator itVoicesEnd = pKey->pActiveVoices->end(); |
for (RTListNoteIterator itNote = pKey->pActiveNotes->first(), |
573 |
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
itNotesEnd = pKey->pActiveNotes->end(); |
574 |
// request a notification from disk thread side for stream deletion |
itNote != itNotesEnd; ++itNote) |
575 |
const Stream::Handle hStream = itVoice->KillImmediately(true); |
{ |
576 |
if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream |
RTListVoiceIterator itVoice = itNote->pActiveVoices->first(); |
577 |
iPendingStreamDeletions++; |
RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end(); |
578 |
} |
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
579 |
// free the voice to the voice pool and update key info |
// request a notification from disk thread side for stream deletion |
580 |
itVoice->VoiceFreed(); |
const Stream::Handle hStream = itVoice->KillImmediately(true); |
581 |
FreeVoice(itVoice); |
if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream |
582 |
|
iPendingStreamDeletions++; |
583 |
|
} |
584 |
|
// free the voice to the voice pool and update key info |
585 |
|
itVoice->VoiceFreed(); |
586 |
|
FreeVoice(itVoice); |
587 |
|
} |
588 |
} |
} |
589 |
} |
} |
590 |
|
|
596 |
* samples they use should be released to the instrument manager when the voices die. |
* samples they use should be released to the instrument manager when the voices die. |
597 |
*/ |
*/ |
598 |
void MarkAllActiveVoicesAsOrphans() { |
void MarkAllActiveVoicesAsOrphans() { |
599 |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
600 |
RTList<uint>::Iterator end = pActiveKeys->end(); |
RTList<uint>::Iterator end = pActiveKeys->end(); |
601 |
for (; iuiKey != end; ++iuiKey) { // iterate through all active keys |
for (; iuiKey != end; ++iuiKey) { // iterate through all active keys |
602 |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
603 |
RTListVoiceIterator itVoice = pKey->pActiveVoices->first(); |
|
604 |
RTListVoiceIterator itVoicesEnd = pKey->pActiveVoices->end(); |
for (RTListNoteIterator itNote = pKey->pActiveNotes->first(), |
605 |
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
itNotesEnd = pKey->pActiveNotes->end(); |
606 |
itVoice->Orphan = true; |
itNote != itNotesEnd; ++itNote) |
607 |
|
{ |
608 |
|
RTListVoiceIterator itVoice = itNote->pActiveVoices->first(); |
609 |
|
RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end(); |
610 |
|
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
611 |
|
itVoice->Orphan = true; |
612 |
|
} |
613 |
} |
} |
614 |
} |
} |
615 |
} |
} |
617 |
void ProcessActiveVoices(VoiceHandler* pVoiceHandler) { |
void ProcessActiveVoices(VoiceHandler* pVoiceHandler) { |
618 |
if (pVoiceHandler == NULL) return; |
if (pVoiceHandler == NULL) return; |
619 |
|
|
620 |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
621 |
RTList<uint>::Iterator end = pActiveKeys->end(); |
RTList<uint>::Iterator end = pActiveKeys->end(); |
622 |
for (; iuiKey != end; ++iuiKey) { // iterate through all active keys |
for (; iuiKey != end; ++iuiKey) { // iterate through all active keys |
623 |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
624 |
if (!pVoiceHandler->Process(pKey)) continue; |
if (!pVoiceHandler->Process(pKey)) continue; |
625 |
|
|
626 |
RTListVoiceIterator itVoice = pKey->pActiveVoices->first(); |
for (RTListNoteIterator itNote = pKey->pActiveNotes->first(), |
627 |
RTListVoiceIterator itVoicesEnd = pKey->pActiveVoices->end(); |
itNotesEnd = pKey->pActiveNotes->end(); |
628 |
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
itNote != itNotesEnd; ++itNote) |
629 |
pVoiceHandler->Process(itVoice); |
{ |
630 |
|
RTListVoiceIterator itVoice = itNote->pActiveVoices->first(); |
631 |
|
RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end(); |
632 |
|
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
633 |
|
pVoiceHandler->Process(itVoice); |
634 |
|
} |
635 |
} |
} |
636 |
} |
} |
637 |
} |
} |
643 |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
644 |
for (; iuiKey; ++iuiKey) { |
for (; iuiKey; ++iuiKey) { |
645 |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
646 |
RTListVoiceIterator itVoice = pKey->pActiveVoices->first(); |
|
647 |
for (; itVoice; ++itVoice) { |
for (RTListNoteIterator itNote = pKey->pActiveNotes->first(), |
648 |
itVoice->onScaleTuningChanged(); |
itNotesEnd = pKey->pActiveNotes->end(); |
649 |
|
itNote != itNotesEnd; ++itNote) |
650 |
|
{ |
651 |
|
RTListVoiceIterator itVoice = itNote->pActiveVoices->first(); |
652 |
|
for (; itVoice; ++itVoice) { |
653 |
|
itVoice->onScaleTuningChanged(); |
654 |
|
} |
655 |
} |
} |
656 |
} |
} |
657 |
} |
} |
737 |
|
|
738 |
protected: |
protected: |
739 |
AbstractEngineChannel* m_engineChannel; |
AbstractEngineChannel* m_engineChannel; |
740 |
|
Pool<V>* m_voicePool; |
741 |
|
|
742 |
class Listeners : public MidiKeyboardListener, public ListenerList<MidiKeyboardListener*> { |
class Listeners : public MidiKeyboardListener, public ListenerList<MidiKeyboardListener*> { |
743 |
public: |
public: |