1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6  *   Copyright (C) 2005-2020 Christian Schoenebeck                         *
7  *   Copyright (C) 2009-2010 Grigor Iliev                                  *
8  *                                                                         *
9  *   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  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  *   This program is distributed in the hope that it will be useful,       *
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
17  *   GNU General Public License for more details.                          *
18  *                                                                         *
19  *   You should have received a copy of the GNU General Public License     *
20  *   along with this program; if not, write to the Free Software           *
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
22  *   MA  02111-1307  USA                                                   *
23  ***************************************************************************/
24 
25 #ifndef __LS_MIDIKEYBOARDMANAGER_H__
26 #define __LS_MIDIKEYBOARDMANAGER_H__
27 
28 #include "Event.h"
29 #include "Stream.h"
30 #include "../../EventListeners.h"
31 #include "../../common/Pool.h"
32 #include "../../common/global_private.h"
33 #include "Note.h"
34 
35 namespace LinuxSampler {
36 
37     /**
38      * This class is used as a listener, which is notified
39      * when MIDI keyboard events occur like note on, note off, etc.
40      * Note that all events are triggered even when the channel is muted
41      */
42     class MidiKeyboardListener {
43         public:
44             /** Called before the engine start processing the note on event */
45             virtual void PreProcessNoteOn(uint8_t key, uint8_t velocity) = 0;
46 
47             /** Called after the engine has processed the note on event */
48             virtual void PostProcessNoteOn(uint8_t key, uint8_t velocity) = 0;
49 
50             /** Called before the engine start processing the note off event */
51             virtual void PreProcessNoteOff(uint8_t key, uint8_t velocity) = 0;
52 
53             /** Called after the engine has processed the note off event */
54             virtual void PostProcessNoteOff(uint8_t key, uint8_t velocity) = 0;
55 
56             /** Called before the engine start processing the sustain pedal up event */
57             virtual void PreProcessSustainPedalUp() = 0;
58 
59             /** Called after the engine has processed the sustain pedal up event */
60             virtual void PostProcessSustainPedalUp() = 0;
61 
62             /** Called before the engine start processing the sustain pedal down event */
63             virtual void PreProcessSustainPedalDown() = 0;
64 
65             /** Called after the engine has processed the sustain pedal down event */
66             virtual void PostProcessSustainPedalDown() = 0;
67 
68             /** Called before the engine start processing the sostenuto pedal up event */
69             virtual void PreProcessSostenutoPedalUp() = 0;
70 
71             /** Called after the engine has processed the sostenuto pedal up event */
72             virtual void PostProcessSostenutoPedalUp() = 0;
73 
74             /** Called before the engine start processing the sostenuto pedal down event */
75             virtual void PreProcessSostenutoPedalDown() = 0;
76 
77             /** Called after the engine has processed the sostenuto pedal down event */
78             virtual void PostProcessSostenutoPedalDown() = 0;
79     };
80 
81     /**
82      * This class exists as convenience for creating listener objects.
83      * The methods in this class are empty.
84      */
85     class MidiKeyboardAdapter : public MidiKeyboardListener {
86         public:
PreProcessNoteOn(uint8_t key,uint8_t velocity)87             virtual void PreProcessNoteOn(uint8_t key, uint8_t velocity) { }
PostProcessNoteOn(uint8_t key,uint8_t velocity)88             virtual void PostProcessNoteOn(uint8_t key, uint8_t velocity) { }
PreProcessNoteOff(uint8_t key,uint8_t velocity)89             virtual void PreProcessNoteOff(uint8_t key, uint8_t velocity) { }
PostProcessNoteOff(uint8_t key,uint8_t velocity)90             virtual void PostProcessNoteOff(uint8_t key, uint8_t velocity) { }
PreProcessSustainPedalUp()91             virtual void PreProcessSustainPedalUp() { }
PostProcessSustainPedalUp()92             virtual void PostProcessSustainPedalUp() { }
PreProcessSustainPedalDown()93             virtual void PreProcessSustainPedalDown() { }
PostProcessSustainPedalDown()94             virtual void PostProcessSustainPedalDown() { }
PreProcessSostenutoPedalUp()95             virtual void PreProcessSostenutoPedalUp() { }
PostProcessSostenutoPedalUp()96             virtual void PostProcessSostenutoPedalUp() { }
PreProcessSostenutoPedalDown()97             virtual void PreProcessSostenutoPedalDown() { }
PostProcessSostenutoPedalDown()98             virtual void PostProcessSostenutoPedalDown() { }
99     };
100 
101     /**
102      * This is the base class for class MidiKeyboardManager::MidiKey. It is
103      * not intended to be instantiated directly. Instead it just defines
104      * the part of class MidiKey which is not dependant on a C++ template
105      * parameter.
106      *
107      * There are also ScriptEvent lists maintained for each key, which are not
108      * stored here though, but on the InstrumentScript structure. Simply because
109      * RTLists are tied to one Pool instance, and it would be error prone to
110      * maintain @c Pool<ScriptEvent> and @c RTList<ScriptEvent> separately,
111      * since one would need to be very careful to reallocate the lists when the
112      * script was changed or when the Engine instance changed, etc.
113      *
114      * @see InstrumentScript::pKeyEvents
115      */
116     class MidiKeyBase {
117         public:
118             bool            KeyPressed;     ///< Is true if the respective MIDI key is currently pressed.
119             bool            Active;         ///< If the key contains active voices.
120             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
122             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.
124             uint32_t*       pRoundRobinIndex; ///< For the round robin dimension: current articulation for this key, will be incremented for each note on
125             uint8_t         Velocity;       ///< Latest Note-on velocity for this key
126             unsigned long   NoteOnTime;     ///< Time for latest Note-on event for this key
127             float           Volume;         ///< Individual volume level for this MIDI key (usually 1.0f unless Roland GS NRPN 0x1Ann was received, nn reflecting the note number, see EngineBase::ProcessHardcodedControllers())
128             float           PanLeft;        ///< Individual volume balance (left channel coefficient) for this MIDI key (usually 1.0f unless Roland GS NRPN 0x1Cnn was received, nn reflecting the note number, see EngineBase::ProcessHardcodedControllers())
129             float           PanRight;       ///< Individual volume balance (right channel coefficient) for this MIDI key (usually 1.0f unless Roland GS NRPN 0x1Cnn was received, nn reflecting the note number, see EngineBase::ProcessHardcodedControllers())
130             optional<float> ReverbSend;     ///< Optional individual reverb send level for this MIDI key (usually not set, unless Roland GS NRPN 0x1Dnn was received, nn reflecting the note number, see EngineBase::ProcessHardcodedControllers())
131             optional<float> ChorusSend;     ///< Optional individual chorus send level for this MIDI key (usually not set, unless Roland GS NRPN 0x1Enn was received, nn reflecting the note number, see EngineBase::ProcessHardcodedControllers())
132     };
133 
134     class MidiKeyboardManagerBase {
135     public:
136         Pool<uint>*           pActiveKeys;  ///< Holds all keys in it's allocation list with active voices.
137         bool                  SoloMode;                 ///< in Solo Mode we only play one voice (group) at a time
138         int                   SoloKey;                  ///< Currently 'active' solo key, that is the key to which the currently sounding voice belongs to (only if SoloMode is enabled)
139         bool                  SustainPedal;             ///< true if sustain pedal is down
140         bool                  SostenutoPedal;           ///< true if sostenuto pedal is down
141         int                   SostenutoKeys[128];
142         int                   SostenutoKeyCount;
143         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.
145 
146         virtual void ProcessReleaseTriggerBySustain(RTList<Event>::Iterator& itEvent) = 0;
147     };
148 
149     template <class V>
150     class MidiKeyboardManager : public MidiKeyboardManagerBase {
151         public:
152             /** @brief Voice Stealing Algorithms
153              *
154              * Enumeration of all possible voice stealing algorithms.
155              */
156             enum voice_steal_algo_t {
157                 voice_steal_algo_none,              ///< Voice stealing disabled.
158                 voice_steal_algo_oldestvoiceonkey,  ///< Try to kill the oldest voice from same key where the new voice should be spawned.
159                 voice_steal_algo_oldestkey          ///< Try to kill the oldest voice from the oldest active key.
160             };
161 
162 
163             /** @brief MIDI key runtime informations
164              *
165              * Reflects runtime informations for one MIDI key.
166              */
167             class MidiKey : public MidiKeyBase {
168             public:
169                 RTList< Note<V> >* pActiveNotes; ///< Contains the active notes associated with the MIDI key.
170 
MidiKey()171                 MidiKey() {
172                     pActiveNotes   = NULL;
173                     KeyPressed     = false;
174                     Active         = false;
175                     ReleaseTrigger = release_trigger_none;
176                     pEvents        = NULL;
177                     VoiceTheftsQueued = 0;
178                     Volume = 1.0f;
179                     PanLeft = 1.0f;
180                     PanRight = 1.0f;
181                 }
182 
Reset()183                 void Reset() {
184                     if (pActiveNotes) {
185                         RTListNoteIterator itNote = pActiveNotes->first();
186                         RTListNoteIterator itNotesEnd = pActiveNotes->end();
187                         for (; itNote != itNotesEnd; ++itNote) { // iterate through all active notes on this key
188                             itNote->reset();
189                         }
190                         pActiveNotes->clear();
191                     }
192                     if (pEvents) pEvents->clear();
193                     KeyPressed        = false;
194                     Active            = false;
195                     ReleaseTrigger    = release_trigger_none;
196                     itSelf            = Pool<uint>::Iterator();
197                     VoiceTheftsQueued = 0;
198                     Volume = 1.0f;
199                     PanLeft = 1.0f;
200                     PanRight = 1.0f;
201                     ReverbSend = optional<float>::nothing;
202                     ChorusSend = optional<float>::nothing;
203                 }
204             };
205 
206             typedef typename RTList< Note<V> >::Iterator RTListNoteIterator;
207             typedef typename RTList<V>::Iterator RTListVoiceIterator;
208             typedef typename Pool<V>::Iterator PoolVoiceIterator;
209 
210             /**
211              * Override this class to iterate through all active keys/voices
212              * using ProcessActiveVoices() method.
213              */
214             class VoiceHandler {
215                 public:
216                     /**
217                      * @returns true if the voices on the specified key should be processed
218                      * adn false to cancel the processing of the active voices for the
219                      * specified key
220                      */
221                     virtual bool Process(MidiKey* pMidiKey) = 0;
222 
223                     virtual void Process(RTListVoiceIterator& itVoice) = 0;
224             };
225 
226             class VoiceHandlerBase : public VoiceHandler {
227                 public:
Process(MidiKey * pMidiKey)228                     virtual bool Process(MidiKey* pMidiKey) { return true; }
Process(RTListVoiceIterator & itVoice)229                     virtual void Process(RTListVoiceIterator& itVoice) { }
230             };
231 
232             MidiKey*              pMIDIKeyInfo; ///< Contains all active voices sorted by MIDI key number and other informations to the respective MIDI key
233 
MidiKeyboardManager(AbstractEngineChannel * pEngineChannel)234             MidiKeyboardManager(AbstractEngineChannel* pEngineChannel) {
235                 pMIDIKeyInfo = new MidiKey[128];
236                 pActiveKeys  = new Pool<uint>(128);
237                 SoloMode     = false;
238                 SustainPedal   = false;
239                 SostenutoPedal = false;
240                 for (int i = 0 ; i < 128 ; i++) {
241                     RoundRobinIndexes[i] = 0;
242                     KeyDown[i] = false;
243 
244                     // by default use one counter for each key (the
245                     // gig engine will change this to one counter per
246                     // region)
247                     pMIDIKeyInfo[i].pRoundRobinIndex = &RoundRobinIndexes[i];
248                 }
249                 m_engineChannel = pEngineChannel;
250                 m_voicePool = NULL;
251             }
252 
~MidiKeyboardManager()253             virtual ~MidiKeyboardManager() {
254                 listeners.RemoveAllListeners();
255                 if (pActiveKeys) delete pActiveKeys;
256                 if (pMIDIKeyInfo) delete[] pMIDIKeyInfo;
257             }
258 
Reset()259             void Reset() {
260                 SoloKey = -1;    // no solo key active yet
261 
262                 // reset key info
263                 for (uint i = 0; i < 128; i++) {
264                     pMIDIKeyInfo[i].Reset();
265                     KeyDown[i] = false;
266                     if (m_engineChannel->pScript)
267                         m_engineChannel->pScript->pKeyEvents[i]->clear();
268                 }
269 
270                 // free all active keys
271                 pActiveKeys->clear();
272             }
273 
AllocateActiveNotesLists(Pool<Note<V>> * pNotePool,Pool<V> * pVoicePool)274             void AllocateActiveNotesLists(Pool< Note<V> >* pNotePool, Pool<V>* pVoicePool) {
275                 DeleteActiveNotesLists();
276 
277                 m_voicePool = pVoicePool;
278 
279                 for (uint i = 0; i < 128; i++) {
280                     pMIDIKeyInfo[i].pActiveNotes = new RTList< Note<V> >(pNotePool);
281                 }
282             }
283 
DeleteActiveNotesLists()284             void DeleteActiveNotesLists() {
285                 for (uint i = 0; i < 128; i++) {
286                     if (pMIDIKeyInfo[i].pActiveNotes) {
287                         delete pMIDIKeyInfo[i].pActiveNotes;
288                         pMIDIKeyInfo[i].pActiveNotes = NULL;
289                     }
290                 }
291                 m_voicePool = NULL;
292             }
293 
AllocateEventsLists(Pool<Event> * pEventPool)294             void AllocateEventsLists(Pool<Event>* pEventPool) {
295                 DeleteEventsLists();
296 
297                 for (uint i = 0; i < 128; i++) {
298                     pMIDIKeyInfo[i].pEvents = new RTList<Event>(pEventPool);
299                 }
300             }
301 
DeleteEventsLists()302             void DeleteEventsLists() {
303                 for (uint i = 0; i < 128; i++) {
304                     if (pMIDIKeyInfo[i].pEvents) {
305                         delete pMIDIKeyInfo[i].pEvents;
306                         pMIDIKeyInfo[i].pEvents = NULL;
307                     }
308                 }
309             }
310 
311             /*void ClearAllActiveKeyEvents() {
312                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
313                 RTList<uint>::Iterator end    = pActiveKeys->end();
314                 for(; iuiKey != end; ++iuiKey) {
315                     pMIDIKeyInfo[*iuiKey].pEvents->clear(); // free all events on the key
316                 }
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              */
markKeyAsActive(MidiKey * pKey)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.
336              *  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
338              *  just was killed.
339              *
340              *  @param itVoice - points to the voice to be freed
341              */
FreeVoice(PoolVoiceIterator & itVoice)342             void FreeVoice(PoolVoiceIterator& itVoice) {
343                 if (itVoice) {
344                     //MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey];
345 
346                     // if the sample and dimension region belong to an
347                     // instrument that is unloaded, tell the disk thread to
348                     // release them
349                     if (itVoice->Orphan) {
350                         if(itVoice->pDiskThread != NULL) {
351                             itVoice->pDiskThread->OrderDeletionOfRegion(itVoice->GetRegion());
352                         }
353                     }
354 
355                     // free the voice object
356                     m_voicePool->free(itVoice);
357                 }
358                 else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;
359             }
360 
361             /**
362              *  Called when there's no more voice left on a key, this call will
363              *  update the key info respectively.
364              *
365              *  @param pEngineChannel - engine channel on which this event occured on
366              *  @param pKey - key which is now inactive
367              */
FreeKey(MidiKey * pKey)368             void FreeKey(MidiKey* pKey) {
369                 if (pKey->pActiveNotes->isEmpty()) {
370                     if (m_engineChannel->pScript)
371                         m_engineChannel->pScript->pKeyEvents[pKey->itSelf]->clear();
372                     pKey->Active = false;
373                     pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
374                     pKey->itSelf = RTList<uint>::Iterator();
375                     pKey->ReleaseTrigger = release_trigger_none;
376                     pKey->pEvents->clear();
377                     dmsg(3,("Key has no more voices now\n"));
378                 }
379                 else dmsg(1,("MidiKeyboardManager: Oops, tried to free a key which contains voices.\n"));
380             }
381 
382             /**
383              * Free all keys which have no active voices left
384              */
FreeAllInactiveKeys()385             void FreeAllInactiveKeys() {
386                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
387                 RTList<uint>::Iterator end    = pActiveKeys->end();
388                 while (iuiKey != end) { // iterate through all active keys
389                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
390                     ++iuiKey;
391                     for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
392                          itNotesEnd = pKey->pActiveNotes->end();
393                          itNote != itNotesEnd; ++itNote)
394                     { // iterate over all active notes on that key ...
395                         if (itNote->pActiveVoices->isEmpty()) { // free note ...
396                             itNote->reset();
397                             pKey->pActiveNotes->free(itNote);
398                         }
399                         #if CONFIG_DEVMODE
400                         else { // just a sanity check for debugging
401                             RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
402                             RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end();
403                             for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
404                                 if (itVoice->itKillEvent) {
405                                     dmsg(1,("gig::Engine: ERROR, killed voice survived !!!\n"));
406                                 }
407                             }
408                         }
409                         #endif // CONFIG_DEVMODE
410                     }
411                     if (pKey->pActiveNotes->isEmpty()) FreeKey(pKey);
412                 }
413             }
414 
StealVoice(Pool<Event>::Iterator & itNoteOnEvent,RTListVoiceIterator * LastStolenVoice,RTListNoteIterator * LastStolenNote,RTList<uint>::Iterator * LastStolenKey)415             int StealVoice (
416                 Pool<Event>::Iterator&   itNoteOnEvent,
417                 RTListVoiceIterator*     LastStolenVoice,
418                 RTListNoteIterator*      LastStolenNote,
419                 RTList<uint>::Iterator*  LastStolenKey
420             ) {
421                 RTListVoiceIterator itSelectedVoice;
422 
423                 // Select one voice for voice stealing
424                 switch (CONFIG_VOICE_STEAL_ALGO) {
425 
426                     // try to pick the oldest voice on the key where the new
427                     // voice should be spawned, if there is no voice on that
428                     // key, or no voice left to kill, then procceed with
429                     // 'oldestkey' algorithm
430                     case voice_steal_algo_oldestvoiceonkey: {
431                         MidiKey* pSelectedKey = &pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
432                         for (RTListNoteIterator itNote = pSelectedKey->pActiveNotes->first(),
433                              itNotesEnd = pSelectedKey->pActiveNotes->end();
434                              itNote != itNotesEnd; ++itNote)
435                         {
436                             for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice)
437                                 if (itSelectedVoice->IsStealable()) // proceed iterating if voice was created in this audio fragment cycle
438                                     goto voiceFound; // selection succeeded
439                         }
440                         // if we haven't found a voice then proceed with algorithm 'oldestkey' ...
441                     } // no break - intentional !
442 
443                     // try to pick the oldest voice on the oldest active key
444                     // from the same engine channel
445                     // (caution: must stay after 'oldestvoiceonkey' algorithm !)
446                     case voice_steal_algo_oldestkey: {
447                         // if we already stole in this fragment, try to proceed to steal on same note
448                         if (*LastStolenVoice) {
449                             itSelectedVoice = *LastStolenVoice;
450                             do {
451                                 ++itSelectedVoice;
452                             } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
453                             // found a "stealable" voice ?
454                             if (itSelectedVoice && itSelectedVoice->IsStealable()) {
455                                 // remember which voice we stole, so we can simply proceed on next voice stealing
456                                 *LastStolenVoice = itSelectedVoice;
457                                 break; // selection succeeded
458                             }
459                         }
460 
461                         // get (next) oldest note
462                         if (*LastStolenNote) {
463                             for (RTListNoteIterator itNote = ++(*LastStolenNote);
464                                  itNote; ++itNote)
465                             {
466                                 for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice) {
467                                     // proceed iterating if voice was created in this audio fragment cycle
468                                     if (itSelectedVoice->IsStealable()) {
469                                         // remember which voice on which note we stole, so we can simply proceed on next voice stealing
470                                         *LastStolenNote  = itNote;
471                                         *LastStolenVoice = itSelectedVoice;
472                                         goto voiceFound; // selection succeeded
473                                     }
474                                 }
475                             }
476                         }
477 
478                         // get (next) oldest key
479                         RTList<uint>::Iterator iuiSelectedKey = (*LastStolenKey) ? ++(*LastStolenKey) : pActiveKeys->first();
480                         for (; iuiSelectedKey; ++iuiSelectedKey) {
481                             MidiKey* pSelectedKey = &pMIDIKeyInfo[*iuiSelectedKey];
482 
483                             for (RTListNoteIterator itNote = pSelectedKey->pActiveNotes->first(),
484                                  itNotesEnd = pSelectedKey->pActiveNotes->end();
485                                  itNote != itNotesEnd; ++itNote)
486                             {
487                                 for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice) {
488                                     // proceed iterating if voice was created in this audio fragment cycle
489                                     if (itSelectedVoice->IsStealable()) {
490                                         // remember which voice on which key we stole, so we can simply proceed on next voice stealing
491                                         *LastStolenKey  = iuiSelectedKey;
492                                         *LastStolenNote = itNote;
493                                         *LastStolenVoice = itSelectedVoice;
494                                         goto voiceFound; // selection succeeded
495                                     }
496                                 }
497                             }
498                         }
499                         break;
500                     }
501 
502                     // don't steal anything
503                     case voice_steal_algo_none:
504                     default: {
505                         dmsg(1,("No free voice (voice stealing disabled)!\n"));
506                         return -1;
507                     }
508                 }
509 
510                 voiceFound:
511 
512                 if (!itSelectedVoice || !itSelectedVoice->IsStealable()) return -1;
513 
514                 #if CONFIG_DEVMODE
515                 if (!itSelectedVoice->IsActive()) {
516                     dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
517                     return -1;
518                 }
519                 #endif // CONFIG_DEVMODE
520 
521                 // now kill the selected voice
522                 itSelectedVoice->Kill(itNoteOnEvent);
523 
524                 return 0;
525             }
526 
527             /**
528              * Releases all voices. All voices will go into
529              * the release stage and thus it might take some time (e.g. dependant to
530              * their envelope release time) until they actually die.
531              *
532              * @param itReleaseEvent - event which caused this releasing of all voices
533              */
ReleaseAllVoices(Pool<Event>::Iterator & itReleaseEvent)534             void ReleaseAllVoices(Pool<Event>::Iterator& itReleaseEvent) {
535                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
536                 while (iuiKey) {
537                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
538                     ++iuiKey;
539                     // append a 'release' event to the key's own event list
540                     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
541                     if (itNewEvent) {
542                         *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
543                         itNewEvent->Type = Event::type_release_key; // transform event type
544                     }
545                     else dmsg(1,("Event pool emtpy!\n"));
546                 }
547             }
548 
549             /**
550              * Kill all active voices.
551              * @returns The number of voices.
552              */
KillAllVoices(Pool<Event>::Iterator & itKillEvent)553             int KillAllVoices(Pool<Event>::Iterator& itKillEvent) {
554                 int count = 0;
555 
556                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
557                 RTList<uint>::Iterator end = pActiveKeys->end();
558                 for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
559                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
560 
561                     for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
562                          itNotesEnd = pKey->pActiveNotes->end();
563                          itNote != itNotesEnd; ++itNote)
564                     {
565                         RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
566                         RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end();
567                         for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
568                             itVoice->Kill(itKillEvent);
569                             count++;
570                         }
571                     }
572                 }
573 
574                 return count;
575             }
576 
577             /**
578              * Kill all voices the *die hard* way.
579              * @returns The number of pending stream deletions
580              */
KillAllVoicesImmediately()581             int KillAllVoicesImmediately() {
582                 int iPendingStreamDeletions = 0;
583 
584                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
585                 RTList<uint>::Iterator end = pActiveKeys->end();
586                 for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
587                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
588 
589                     for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
590                          itNotesEnd = pKey->pActiveNotes->end();
591                          itNote != itNotesEnd; ++itNote)
592                     {
593                         RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
594                         RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end();
595                         for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
596                             // request a notification from disk thread side for stream deletion
597                             const Stream::Handle hStream = itVoice->KillImmediately(true);
598                             if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream
599                                 iPendingStreamDeletions++;
600                             }
601                             // free the voice to the voice pool and update key info
602                             itVoice->VoiceFreed();
603                             FreeVoice(itVoice);
604                         }
605                     }
606                 }
607 
608                 return iPendingStreamDeletions;
609             }
610 
611             /**
612              * Mark all currently active voices as "orphans", which means that the regions and
613              * samples they use should be released to the instrument manager when the voices die.
614              */
MarkAllActiveVoicesAsOrphans()615             void MarkAllActiveVoicesAsOrphans() {
616                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
617                 RTList<uint>::Iterator end = pActiveKeys->end();
618                 for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
619                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
620 
621                     for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
622                          itNotesEnd = pKey->pActiveNotes->end();
623                          itNote != itNotesEnd; ++itNote)
624                     {
625                         RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
626                         RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end();
627                         for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
628                             itVoice->Orphan = true;
629                         }
630                     }
631                 }
632             }
633 
ProcessActiveVoices(VoiceHandler * pVoiceHandler)634             void ProcessActiveVoices(VoiceHandler* pVoiceHandler) {
635                 if (pVoiceHandler == NULL) return;
636 
637                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
638                 RTList<uint>::Iterator end = pActiveKeys->end();
639                 for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
640                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
641                     if (!pVoiceHandler->Process(pKey)) continue;
642 
643                     for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
644                          itNotesEnd = pKey->pActiveNotes->end();
645                          itNote != itNotesEnd; ++itNote)
646                     {
647                         RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
648                         RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end();
649                         for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
650                             pVoiceHandler->Process(itVoice);
651                         }
652                     }
653                 }
654             }
655 
656             /**
657              * Recalculate the pitch of all active voices.
658              */
OnScaleTuningChanged()659             void OnScaleTuningChanged() {
660                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
661                 for (; iuiKey; ++iuiKey) {
662                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
663 
664                     for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
665                          itNotesEnd = pKey->pActiveNotes->end();
666                          itNote != itNotesEnd; ++itNote)
667                     {
668                         RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
669                         for (; itVoice; ++itVoice) {
670                             itVoice->onScaleTuningChanged();
671                         }
672                     }
673                 }
674             }
675 
ProcessSustainPedalDown(Pool<Event>::Iterator & itEvent)676             void ProcessSustainPedalDown(Pool<Event>::Iterator& itEvent) {
677                 // Cancel release process of all voices
678                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
679                 for (; iuiKey; ++iuiKey) {
680                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
681                     if (!pKey->KeyPressed) {
682                         RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
683                         if (itNewEvent) {
684                             *itNewEvent = *itEvent; // copy event to the key's own event list
685                             itNewEvent->Type = Event::type_cancel_release_key; // transform event type
686                         }
687                         else dmsg(1,("Event pool emtpy!\n"));
688                     }
689                 }
690             }
691 
ProcessSustainPedalUp(Pool<Event>::Iterator & itEvent)692             void ProcessSustainPedalUp(Pool<Event>::Iterator& itEvent) {
693                 // release voices if their respective key is not pressed
694                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
695                 for (; iuiKey; ++iuiKey) {
696                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
697                     if (!pKey->KeyPressed && ShouldReleaseVoice(*iuiKey)) {
698                         RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
699                         if (itNewEvent) {
700                             *itNewEvent = *itEvent; // copy event to the key's own event list
701                             itNewEvent->Type = Event::type_release_key; // transform event type
702                             itNewEvent->Param.Note.Key = *iuiKey;
703                             itNewEvent->Param.Note.Velocity = 127;
704 
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
711                                 AbstractEngineChannel* pChannel = (AbstractEngineChannel*) itEvent->pEngineChannel;
712                                 const int8_t CC64Value = pChannel->ControllerTable[64];
713                                 pChannel->ControllerTable[64] = 127;
714 
715                                 // now spawn release trigger voices (if required)
716                                 ProcessReleaseTriggerBySustain(itNewEvent);
717 
718                                 //HACK: reset sustain pedal CC value to old one (see comment above)
719                                 pChannel->ControllerTable[64] = CC64Value;
720                             }
721                         }
722                         else dmsg(1,("Event pool emtpy!\n"));
723                     }
724                 }
725             }
726 
727             /**
728              * Whether @a key is still kept active due to sostenuto pedal usage.
729              *
730              * @param key - note number of key
731              */
SostenutoActiveOnKey(int key)732             inline bool SostenutoActiveOnKey(int key) const {
733                 if (SostenutoPedal) {
734                     for (int i = 0; i < SostenutoKeyCount; i++)
735                         if (key == SostenutoKeys[i]) return true;
736                 }
737                 return false;
738             }
739 
740             /**
741              * Determines whether the specified voice should be released.
742              *
743              * @param pEngineChannel - The engine channel on which the voice should be checked
744              * @param Key - The key number
745              * @returns true if the specified voice should be released, false otherwise.
746              */
ShouldReleaseVoice(int Key)747             bool ShouldReleaseVoice(int Key) {
748                 if (SustainPedal) return false;
749                 if (SostenutoActiveOnKey(Key)) return false;
750                 return true;
751             }
752 
ProcessSostenutoPedalDown()753             void ProcessSostenutoPedalDown() {
754                 SostenutoKeyCount = 0;
755                 // Remeber the pressed keys
756                 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
757                 for (; iuiKey; ++iuiKey) {
758                     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
759                     if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
760                 }
761             }
762 
ProcessSostenutoPedalUp(Pool<Event>::Iterator & itEvent)763             void ProcessSostenutoPedalUp(Pool<Event>::Iterator& itEvent) {
764                 // release voices if the damper pedal is up and their respective key is not pressed
765                 for (int i = 0; i < SostenutoKeyCount; i++) {
766                     MidiKey* pKey = &pMIDIKeyInfo[SostenutoKeys[i]];
767                     if (!pKey->KeyPressed && !SustainPedal) {
768                         RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
769                         if (itNewEvent) {
770                             *itNewEvent = *itEvent; // copy event to the key's own event list
771                             itNewEvent->Type = Event::type_release_key; // transform event type
772                         }
773                         else dmsg(1,("Event pool emtpy!\n"));
774                     }
775                 }
776             }
777 
AddMidiKeyboardListener(MidiKeyboardListener * l)778             void AddMidiKeyboardListener(MidiKeyboardListener* l) { listeners.AddListener(l); }
779 
RemoveMidiKeyboardListener(MidiKeyboardListener * l)780             void RemoveMidiKeyboardListener(MidiKeyboardListener* l) { listeners.RemoveListener(l); }
781 
782         protected:
783             AbstractEngineChannel* m_engineChannel;
784             Pool<V>* m_voicePool;
785 
786             class Listeners : public MidiKeyboardListener, public ListenerList<MidiKeyboardListener*> {
787             public:
788                 REGISTER_FIRE_EVENT_METHOD_ARG2(PreProcessNoteOn, uint8_t, uint8_t)
789                 REGISTER_FIRE_EVENT_METHOD_ARG2(PostProcessNoteOn, uint8_t, uint8_t)
790                 REGISTER_FIRE_EVENT_METHOD_ARG2(PreProcessNoteOff, uint8_t, uint8_t)
791                 REGISTER_FIRE_EVENT_METHOD_ARG2(PostProcessNoteOff, uint8_t, uint8_t)
792                 REGISTER_FIRE_EVENT_METHOD(PreProcessSustainPedalUp)
793                 REGISTER_FIRE_EVENT_METHOD(PostProcessSustainPedalUp)
794                 REGISTER_FIRE_EVENT_METHOD(PreProcessSustainPedalDown)
795                 REGISTER_FIRE_EVENT_METHOD(PostProcessSustainPedalDown)
796                 REGISTER_FIRE_EVENT_METHOD(PreProcessSostenutoPedalUp)
797                 REGISTER_FIRE_EVENT_METHOD(PostProcessSostenutoPedalUp)
798                 REGISTER_FIRE_EVENT_METHOD(PreProcessSostenutoPedalDown)
799                 REGISTER_FIRE_EVENT_METHOD(PostProcessSostenutoPedalDown)
800             } listeners;
801     };
802 } // namespace LinuxSampler
803 
804 #endif  /* __LS_MIDIKEYBOARDMANAGER_H__ */
805