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" |
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 |
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 |
|
class MidiKeyBase { |
107 |
|
public: |
108 |
|
bool KeyPressed; ///< Is true if the respective MIDI key is currently pressed. |
109 |
|
bool Active; ///< If the key contains active voices. |
110 |
|
bool ReleaseTrigger; ///< If we have to launch release triggered voice(s) when the key is released |
111 |
|
Pool<uint>::Iterator itSelf; ///< hack to allow fast deallocation of the key from the list of active keys |
112 |
|
RTList<Event>* pEvents; ///< Key specific events (only Note-on, Note-off and sustain pedal currently) |
113 |
|
int VoiceTheftsQueued; ///< Amount of voices postponed due to shortage of voices. |
114 |
|
uint32_t* pRoundRobinIndex; ///< For the round robin dimension: current articulation for this key, will be incremented for each note on |
115 |
|
uint8_t Velocity; ///< Latest Note-on velocity for this key |
116 |
|
unsigned long NoteOnTime; ///< Time for latest Note-on event for this key |
117 |
|
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()) |
118 |
|
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()) |
119 |
|
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()) |
120 |
|
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()) |
121 |
|
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()) |
122 |
|
}; |
123 |
|
|
124 |
template <class V> |
template <class V> |
125 |
class MidiKeyboardManager { |
class MidiKeyboardManager { |
139 |
* |
* |
140 |
* Reflects runtime informations for one MIDI key. |
* Reflects runtime informations for one MIDI key. |
141 |
*/ |
*/ |
142 |
class MidiKey { |
class MidiKey : public MidiKeyBase { |
143 |
public: |
public: |
144 |
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. |
|
|
uint32_t* pRoundRobinIndex; ///< 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 |
|
145 |
|
|
146 |
MidiKey() { |
MidiKey() { |
147 |
pActiveVoices = NULL; |
pActiveVoices = NULL; |
150 |
ReleaseTrigger = false; |
ReleaseTrigger = false; |
151 |
pEvents = NULL; |
pEvents = NULL; |
152 |
VoiceTheftsQueued = 0; |
VoiceTheftsQueued = 0; |
153 |
|
Volume = 1.0f; |
154 |
|
PanLeft = 1.0f; |
155 |
|
PanRight = 1.0f; |
156 |
} |
} |
157 |
|
|
158 |
void Reset() { |
void Reset() { |
159 |
if (pActiveVoices) pActiveVoices->clear(); |
if (pActiveVoices) { |
160 |
|
RTListVoiceIterator itVoice = pActiveVoices->first(); |
161 |
|
RTListVoiceIterator itVoicesEnd = pActiveVoices->end(); |
162 |
|
for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key |
163 |
|
itVoice->VoiceFreed(); |
164 |
|
} |
165 |
|
pActiveVoices->clear(); |
166 |
|
} |
167 |
if (pEvents) pEvents->clear(); |
if (pEvents) pEvents->clear(); |
168 |
KeyPressed = false; |
KeyPressed = false; |
169 |
Active = false; |
Active = false; |
170 |
ReleaseTrigger = false; |
ReleaseTrigger = false; |
171 |
itSelf = Pool<uint>::Iterator(); |
itSelf = Pool<uint>::Iterator(); |
172 |
VoiceTheftsQueued = 0; |
VoiceTheftsQueued = 0; |
173 |
|
Volume = 1.0f; |
174 |
|
PanLeft = 1.0f; |
175 |
|
PanRight = 1.0f; |
176 |
|
ReverbSend = optional<float>::nothing; |
177 |
|
ChorusSend = optional<float>::nothing; |
178 |
} |
} |
179 |
}; |
}; |
180 |
|
|
205 |
|
|
206 |
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 |
207 |
Pool<uint>* pActiveKeys; ///< Holds all keys in it's allocation list with active voices. |
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. |
|
208 |
bool SoloMode; ///< in Solo Mode we only play one voice (group) at a time |
bool SoloMode; ///< in Solo Mode we only play one voice (group) at a time |
209 |
int SoloKey; ///< Currently 'active' solo key, that is the key to which the currently sounding voice belongs to (only if SoloMode is enabled) |
int SoloKey; ///< Currently 'active' solo key, that is the key to which the currently sounding voice belongs to (only if SoloMode is enabled) |
210 |
bool SustainPedal; ///< true if sustain pedal is down |
bool SustainPedal; ///< true if sustain pedal is down |
235 |
if (pMIDIKeyInfo) delete[] pMIDIKeyInfo; |
if (pMIDIKeyInfo) delete[] pMIDIKeyInfo; |
236 |
} |
} |
237 |
|
|
238 |
void Reset(){ |
void Reset() { |
239 |
SoloKey = -1; // no solo key active yet |
SoloKey = -1; // no solo key active yet |
240 |
|
|
|
// reset all key groups |
|
|
std::map<uint,uint*>::iterator iter = ActiveKeyGroups.begin(); |
|
|
for (; iter != ActiveKeyGroups.end(); iter++) iter->second = NULL; |
|
|
|
|
241 |
// reset key info |
// reset key info |
242 |
for (uint i = 0; i < 128; i++) pMIDIKeyInfo[i].Reset(); |
for (uint i = 0; i < 128; i++) pMIDIKeyInfo[i].Reset(); |
243 |
|
|
299 |
if (itVoice) { |
if (itVoice) { |
300 |
MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey]; |
MidiKey* pKey = &pMIDIKeyInfo[itVoice->MIDIKey]; |
301 |
|
|
|
uint keygroup = itVoice->KeyGroup; |
|
|
|
|
302 |
// if the sample and dimension region belong to an |
// if the sample and dimension region belong to an |
303 |
// instrument that is unloaded, tell the disk thread to |
// instrument that is unloaded, tell the disk thread to |
304 |
// release them |
// release them |
310 |
|
|
311 |
// free the voice object |
// free the voice object |
312 |
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 |
|
|
} |
|
313 |
} |
} |
314 |
else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush; |
else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush; |
315 |
} |
} |
502 |
iPendingStreamDeletions++; |
iPendingStreamDeletions++; |
503 |
} |
} |
504 |
// free the voice to the voice pool and update key info |
// free the voice to the voice pool and update key info |
505 |
|
itVoice->VoiceFreed(); |
506 |
FreeVoice(itVoice); |
FreeVoice(itVoice); |
507 |
} |
} |
508 |
} |
} |
642 |
}; |
}; |
643 |
} // namespace LinuxSampler |
} // namespace LinuxSampler |
644 |
|
|
645 |
#endif /* __LS_MIDIKEYBOARDMANAGER_H__ */ |
#endif /* __LS_MIDIKEYBOARDMANAGER_H__ */ |
|
|
|