--- linuxsampler/trunk/src/engines/EngineChannelBase.h 2009/10/23 17:53:17 2012 +++ linuxsampler/trunk/src/engines/EngineChannelBase.h 2010/02/28 07:28:56 2063 @@ -347,6 +347,42 @@ } virtual void ProcessKeySwitchChange(int key) = 0; + + /** + * Handle key group (a.k.a. exclusive group) conflicts + */ + void HandleKeyGroupConflicts(uint KeyGroup, Pool::Iterator& itNoteOnEvent, bool UseRelease = false) { + if (KeyGroup) { // if this voice / key belongs to a key group + uint* pKeyGroup = MidiKeyboardManager::ActiveKeyGroups[KeyGroup]; + if (pKeyGroup) { // if there's already an active key in that key group + MidiKey* pOtherKey = &MidiKeyboardManager::pMIDIKeyInfo[*pKeyGroup]; + + if (UseRelease) { + // send a note off to the other key + if (pOtherKey->KeyPressed && itNoteOnEvent->Param.Note.Key != *pKeyGroup) { + RTList::Iterator itNewEvent = pEngine->pGlobalEvents->allocAppend(); + if (itNewEvent) { + pOtherKey->ReleaseTrigger = false; + *itNewEvent = *itNoteOnEvent; + itNewEvent->Type = Event::type_note_off; + itNewEvent->Param.Note.Key = *pKeyGroup; + pEngine->ProcessNoteOff(this, itNewEvent); + } + } + } else { + // kill all voices on the (other) key + typename RTList::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first(); + typename RTList::Iterator end = pOtherKey->pActiveVoices->end(); + for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) { + if (itVoiceToBeKilled->Type != Voice::type_release_trigger) { + itVoiceToBeKilled->Kill(itNoteOnEvent); + --pEngine->VoiceSpawnsLeft; //FIXME: just a hack, we should better check in StealVoice() if the voice was killed due to key conflict + } + } + } + } + } + } }; } // namespace LinuxSampler