/[svn]/linuxsampler/trunk/src/engines/common/MidiKeyboardManager.h
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/common/MidiKeyboardManager.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3306 - (hide annotations) (download) (as text)
Tue Jul 11 15:50:05 2017 UTC (6 years, 9 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 40617 byte(s)
* Fixed Note object leak when triggering notes on keys which did
  not have a valid sample mapped (fixes bug #252).
* Fixed compilation errors when compiling with CONFIG_DEVMODE
  enabled.
* Bumped version (2.0.0.svn69).

1 iliev 2012 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck *
6 persson 2114 * Copyright (C) 2005-2008 Christian Schoenebeck *
7     * Copyright (C) 2009-2010 Christian Schoenebeck and Grigor Iliev *
8 iliev 2012 * *
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 persson 2114 #define __LS_MIDIKEYBOARDMANAGER_H__
27 iliev 2012
28     #include "Event.h"
29     #include "Stream.h"
30     #include "../../EventListeners.h"
31     #include "../../common/Pool.h"
32     #include "../../common/global_private.h"
33 schoenebeck 2879 #include "Note.h"
34 iliev 2012
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:
87     virtual void PreProcessNoteOn(uint8_t key, uint8_t velocity) { }
88     virtual void PostProcessNoteOn(uint8_t key, uint8_t velocity) { }
89     virtual void PreProcessNoteOff(uint8_t key, uint8_t velocity) { }
90     virtual void PostProcessNoteOff(uint8_t key, uint8_t velocity) { }
91     virtual void PreProcessSustainPedalUp() { }
92     virtual void PostProcessSustainPedalUp() { }
93     virtual void PreProcessSustainPedalDown() { }
94     virtual void PostProcessSustainPedalDown() { }
95     virtual void PreProcessSostenutoPedalUp() { }
96     virtual void PostProcessSostenutoPedalUp() { }
97     virtual void PreProcessSostenutoPedalDown() { }
98     virtual void PostProcessSostenutoPedalDown() { }
99     };
100 schoenebeck 2645
101 schoenebeck 2121 /**
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 schoenebeck 2645 *
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 schoenebeck 2121 */
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     bool ReleaseTrigger; ///< If we have to launch release triggered voice(s) when the key 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 iliev 2012
134 schoenebeck 2613 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 schoenebeck 2927
146     virtual void ProcessReleaseTrigger(RTList<Event>::Iterator& itEvent) = 0;
147 schoenebeck 2613 };
148    
149 iliev 2012 template <class V>
150 schoenebeck 2613 class MidiKeyboardManager : public MidiKeyboardManagerBase {
151 iliev 2012 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 persson 2043
163 iliev 2012 /** @brief MIDI key runtime informations
164     *
165     * Reflects runtime informations for one MIDI key.
166     */
167 schoenebeck 2121 class MidiKey : public MidiKeyBase {
168 iliev 2012 public:
169 schoenebeck 2879 RTList< Note<V> >* pActiveNotes; ///< Contains the active notes associated with the MIDI key.
170 iliev 2012
171     MidiKey() {
172 schoenebeck 2879 pActiveNotes = NULL;
173 iliev 2012 KeyPressed = false;
174     Active = false;
175     ReleaseTrigger = false;
176     pEvents = NULL;
177     VoiceTheftsQueued = 0;
178 schoenebeck 2121 Volume = 1.0f;
179     PanLeft = 1.0f;
180     PanRight = 1.0f;
181 iliev 2012 }
182    
183     void Reset() {
184 schoenebeck 2879 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 iliev 2244 }
190 schoenebeck 2879 pActiveNotes->clear();
191 iliev 2244 }
192 iliev 2012 if (pEvents) pEvents->clear();
193     KeyPressed = false;
194     Active = false;
195     ReleaseTrigger = false;
196     itSelf = Pool<uint>::Iterator();
197     VoiceTheftsQueued = 0;
198 schoenebeck 2121 Volume = 1.0f;
199     PanLeft = 1.0f;
200     PanRight = 1.0f;
201     ReverbSend = optional<float>::nothing;
202     ChorusSend = optional<float>::nothing;
203 iliev 2012 }
204     };
205    
206 schoenebeck 2879 typedef typename RTList< Note<V> >::Iterator RTListNoteIterator;
207 iliev 2012 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:
228     virtual bool Process(MidiKey* pMidiKey) { return true; }
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    
234 schoenebeck 2645 MidiKeyboardManager(AbstractEngineChannel* pEngineChannel) {
235 iliev 2012 pMIDIKeyInfo = new MidiKey[128];
236     pActiveKeys = new Pool<uint>(128);
237     SoloMode = false;
238     SustainPedal = false;
239     SostenutoPedal = false;
240 persson 2043 for (int i = 0 ; i < 128 ; i++) {
241     RoundRobinIndexes[i] = 0;
242 schoenebeck 2613 KeyDown[i] = false;
243 persson 2043
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 schoenebeck 2645 m_engineChannel = pEngineChannel;
250 schoenebeck 2879 m_voicePool = NULL;
251 iliev 2012 }
252    
253     virtual ~MidiKeyboardManager() {
254     listeners.RemoveAllListeners();
255     if (pActiveKeys) delete pActiveKeys;
256     if (pMIDIKeyInfo) delete[] pMIDIKeyInfo;
257     }
258    
259 persson 2114 void Reset() {
260 iliev 2012 SoloKey = -1; // no solo key active yet
261    
262     // reset key info
263 schoenebeck 2613 for (uint i = 0; i < 128; i++) {
264     pMIDIKeyInfo[i].Reset();
265     KeyDown[i] = false;
266 schoenebeck 2645 if (m_engineChannel->pScript)
267     m_engineChannel->pScript->pKeyEvents[i]->clear();
268 schoenebeck 2613 }
269 iliev 2012
270     // free all active keys
271     pActiveKeys->clear();
272     }
273    
274 schoenebeck 2879 void AllocateActiveNotesLists(Pool< Note<V> >* pNotePool, Pool<V>* pVoicePool) {
275     DeleteActiveNotesLists();
276 iliev 2012
277 schoenebeck 2879 m_voicePool = pVoicePool;
278    
279 iliev 2012 for (uint i = 0; i < 128; i++) {
280 schoenebeck 2879 pMIDIKeyInfo[i].pActiveNotes = new RTList< Note<V> >(pNotePool);
281 iliev 2012 }
282     }
283    
284 schoenebeck 2879 void DeleteActiveNotesLists() {
285 iliev 2012 for (uint i = 0; i < 128; i++) {
286 schoenebeck 2879 if (pMIDIKeyInfo[i].pActiveNotes) {
287     delete pMIDIKeyInfo[i].pActiveNotes;
288     pMIDIKeyInfo[i].pActiveNotes = NULL;
289 iliev 2012 }
290     }
291 schoenebeck 2879 m_voicePool = NULL;
292 iliev 2012 }
293    
294 schoenebeck 2879 void AllocateEventsLists(Pool<Event>* pEventPool) {
295     DeleteEventsLists();
296 iliev 2012
297     for (uint i = 0; i < 128; i++) {
298     pMIDIKeyInfo[i].pEvents = new RTList<Event>(pEventPool);
299     }
300     }
301    
302 schoenebeck 2879 void DeleteEventsLists() {
303 iliev 2012 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 schoenebeck 2645 /*void ClearAllActiveKeyEvents() {
312 iliev 2012 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 schoenebeck 2645 }*/
318 iliev 2012
319     /**
320 schoenebeck 3306 * 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 = pKey - &pMIDIKeyInfo[0];
330     *pKey->itSelf = iKey;
331     }
332     }
333    
334     /**
335 iliev 2012 * 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     */
342     void FreeVoice(PoolVoiceIterator& itVoice) {
343     if (itVoice) {
344 schoenebeck 2879 //MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey];
345 iliev 2012
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 schoenebeck 2879 m_voicePool->free(itVoice);
357 iliev 2012 }
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     */
368     void FreeKey(MidiKey* pKey) {
369 schoenebeck 2879 if (pKey->pActiveNotes->isEmpty()) {
370 schoenebeck 2645 if (m_engineChannel->pScript)
371     m_engineChannel->pScript->pKeyEvents[pKey->itSelf]->clear();
372 iliev 2012 pKey->Active = false;
373     pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
374     pKey->itSelf = RTList<uint>::Iterator();
375     pKey->ReleaseTrigger = false;
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     */
385 schoenebeck 3306 void FreeAllInactiveKeys() {
386 iliev 2012 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
387     RTList<uint>::Iterator end = pActiveKeys->end();
388     while (iuiKey != end) { // iterate through all active keys
389 schoenebeck 2645 MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
390 iliev 2012 ++iuiKey;
391 schoenebeck 2879 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 iliev 2012 }
408     }
409 schoenebeck 2879 #endif // CONFIG_DEVMODE
410 iliev 2012 }
411 schoenebeck 2879 if (pKey->pActiveNotes->isEmpty()) FreeKey(pKey);
412 iliev 2012 }
413     }
414    
415     int StealVoice (
416     Pool<Event>::Iterator& itNoteOnEvent,
417     RTListVoiceIterator* LastStolenVoice,
418 schoenebeck 2879 RTListNoteIterator* LastStolenNote,
419 iliev 2012 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 schoenebeck 2879 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 iliev 2012 } // 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 schoenebeck 2879 // if we already stole in this fragment, try to proceed to steal on same note
448 iliev 2012 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 schoenebeck 2879
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 iliev 2012 // get (next) oldest key
479     RTList<uint>::Iterator iuiSelectedKey = (*LastStolenKey) ? ++(*LastStolenKey) : pActiveKeys->first();
480 schoenebeck 2879 for (; iuiSelectedKey; ++iuiSelectedKey) {
481 iliev 2012 MidiKey* pSelectedKey = &pMIDIKeyInfo[*iuiSelectedKey];
482 schoenebeck 2879
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 iliev 2012 }
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 schoenebeck 2879
510     voiceFound:
511 iliev 2012
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     */
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 schoenebeck 2938 itNewEvent->Type = Event::type_release_key; // transform event type
544 iliev 2012 }
545     else dmsg(1,("Event pool emtpy!\n"));
546     }
547     }
548 schoenebeck 2879
549 iliev 2012 /**
550     * Kill all active voices.
551     * @returns The number of voices.
552     */
553     int KillAllVoices(Pool<Event>::Iterator& itKillEvent) {
554     int count = 0;
555    
556 schoenebeck 2879 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
557 iliev 2012 RTList<uint>::Iterator end = pActiveKeys->end();
558     for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
559     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
560 schoenebeck 2879
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 iliev 2012 }
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     */
581     int KillAllVoicesImmediately() {
582     int iPendingStreamDeletions = 0;
583    
584 schoenebeck 2879 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
585 iliev 2012 RTList<uint>::Iterator end = pActiveKeys->end();
586     for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
587     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
588 schoenebeck 2879
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 iliev 2012 }
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     */
615     void MarkAllActiveVoicesAsOrphans() {
616 schoenebeck 2879 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
617 iliev 2012 RTList<uint>::Iterator end = pActiveKeys->end();
618     for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
619     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
620 schoenebeck 2879
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 iliev 2012 }
631     }
632     }
633    
634     void ProcessActiveVoices(VoiceHandler* pVoiceHandler) {
635     if (pVoiceHandler == NULL) return;
636    
637 schoenebeck 2879 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
638 iliev 2012 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 schoenebeck 2879 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 iliev 2012 }
653     }
654     }
655 schoenebeck 2448
656     /**
657     * Recalculate the pitch of all active voices.
658     */
659     void OnScaleTuningChanged() {
660     RTList<uint>::Iterator iuiKey = pActiveKeys->first();
661     for (; iuiKey; ++iuiKey) {
662     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
663 schoenebeck 2879
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 schoenebeck 2448 }
673     }
674     }
675    
676 iliev 2012 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 schoenebeck 2938 itNewEvent->Type = Event::type_cancel_release_key; // transform event type
686 iliev 2012 }
687     else dmsg(1,("Event pool emtpy!\n"));
688     }
689     }
690     }
691    
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 schoenebeck 2938 itNewEvent->Type = Event::type_release_key; // transform event type
702 schoenebeck 2927 itNewEvent->Param.Note.Key = *iuiKey;
703     itNewEvent->Param.Note.Velocity = 127;
704     if (!SostenutoActiveOnKey(*iuiKey)) {
705     //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
706     AbstractEngineChannel* pChannel = (AbstractEngineChannel*) itEvent->pEngineChannel;
707     const int8_t CC64Value = pChannel->ControllerTable[64];
708     pChannel->ControllerTable[64] = 127;
709    
710     // now spawn release trigger voices (if required)
711     ProcessReleaseTrigger(itNewEvent);
712    
713     //HACK: reset sustain pedal CC value to old one (see comment above)
714     pChannel->ControllerTable[64] = CC64Value;
715     }
716 iliev 2012 }
717     else dmsg(1,("Event pool emtpy!\n"));
718     }
719     }
720     }
721    
722     /**
723 schoenebeck 2927 * Whether @a key is still kept active due to sostenuto pedal usage.
724     *
725     * @param key - note number of key
726     */
727     inline bool SostenutoActiveOnKey(int key) const {
728     if (SostenutoPedal) {
729     for (int i = 0; i < SostenutoKeyCount; i++)
730     if (key == SostenutoKeys[i]) return true;
731     }
732     return false;
733     }
734    
735     /**
736 iliev 2012 * Determines whether the specified voice should be released.
737     *
738     * @param pEngineChannel - The engine channel on which the voice should be checked
739     * @param Key - The key number
740     * @returns true if the specified voice should be released, false otherwise.
741     */
742     bool ShouldReleaseVoice(int Key) {
743     if (SustainPedal) return false;
744 schoenebeck 2927 if (SostenutoActiveOnKey(Key)) return false;
745 iliev 2012 return true;
746     }
747    
748     void ProcessSostenutoPedalDown() {
749     SostenutoKeyCount = 0;
750     // Remeber the pressed keys
751     RTList<uint>::Iterator iuiKey = pActiveKeys->first();
752     for (; iuiKey; ++iuiKey) {
753     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
754     if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
755     }
756     }
757    
758     void ProcessSostenutoPedalUp(Pool<Event>::Iterator& itEvent) {
759     // release voices if the damper pedal is up and their respective key is not pressed
760     for (int i = 0; i < SostenutoKeyCount; i++) {
761     MidiKey* pKey = &pMIDIKeyInfo[SostenutoKeys[i]];
762     if (!pKey->KeyPressed && !SustainPedal) {
763     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
764     if (itNewEvent) {
765     *itNewEvent = *itEvent; // copy event to the key's own event list
766 schoenebeck 2938 itNewEvent->Type = Event::type_release_key; // transform event type
767 iliev 2012 }
768     else dmsg(1,("Event pool emtpy!\n"));
769     }
770     }
771     }
772    
773     void AddMidiKeyboardListener(MidiKeyboardListener* l) { listeners.AddListener(l); }
774    
775     void RemoveMidiKeyboardListener(MidiKeyboardListener* l) { listeners.RemoveListener(l); }
776    
777     protected:
778 schoenebeck 2645 AbstractEngineChannel* m_engineChannel;
779 schoenebeck 2879 Pool<V>* m_voicePool;
780 schoenebeck 2645
781 iliev 2012 class Listeners : public MidiKeyboardListener, public ListenerList<MidiKeyboardListener*> {
782     public:
783     REGISTER_FIRE_EVENT_METHOD_ARG2(PreProcessNoteOn, uint8_t, uint8_t)
784     REGISTER_FIRE_EVENT_METHOD_ARG2(PostProcessNoteOn, uint8_t, uint8_t)
785     REGISTER_FIRE_EVENT_METHOD_ARG2(PreProcessNoteOff, uint8_t, uint8_t)
786     REGISTER_FIRE_EVENT_METHOD_ARG2(PostProcessNoteOff, uint8_t, uint8_t)
787     REGISTER_FIRE_EVENT_METHOD(PreProcessSustainPedalUp)
788     REGISTER_FIRE_EVENT_METHOD(PostProcessSustainPedalUp)
789     REGISTER_FIRE_EVENT_METHOD(PreProcessSustainPedalDown)
790     REGISTER_FIRE_EVENT_METHOD(PostProcessSustainPedalDown)
791     REGISTER_FIRE_EVENT_METHOD(PreProcessSostenutoPedalUp)
792     REGISTER_FIRE_EVENT_METHOD(PostProcessSostenutoPedalUp)
793     REGISTER_FIRE_EVENT_METHOD(PreProcessSostenutoPedalDown)
794     REGISTER_FIRE_EVENT_METHOD(PostProcessSostenutoPedalDown)
795     } listeners;
796     };
797     } // namespace LinuxSampler
798    
799 persson 2114 #endif /* __LS_MIDIKEYBOARDMANAGER_H__ */

  ViewVC Help
Powered by ViewVC