3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005-2008 Christian Schoenebeck * |
* Copyright (C) 2005-2020 Christian Schoenebeck * |
7 |
* Copyright (C) 2009-2010 Christian Schoenebeck and Grigor Iliev * |
* Copyright (C) 2009-2010 Grigor Iliev * |
8 |
* * |
* * |
9 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
10 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
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; |
317 |
}*/ |
}*/ |
318 |
|
|
319 |
/** |
/** |
320 |
|
* Make sure the passed MIDI key is part of the list of active keys, |
321 |
|
* if it is not already, then add it to that list. Accordingly it is |
322 |
|
* safe to call this method even if the requested key is already |
323 |
|
* marked as active. |
324 |
|
*/ |
325 |
|
void markKeyAsActive(MidiKey* pKey) { |
326 |
|
if (!pKey->Active) { // mark as active key |
327 |
|
pKey->Active = true; |
328 |
|
pKey->itSelf = pActiveKeys->allocAppend(); |
329 |
|
const int iKey = int( pKey - &pMIDIKeyInfo[0] ); |
330 |
|
*pKey->itSelf = iKey; |
331 |
|
} |
332 |
|
} |
333 |
|
|
334 |
|
/** |
335 |
* Removes the given voice from the MIDI key's list of active voices. |
* Removes the given voice from the MIDI key's list of active voices. |
336 |
* This method will be called when a voice went inactive, e.g. because |
* This method will be called when a voice went inactive, e.g. because |
337 |
* it finished to playback its sample, finished its release stage or |
* it finished to playback its sample, finished its release stage or |
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 |
} |
} |
382 |
/** |
/** |
383 |
* Free all keys which have no active voices left |
* Free all keys which have no active voices left |
384 |
*/ |
*/ |
385 |
void FreeAllInactiveKyes() { |
void FreeAllInactiveKeys() { |
386 |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
387 |
RTList<uint>::Iterator end = pActiveKeys->end(); |
RTList<uint>::Iterator end = pActiveKeys->end(); |
388 |
while (iuiKey != end) { // iterate through all active keys |
while (iuiKey != end) { // iterate through all active keys |
540 |
RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend(); |
RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend(); |
541 |
if (itNewEvent) { |
if (itNewEvent) { |
542 |
*itNewEvent = *itReleaseEvent; // copy original event (to the key's event list) |
*itNewEvent = *itReleaseEvent; // copy original event (to the key's event list) |
543 |
itNewEvent->Type = Event::type_release; // transform event type |
itNewEvent->Type = Event::type_release_key; // transform event type |
544 |
} |
} |
545 |
else dmsg(1,("Event pool emtpy!\n")); |
else dmsg(1,("Event pool emtpy!\n")); |
546 |
} |
} |
682 |
RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend(); |
RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend(); |
683 |
if (itNewEvent) { |
if (itNewEvent) { |
684 |
*itNewEvent = *itEvent; // copy event to the key's own event list |
*itNewEvent = *itEvent; // copy event to the key's own event list |
685 |
itNewEvent->Type = Event::type_cancel_release; // transform event type |
itNewEvent->Type = Event::type_cancel_release_key; // transform event type |
686 |
} |
} |
687 |
else dmsg(1,("Event pool emtpy!\n")); |
else dmsg(1,("Event pool emtpy!\n")); |
688 |
} |
} |
698 |
RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend(); |
RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend(); |
699 |
if (itNewEvent) { |
if (itNewEvent) { |
700 |
*itNewEvent = *itEvent; // copy event to the key's own event list |
*itNewEvent = *itEvent; // copy event to the key's own event list |
701 |
itNewEvent->Type = Event::type_release; // transform event type |
itNewEvent->Type = Event::type_release_key; // transform event type |
702 |
itNewEvent->Param.Note.Key = *iuiKey; |
itNewEvent->Param.Note.Key = *iuiKey; |
703 |
itNewEvent->Param.Note.Velocity = 127; |
itNewEvent->Param.Note.Velocity = 127; |
704 |
if (!SostenutoActiveOnKey(*iuiKey)) { |
|
705 |
|
// process release trigger (if requested) |
706 |
|
if (pKey->ReleaseTrigger & release_trigger_sustain) { |
707 |
|
if (pKey->ReleaseTrigger & release_trigger_sustain_keyvelocity) |
708 |
|
itNewEvent->Param.Note.Velocity = pKey->Velocity; |
709 |
|
|
710 |
//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 |
//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 |
711 |
AbstractEngineChannel* pChannel = (AbstractEngineChannel*) itEvent->pEngineChannel; |
AbstractEngineChannel* pChannel = (AbstractEngineChannel*) itEvent->pEngineChannel; |
712 |
const int8_t CC64Value = pChannel->ControllerTable[64]; |
const int8_t CC64Value = pChannel->ControllerTable[64]; |
713 |
pChannel->ControllerTable[64] = 127; |
pChannel->ControllerTable[64] = 127; |
714 |
|
|
715 |
// now spawn release trigger voices (if required) |
// now spawn release trigger voices (if required) |
716 |
ProcessReleaseTrigger(itNewEvent); |
ProcessReleaseTriggerBySustain(itNewEvent); |
717 |
|
|
718 |
//HACK: reset sustain pedal CC value to old one (see comment above) |
//HACK: reset sustain pedal CC value to old one (see comment above) |
719 |
pChannel->ControllerTable[64] = CC64Value; |
pChannel->ControllerTable[64] = CC64Value; |
720 |
} |
} |
721 |
} |
} |
722 |
else dmsg(1,("Event pool emtpy!\n")); |
else dmsg(1,("Event pool emtpy!\n")); |
768 |
RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend(); |
RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend(); |
769 |
if (itNewEvent) { |
if (itNewEvent) { |
770 |
*itNewEvent = *itEvent; // copy event to the key's own event list |
*itNewEvent = *itEvent; // copy event to the key's own event list |
771 |
itNewEvent->Type = Event::type_release; // transform event type |
itNewEvent->Type = Event::type_release_key; // transform event type |
772 |
} |
} |
773 |
else dmsg(1,("Event pool emtpy!\n")); |
else dmsg(1,("Event pool emtpy!\n")); |
774 |
} |
} |