97 |
pAudioOutputDevice = NULL; |
pAudioOutputDevice = NULL; |
98 |
pDiskThread = NULL; |
pDiskThread = NULL; |
99 |
pEventGenerator = NULL; |
pEventGenerator = NULL; |
100 |
pSysexBuffer = new RingBuffer<uint8_t>(CONFIG_SYSEX_BUFFER_SIZE, 0); |
pSysexBuffer = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0); |
101 |
pEventQueue = new RingBuffer<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0); |
pEventQueue = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0); |
102 |
pEventPool = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT); |
pEventPool = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT); |
103 |
pVoicePool = new Pool<Voice>(CONFIG_MAX_VOICES); |
pVoicePool = new Pool<Voice>(CONFIG_MAX_VOICES); |
104 |
pVoiceStealingQueue = new RTList<Event>(pEventPool); |
pVoiceStealingQueue = new RTList<Event>(pEventPool); |
228 |
} |
} |
229 |
catch (AudioOutputException e) { |
catch (AudioOutputException e) { |
230 |
String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message(); |
String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message(); |
231 |
throw LinuxSamplerException(msg); |
throw Exception(msg); |
232 |
} |
} |
233 |
|
|
234 |
this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle(); |
this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle(); |
306 |
* current audio cycle |
* current audio cycle |
307 |
*/ |
*/ |
308 |
void Engine::ImportEvents(uint Samples) { |
void Engine::ImportEvents(uint Samples) { |
309 |
RingBuffer<Event>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader(); |
RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader(); |
310 |
Event* pEvent; |
Event* pEvent; |
311 |
while (true) { |
while (true) { |
312 |
// get next event from input event queue |
// get next event from input event queue |
329 |
} |
} |
330 |
|
|
331 |
/** |
/** |
332 |
* Let this engine proceed to render the given amount of sample points. The |
* Let this engine proceed to render the given amount of sample points. |
333 |
* calculated audio data of all voices of this engine will be placed into |
* The engine will iterate through all engine channels and render audio |
334 |
* the engine's audio sum buffer which has to be copied and eventually be |
* for each engine channel independently. The calculated audio data of |
335 |
* converted to the appropriate value range by the audio output class (e.g. |
* all voices of each engine channel will be placed into the audio sum |
336 |
* AlsaIO or JackIO) right after. |
* buffers of the respective audio output device, connected to the |
337 |
|
* respective engine channel. |
338 |
* |
* |
339 |
* @param Samples - number of sample points to be rendered |
* @param Samples - number of sample points to be rendered |
340 |
* @returns 0 on success |
* @returns 0 on success |
341 |
*/ |
*/ |
342 |
int Engine::RenderAudio(uint Samples) { |
int Engine::RenderAudio(uint Samples) { |
343 |
dmsg(5,("RenderAudio(Samples=%d)\n", Samples)); |
dmsg(7,("RenderAudio(Samples=%d)\n", Samples)); |
344 |
|
|
345 |
// return if engine disabled |
// return if engine disabled |
346 |
if (EngineDisabled.Pop()) { |
if (EngineDisabled.Pop()) { |
643 |
{ |
{ |
644 |
const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument; |
const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument; |
645 |
if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high) |
if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high) |
646 |
pEngineChannel->CurrentKeyDimension = ((key - pInstrument->DimensionKeyRange.low) * 128) / |
pEngineChannel->CurrentKeyDimension = float(key - pInstrument->DimensionKeyRange.low) / |
647 |
(pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1); |
(pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1); |
648 |
} |
} |
649 |
|
|
871 |
DimValues[i] = itNoteOnEvent->Param.Note.Velocity; |
DimValues[i] = itNoteOnEvent->Param.Note.Velocity; |
872 |
break; |
break; |
873 |
case ::gig::dimension_channelaftertouch: |
case ::gig::dimension_channelaftertouch: |
874 |
DimValues[i] = 0; //TODO: we currently ignore this dimension |
DimValues[i] = pEngineChannel->ControllerTable[128]; |
875 |
break; |
break; |
876 |
case ::gig::dimension_releasetrigger: |
case ::gig::dimension_releasetrigger: |
877 |
VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal; |
VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal; |
878 |
DimValues[i] = (uint) ReleaseTriggerVoice; |
DimValues[i] = (uint) ReleaseTriggerVoice; |
879 |
break; |
break; |
880 |
case ::gig::dimension_keyboard: |
case ::gig::dimension_keyboard: |
881 |
DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension; |
DimValues[i] = (uint) (pEngineChannel->CurrentKeyDimension * pRegion->pDimensionDefinitions[i].zones); |
882 |
break; |
break; |
883 |
case ::gig::dimension_roundrobin: |
case ::gig::dimension_roundrobin: |
884 |
DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on |
DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on |
1243 |
} |
} |
1244 |
case 7: { // volume |
case 7: { // volume |
1245 |
//TODO: not sample accurate yet |
//TODO: not sample accurate yet |
1246 |
pEngineChannel->GlobalVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value] * CONFIG_GLOBAL_ATTENUATION; |
pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value]; |
1247 |
pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag |
pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag |
1248 |
break; |
break; |
1249 |
} |
} |
1382 |
* @param itSysexEvent - sysex data size and time stamp of the sysex event |
* @param itSysexEvent - sysex data size and time stamp of the sysex event |
1383 |
*/ |
*/ |
1384 |
void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) { |
void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) { |
1385 |
RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader(); |
RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader(); |
1386 |
|
|
1387 |
uint8_t exclusive_status, id; |
uint8_t exclusive_status, id; |
1388 |
if (!reader.pop(&exclusive_status)) goto free_sysex_data; |
if (!reader.pop(&exclusive_status)) goto free_sysex_data; |
1401 |
|
|
1402 |
// command address |
// command address |
1403 |
uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB) |
uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB) |
1404 |
const RingBuffer<uint8_t>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later |
const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later |
1405 |
if (reader.read(&addr[0], 3) != 3) goto free_sysex_data; |
if (reader.read(&addr[0], 3) != 3) goto free_sysex_data; |
1406 |
if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters |
if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters |
1407 |
dmsg(3,("\tSystem Parameter\n")); |
dmsg(3,("\tSystem Parameter\n")); |
1448 |
* question |
* question |
1449 |
* @param DataSize - size of the GS message data (in bytes) |
* @param DataSize - size of the GS message data (in bytes) |
1450 |
*/ |
*/ |
1451 |
uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t>::NonVolatileReader AddrReader, uint DataSize) { |
uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) { |
1452 |
RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader; |
RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader; |
1453 |
uint bytes = 3 /*addr*/ + DataSize; |
uint bytes = 3 /*addr*/ + DataSize; |
1454 |
uint8_t addr_and_data[bytes]; |
uint8_t addr_and_data[bytes]; |
1455 |
reader.read(&addr_and_data[0], bytes); |
reader.read(&addr_and_data[0], bytes); |
1568 |
} |
} |
1569 |
|
|
1570 |
String Engine::Version() { |
String Engine::Version() { |
1571 |
String s = "$Revision: 1.61 $"; |
String s = "$Revision: 1.67 $"; |
1572 |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
1573 |
} |
} |
1574 |
|
|
1575 |
|
InstrumentManager* Engine::GetInstrumentManager() { |
1576 |
|
return &instruments; |
1577 |
|
} |
1578 |
|
|
1579 |
// static constant initializers |
// static constant initializers |
1580 |
const float* Engine::VolumeCurve(InitVolumeCurve()); |
const float* Engine::VolumeCurve(InitVolumeCurve()); |
1581 |
const float* Engine::PanCurve(InitPanCurve()); |
const float* Engine::PanCurve(InitPanCurve()); |