/[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 2927 - (hide annotations) (download) (as text)
Thu Jun 30 16:44:46 2016 UTC (7 years, 9 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 39947 byte(s)
* Fix: Release trigger voices were not spawned on sustain pedal up
  (CC #64) events.
* Fix: Release trigger voices can now also distinguish correctly between
  note-off and sustain pedal up events.
* Bumped version (2.0.0.svn10).

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     * Removes the given voice from the MIDI key's list of active voices.
321     * This method will be called when a voice went inactive, e.g. because
322     * it finished to playback its sample, finished its release stage or
323     * just was killed.
324     *
325     * @param itVoice - points to the voice to be freed
326     */
327     void FreeVoice(PoolVoiceIterator& itVoice) {
328     if (itVoice) {
329 schoenebeck 2879 //MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey];
330 iliev 2012
331     // if the sample and dimension region belong to an
332     // instrument that is unloaded, tell the disk thread to
333     // release them
334     if (itVoice->Orphan) {
335     if(itVoice->pDiskThread != NULL) {
336     itVoice->pDiskThread->OrderDeletionOfRegion(itVoice->GetRegion());
337     }
338     }
339    
340     // free the voice object
341 schoenebeck 2879 m_voicePool->free(itVoice);
342 iliev 2012 }
343     else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;
344     }
345    
346     /**
347     * Called when there's no more voice left on a key, this call will
348     * update the key info respectively.
349     *
350     * @param pEngineChannel - engine channel on which this event occured on
351     * @param pKey - key which is now inactive
352     */
353     void FreeKey(MidiKey* pKey) {
354 schoenebeck 2879 if (pKey->pActiveNotes->isEmpty()) {
355 schoenebeck 2645 if (m_engineChannel->pScript)
356     m_engineChannel->pScript->pKeyEvents[pKey->itSelf]->clear();
357 iliev 2012 pKey->Active = false;
358     pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
359     pKey->itSelf = RTList<uint>::Iterator();
360     pKey->ReleaseTrigger = false;
361     pKey->pEvents->clear();
362     dmsg(3,("Key has no more voices now\n"));
363     }
364     else dmsg(1,("MidiKeyboardManager: Oops, tried to free a key which contains voices.\n"));
365     }
366    
367     /**
368     * Free all keys which have no active voices left
369     */
370     void FreeAllInactiveKyes() {
371     RTList<uint>::Iterator iuiKey = pActiveKeys->first();
372     RTList<uint>::Iterator end = pActiveKeys->end();
373     while (iuiKey != end) { // iterate through all active keys
374 schoenebeck 2645 MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
375 iliev 2012 ++iuiKey;
376 schoenebeck 2879 for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
377     itNotesEnd = pKey->pActiveNotes->end();
378     itNote != itNotesEnd; ++itNote)
379     { // iterate over all active notes on that key ...
380     if (itNote->pActiveVoices->isEmpty()) { // free note ...
381     itNote->reset();
382     pKey->pActiveNotes->free(itNote);
383     }
384     #if CONFIG_DEVMODE
385     else { // just a sanity check for debugging
386     RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
387     RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end();
388     for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
389     if (itVoice->itKillEvent) {
390     dmsg(1,("gig::Engine: ERROR, killed voice survived !!!\n"));
391     }
392 iliev 2012 }
393     }
394 schoenebeck 2879 #endif // CONFIG_DEVMODE
395 iliev 2012 }
396 schoenebeck 2879 if (pKey->pActiveNotes->isEmpty()) FreeKey(pKey);
397 iliev 2012 }
398     }
399    
400     int StealVoice (
401     Pool<Event>::Iterator& itNoteOnEvent,
402     RTListVoiceIterator* LastStolenVoice,
403 schoenebeck 2879 RTListNoteIterator* LastStolenNote,
404 iliev 2012 RTList<uint>::Iterator* LastStolenKey
405     ) {
406     RTListVoiceIterator itSelectedVoice;
407    
408     // Select one voice for voice stealing
409     switch (CONFIG_VOICE_STEAL_ALGO) {
410    
411     // try to pick the oldest voice on the key where the new
412     // voice should be spawned, if there is no voice on that
413     // key, or no voice left to kill, then procceed with
414     // 'oldestkey' algorithm
415     case voice_steal_algo_oldestvoiceonkey: {
416     MidiKey* pSelectedKey = &pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
417 schoenebeck 2879 for (RTListNoteIterator itNote = pSelectedKey->pActiveNotes->first(),
418     itNotesEnd = pSelectedKey->pActiveNotes->end();
419     itNote != itNotesEnd; ++itNote)
420     {
421     for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice)
422     if (itSelectedVoice->IsStealable()) // proceed iterating if voice was created in this audio fragment cycle
423     goto voiceFound; // selection succeeded
424     }
425     // if we haven't found a voice then proceed with algorithm 'oldestkey' ...
426 iliev 2012 } // no break - intentional !
427    
428     // try to pick the oldest voice on the oldest active key
429     // from the same engine channel
430     // (caution: must stay after 'oldestvoiceonkey' algorithm !)
431     case voice_steal_algo_oldestkey: {
432 schoenebeck 2879 // if we already stole in this fragment, try to proceed to steal on same note
433 iliev 2012 if (*LastStolenVoice) {
434     itSelectedVoice = *LastStolenVoice;
435     do {
436     ++itSelectedVoice;
437     } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
438     // found a "stealable" voice ?
439     if (itSelectedVoice && itSelectedVoice->IsStealable()) {
440     // remember which voice we stole, so we can simply proceed on next voice stealing
441     *LastStolenVoice = itSelectedVoice;
442     break; // selection succeeded
443     }
444     }
445 schoenebeck 2879
446     // get (next) oldest note
447     if (*LastStolenNote) {
448     for (RTListNoteIterator itNote = ++(*LastStolenNote);
449     itNote; ++itNote)
450     {
451     for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice) {
452     // proceed iterating if voice was created in this audio fragment cycle
453     if (itSelectedVoice->IsStealable()) {
454     // remember which voice on which note we stole, so we can simply proceed on next voice stealing
455     *LastStolenNote = itNote;
456     *LastStolenVoice = itSelectedVoice;
457     goto voiceFound; // selection succeeded
458     }
459     }
460     }
461     }
462    
463 iliev 2012 // get (next) oldest key
464     RTList<uint>::Iterator iuiSelectedKey = (*LastStolenKey) ? ++(*LastStolenKey) : pActiveKeys->first();
465 schoenebeck 2879 for (; iuiSelectedKey; ++iuiSelectedKey) {
466 iliev 2012 MidiKey* pSelectedKey = &pMIDIKeyInfo[*iuiSelectedKey];
467 schoenebeck 2879
468     for (RTListNoteIterator itNote = pSelectedKey->pActiveNotes->first(),
469     itNotesEnd = pSelectedKey->pActiveNotes->end();
470     itNote != itNotesEnd; ++itNote)
471     {
472     for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice) {
473     // proceed iterating if voice was created in this audio fragment cycle
474     if (itSelectedVoice->IsStealable()) {
475     // remember which voice on which key we stole, so we can simply proceed on next voice stealing
476     *LastStolenKey = iuiSelectedKey;
477     *LastStolenNote = itNote;
478     *LastStolenVoice = itSelectedVoice;
479     goto voiceFound; // selection succeeded
480     }
481     }
482 iliev 2012 }
483     }
484     break;
485     }
486    
487     // don't steal anything
488     case voice_steal_algo_none:
489     default: {
490     dmsg(1,("No free voice (voice stealing disabled)!\n"));
491     return -1;
492     }
493     }
494 schoenebeck 2879
495     voiceFound:
496 iliev 2012
497     if (!itSelectedVoice || !itSelectedVoice->IsStealable()) return -1;
498    
499     #if CONFIG_DEVMODE
500     if (!itSelectedVoice->IsActive()) {
501     dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
502     return -1;
503     }
504     #endif // CONFIG_DEVMODE
505    
506     // now kill the selected voice
507     itSelectedVoice->Kill(itNoteOnEvent);
508    
509     return 0;
510     }
511    
512     /**
513     * Releases all voices. All voices will go into
514     * the release stage and thus it might take some time (e.g. dependant to
515     * their envelope release time) until they actually die.
516     *
517     * @param itReleaseEvent - event which caused this releasing of all voices
518     */
519     void ReleaseAllVoices(Pool<Event>::Iterator& itReleaseEvent) {
520     RTList<uint>::Iterator iuiKey = pActiveKeys->first();
521     while (iuiKey) {
522     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
523     ++iuiKey;
524     // append a 'release' event to the key's own event list
525     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
526     if (itNewEvent) {
527     *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
528     itNewEvent->Type = Event::type_release; // transform event type
529     }
530     else dmsg(1,("Event pool emtpy!\n"));
531     }
532     }
533 schoenebeck 2879
534 iliev 2012 /**
535     * Kill all active voices.
536     * @returns The number of voices.
537     */
538     int KillAllVoices(Pool<Event>::Iterator& itKillEvent) {
539     int count = 0;
540    
541 schoenebeck 2879 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
542 iliev 2012 RTList<uint>::Iterator end = pActiveKeys->end();
543     for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
544     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
545 schoenebeck 2879
546     for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
547     itNotesEnd = pKey->pActiveNotes->end();
548     itNote != itNotesEnd; ++itNote)
549     {
550     RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
551     RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end();
552     for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
553     itVoice->Kill(itKillEvent);
554     count++;
555     }
556 iliev 2012 }
557     }
558    
559     return count;
560     }
561    
562     /**
563     * Kill all voices the *die hard* way.
564     * @returns The number of pending stream deletions
565     */
566     int KillAllVoicesImmediately() {
567     int iPendingStreamDeletions = 0;
568    
569 schoenebeck 2879 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
570 iliev 2012 RTList<uint>::Iterator end = pActiveKeys->end();
571     for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
572     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
573 schoenebeck 2879
574     for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
575     itNotesEnd = pKey->pActiveNotes->end();
576     itNote != itNotesEnd; ++itNote)
577     {
578     RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
579     RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end();
580     for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
581     // request a notification from disk thread side for stream deletion
582     const Stream::Handle hStream = itVoice->KillImmediately(true);
583     if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream
584     iPendingStreamDeletions++;
585     }
586     // free the voice to the voice pool and update key info
587     itVoice->VoiceFreed();
588     FreeVoice(itVoice);
589 iliev 2012 }
590     }
591     }
592    
593     return iPendingStreamDeletions;
594     }
595    
596     /**
597     * Mark all currently active voices as "orphans", which means that the regions and
598     * samples they use should be released to the instrument manager when the voices die.
599     */
600     void MarkAllActiveVoicesAsOrphans() {
601 schoenebeck 2879 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
602 iliev 2012 RTList<uint>::Iterator end = pActiveKeys->end();
603     for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
604     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
605 schoenebeck 2879
606     for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
607     itNotesEnd = pKey->pActiveNotes->end();
608     itNote != itNotesEnd; ++itNote)
609     {
610     RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
611     RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end();
612     for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
613     itVoice->Orphan = true;
614     }
615 iliev 2012 }
616     }
617     }
618    
619     void ProcessActiveVoices(VoiceHandler* pVoiceHandler) {
620     if (pVoiceHandler == NULL) return;
621    
622 schoenebeck 2879 RTList<uint>::Iterator iuiKey = pActiveKeys->first();
623 iliev 2012 RTList<uint>::Iterator end = pActiveKeys->end();
624     for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
625     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
626     if (!pVoiceHandler->Process(pKey)) continue;
627    
628 schoenebeck 2879 for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
629     itNotesEnd = pKey->pActiveNotes->end();
630     itNote != itNotesEnd; ++itNote)
631     {
632     RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
633     RTListVoiceIterator itVoicesEnd = itNote->pActiveVoices->end();
634     for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
635     pVoiceHandler->Process(itVoice);
636     }
637 iliev 2012 }
638     }
639     }
640 schoenebeck 2448
641     /**
642     * Recalculate the pitch of all active voices.
643     */
644     void OnScaleTuningChanged() {
645     RTList<uint>::Iterator iuiKey = pActiveKeys->first();
646     for (; iuiKey; ++iuiKey) {
647     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
648 schoenebeck 2879
649     for (RTListNoteIterator itNote = pKey->pActiveNotes->first(),
650     itNotesEnd = pKey->pActiveNotes->end();
651     itNote != itNotesEnd; ++itNote)
652     {
653     RTListVoiceIterator itVoice = itNote->pActiveVoices->first();
654     for (; itVoice; ++itVoice) {
655     itVoice->onScaleTuningChanged();
656     }
657 schoenebeck 2448 }
658     }
659     }
660    
661 iliev 2012 void ProcessSustainPedalDown(Pool<Event>::Iterator& itEvent) {
662     // Cancel release process of all voices
663     RTList<uint>::Iterator iuiKey = pActiveKeys->first();
664     for (; iuiKey; ++iuiKey) {
665     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
666     if (!pKey->KeyPressed) {
667     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
668     if (itNewEvent) {
669     *itNewEvent = *itEvent; // copy event to the key's own event list
670     itNewEvent->Type = Event::type_cancel_release; // transform event type
671     }
672     else dmsg(1,("Event pool emtpy!\n"));
673     }
674     }
675     }
676    
677     void ProcessSustainPedalUp(Pool<Event>::Iterator& itEvent) {
678     // release voices if their respective key is not pressed
679     RTList<uint>::Iterator iuiKey = pActiveKeys->first();
680     for (; iuiKey; ++iuiKey) {
681     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
682     if (!pKey->KeyPressed && ShouldReleaseVoice(*iuiKey)) {
683     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
684     if (itNewEvent) {
685     *itNewEvent = *itEvent; // copy event to the key's own event list
686     itNewEvent->Type = Event::type_release; // transform event type
687 schoenebeck 2927 itNewEvent->Param.Note.Key = *iuiKey;
688     itNewEvent->Param.Note.Velocity = 127;
689     if (!SostenutoActiveOnKey(*iuiKey)) {
690     //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
691     AbstractEngineChannel* pChannel = (AbstractEngineChannel*) itEvent->pEngineChannel;
692     const int8_t CC64Value = pChannel->ControllerTable[64];
693     pChannel->ControllerTable[64] = 127;
694    
695     // now spawn release trigger voices (if required)
696     ProcessReleaseTrigger(itNewEvent);
697    
698     //HACK: reset sustain pedal CC value to old one (see comment above)
699     pChannel->ControllerTable[64] = CC64Value;
700     }
701 iliev 2012 }
702     else dmsg(1,("Event pool emtpy!\n"));
703     }
704     }
705     }
706    
707     /**
708 schoenebeck 2927 * Whether @a key is still kept active due to sostenuto pedal usage.
709     *
710     * @param key - note number of key
711     */
712     inline bool SostenutoActiveOnKey(int key) const {
713     if (SostenutoPedal) {
714     for (int i = 0; i < SostenutoKeyCount; i++)
715     if (key == SostenutoKeys[i]) return true;
716     }
717     return false;
718     }
719    
720     /**
721 iliev 2012 * Determines whether the specified voice should be released.
722     *
723     * @param pEngineChannel - The engine channel on which the voice should be checked
724     * @param Key - The key number
725     * @returns true if the specified voice should be released, false otherwise.
726     */
727     bool ShouldReleaseVoice(int Key) {
728     if (SustainPedal) return false;
729 schoenebeck 2927 if (SostenutoActiveOnKey(Key)) return false;
730 iliev 2012 return true;
731     }
732    
733     void ProcessSostenutoPedalDown() {
734     SostenutoKeyCount = 0;
735     // Remeber the pressed keys
736     RTList<uint>::Iterator iuiKey = pActiveKeys->first();
737     for (; iuiKey; ++iuiKey) {
738     MidiKey* pKey = &pMIDIKeyInfo[*iuiKey];
739     if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
740     }
741     }
742    
743     void ProcessSostenutoPedalUp(Pool<Event>::Iterator& itEvent) {
744     // release voices if the damper pedal is up and their respective key is not pressed
745     for (int i = 0; i < SostenutoKeyCount; i++) {
746     MidiKey* pKey = &pMIDIKeyInfo[SostenutoKeys[i]];
747     if (!pKey->KeyPressed && !SustainPedal) {
748     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
749     if (itNewEvent) {
750     *itNewEvent = *itEvent; // copy event to the key's own event list
751     itNewEvent->Type = Event::type_release; // transform event type
752     }
753     else dmsg(1,("Event pool emtpy!\n"));
754     }
755     }
756     }
757    
758     void AddMidiKeyboardListener(MidiKeyboardListener* l) { listeners.AddListener(l); }
759    
760     void RemoveMidiKeyboardListener(MidiKeyboardListener* l) { listeners.RemoveListener(l); }
761    
762     protected:
763 schoenebeck 2645 AbstractEngineChannel* m_engineChannel;
764 schoenebeck 2879 Pool<V>* m_voicePool;
765 schoenebeck 2645
766 iliev 2012 class Listeners : public MidiKeyboardListener, public ListenerList<MidiKeyboardListener*> {
767     public:
768     REGISTER_FIRE_EVENT_METHOD_ARG2(PreProcessNoteOn, uint8_t, uint8_t)
769     REGISTER_FIRE_EVENT_METHOD_ARG2(PostProcessNoteOn, uint8_t, uint8_t)
770     REGISTER_FIRE_EVENT_METHOD_ARG2(PreProcessNoteOff, uint8_t, uint8_t)
771     REGISTER_FIRE_EVENT_METHOD_ARG2(PostProcessNoteOff, uint8_t, uint8_t)
772     REGISTER_FIRE_EVENT_METHOD(PreProcessSustainPedalUp)
773     REGISTER_FIRE_EVENT_METHOD(PostProcessSustainPedalUp)
774     REGISTER_FIRE_EVENT_METHOD(PreProcessSustainPedalDown)
775     REGISTER_FIRE_EVENT_METHOD(PostProcessSustainPedalDown)
776     REGISTER_FIRE_EVENT_METHOD(PreProcessSostenutoPedalUp)
777     REGISTER_FIRE_EVENT_METHOD(PostProcessSostenutoPedalUp)
778     REGISTER_FIRE_EVENT_METHOD(PreProcessSostenutoPedalDown)
779     REGISTER_FIRE_EVENT_METHOD(PostProcessSostenutoPedalDown)
780     } listeners;
781     };
782     } // namespace LinuxSampler
783    
784 persson 2114 #endif /* __LS_MIDIKEYBOARDMANAGER_H__ */

  ViewVC Help
Powered by ViewVC