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-2012 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 * |
68 |
virtual void ClearRegionsInUse() { |
virtual void ClearRegionsInUse() { |
69 |
{ |
{ |
70 |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate(); |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate(); |
71 |
if(cmd.pRegionsInUse != NULL) cmd.pRegionsInUse->clear(); |
if (cmd.pRegionsInUse) cmd.pRegionsInUse->clear(); |
72 |
|
cmd.bChangeInstrument = false; |
73 |
} |
} |
74 |
{ |
{ |
75 |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig(); |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig(); |
76 |
if(cmd.pRegionsInUse != NULL) cmd.pRegionsInUse->clear(); |
if (cmd.pRegionsInUse) cmd.pRegionsInUse->clear(); |
77 |
|
cmd.bChangeInstrument = false; |
78 |
} |
} |
79 |
} |
} |
80 |
|
|
86 |
virtual void DeleteRegionsInUse() { |
virtual void DeleteRegionsInUse() { |
87 |
{ |
{ |
88 |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate(); |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate(); |
89 |
if(cmd.pRegionsInUse != NULL) { |
if (cmd.pRegionsInUse) { |
90 |
delete cmd.pRegionsInUse; |
delete cmd.pRegionsInUse; |
91 |
cmd.pRegionsInUse = NULL; |
cmd.pRegionsInUse = NULL; |
92 |
} |
} |
93 |
|
cmd.bChangeInstrument = false; |
94 |
} |
} |
95 |
{ |
{ |
96 |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig(); |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig(); |
97 |
if(cmd.pRegionsInUse != NULL) { |
if (cmd.pRegionsInUse) { |
98 |
delete cmd.pRegionsInUse; |
delete cmd.pRegionsInUse; |
99 |
cmd.pRegionsInUse = NULL; |
cmd.pRegionsInUse = NULL; |
100 |
} |
} |
101 |
|
cmd.bChangeInstrument = false; |
102 |
} |
} |
103 |
} |
} |
104 |
|
|
106 |
{ |
{ |
107 |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate(); |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate(); |
108 |
cmd.pRegionsInUse = new RTList<R*>(pRegionPool[0]); |
cmd.pRegionsInUse = new RTList<R*>(pRegionPool[0]); |
109 |
|
cmd.bChangeInstrument = false; |
110 |
} |
} |
111 |
{ |
{ |
112 |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig(); |
InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig(); |
113 |
cmd.pRegionsInUse = new RTList<R*>(pRegionPool[1]); |
cmd.pRegionsInUse = new RTList<R*>(pRegionPool[1]); |
114 |
|
cmd.bChangeInstrument = false; |
115 |
} |
} |
116 |
} |
} |
117 |
|
|
120 |
if (pEngine->pAudioOutputDevice == pAudioOut) return; |
if (pEngine->pAudioOutputDevice == pAudioOut) return; |
121 |
DisconnectAudioOutputDevice(); |
DisconnectAudioOutputDevice(); |
122 |
} |
} |
123 |
pEngine = AbstractEngine::AcquireEngine(this, pAudioOut); |
AbstractEngine* newEngine = AbstractEngine::AcquireEngine(this, pAudioOut); |
124 |
|
EngineMutex.Lock(); |
125 |
|
pEngine = newEngine; |
126 |
|
EngineMutex.Unlock(); |
127 |
ResetInternal(); |
ResetInternal(); |
128 |
pEvents = new RTList<Event>(pEngine->pEventPool); |
pEvents = new RTList<Event>(pEngine->pEventPool); |
129 |
|
|
192 |
|
|
193 |
MidiKeyboardManager<V>::DeleteActiveVoices(); |
MidiKeyboardManager<V>::DeleteActiveVoices(); |
194 |
MidiKeyboardManager<V>::DeleteEvents(); |
MidiKeyboardManager<V>::DeleteEvents(); |
195 |
|
DeleteGroupEventLists(); |
196 |
|
|
197 |
AudioOutputDevice* oldAudioDevice = pEngine->pAudioOutputDevice; |
AudioOutputDevice* oldAudioDevice = pEngine->pAudioOutputDevice; |
198 |
|
EngineMutex.Lock(); |
199 |
pEngine = NULL; |
pEngine = NULL; |
200 |
|
EngineMutex.Unlock(); |
201 |
AbstractEngine::FreeEngine(this, oldAudioDevice); |
AbstractEngine::FreeEngine(this, oldAudioDevice); |
202 |
AudioDeviceChannelLeft = -1; |
AudioDeviceChannelLeft = -1; |
203 |
AudioDeviceChannelRight = -1; |
AudioDeviceChannelRight = -1; |
219 |
pEvents->clear(); |
pEvents->clear(); |
220 |
// empty MIDI key specific event lists |
// empty MIDI key specific event lists |
221 |
ClearEventListsHandler handler; |
ClearEventListsHandler handler; |
222 |
ProcessActiveVoices(&handler); |
this->ProcessActiveVoices(&handler); |
223 |
|
|
224 |
|
// empty exclusive group specific event lists |
225 |
|
ClearGroupEventLists(); |
226 |
} |
} |
227 |
|
|
228 |
// implementation of abstract methods derived from interface class 'InstrumentConsumer' |
// implementation of abstract methods derived from interface class 'InstrumentConsumer' |
263 |
|
|
264 |
void RenderActiveVoices(uint Samples) { |
void RenderActiveVoices(uint Samples) { |
265 |
RenderVoicesHandler handler(this, Samples); |
RenderVoicesHandler handler(this, Samples); |
266 |
ProcessActiveVoices(&handler); |
this->ProcessActiveVoices(&handler); |
267 |
|
|
268 |
SetVoiceCount(handler.VoiceCount); |
SetVoiceCount(handler.VoiceCount); |
269 |
SetDiskStreamCount(handler.StreamCount); |
SetDiskStreamCount(handler.StreamCount); |
321 |
if ((itVoice->DiskStreamRef).State != Stream::state_unused) StreamCount++; |
if ((itVoice->DiskStreamRef).State != Stream::state_unused) StreamCount++; |
322 |
} |
} |
323 |
} else { // voice reached end, is now inactive |
} else { // voice reached end, is now inactive |
324 |
|
itVoice->VoiceFreed(); |
325 |
pChannel->FreeVoice(itVoice); // remove voice from the list of active voices |
pChannel->FreeVoice(itVoice); // remove voice from the list of active voices |
326 |
} |
} |
327 |
} |
} |
363 |
} |
} |
364 |
|
|
365 |
virtual void ProcessKeySwitchChange(int key) = 0; |
virtual void ProcessKeySwitchChange(int key) = 0; |
|
|
|
|
/** |
|
|
* Handle key group (a.k.a. exclusive group) conflicts |
|
|
*/ |
|
|
void HandleKeyGroupConflicts(uint KeyGroup, Pool<Event>::Iterator& itNoteOnEvent, bool UseRelease = false) { |
|
|
if (KeyGroup) { // if this voice / key belongs to a key group |
|
|
uint* pKeyGroup = MidiKeyboardManager<V>::ActiveKeyGroups[KeyGroup]; |
|
|
if (pKeyGroup) { // if there's already an active key in that key group |
|
|
MidiKey* pOtherKey = &MidiKeyboardManager<V>::pMIDIKeyInfo[*pKeyGroup]; |
|
|
|
|
|
if (UseRelease) { |
|
|
// send a note off to the other key |
|
|
if (pOtherKey->KeyPressed && itNoteOnEvent->Param.Note.Key != *pKeyGroup) { |
|
|
RTList<Event>::Iterator itNewEvent = pEngine->pGlobalEvents->allocAppend(); |
|
|
if (itNewEvent) { |
|
|
pOtherKey->ReleaseTrigger = false; |
|
|
*itNewEvent = *itNoteOnEvent; |
|
|
itNewEvent->Type = Event::type_note_off; |
|
|
itNewEvent->Param.Note.Key = *pKeyGroup; |
|
|
pEngine->ProcessNoteOff(this, itNewEvent); |
|
|
} |
|
|
} |
|
|
} else { |
|
|
// kill all voices on the (other) key |
|
|
typename RTList<V>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first(); |
|
|
typename RTList<V>::Iterator end = pOtherKey->pActiveVoices->end(); |
|
|
for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) { |
|
|
if (itVoiceToBeKilled->Type != Voice::type_release_trigger) { |
|
|
itVoiceToBeKilled->Kill(itNoteOnEvent); |
|
|
--pEngine->VoiceSpawnsLeft; //FIXME: just a hack, we should better check in StealVoice() if the voice was killed due to key conflict |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
366 |
}; |
}; |
367 |
|
|
368 |
} // namespace LinuxSampler |
} // namespace LinuxSampler |