3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005-2009 Christian Schoenebeck * |
* Copyright (C) 2005-2008 Christian Schoenebeck * |
7 |
* Copyright (C) 2009 Grigor Iliev * |
* Copyright (C) 2009-2010 Christian Schoenebeck and Grigor Iliev * |
8 |
* * |
* * |
9 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
10 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
23 |
***************************************************************************/ |
***************************************************************************/ |
24 |
|
|
25 |
#ifndef __LS_MIDIKEYBOARDMANAGER_H__ |
#ifndef __LS_MIDIKEYBOARDMANAGER_H__ |
26 |
#define __LS_MIDIKEYBOARDMANAGER_H__ |
#define __LS_MIDIKEYBOARDMANAGER_H__ |
27 |
|
|
28 |
#include "Event.h" |
#include "Event.h" |
29 |
#include "Stream.h" |
#include "Stream.h" |
97 |
virtual void PostProcessSostenutoPedalDown() { } |
virtual void PostProcessSostenutoPedalDown() { } |
98 |
}; |
}; |
99 |
|
|
100 |
|
/** |
101 |
|
* This is the base class for class MidiKeyboardManager::MidiKey. It is |
102 |
|
* not intended to be instantiated directly. Instead it just defines |
103 |
|
* the part of class MidiKey which is not dependant on a C++ template |
104 |
|
* parameter. |
105 |
|
* |
106 |
|
* There are also ScriptEvent lists maintained for each key, which are not |
107 |
|
* stored here though, but on the InstrumentScript structure. Simply because |
108 |
|
* RTLists are tied to one Pool instance, and it would be error prone to |
109 |
|
* maintain @c Pool<ScriptEvent> and @c RTList<ScriptEvent> separately, |
110 |
|
* since one would need to be very careful to reallocate the lists when the |
111 |
|
* script was changed or when the Engine instance changed, etc. |
112 |
|
* |
113 |
|
* @see InstrumentScript::pKeyEvents |
114 |
|
*/ |
115 |
|
class MidiKeyBase { |
116 |
|
public: |
117 |
|
bool KeyPressed; ///< Is true if the respective MIDI key is currently pressed. |
118 |
|
bool Active; ///< If the key contains active voices. |
119 |
|
bool ReleaseTrigger; ///< If we have to launch release triggered voice(s) when the key is released |
120 |
|
Pool<uint>::Iterator itSelf; ///< hack to allow fast deallocation of the key from the list of active keys |
121 |
|
RTList<Event>* pEvents; ///< Key specific events (only Note-on, Note-off and sustain pedal currently) |
122 |
|
int VoiceTheftsQueued; ///< Amount of voices postponed due to shortage of voices. |
123 |
|
uint32_t* pRoundRobinIndex; ///< For the round robin dimension: current articulation for this key, will be incremented for each note on |
124 |
|
uint8_t Velocity; ///< Latest Note-on velocity for this key |
125 |
|
unsigned long NoteOnTime; ///< Time for latest Note-on event for this key |
126 |
|
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()) |
127 |
|
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()) |
128 |
|
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()) |
129 |
|
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()) |
130 |
|
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()) |
131 |
|
}; |
132 |
|
|
133 |
|
class MidiKeyboardManagerBase { |
134 |
|
public: |
135 |
|
Pool<uint>* pActiveKeys; ///< Holds all keys in it's allocation list with active voices. |
136 |
|
bool SoloMode; ///< in Solo Mode we only play one voice (group) at a time |
137 |
|
int SoloKey; ///< Currently 'active' solo key, that is the key to which the currently sounding voice belongs to (only if SoloMode is enabled) |
138 |
|
bool SustainPedal; ///< true if sustain pedal is down |
139 |
|
bool SostenutoPedal; ///< true if sostenuto pedal is down |
140 |
|
int SostenutoKeys[128]; |
141 |
|
int SostenutoKeyCount; |
142 |
|
uint32_t RoundRobinIndexes[128]; |
143 |
|
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. |
144 |
|
}; |
145 |
|
|
146 |
template <class V> |
template <class V> |
147 |
class MidiKeyboardManager { |
class MidiKeyboardManager : public MidiKeyboardManagerBase { |
148 |
public: |
public: |
149 |
/** @brief Voice Stealing Algorithms |
/** @brief Voice Stealing Algorithms |
150 |
* |
* |
155 |
voice_steal_algo_oldestvoiceonkey, ///< Try to kill the oldest voice from same key where the new voice should be spawned. |
voice_steal_algo_oldestvoiceonkey, ///< Try to kill the oldest voice from same key where the new voice should be spawned. |
156 |
voice_steal_algo_oldestkey ///< Try to kill the oldest voice from the oldest active key. |
voice_steal_algo_oldestkey ///< Try to kill the oldest voice from the oldest active key. |
157 |
}; |
}; |
158 |
|
|
159 |
|
|
160 |
/** @brief MIDI key runtime informations |
/** @brief MIDI key runtime informations |
161 |
* |
* |
162 |
* Reflects runtime informations for one MIDI key. |
* Reflects runtime informations for one MIDI key. |
163 |
*/ |
*/ |
164 |
class MidiKey { |
class MidiKey : public MidiKeyBase { |
165 |
public: |
public: |
166 |
RTList<V>* pActiveVoices; ///< Contains the active voices associated with the MIDI key. |
RTList<V>* pActiveVoices; ///< Contains the active voices associated with the MIDI key. |
|
bool KeyPressed; ///< Is true if the respective MIDI key is currently pressed. |
|
|
bool Active; ///< If the key contains active voices. |
|
|
bool ReleaseTrigger; ///< If we have to launch release triggered voice(s) when the key is released |
|
|
Pool<uint>::Iterator itSelf; ///< hack to allow fast deallocation of the key from the list of active keys |
|
|
RTList<Event>* pEvents; ///< Key specific events (only Note-on, Note-off and sustain pedal currently) |
|
|
int VoiceTheftsQueued; ///< Amount of voices postponed due to shortage of voices. |
|
|
uint8_t RoundRobinIndex; ///< For the round robin dimension: current articulation for this key, will be incremented for each note on |
|
|
uint8_t Velocity; ///< Latest Note-on velocity for this key |
|
|
unsigned long NoteOnTime; ///< Time for latest Note-on event for this key |
|
167 |
|
|
168 |
MidiKey() { |
MidiKey() { |
169 |
pActiveVoices = NULL; |
pActiveVoices = NULL; |
172 |
ReleaseTrigger = false; |
ReleaseTrigger = false; |
173 |
pEvents = NULL; |
pEvents = NULL; |
174 |
VoiceTheftsQueued = 0; |
VoiceTheftsQueued = 0; |
175 |
RoundRobinIndex = 0; |
Volume = 1.0f; |
176 |
|
PanLeft = 1.0f; |
177 |
|
PanRight = 1.0f; |
178 |
} |
} |
179 |
|
|
180 |
void Reset() { |
void Reset() { |
181 |
if (pActiveVoices) pActiveVoices->clear(); |
if (pActiveVoices) { |
182 |
|
RTListVoiceIterator itVoice = pActiveVoices->first(); |
183 |
|
RTListVoiceIterator itVoicesEnd = pActiveVoices->end(); |
184 |
|
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
185 |
|
itVoice->VoiceFreed(); |
186 |
|
} |
187 |
|
pActiveVoices->clear(); |
188 |
|
} |
189 |
if (pEvents) pEvents->clear(); |
if (pEvents) pEvents->clear(); |
190 |
KeyPressed = false; |
KeyPressed = false; |
191 |
Active = false; |
Active = false; |
192 |
ReleaseTrigger = false; |
ReleaseTrigger = false; |
193 |
itSelf = Pool<uint>::Iterator(); |
itSelf = Pool<uint>::Iterator(); |
194 |
VoiceTheftsQueued = 0; |
VoiceTheftsQueued = 0; |
195 |
|
Volume = 1.0f; |
196 |
|
PanLeft = 1.0f; |
197 |
|
PanRight = 1.0f; |
198 |
|
ReverbSend = optional<float>::nothing; |
199 |
|
ChorusSend = optional<float>::nothing; |
200 |
} |
} |
201 |
}; |
}; |
202 |
|
|
226 |
}; |
}; |
227 |
|
|
228 |
MidiKey* pMIDIKeyInfo; ///< Contains all active voices sorted by MIDI key number and other informations to the respective MIDI key |
MidiKey* pMIDIKeyInfo; ///< Contains all active voices sorted by MIDI key number and other informations to the respective MIDI key |
|
Pool<uint>* pActiveKeys; ///< Holds all keys in it's allocation list with active voices. |
|
|
std::map<uint,uint*> ActiveKeyGroups; ///< Contains active keys (in case they belong to a key group) ordered by key group ID. |
|
|
bool SoloMode; ///< in Solo Mode we only play one voice (group) at a time |
|
|
int SoloKey; ///< Currently 'active' solo key, that is the key to which the currently sounding voice belongs to (only if SoloMode is enabled) |
|
|
bool SustainPedal; ///< true if sustain pedal is down |
|
|
bool SostenutoPedal; ///< true if sostenuto pedal is down |
|
|
int SostenutoKeys[128]; |
|
|
int SostenutoKeyCount; |
|
229 |
|
|
230 |
MidiKeyboardManager() { |
MidiKeyboardManager(AbstractEngineChannel* pEngineChannel) { |
231 |
pMIDIKeyInfo = new MidiKey[128]; |
pMIDIKeyInfo = new MidiKey[128]; |
232 |
pActiveKeys = new Pool<uint>(128); |
pActiveKeys = new Pool<uint>(128); |
233 |
SoloMode = false; |
SoloMode = false; |
234 |
SustainPedal = false; |
SustainPedal = false; |
235 |
SostenutoPedal = false; |
SostenutoPedal = false; |
236 |
|
for (int i = 0 ; i < 128 ; i++) { |
237 |
|
RoundRobinIndexes[i] = 0; |
238 |
|
KeyDown[i] = false; |
239 |
|
|
240 |
|
// by default use one counter for each key (the |
241 |
|
// gig engine will change this to one counter per |
242 |
|
// region) |
243 |
|
pMIDIKeyInfo[i].pRoundRobinIndex = &RoundRobinIndexes[i]; |
244 |
|
} |
245 |
|
m_engineChannel = pEngineChannel; |
246 |
} |
} |
247 |
|
|
248 |
virtual ~MidiKeyboardManager() { |
virtual ~MidiKeyboardManager() { |
251 |
if (pMIDIKeyInfo) delete[] pMIDIKeyInfo; |
if (pMIDIKeyInfo) delete[] pMIDIKeyInfo; |
252 |
} |
} |
253 |
|
|
254 |
void Reset(){ |
void Reset() { |
255 |
SoloKey = -1; // no solo key active yet |
SoloKey = -1; // no solo key active yet |
256 |
|
|
|
// reset all key groups |
|
|
std::map<uint,uint*>::iterator iter = ActiveKeyGroups.begin(); |
|
|
for (; iter != ActiveKeyGroups.end(); iter++) iter->second = NULL; |
|
|
|
|
257 |
// reset key info |
// reset key info |
258 |
for (uint i = 0; i < 128; i++) pMIDIKeyInfo[i].Reset(); |
for (uint i = 0; i < 128; i++) { |
259 |
|
pMIDIKeyInfo[i].Reset(); |
260 |
|
KeyDown[i] = false; |
261 |
|
if (m_engineChannel->pScript) |
262 |
|
m_engineChannel->pScript->pKeyEvents[i]->clear(); |
263 |
|
} |
264 |
|
|
265 |
// free all active keys |
// free all active keys |
266 |
pActiveKeys->clear(); |
pActiveKeys->clear(); |
300 |
} |
} |
301 |
} |
} |
302 |
|
|
303 |
void ClearAllActiveKeyEvents() { |
/*void ClearAllActiveKeyEvents() { |
304 |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
305 |
RTList<uint>::Iterator end = pActiveKeys->end(); |
RTList<uint>::Iterator end = pActiveKeys->end(); |
306 |
for(; iuiKey != end; ++iuiKey) { |
for(; iuiKey != end; ++iuiKey) { |
307 |
pMIDIKeyInfo[*iuiKey].pEvents->clear(); // free all events on the key |
pMIDIKeyInfo[*iuiKey].pEvents->clear(); // free all events on the key |
308 |
} |
} |
309 |
} |
}*/ |
310 |
|
|
311 |
/** |
/** |
312 |
* Removes the given voice from the MIDI key's list of active voices. |
* Removes the given voice from the MIDI key's list of active voices. |
320 |
if (itVoice) { |
if (itVoice) { |
321 |
MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey]; |
MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey]; |
322 |
|
|
|
uint keygroup = itVoice->KeyGroup; |
|
|
|
|
323 |
// if the sample and dimension region belong to an |
// if the sample and dimension region belong to an |
324 |
// instrument that is unloaded, tell the disk thread to |
// instrument that is unloaded, tell the disk thread to |
325 |
// release them |
// release them |
331 |
|
|
332 |
// free the voice object |
// free the voice object |
333 |
pKey->pActiveVoices->free(itVoice); |
pKey->pActiveVoices->free(itVoice); |
|
|
|
|
// if no other voices left and member of a key group, remove from key group |
|
|
if (pKey->pActiveVoices->isEmpty() && keygroup) { |
|
|
uint** ppKeyGroup = &ActiveKeyGroups[keygroup]; |
|
|
if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group |
|
|
} |
|
334 |
} |
} |
335 |
else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush; |
else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush; |
336 |
} |
} |
344 |
*/ |
*/ |
345 |
void FreeKey(MidiKey* pKey) { |
void FreeKey(MidiKey* pKey) { |
346 |
if (pKey->pActiveVoices->isEmpty()) { |
if (pKey->pActiveVoices->isEmpty()) { |
347 |
|
if (m_engineChannel->pScript) |
348 |
|
m_engineChannel->pScript->pKeyEvents[pKey->itSelf]->clear(); |
349 |
pKey->Active = false; |
pKey->Active = false; |
350 |
pActiveKeys->free(pKey->itSelf); // remove key from list of active keys |
pActiveKeys->free(pKey->itSelf); // remove key from list of active keys |
351 |
pKey->itSelf = RTList<uint>::Iterator(); |
pKey->itSelf = RTList<uint>::Iterator(); |
363 |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
364 |
RTList<uint>::Iterator end = pActiveKeys->end(); |
RTList<uint>::Iterator end = pActiveKeys->end(); |
365 |
while (iuiKey != end) { // iterate through all active keys |
while (iuiKey != end) { // iterate through all active keys |
366 |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
367 |
++iuiKey; |
++iuiKey; |
368 |
if (pKey->pActiveVoices->isEmpty()) FreeKey(pKey); |
if (pKey->pActiveVoices->isEmpty()) FreeKey(pKey); |
369 |
#if CONFIG_DEVMODE |
#if CONFIG_DEVMODE |
525 |
iPendingStreamDeletions++; |
iPendingStreamDeletions++; |
526 |
} |
} |
527 |
// free the voice to the voice pool and update key info |
// free the voice to the voice pool and update key info |
528 |
|
itVoice->VoiceFreed(); |
529 |
FreeVoice(itVoice); |
FreeVoice(itVoice); |
530 |
} |
} |
531 |
} |
} |
566 |
} |
} |
567 |
} |
} |
568 |
} |
} |
569 |
|
|
570 |
|
/** |
571 |
|
* Recalculate the pitch of all active voices. |
572 |
|
*/ |
573 |
|
void OnScaleTuningChanged() { |
574 |
|
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
575 |
|
for (; iuiKey; ++iuiKey) { |
576 |
|
MidiKey* pKey = &pMIDIKeyInfo[*iuiKey]; |
577 |
|
RTListVoiceIterator itVoice = pKey->pActiveVoices->first(); |
578 |
|
for (; itVoice; ++itVoice) { |
579 |
|
itVoice->onScaleTuningChanged(); |
580 |
|
} |
581 |
|
} |
582 |
|
} |
583 |
|
|
584 |
void ProcessSustainPedalDown(Pool<Event>::Iterator& itEvent) { |
void ProcessSustainPedalDown(Pool<Event>::Iterator& itEvent) { |
585 |
// Cancel release process of all voices |
// Cancel release process of all voices |
586 |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
RTList<uint>::Iterator iuiKey = pActiveKeys->first(); |
661 |
void RemoveMidiKeyboardListener(MidiKeyboardListener* l) { listeners.RemoveListener(l); } |
void RemoveMidiKeyboardListener(MidiKeyboardListener* l) { listeners.RemoveListener(l); } |
662 |
|
|
663 |
protected: |
protected: |
664 |
|
AbstractEngineChannel* m_engineChannel; |
665 |
|
|
666 |
class Listeners : public MidiKeyboardListener, public ListenerList<MidiKeyboardListener*> { |
class Listeners : public MidiKeyboardListener, public ListenerList<MidiKeyboardListener*> { |
667 |
public: |
public: |
668 |
REGISTER_FIRE_EVENT_METHOD_ARG2(PreProcessNoteOn, uint8_t, uint8_t) |
REGISTER_FIRE_EVENT_METHOD_ARG2(PreProcessNoteOn, uint8_t, uint8_t) |
681 |
}; |
}; |
682 |
} // namespace LinuxSampler |
} // namespace LinuxSampler |
683 |
|
|
684 |
#endif /* __LS_MIDIKEYBOARDMANAGER_H__ */ |
#endif /* __LS_MIDIKEYBOARDMANAGER_H__ */ |
|
|
|