24 |
|
|
25 |
#include "Engine.h" |
#include "Engine.h" |
26 |
#include "EngineChannel.h" |
#include "EngineChannel.h" |
27 |
|
#include "InstrumentScriptVM.h" |
28 |
|
|
29 |
namespace LinuxSampler { namespace gig { |
namespace LinuxSampler { namespace gig { |
30 |
Engine::Format Engine::GetEngineFormat() { return GIG; } |
Engine::Format Engine::GetEngineFormat() { return GIG; } |
31 |
|
|
32 |
|
void Engine::CreateInstrumentScriptVM() { |
33 |
|
dmsg(2,("gig::Engine created Giga format scriptvm\n")); |
34 |
|
if (pScriptVM) return; |
35 |
|
pScriptVM = new InstrumentScriptVM; // gig format specific extended script runner |
36 |
|
} |
37 |
|
|
38 |
/** |
/** |
39 |
* Reacts on supported control change commands (e.g. pitch bend wheel, |
* Reacts on supported control change commands (e.g. pitch bend wheel, |
40 |
* modulation wheel, aftertouch). |
* modulation wheel, aftertouch). |
116 |
ProcessFxSendControllers(pChannel, itControlChangeEvent); |
ProcessFxSendControllers(pChannel, itControlChangeEvent); |
117 |
} |
} |
118 |
|
|
119 |
|
void Engine::ProcessChannelPressure(LinuxSampler::EngineChannel* pEngineChannel, Pool<Event>::Iterator& itChannelPressureEvent) { |
120 |
|
// if required: engine global aftertouch handling (apart from the per voice handling) |
121 |
|
} |
122 |
|
|
123 |
|
void Engine::ProcessPolyphonicKeyPressure(LinuxSampler::EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNotePressureEvent) { |
124 |
|
// if required: engine global aftertouch handling (apart from the per voice handling) |
125 |
|
} |
126 |
|
|
127 |
DiskThread* Engine::CreateDiskThread() { |
DiskThread* Engine::CreateDiskThread() { |
128 |
return new DiskThread ( |
return new DiskThread ( |
129 |
iMaxDiskStreams, |
iMaxDiskStreams, |
140 |
EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel); |
EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel); |
141 |
// first, get total amount of required voices (dependant on amount of layers) |
// first, get total amount of required voices (dependant on amount of layers) |
142 |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(itNoteOnEvent->Param.Note.Key); |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(itNoteOnEvent->Param.Note.Key); |
143 |
if (pRegion && !RegionSuspended(pRegion)) { |
if (!pRegion || RegionSuspended(pRegion)) |
144 |
int voicesRequired = pRegion->Layers; |
return; |
145 |
// now launch the required amount of voices |
const int voicesRequired = pRegion->Layers; |
146 |
for (int i = 0; i < voicesRequired; i++) |
if (voicesRequired <= 0) |
147 |
|
return; |
148 |
|
|
149 |
|
NoteIterator itNote = GetNotePool()->fromID(itNoteOnEvent->Param.Note.ID); |
150 |
|
if (!itNote) { |
151 |
|
dmsg(1,("gig::Engine: No Note object for triggering new voices!\n")); |
152 |
|
return; |
153 |
|
} |
154 |
|
|
155 |
|
// now launch the required amount of voices |
156 |
|
for (int i = 0; i < voicesRequired; i++) { |
157 |
|
VoiceIterator itNewVoice = |
158 |
LaunchVoice(pChannel, itNoteOnEvent, i, false, true, HandleKeyGroupConflicts); |
LaunchVoice(pChannel, itNoteOnEvent, i, false, true, HandleKeyGroupConflicts); |
159 |
|
if (!itNewVoice) continue; |
160 |
|
itNewVoice.moveToEndOf(itNote->pActiveVoices); |
161 |
} |
} |
162 |
} |
} |
163 |
|
|
169 |
MidiKey* pKey = &pChannel->pMIDIKeyInfo[itNoteOffEvent->Param.Note.Key]; |
MidiKey* pKey = &pChannel->pMIDIKeyInfo[itNoteOffEvent->Param.Note.Key]; |
170 |
// first, get total amount of required voices (dependant on amount of layers) |
// first, get total amount of required voices (dependant on amount of layers) |
171 |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(itNoteOffEvent->Param.Note.Key); |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(itNoteOffEvent->Param.Note.Key); |
172 |
if (pRegion) { |
if (!pRegion) |
173 |
int voicesRequired = pRegion->Layers; |
return; |
174 |
|
const int voicesRequired = pRegion->Layers; |
175 |
|
if (voicesRequired <= 0) |
176 |
|
return; |
177 |
|
|
178 |
|
NoteIterator itNote = GetNotePool()->fromID(itNoteOffEvent->Param.Note.ID); |
179 |
|
if (!itNote) { |
180 |
|
dmsg(1,("gig::Engine: No Note object for triggering new release voices!\n")); |
181 |
|
return; |
182 |
|
} |
183 |
|
|
184 |
// MIDI note-on velocity is used instead of note-off velocity |
// MIDI note-on velocity is used instead of note-off velocity |
185 |
itNoteOffEvent->Param.Note.Velocity = pKey->Velocity; |
itNoteOffEvent->Param.Note.Velocity = pKey->Velocity; |
186 |
|
|
187 |
// now launch the required amount of voices |
// now launch the required amount of voices |
188 |
for (int i = 0; i < voicesRequired; i++) |
for (int i = 0; i < voicesRequired; i++) { |
189 |
|
VoiceIterator itNewVoice = |
190 |
LaunchVoice(pChannel, itNoteOffEvent, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples |
LaunchVoice(pChannel, itNoteOffEvent, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples |
191 |
|
if (!itNewVoice) continue; |
192 |
|
itNewVoice.moveToEndOf(itNote->pActiveVoices); |
193 |
} |
} |
194 |
} |
} |
195 |
|
|
203 |
) { |
) { |
204 |
EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel); |
EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel); |
205 |
int MIDIKey = itNoteOnEvent->Param.Note.Key; |
int MIDIKey = itNoteOnEvent->Param.Note.Key; |
206 |
EngineChannel::MidiKey* pKey = &pChannel->pMIDIKeyInfo[MIDIKey]; |
//EngineChannel::MidiKey* pKey = &pChannel->pMIDIKeyInfo[MIDIKey]; |
207 |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(MIDIKey); |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(MIDIKey); |
208 |
|
|
209 |
// if nothing defined for this key |
// if nothing defined for this key |
250 |
case ::gig::dimension_random: |
case ::gig::dimension_random: |
251 |
DimValues[i] = uint(Random() * pRegion->pDimensionDefinitions[i].zones); |
DimValues[i] = uint(Random() * pRegion->pDimensionDefinitions[i].zones); |
252 |
break; |
break; |
253 |
|
case ::gig::dimension_smartmidi: |
254 |
|
DimValues[i] = 0; |
255 |
|
break; |
256 |
case ::gig::dimension_modwheel: |
case ::gig::dimension_modwheel: |
257 |
DimValues[i] = pChannel->ControllerTable[1]; |
DimValues[i] = pChannel->ControllerTable[1]; |
258 |
break; |
break; |
335 |
// change has occured between note on and off) |
// change has occured between note on and off) |
336 |
if (ReleaseTriggerVoice && !(VoiceType & Voice::type_release_trigger)) return Pool<Voice>::Iterator(); |
if (ReleaseTriggerVoice && !(VoiceType & Voice::type_release_trigger)) return Pool<Voice>::Iterator(); |
337 |
|
|
338 |
::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues); |
NoteIterator itNote = GetNotePool()->fromID(itNoteOnEvent->Param.Note.ID); |
339 |
|
|
340 |
|
::gig::DimensionRegion* pDimRgn; |
341 |
|
if (!itNote->Format.Gig.DimMask) { // normal case ... |
342 |
|
pDimRgn = pRegion->GetDimensionRegionByValue(DimValues); |
343 |
|
} else { // some dimension zones were overridden (i.e. by instrument script) ... |
344 |
|
dmsg(3,("trigger with dim mask=%d val=%d\n", itNote->Format.Gig.DimMask, itNote->Format.Gig.DimBits)); |
345 |
|
int index = pRegion->GetDimensionRegionIndexByValue(DimValues); |
346 |
|
index &= ~itNote->Format.Gig.DimMask; |
347 |
|
index |= itNote->Format.Gig.DimBits & itNote->Format.Gig.DimMask; |
348 |
|
pDimRgn = pRegion->pDimensionRegions[index & 255]; |
349 |
|
} |
350 |
|
if (!pDimRgn) return Pool<Voice>::Iterator(); // error (could not resolve dimension region) |
351 |
|
|
352 |
// no need to continue if sample is silent |
// no need to continue if sample is silent |
353 |
if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator(); |
if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator(); |
354 |
|
|
355 |
|
dmsg(2,("sample -> \"%s\"\n", pDimRgn->pSample->pInfo->Name.c_str())); |
356 |
|
|
357 |
// allocate a new voice for the key |
// allocate a new voice for the key |
358 |
Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend(); |
Pool<Voice>::Iterator itNewVoice = GetVoicePool()->allocAppend(); |
359 |
|
|
360 |
int res = InitNewVoice ( |
int res = InitNewVoice ( |
361 |
pChannel, pDimRgn, itNoteOnEvent, VoiceType, iLayer, |
pChannel, pDimRgn, itNoteOnEvent, VoiceType, iLayer, |