96 |
virtual void PreProcessSostenutoPedalDown() { } |
virtual void PreProcessSostenutoPedalDown() { } |
97 |
virtual void PostProcessSostenutoPedalDown() { } |
virtual void PostProcessSostenutoPedalDown() { } |
98 |
}; |
}; |
99 |
|
|
100 |
/** |
/** |
101 |
* This is the base class for class MidiKeyboardManager::MidiKey. It is |
* This is the base class for class MidiKeyboardManager::MidiKey. It is |
102 |
* not intended to be instantiated directly. Instead it just defines |
* not intended to be instantiated directly. Instead it just defines |
103 |
* the part of class MidiKey which is not dependant on a C++ template |
* the part of class MidiKey which is not dependant on a C++ template |
104 |
* parameter. |
* 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 { |
class MidiKeyBase { |
116 |
public: |
public: |
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()) |
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 |
* |
* |
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. |
|
|
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; |
|
|
uint32_t RoundRobinIndexes[128]; |
|
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; |
235 |
SostenutoPedal = false; |
SostenutoPedal = false; |
236 |
for (int i = 0 ; i < 128 ; i++) { |
for (int i = 0 ; i < 128 ; i++) { |
237 |
RoundRobinIndexes[i] = 0; |
RoundRobinIndexes[i] = 0; |
238 |
|
KeyDown[i] = false; |
239 |
|
|
240 |
// by default use one counter for each key (the |
// by default use one counter for each key (the |
241 |
// gig engine will change this to one counter per |
// gig engine will change this to one counter per |
242 |
// region) |
// region) |
243 |
pMIDIKeyInfo[i].pRoundRobinIndex = &RoundRobinIndexes[i]; |
pMIDIKeyInfo[i].pRoundRobinIndex = &RoundRobinIndexes[i]; |
244 |
} |
} |
245 |
|
m_engineChannel = pEngineChannel; |
246 |
} |
} |
247 |
|
|
248 |
virtual ~MidiKeyboardManager() { |
virtual ~MidiKeyboardManager() { |
255 |
SoloKey = -1; // no solo key active yet |
SoloKey = -1; // no solo key active yet |
256 |
|
|
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. |
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 |
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) |