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 |
|
// forward this to the CC routine, so it updates the current aftertouch value and may handle aftertouch trigger rules |
121 |
|
ProcessControlChange(pEngineChannel, itChannelPressureEvent); |
122 |
|
|
123 |
|
// if required: engine global aftertouch handling (apart from the per voice handling) |
124 |
|
} |
125 |
|
|
126 |
|
void Engine::ProcessPolyphonicKeyPressure(LinuxSampler::EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNotePressureEvent) { |
127 |
|
// if required: engine global aftertouch handling (apart from the per voice handling) |
128 |
|
} |
129 |
|
|
130 |
DiskThread* Engine::CreateDiskThread() { |
DiskThread* Engine::CreateDiskThread() { |
131 |
return new DiskThread ( |
return new DiskThread ( |
132 |
iMaxDiskStreams, |
iMaxDiskStreams, |
143 |
EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel); |
EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel); |
144 |
// first, get total amount of required voices (dependant on amount of layers) |
// first, get total amount of required voices (dependant on amount of layers) |
145 |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(itNoteOnEvent->Param.Note.Key); |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(itNoteOnEvent->Param.Note.Key); |
146 |
if (pRegion && !RegionSuspended(pRegion)) { |
if (!pRegion || RegionSuspended(pRegion)) |
147 |
int voicesRequired = pRegion->Layers; |
return; |
148 |
// now launch the required amount of voices |
const int voicesRequired = pRegion->Layers; |
149 |
for (int i = 0; i < voicesRequired; i++) |
if (voicesRequired <= 0) |
150 |
|
return; |
151 |
|
|
152 |
|
NoteIterator itNote = GetNotePool()->fromID(itNoteOnEvent->Param.Note.ID); |
153 |
|
if (!itNote) { |
154 |
|
dmsg(1,("gig::Engine: No Note object for triggering new voices!\n")); |
155 |
|
return; |
156 |
|
} |
157 |
|
|
158 |
|
// now launch the required amount of voices |
159 |
|
for (int i = 0; i < voicesRequired; i++) { |
160 |
|
VoiceIterator itNewVoice = |
161 |
LaunchVoice(pChannel, itNoteOnEvent, i, false, true, HandleKeyGroupConflicts); |
LaunchVoice(pChannel, itNoteOnEvent, i, false, true, HandleKeyGroupConflicts); |
162 |
|
if (!itNewVoice) continue; |
163 |
|
itNewVoice.moveToEndOf(itNote->pActiveVoices); |
164 |
} |
} |
165 |
} |
} |
166 |
|
|
172 |
MidiKey* pKey = &pChannel->pMIDIKeyInfo[itNoteOffEvent->Param.Note.Key]; |
MidiKey* pKey = &pChannel->pMIDIKeyInfo[itNoteOffEvent->Param.Note.Key]; |
173 |
// first, get total amount of required voices (dependant on amount of layers) |
// first, get total amount of required voices (dependant on amount of layers) |
174 |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(itNoteOffEvent->Param.Note.Key); |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(itNoteOffEvent->Param.Note.Key); |
175 |
if (pRegion) { |
if (!pRegion) |
176 |
int voicesRequired = pRegion->Layers; |
return; |
177 |
|
const int voicesRequired = pRegion->Layers; |
178 |
|
if (voicesRequired <= 0) |
179 |
|
return; |
180 |
|
|
181 |
|
NoteIterator itNote = GetNotePool()->fromID(itNoteOffEvent->Param.Note.ID); |
182 |
|
if (!itNote) { |
183 |
|
dmsg(1,("gig::Engine: No Note object for triggering new release voices!\n")); |
184 |
|
return; |
185 |
|
} |
186 |
|
|
187 |
// MIDI note-on velocity is used instead of note-off velocity |
// MIDI note-on velocity is used instead of note-off velocity |
188 |
itNoteOffEvent->Param.Note.Velocity = pKey->Velocity; |
itNoteOffEvent->Param.Note.Velocity = pKey->Velocity; |
189 |
|
|
190 |
// now launch the required amount of voices |
// now launch the required amount of voices |
191 |
for (int i = 0; i < voicesRequired; i++) |
for (int i = 0; i < voicesRequired; i++) { |
192 |
|
VoiceIterator itNewVoice = |
193 |
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 |
194 |
|
if (!itNewVoice) continue; |
195 |
|
itNewVoice.moveToEndOf(itNote->pActiveVoices); |
196 |
} |
} |
197 |
} |
} |
198 |
|
|
206 |
) { |
) { |
207 |
EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel); |
EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel); |
208 |
int MIDIKey = itNoteOnEvent->Param.Note.Key; |
int MIDIKey = itNoteOnEvent->Param.Note.Key; |
209 |
EngineChannel::MidiKey* pKey = &pChannel->pMIDIKeyInfo[MIDIKey]; |
//EngineChannel::MidiKey* pKey = &pChannel->pMIDIKeyInfo[MIDIKey]; |
210 |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(MIDIKey); |
::gig::Region* pRegion = pChannel->pInstrument->GetRegion(MIDIKey); |
211 |
|
|
212 |
// if nothing defined for this key |
// if nothing defined for this key |
253 |
case ::gig::dimension_random: |
case ::gig::dimension_random: |
254 |
DimValues[i] = uint(Random() * pRegion->pDimensionDefinitions[i].zones); |
DimValues[i] = uint(Random() * pRegion->pDimensionDefinitions[i].zones); |
255 |
break; |
break; |
256 |
|
case ::gig::dimension_smartmidi: |
257 |
|
DimValues[i] = 0; |
258 |
|
break; |
259 |
case ::gig::dimension_modwheel: |
case ::gig::dimension_modwheel: |
260 |
DimValues[i] = pChannel->ControllerTable[1]; |
DimValues[i] = pChannel->ControllerTable[1]; |
261 |
break; |
break; |
338 |
// change has occured between note on and off) |
// change has occured between note on and off) |
339 |
if (ReleaseTriggerVoice && !(VoiceType & Voice::type_release_trigger)) return Pool<Voice>::Iterator(); |
if (ReleaseTriggerVoice && !(VoiceType & Voice::type_release_trigger)) return Pool<Voice>::Iterator(); |
340 |
|
|
341 |
::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues); |
NoteIterator itNote = GetNotePool()->fromID(itNoteOnEvent->Param.Note.ID); |
342 |
|
|
343 |
|
::gig::DimensionRegion* pDimRgn; |
344 |
|
if (!itNote->Format.Gig.DimMask) { // normal case ... |
345 |
|
pDimRgn = pRegion->GetDimensionRegionByValue(DimValues); |
346 |
|
} else { // some dimension zones were overridden (i.e. by instrument script) ... |
347 |
|
dmsg(3,("trigger with dim mask=%d val=%d\n", itNote->Format.Gig.DimMask, itNote->Format.Gig.DimBits)); |
348 |
|
int index = pRegion->GetDimensionRegionIndexByValue(DimValues); |
349 |
|
index &= ~itNote->Format.Gig.DimMask; |
350 |
|
index |= itNote->Format.Gig.DimBits & itNote->Format.Gig.DimMask; |
351 |
|
pDimRgn = pRegion->pDimensionRegions[index & 255]; |
352 |
|
} |
353 |
|
if (!pDimRgn) return Pool<Voice>::Iterator(); // error (could not resolve dimension region) |
354 |
|
|
355 |
// no need to continue if sample is silent |
// no need to continue if sample is silent |
356 |
if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator(); |
if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator(); |
357 |
|
|
358 |
|
dmsg(2,("sample -> \"%s\"\n", pDimRgn->pSample->pInfo->Name.c_str())); |
359 |
|
|
360 |
// allocate a new voice for the key |
// allocate a new voice for the key |
361 |
Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend(); |
Pool<Voice>::Iterator itNewVoice = GetVoicePool()->allocAppend(); |
362 |
|
|
363 |
int res = InitNewVoice ( |
int res = InitNewVoice ( |
364 |
pChannel, pDimRgn, itNoteOnEvent, VoiceType, iLayer, |
pChannel, pDimRgn, itNoteOnEvent, VoiceType, iLayer, |