117 |
public: |
public: |
118 |
bool KeyPressed; ///< Is true if the respective MIDI key is currently pressed. |
bool KeyPressed; ///< Is true if the respective MIDI key is currently pressed. |
119 |
bool Active; ///< If the key contains active voices. |
bool Active; ///< If the key contains active voices. |
120 |
bool ReleaseTrigger; ///< If we have to launch release triggered voice(s) when the key is released |
release_trigger_t ReleaseTrigger; ///< If we have to launch release triggered voice(s) when either the key or sustain pedal is released. |
121 |
Pool<uint>::Iterator itSelf; ///< hack to allow fast deallocation of the key from the list of active keys |
Pool<uint>::Iterator itSelf; ///< hack to allow fast deallocation of the key from the list of active keys |
122 |
RTList<Event>* pEvents; ///< Key specific events (only Note-on, Note-off and sustain pedal currently) |
RTList<Event>* pEvents; ///< Key specific events (only Note-on, Note-off and sustain pedal currently) |
123 |
int VoiceTheftsQueued; ///< Amount of voices postponed due to shortage of voices. |
int VoiceTheftsQueued; ///< Amount of voices postponed due to shortage of voices. |
143 |
uint32_t RoundRobinIndexes[128]; |
uint32_t RoundRobinIndexes[128]; |
144 |
int8_t KeyDown[128]; ///< True if the respective key is currently pressed down. Currently only used as built-in instrument script array variable %KEY_DOWN. It is currently not used by the sampler for any other purpose. |
int8_t KeyDown[128]; ///< True if the respective key is currently pressed down. Currently only used as built-in instrument script array variable %KEY_DOWN. It is currently not used by the sampler for any other purpose. |
145 |
|
|
146 |
virtual void ProcessReleaseTrigger(RTList<Event>::Iterator& itEvent) = 0; |
virtual void ProcessReleaseTriggerBySustain(RTList<Event>::Iterator& itEvent) = 0; |
147 |
}; |
}; |
148 |
|
|
149 |
template <class V> |
template <class V> |
172 |
pActiveNotes = NULL; |
pActiveNotes = NULL; |
173 |
KeyPressed = false; |
KeyPressed = false; |
174 |
Active = false; |
Active = false; |
175 |
ReleaseTrigger = false; |
ReleaseTrigger = release_trigger_none; |
176 |
pEvents = NULL; |
pEvents = NULL; |
177 |
VoiceTheftsQueued = 0; |
VoiceTheftsQueued = 0; |
178 |
Volume = 1.0f; |
Volume = 1.0f; |
192 |
if (pEvents) pEvents->clear(); |
if (pEvents) pEvents->clear(); |
193 |
KeyPressed = false; |
KeyPressed = false; |
194 |
Active = false; |
Active = false; |
195 |
ReleaseTrigger = false; |
ReleaseTrigger = release_trigger_none; |
196 |
itSelf = Pool<uint>::Iterator(); |
itSelf = Pool<uint>::Iterator(); |
197 |
VoiceTheftsQueued = 0; |
VoiceTheftsQueued = 0; |
198 |
Volume = 1.0f; |
Volume = 1.0f; |
372 |
pKey->Active = false; |
pKey->Active = false; |
373 |
pActiveKeys->free(pKey->itSelf); // remove key from list of active keys |
pActiveKeys->free(pKey->itSelf); // remove key from list of active keys |
374 |
pKey->itSelf = RTList<uint>::Iterator(); |
pKey->itSelf = RTList<uint>::Iterator(); |
375 |
pKey->ReleaseTrigger = false; |
pKey->ReleaseTrigger = release_trigger_none; |
376 |
pKey->pEvents->clear(); |
pKey->pEvents->clear(); |
377 |
dmsg(3,("Key has no more voices now\n")); |
dmsg(3,("Key has no more voices now\n")); |
378 |
} |
} |
694 |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
695 |
for (; iuiKey; ++iuiKey) { |
for (; iuiKey; ++iuiKey) { |
696 |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
697 |
if (!pKey->KeyPressed && ShouldReleaseVoice(*iuiKey)) { |
if (!pKey->KeyPressed && |
698 |
|
(pKey->ReleaseTrigger & release_trigger_sustain) && |
699 |
|
ShouldReleaseVoice(*iuiKey)) |
700 |
|
{ |
701 |
RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend(); |
RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend(); |
702 |
if (itNewEvent) { |
if (itNewEvent) { |
703 |
*itNewEvent = *itEvent; // copy event to the key's own event list |
*itNewEvent = *itEvent; // copy event to the key's own event list |
704 |
itNewEvent->Type = Event::type_release_key; // transform event type |
itNewEvent->Type = Event::type_release_key; // transform event type |
705 |
itNewEvent->Param.Note.Key = *iuiKey; |
itNewEvent->Param.Note.Key = *iuiKey; |
706 |
itNewEvent->Param.Note.Velocity = 127; |
if (pKey->ReleaseTrigger & release_trigger_sustain_maxvelocity) |
707 |
if (!SostenutoActiveOnKey(*iuiKey)) { |
itNewEvent->Param.Note.Velocity = 127; |
708 |
//HACK: set sustain CC (64) as "pressed down" for a short moment, so that release trigger voices can distinguish between note off and sustain pedal up cases |
else // release_trigger_sustain_keyvelocity ... |
709 |
AbstractEngineChannel* pChannel = (AbstractEngineChannel*) itEvent->pEngineChannel; |
itNewEvent->Param.Note.Velocity = pKey->Velocity; |
710 |
const int8_t CC64Value = pChannel->ControllerTable[64]; |
|
711 |
pChannel->ControllerTable[64] = 127; |
//HACK: set sustain CC (64) as "pressed down" for a short moment, so that release trigger voices can distinguish between note off and sustain pedal up cases |
712 |
|
AbstractEngineChannel* pChannel = (AbstractEngineChannel*) itEvent->pEngineChannel; |
713 |
|
const int8_t CC64Value = pChannel->ControllerTable[64]; |
714 |
|
pChannel->ControllerTable[64] = 127; |
715 |
|
|
716 |
// now spawn release trigger voices (if required) |
// now spawn release trigger voices (if required) |
717 |
ProcessReleaseTrigger(itNewEvent); |
ProcessReleaseTriggerBySustain(itNewEvent); |
718 |
|
|
719 |
//HACK: reset sustain pedal CC value to old one (see comment above) |
//HACK: reset sustain pedal CC value to old one (see comment above) |
720 |
pChannel->ControllerTable[64] = CC64Value; |
pChannel->ControllerTable[64] = CC64Value; |
|
} |
|
721 |
} |
} |
722 |
else dmsg(1,("Event pool emtpy!\n")); |
else dmsg(1,("Event pool emtpy!\n")); |
723 |
} |
} |