/[svn]/linuxsampler/trunk/src/engines/gig/Engine.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/gig/Engine.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1044 - (show annotations) (download)
Wed Feb 7 21:51:19 2007 UTC (13 years, 9 months ago) by schoenebeck
File size: 87024 byte(s)
- small fix regarding previously added MIDI RPN controller handling
  (all subsequent CC #6 messages were misinterpreted as being
  values for the previously selected RPN controller)

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005-2007 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #include <sstream>
25 #include "DiskThread.h"
26 #include "Voice.h"
27 #include "EGADSR.h"
28 #include "../EngineFactory.h"
29
30 #include "Engine.h"
31
32 namespace LinuxSampler { namespace gig {
33
34 InstrumentResourceManager Engine::instruments;
35
36 std::map<AudioOutputDevice*,Engine*> Engine::engines;
37
38 /**
39 * Get a gig::Engine object for the given gig::EngineChannel and the
40 * given AudioOutputDevice. All engine channels which are connected to
41 * the same audio output device will use the same engine instance. This
42 * method will be called by a gig::EngineChannel whenever it's
43 * connecting to a audio output device.
44 *
45 * @param pChannel - engine channel which acquires an engine object
46 * @param pDevice - the audio output device \a pChannel is connected to
47 */
48 Engine* Engine::AcquireEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
49 Engine* pEngine = NULL;
50 // check if there's already an engine for the given audio output device
51 if (engines.count(pDevice)) {
52 dmsg(4,("Using existing gig::Engine.\n"));
53 pEngine = engines[pDevice];
54
55 // Disable the engine while the new engine channel is
56 // added and initialized. The engine will be enabled again
57 // in EngineChannel::Connect.
58 pEngine->DisableAndLock();
59 } else { // create a new engine (and disk thread) instance for the given audio output device
60 dmsg(4,("Creating new gig::Engine.\n"));
61 pEngine = (Engine*) EngineFactory::Create("gig");
62 pEngine->Connect(pDevice);
63 engines[pDevice] = pEngine;
64 }
65 // register engine channel to the engine instance
66 pEngine->engineChannels.add(pChannel);
67 // remember index in the ArrayList
68 pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
69 dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
70 return pEngine;
71 }
72
73 /**
74 * Once an engine channel is disconnected from an audio output device,
75 * it wil immediately call this method to unregister itself from the
76 * engine instance and if that engine instance is not used by any other
77 * engine channel anymore, then that engine instance will be destroyed.
78 *
79 * @param pChannel - engine channel which wants to disconnect from it's
80 * engine instance
81 * @param pDevice - audio output device \a pChannel was connected to
82 */
83 void Engine::FreeEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
84 dmsg(4,("Disconnecting EngineChannel from gig::Engine.\n"));
85 Engine* pEngine = engines[pDevice];
86 // unregister EngineChannel from the Engine instance
87 pEngine->engineChannels.remove(pChannel);
88 // if the used Engine instance is not used anymore, then destroy it
89 if (pEngine->engineChannels.empty()) {
90 pDevice->Disconnect(pEngine);
91 engines.erase(pDevice);
92 delete pEngine;
93 dmsg(4,("Destroying gig::Engine.\n"));
94 }
95 else dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
96 }
97
98 /**
99 * Constructor
100 */
101 Engine::Engine() {
102 pAudioOutputDevice = NULL;
103 pDiskThread = NULL;
104 pEventGenerator = NULL;
105 pSysexBuffer = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);
106 pEventQueue = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
107 pEventPool = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
108 pVoicePool = new Pool<Voice>(CONFIG_MAX_VOICES);
109 pDimRegionsInUse = new ::gig::DimensionRegion*[CONFIG_MAX_VOICES + 1];
110 pVoiceStealingQueue = new RTList<Event>(pEventPool);
111 pGlobalEvents = new RTList<Event>(pEventPool);
112 InstrumentChangeQueue = new RingBuffer<instrument_change_command_t,false>(1, 0);
113 InstrumentChangeReplyQueue = new RingBuffer<instrument_change_reply_t,false>(1, 0);
114
115 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
116 iterVoice->SetEngine(this);
117 }
118 pVoicePool->clear();
119
120 ResetInternal();
121 ResetScaleTuning();
122 }
123
124 /**
125 * Destructor
126 */
127 Engine::~Engine() {
128 MidiInputPort::RemoveSysexListener(this);
129 if (pDiskThread) {
130 dmsg(1,("Stopping disk thread..."));
131 pDiskThread->StopThread();
132 delete pDiskThread;
133 dmsg(1,("OK\n"));
134 }
135 if (pEventQueue) delete pEventQueue;
136 if (pEventPool) delete pEventPool;
137 if (pVoicePool) {
138 pVoicePool->clear();
139 delete pVoicePool;
140 }
141 if (pEventGenerator) delete pEventGenerator;
142 if (pVoiceStealingQueue) delete pVoiceStealingQueue;
143 if (pSysexBuffer) delete pSysexBuffer;
144 Unregister();
145 }
146
147 void Engine::Enable() {
148 dmsg(3,("gig::Engine: enabling\n"));
149 EngineDisabled.PushAndUnlock(false, 2); // set condition object 'EngineDisabled' to false (wait max. 2s)
150 dmsg(3,("gig::Engine: enabled (val=%d)\n", EngineDisabled.GetUnsafe()));
151 }
152
153 void Engine::Disable() {
154 dmsg(3,("gig::Engine: disabling\n"));
155 bool* pWasDisabled = EngineDisabled.PushAndUnlock(true, 2); // wait max. 2s
156 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
157 }
158
159 void Engine::DisableAndLock() {
160 dmsg(3,("gig::Engine: disabling\n"));
161 bool* pWasDisabled = EngineDisabled.Push(true, 2); // wait max. 2s
162 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
163 }
164
165 /**
166 * Reset all voices and disk thread and clear input event queue and all
167 * control and status variables.
168 */
169 void Engine::Reset() {
170 DisableAndLock();
171 ResetInternal();
172 ResetScaleTuning();
173 Enable();
174 }
175
176 /**
177 * Reset all voices and disk thread and clear input event queue and all
178 * control and status variables. This method is protected by a mutex.
179 */
180 void Engine::ResetInternal() {
181 ResetInternalMutex.Lock();
182
183 // make sure that the engine does not get any sysex messages
184 // while it's reseting
185 bool sysexDisabled = MidiInputPort::RemoveSysexListener(this);
186 ActiveVoiceCount = 0;
187 ActiveVoiceCountMax = 0;
188
189 // reset voice stealing parameters
190 pVoiceStealingQueue->clear();
191 itLastStolenVoice = RTList<Voice>::Iterator();
192 itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
193 iuiLastStolenKey = RTList<uint>::Iterator();
194 iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
195 pLastStolenChannel = NULL;
196
197 // reset all voices
198 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
199 iterVoice->Reset();
200 }
201 pVoicePool->clear();
202
203 // reset disk thread
204 if (pDiskThread) pDiskThread->Reset();
205
206 // delete all input events
207 pEventQueue->init();
208 pSysexBuffer->init();
209 if (sysexDisabled) MidiInputPort::AddSysexListener(this);
210 ResetInternalMutex.Unlock();
211 }
212
213 /**
214 * Reset to normal, chromatic scale (means equal tempered).
215 */
216 void Engine::ResetScaleTuning() {
217 memset(&ScaleTuning[0], 0x00, 12);
218 }
219
220 /**
221 * Connect this engine instance with the given audio output device.
222 * This method will be called when an Engine instance is created.
223 * All of the engine's data structures which are dependant to the used
224 * audio output device / driver will be (re)allocated and / or
225 * adjusted appropriately.
226 *
227 * @param pAudioOut - audio output device to connect to
228 */
229 void Engine::Connect(AudioOutputDevice* pAudioOut) {
230 pAudioOutputDevice = pAudioOut;
231
232 ResetInternal();
233
234 // inform audio driver for the need of two channels
235 try {
236 pAudioOutputDevice->AcquireChannels(2); // gig engine only stereo
237 }
238 catch (AudioOutputException e) {
239 String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
240 throw Exception(msg);
241 }
242
243 this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
244 this->SampleRate = pAudioOutputDevice->SampleRate();
245
246 // FIXME: audio drivers with varying fragment sizes might be a problem here
247 MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;
248 if (MaxFadeOutPos < 0) {
249 std::cerr << "gig::Engine: WARNING, CONFIG_EG_MIN_RELEASE_TIME "
250 << "too big for current audio fragment size & sampling rate! "
251 << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;
252 // force volume ramp downs at the beginning of each fragment
253 MaxFadeOutPos = 0;
254 // lower minimum release time
255 const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
256 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
257 iterVoice->EG1.CalculateFadeOutCoeff(minReleaseTime, SampleRate);
258 }
259 pVoicePool->clear();
260 }
261
262 // (re)create disk thread
263 if (this->pDiskThread) {
264 dmsg(1,("Stopping disk thread..."));
265 this->pDiskThread->StopThread();
266 delete this->pDiskThread;
267 dmsg(1,("OK\n"));
268 }
269 this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6, //FIXME: assuming stereo
270 &instruments);
271 if (!pDiskThread) {
272 dmsg(0,("gig::Engine new diskthread = NULL\n"));
273 exit(EXIT_FAILURE);
274 }
275
276 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
277 iterVoice->pDiskThread = this->pDiskThread;
278 dmsg(3,("d"));
279 }
280 pVoicePool->clear();
281
282 // (re)create event generator
283 if (pEventGenerator) delete pEventGenerator;
284 pEventGenerator = new EventGenerator(pAudioOut->SampleRate());
285
286 dmsg(1,("Starting disk thread..."));
287 pDiskThread->StartThread();
288 dmsg(1,("OK\n"));
289
290 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
291 if (!iterVoice->pDiskThread) {
292 dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
293 exit(EXIT_FAILURE);
294 }
295 }
296 }
297
298 /**
299 * Clear all engine global event lists.
300 */
301 void Engine::ClearEventLists() {
302 pGlobalEvents->clear();
303 }
304
305 /**
306 * Copy all events from the engine's global input queue buffer to the
307 * engine's internal event list. This will be done at the beginning of
308 * each audio cycle (that is each RenderAudio() call) to distinguish
309 * all global events which have to be processed in the current audio
310 * cycle. These events are usually just SysEx messages. Every
311 * EngineChannel has it's own input event queue buffer and event list
312 * to handle common events like NoteOn, NoteOff and ControlChange
313 * events.
314 *
315 * @param Samples - number of sample points to be processed in the
316 * current audio cycle
317 */
318 void Engine::ImportEvents(uint Samples) {
319 RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
320 Event* pEvent;
321 while (true) {
322 // get next event from input event queue
323 if (!(pEvent = eventQueueReader.pop())) break;
324 // if younger event reached, ignore that and all subsequent ones for now
325 if (pEvent->FragmentPos() >= Samples) {
326 eventQueueReader--;
327 dmsg(2,("Younger Event, pos=%d ,Samples=%d!\n",pEvent->FragmentPos(),Samples));
328 pEvent->ResetFragmentPos();
329 break;
330 }
331 // copy event to internal event list
332 if (pGlobalEvents->poolIsEmpty()) {
333 dmsg(1,("Event pool emtpy!\n"));
334 break;
335 }
336 *pGlobalEvents->allocAppend() = *pEvent;
337 }
338 eventQueueReader.free(); // free all copied events from input queue
339 }
340
341 /**
342 * Let this engine proceed to render the given amount of sample points.
343 * The engine will iterate through all engine channels and render audio
344 * for each engine channel independently. The calculated audio data of
345 * all voices of each engine channel will be placed into the audio sum
346 * buffers of the respective audio output device, connected to the
347 * respective engine channel.
348 *
349 * @param Samples - number of sample points to be rendered
350 * @returns 0 on success
351 */
352 int Engine::RenderAudio(uint Samples) {
353 dmsg(7,("RenderAudio(Samples=%d)\n", Samples));
354
355 // return if engine disabled
356 if (EngineDisabled.Pop()) {
357 dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
358 return 0;
359 }
360
361 // update time of start and end of this audio fragment (as events' time stamps relate to this)
362 pEventGenerator->UpdateFragmentTime(Samples);
363
364 // We only allow a maximum of CONFIG_MAX_VOICES voices to be spawned
365 // in each audio fragment. All subsequent request for spawning new
366 // voices in the same audio fragment will be ignored.
367 VoiceSpawnsLeft = CONFIG_MAX_VOICES;
368
369 // get all events from the engine's global input event queue which belong to the current fragment
370 // (these are usually just SysEx messages)
371 ImportEvents(Samples);
372
373 // process engine global events (these are currently only MIDI System Exclusive messages)
374 {
375 RTList<Event>::Iterator itEvent = pGlobalEvents->first();
376 RTList<Event>::Iterator end = pGlobalEvents->end();
377 for (; itEvent != end; ++itEvent) {
378 switch (itEvent->Type) {
379 case Event::type_sysex:
380 dmsg(5,("Engine: Sysex received\n"));
381 ProcessSysex(itEvent);
382 break;
383 }
384 }
385 }
386
387 // reset internal voice counter (just for statistic of active voices)
388 ActiveVoiceCountTemp = 0;
389
390 // handle instrument change commands
391 instrument_change_command_t command;
392 if (InstrumentChangeQueue->pop(&command) > 0) {
393 EngineChannel* pEngineChannel = command.pEngineChannel;
394 pEngineChannel->pInstrument = command.pInstrument;
395
396 // iterate through all active voices and mark their
397 // dimension regions as "in use". The instrument resource
398 // manager may delete all of the instrument except the
399 // dimension regions and samples that are in use.
400 int i = 0;
401 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
402 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
403 while (iuiKey != end) { // iterate through all active keys
404 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
405 ++iuiKey;
406
407 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
408 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
409 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
410 if (!itVoice->Orphan) {
411 itVoice->Orphan = true;
412 pDimRegionsInUse[i++] = itVoice->pDimRgn;
413 }
414 }
415 }
416 pDimRegionsInUse[i] = 0; // end of list
417
418 // send a reply to the calling thread, which is waiting
419 instrument_change_reply_t reply;
420 InstrumentChangeReplyQueue->push(&reply);
421 }
422
423 // handle events on all engine channels
424 for (int i = 0; i < engineChannels.size(); i++) {
425 ProcessEvents(engineChannels[i], Samples);
426 }
427
428 // render all 'normal', active voices on all engine channels
429 for (int i = 0; i < engineChannels.size(); i++) {
430 RenderActiveVoices(engineChannels[i], Samples);
431 }
432
433 // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
434 RenderStolenVoices(Samples);
435
436 // handle audio routing for engine channels with FX sends
437 for (int i = 0; i < engineChannels.size(); i++) {
438 if (engineChannels[i]->fxSends.empty()) continue; // ignore if no FX sends
439 RouteAudio(engineChannels[i], Samples);
440 }
441
442 // handle cleanup on all engine channels for the next audio fragment
443 for (int i = 0; i < engineChannels.size(); i++) {
444 PostProcess(engineChannels[i]);
445 }
446
447
448 // empty the engine's event list for the next audio fragment
449 ClearEventLists();
450
451 // reset voice stealing for the next audio fragment
452 pVoiceStealingQueue->clear();
453
454 // just some statistics about this engine instance
455 ActiveVoiceCount = ActiveVoiceCountTemp;
456 if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
457
458 FrameTime += Samples;
459
460 return 0;
461 }
462
463 /**
464 * Dispatch and handle all events in this audio fragment for the given
465 * engine channel.
466 *
467 * @param pEngineChannel - engine channel on which events should be
468 * processed
469 * @param Samples - amount of sample points to be processed in
470 * this audio fragment cycle
471 */
472 void Engine::ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
473 // get all events from the engine channels's input event queue which belong to the current fragment
474 // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
475 pEngineChannel->ImportEvents(Samples);
476
477 // process events
478 {
479 RTList<Event>::Iterator itEvent = pEngineChannel->pEvents->first();
480 RTList<Event>::Iterator end = pEngineChannel->pEvents->end();
481 for (; itEvent != end; ++itEvent) {
482 switch (itEvent->Type) {
483 case Event::type_note_on:
484 dmsg(5,("Engine: Note on received\n"));
485 ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
486 break;
487 case Event::type_note_off:
488 dmsg(5,("Engine: Note off received\n"));
489 ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
490 break;
491 case Event::type_control_change:
492 dmsg(5,("Engine: MIDI CC received\n"));
493 ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
494 break;
495 case Event::type_pitchbend:
496 dmsg(5,("Engine: Pitchbend received\n"));
497 ProcessPitchbend((EngineChannel*)itEvent->pEngineChannel, itEvent);
498 break;
499 }
500 }
501 }
502
503 // reset voice stealing for the next engine channel (or next audio fragment)
504 itLastStolenVoice = RTList<Voice>::Iterator();
505 itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
506 iuiLastStolenKey = RTList<uint>::Iterator();
507 iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
508 pLastStolenChannel = NULL;
509 }
510
511 /**
512 * Render all 'normal' voices (that is voices which were not stolen in
513 * this fragment) on the given engine channel.
514 *
515 * @param pEngineChannel - engine channel on which audio should be
516 * rendered
517 * @param Samples - amount of sample points to be rendered in
518 * this audio fragment cycle
519 */
520 void Engine::RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
521 #if !CONFIG_PROCESS_MUTED_CHANNELS
522 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
523 #endif
524
525 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
526 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
527 while (iuiKey != end) { // iterate through all active keys
528 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
529 ++iuiKey;
530
531 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
532 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
533 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
534 // now render current voice
535 itVoice->Render(Samples);
536 if (itVoice->IsActive()) ActiveVoiceCountTemp++; // still active
537 else { // voice reached end, is now inactive
538 FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices
539 }
540 }
541 }
542 }
543
544 /**
545 * Render all stolen voices (only voices which were stolen in this
546 * fragment) on the given engine channel. Stolen voices are rendered
547 * after all normal voices have been rendered; this is needed to render
548 * audio of those voices which were selected for voice stealing until
549 * the point were the stealing (that is the take over of the voice)
550 * actually happened.
551 *
552 * @param pEngineChannel - engine channel on which audio should be
553 * rendered
554 * @param Samples - amount of sample points to be rendered in
555 * this audio fragment cycle
556 */
557 void Engine::RenderStolenVoices(uint Samples) {
558 RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
559 RTList<Event>::Iterator end = pVoiceStealingQueue->end();
560 for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
561 EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
562 if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
563 Pool<Voice>::Iterator itNewVoice =
564 LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
565 if (itNewVoice) {
566 itNewVoice->Render(Samples);
567 if (itNewVoice->IsActive()) ActiveVoiceCountTemp++; // still active
568 else { // voice reached end, is now inactive
569 FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices
570 }
571 }
572 else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));
573
574 // we need to clear the key's event list explicitly here in case key was never active
575 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoiceStealEvent->Param.Note.Key];
576 pKey->VoiceTheftsQueued--;
577 if (!pKey->Active && !pKey->VoiceTheftsQueued) pKey->pEvents->clear();
578 }
579 }
580
581 /**
582 * Will be called in case the respective engine channel sports FX send
583 * channels. In this particular case, engine channel local buffers are
584 * used to render and mix all voices to. This method is responsible for
585 * copying the audio data from those local buffers to the master audio
586 * output channels as well as to the FX send audio output channels with
587 * their respective FX send levels.
588 *
589 * @param pEngineChannel - engine channel from which audio should be
590 * routed
591 * @param Samples - amount of sample points to be routed in
592 * this audio fragment cycle
593 */
594 void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
595 // route master signal
596 {
597 AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);
598 AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);
599 pEngineChannel->pChannelLeft->MixTo(pDstL, Samples);
600 pEngineChannel->pChannelRight->MixTo(pDstR, Samples);
601 }
602 // route FX send signal
603 {
604 for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
605 FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
606 // left channel
607 const int iDstL = pFxSend->DestinationChannel(0);
608 if (iDstL < 0) {
609 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));
610 } else {
611 AudioChannel* pDstL = pAudioOutputDevice->Channel(iDstL);
612 if (!pDstL) {
613 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));
614 } else pEngineChannel->pChannelLeft->MixTo(pDstL, Samples, pFxSend->Level());
615 }
616 // right channel
617 const int iDstR = pFxSend->DestinationChannel(1);
618 if (iDstR < 0) {
619 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));
620 } else {
621 AudioChannel* pDstR = pAudioOutputDevice->Channel(iDstR);
622 if (!pDstR) {
623 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));
624 } else pEngineChannel->pChannelRight->MixTo(pDstR, Samples, pFxSend->Level());
625 }
626 }
627 }
628 // reset buffers with silence (zero out) for the next audio cycle
629 pEngineChannel->pChannelLeft->Clear();
630 pEngineChannel->pChannelRight->Clear();
631 }
632
633 /**
634 * Free all keys which have turned inactive in this audio fragment, from
635 * the list of active keys and clear all event lists on that engine
636 * channel.
637 *
638 * @param pEngineChannel - engine channel to cleanup
639 */
640 void Engine::PostProcess(EngineChannel* pEngineChannel) {
641 // free all keys which have no active voices left
642 {
643 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
644 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
645 while (iuiKey != end) { // iterate through all active keys
646 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
647 ++iuiKey;
648 if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);
649 #if CONFIG_DEVMODE
650 else { // just a sanity check for debugging
651 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
652 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
653 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
654 if (itVoice->itKillEvent) {
655 dmsg(1,("gig::Engine: ERROR, killed voice survived !!!\n"));
656 }
657 }
658 }
659 #endif // CONFIG_DEVMODE
660 }
661 }
662
663 // empty the engine channel's own event lists
664 pEngineChannel->ClearEventLists();
665 }
666
667 /**
668 * Will be called by the MIDI input device whenever a MIDI system
669 * exclusive message has arrived.
670 *
671 * @param pData - pointer to sysex data
672 * @param Size - lenght of sysex data (in bytes)
673 */
674 void Engine::SendSysex(void* pData, uint Size) {
675 Event event = pEventGenerator->CreateEvent();
676 event.Type = Event::type_sysex;
677 event.Param.Sysex.Size = Size;
678 event.pEngineChannel = NULL; // as Engine global event
679 if (pEventQueue->write_space() > 0) {
680 if (pSysexBuffer->write_space() >= Size) {
681 // copy sysex data to input buffer
682 uint toWrite = Size;
683 uint8_t* pPos = (uint8_t*) pData;
684 while (toWrite) {
685 const uint writeNow = RTMath::Min(toWrite, pSysexBuffer->write_space_to_end());
686 pSysexBuffer->write(pPos, writeNow);
687 toWrite -= writeNow;
688 pPos += writeNow;
689
690 }
691 // finally place sysex event into input event queue
692 pEventQueue->push(&event);
693 }
694 else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,CONFIG_SYSEX_BUFFER_SIZE));
695 }
696 else dmsg(1,("Engine: Input event queue full!"));
697 }
698
699 /**
700 * Assigns and triggers a new voice for the respective MIDI key.
701 *
702 * @param pEngineChannel - engine channel on which this event occured on
703 * @param itNoteOnEvent - key, velocity and time stamp of the event
704 */
705 void Engine::ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
706 #if !CONFIG_PROCESS_MUTED_CHANNELS
707 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
708 #endif
709
710 if (!pEngineChannel->pInstrument) return; // ignore if no instrument loaded
711
712 //HACK: we should better add the transpose value only to the most mandatory places (like for retrieving the region and calculating the tuning), because otherwise voices will unintendedly survive when changing transpose while playing
713 itNoteOnEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
714
715 const int key = itNoteOnEvent->Param.Note.Key;
716 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
717
718 // move note on event to the key's own event list
719 RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
720
721 // if Solo Mode then kill all already active voices
722 if (pEngineChannel->SoloMode) {
723 Pool<uint>::Iterator itYoungestKey = pEngineChannel->pActiveKeys->last();
724 if (itYoungestKey) {
725 const int iYoungestKey = *itYoungestKey;
726 const midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[iYoungestKey];
727 if (pOtherKey->Active) {
728 // get final portamento position of currently active voice
729 if (pEngineChannel->PortamentoMode) {
730 RTList<Voice>::Iterator itVoice = pOtherKey->pActiveVoices->last();
731 if (itVoice) itVoice->UpdatePortamentoPos(itNoteOnEventOnKeyList);
732 }
733 // kill all voices on the (other) key
734 RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
735 RTList<Voice>::Iterator end = pOtherKey->pActiveVoices->end();
736 for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
737 if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
738 itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
739 }
740 }
741 }
742 // set this key as 'currently active solo key'
743 pEngineChannel->SoloKey = key;
744 }
745
746 // Change key dimension value if key is in keyswitching area
747 {
748 const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
749 if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
750 pEngineChannel->CurrentKeyDimension = float(key - pInstrument->DimensionKeyRange.low) /
751 (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
752 }
753
754 pKey->KeyPressed = true; // the MIDI key was now pressed down
755 pKey->Velocity = itNoteOnEventOnKeyList->Param.Note.Velocity;
756 pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
757
758 // cancel release process of voices on this key if needed
759 if (pKey->Active && !pEngineChannel->SustainPedal) {
760 RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
761 if (itCancelReleaseEvent) {
762 *itCancelReleaseEvent = *itNoteOnEventOnKeyList; // copy event
763 itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
764 }
765 else dmsg(1,("Event pool emtpy!\n"));
766 }
767
768 // allocate and trigger new voice(s) for the key
769 {
770 // first, get total amount of required voices (dependant on amount of layers)
771 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOnEventOnKeyList->Param.Note.Key);
772 if (pRegion) {
773 int voicesRequired = pRegion->Layers;
774 // now launch the required amount of voices
775 for (int i = 0; i < voicesRequired; i++)
776 LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true, true);
777 }
778 }
779
780 // if neither a voice was spawned or postponed then remove note on event from key again
781 if (!pKey->Active && !pKey->VoiceTheftsQueued)
782 pKey->pEvents->free(itNoteOnEventOnKeyList);
783
784 if (!pEngineChannel->SoloMode || pEngineChannel->PortamentoPos < 0.0f) pEngineChannel->PortamentoPos = (float) key;
785 pKey->RoundRobinIndex++;
786 }
787
788 /**
789 * Releases the voices on the given key if sustain pedal is not pressed.
790 * If sustain is pressed, the release of the note will be postponed until
791 * sustain pedal will be released or voice turned inactive by itself (e.g.
792 * due to completion of sample playback).
793 *
794 * @param pEngineChannel - engine channel on which this event occured on
795 * @param itNoteOffEvent - key, velocity and time stamp of the event
796 */
797 void Engine::ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
798 #if !CONFIG_PROCESS_MUTED_CHANNELS
799 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
800 #endif
801
802 //HACK: we should better add the transpose value only to the most mandatory places (like for retrieving the region and calculating the tuning), because otherwise voices will unintendedly survive when changing transpose while playing
803 itNoteOffEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
804
805 const int iKey = itNoteOffEvent->Param.Note.Key;
806 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[iKey];
807 pKey->KeyPressed = false; // the MIDI key was now released
808
809 // move event to the key's own event list
810 RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
811
812 bool bShouldRelease = pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEventOnKeyList->Param.Note.Key);
813
814 // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
815 if (pEngineChannel->SoloMode && pEngineChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
816 bool bOtherKeysPressed = false;
817 if (iKey == pEngineChannel->SoloKey) {
818 pEngineChannel->SoloKey = -1;
819 // if there's still a key pressed down, respawn a voice (group) on the highest key
820 for (int i = 127; i > 0; i--) {
821 midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[i];
822 if (pOtherKey->KeyPressed) {
823 bOtherKeysPressed = true;
824 // make the other key the new 'currently active solo key'
825 pEngineChannel->SoloKey = i;
826 // get final portamento position of currently active voice
827 if (pEngineChannel->PortamentoMode) {
828 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
829 if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);
830 }
831 // create a pseudo note on event
832 RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
833 if (itPseudoNoteOnEvent) {
834 // copy event
835 *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
836 // transform event to a note on event
837 itPseudoNoteOnEvent->Type = Event::type_note_on;
838 itPseudoNoteOnEvent->Param.Note.Key = i;
839 itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
840 // allocate and trigger new voice(s) for the other key
841 {
842 // first, get total amount of required voices (dependant on amount of layers)
843 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(i);
844 if (pRegion) {
845 int voicesRequired = pRegion->Layers;
846 // now launch the required amount of voices
847 for (int iLayer = 0; iLayer < voicesRequired; iLayer++)
848 LaunchVoice(pEngineChannel, itPseudoNoteOnEvent, iLayer, false, true, false);
849 }
850 }
851 // if neither a voice was spawned or postponed then remove note on event from key again
852 if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
853 pOtherKey->pEvents->free(itPseudoNoteOnEvent);
854
855 } else dmsg(1,("Could not respawn voice, no free event left\n"));
856 break; // done
857 }
858 }
859 }
860 if (bOtherKeysPressed) {
861 if (pKey->Active) { // kill all voices on this key
862 bShouldRelease = false; // no need to release, as we kill it here
863 RTList<Voice>::Iterator itVoiceToBeKilled = pKey->pActiveVoices->first();
864 RTList<Voice>::Iterator end = pKey->pActiveVoices->end();
865 for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
866 if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
867 itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
868 }
869 }
870 } else pEngineChannel->PortamentoPos = -1.0f;
871 }
872
873 // if no solo mode (the usual case) or if solo mode and no other key pressed, then release voices on this key if needed
874 if (bShouldRelease) {
875 itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type
876
877 // spawn release triggered voice(s) if needed
878 if (pKey->ReleaseTrigger && pEngineChannel->pInstrument) {
879 // first, get total amount of required voices (dependant on amount of layers)
880 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
881 if (pRegion) {
882 int voicesRequired = pRegion->Layers;
883
884 // MIDI note-on velocity is used instead of note-off velocity
885 itNoteOffEventOnKeyList->Param.Note.Velocity = pKey->Velocity;
886
887 // now launch the required amount of voices
888 for (int i = 0; i < voicesRequired; i++)
889 LaunchVoice(pEngineChannel, itNoteOffEventOnKeyList, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples
890 }
891 pKey->ReleaseTrigger = false;
892 }
893 }
894
895 // if neither a voice was spawned or postponed on this key then remove note off event from key again
896 if (!pKey->Active && !pKey->VoiceTheftsQueued)
897 pKey->pEvents->free(itNoteOffEventOnKeyList);
898 }
899
900 /**
901 * Moves pitchbend event from the general (input) event list to the engine
902 * channel's event list. It will actually processed later by the
903 * respective voice.
904 *
905 * @param pEngineChannel - engine channel on which this event occured on
906 * @param itPitchbendEvent - absolute pitch value and time stamp of the event
907 */
908 void Engine::ProcessPitchbend(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
909 pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
910 }
911
912 /**
913 * Allocates and triggers a new voice. This method will usually be
914 * called by the ProcessNoteOn() method and by the voices itself
915 * (e.g. to spawn further voices on the same key for layered sounds).
916 *
917 * @param pEngineChannel - engine channel on which this event occured on
918 * @param itNoteOnEvent - key, velocity and time stamp of the event
919 * @param iLayer - layer index for the new voice (optional - only
920 * in case of layered sounds of course)
921 * @param ReleaseTriggerVoice - if new voice is a release triggered voice
922 * (optional, default = false)
923 * @param VoiceStealing - if voice stealing should be performed
924 * when there is no free voice
925 * (optional, default = true)
926 * @param HandleKeyGroupConflicts - if voices should be killed due to a
927 * key group conflict
928 * @returns pointer to new voice or NULL if there was no free voice or
929 * if the voice wasn't triggered (for example when no region is
930 * defined for the given key).
931 */
932 Pool<Voice>::Iterator Engine::LaunchVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing, bool HandleKeyGroupConflicts) {
933 int MIDIKey = itNoteOnEvent->Param.Note.Key;
934 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[MIDIKey];
935 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(MIDIKey);
936
937 // if nothing defined for this key
938 if (!pRegion) return Pool<Voice>::Iterator(); // nothing to do
939
940 // only mark the first voice of a layered voice (group) to be in a
941 // key group, so the layered voices won't kill each other
942 int iKeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0;
943
944 // handle key group (a.k.a. exclusive group) conflicts
945 if (HandleKeyGroupConflicts) {
946 if (iKeyGroup) { // if this voice / key belongs to a key group
947 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[iKeyGroup];
948 if (*ppKeyGroup) { // if there's already an active key in that key group
949 midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[**ppKeyGroup];
950 // kill all voices on the (other) key
951 RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
952 RTList<Voice>::Iterator end = pOtherKey->pActiveVoices->end();
953 for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
954 if (itVoiceToBeKilled->Type != Voice::type_release_trigger) {
955 itVoiceToBeKilled->Kill(itNoteOnEvent);
956 --VoiceSpawnsLeft; //FIXME: just a hack, we should better check in StealVoice() if the voice was killed due to key conflict
957 }
958 }
959 }
960 }
961 }
962
963 Voice::type_t VoiceType = Voice::type_normal;
964
965 // get current dimension values to select the right dimension region
966 //TODO: for stolen voices this dimension region selection block is processed twice, this should be changed
967 //FIXME: controller values for selecting the dimension region here are currently not sample accurate
968 uint DimValues[8] = { 0 };
969 for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
970 switch (pRegion->pDimensionDefinitions[i].dimension) {
971 case ::gig::dimension_samplechannel:
972 DimValues[i] = 0; //TODO: we currently ignore this dimension
973 break;
974 case ::gig::dimension_layer:
975 DimValues[i] = iLayer;
976 break;
977 case ::gig::dimension_velocity:
978 DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
979 break;
980 case ::gig::dimension_channelaftertouch:
981 DimValues[i] = pEngineChannel->ControllerTable[128];
982 break;
983 case ::gig::dimension_releasetrigger:
984 VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal;
985 DimValues[i] = (uint) ReleaseTriggerVoice;
986 break;
987 case ::gig::dimension_keyboard:
988 DimValues[i] = (uint) (pEngineChannel->CurrentKeyDimension * pRegion->pDimensionDefinitions[i].zones);
989 break;
990 case ::gig::dimension_roundrobin:
991 DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
992 break;
993 case ::gig::dimension_random:
994 RandomSeed = RandomSeed * 1103515245 + 12345; // classic pseudo random number generator
995 DimValues[i] = (uint) RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random
996 break;
997 case ::gig::dimension_modwheel:
998 DimValues[i] = pEngineChannel->ControllerTable[1];
999 break;
1000 case ::gig::dimension_breath:
1001 DimValues[i] = pEngineChannel->ControllerTable[2];
1002 break;
1003 case ::gig::dimension_foot:
1004 DimValues[i] = pEngineChannel->ControllerTable[4];
1005 break;
1006 case ::gig::dimension_portamentotime:
1007 DimValues[i] = pEngineChannel->ControllerTable[5];
1008 break;
1009 case ::gig::dimension_effect1:
1010 DimValues[i] = pEngineChannel->ControllerTable[12];
1011 break;
1012 case ::gig::dimension_effect2:
1013 DimValues[i] = pEngineChannel->ControllerTable[13];
1014 break;
1015 case ::gig::dimension_genpurpose1:
1016 DimValues[i] = pEngineChannel->ControllerTable[16];
1017 break;
1018 case ::gig::dimension_genpurpose2:
1019 DimValues[i] = pEngineChannel->ControllerTable[17];
1020 break;
1021 case ::gig::dimension_genpurpose3:
1022 DimValues[i] = pEngineChannel->ControllerTable[18];
1023 break;
1024 case ::gig::dimension_genpurpose4:
1025 DimValues[i] = pEngineChannel->ControllerTable[19];
1026 break;
1027 case ::gig::dimension_sustainpedal:
1028 DimValues[i] = pEngineChannel->ControllerTable[64];
1029 break;
1030 case ::gig::dimension_portamento:
1031 DimValues[i] = pEngineChannel->ControllerTable[65];
1032 break;
1033 case ::gig::dimension_sostenutopedal:
1034 DimValues[i] = pEngineChannel->ControllerTable[66];
1035 break;
1036 case ::gig::dimension_softpedal:
1037 DimValues[i] = pEngineChannel->ControllerTable[67];
1038 break;
1039 case ::gig::dimension_genpurpose5:
1040 DimValues[i] = pEngineChannel->ControllerTable[80];
1041 break;
1042 case ::gig::dimension_genpurpose6:
1043 DimValues[i] = pEngineChannel->ControllerTable[81];
1044 break;
1045 case ::gig::dimension_genpurpose7:
1046 DimValues[i] = pEngineChannel->ControllerTable[82];
1047 break;
1048 case ::gig::dimension_genpurpose8:
1049 DimValues[i] = pEngineChannel->ControllerTable[83];
1050 break;
1051 case ::gig::dimension_effect1depth:
1052 DimValues[i] = pEngineChannel->ControllerTable[91];
1053 break;
1054 case ::gig::dimension_effect2depth:
1055 DimValues[i] = pEngineChannel->ControllerTable[92];
1056 break;
1057 case ::gig::dimension_effect3depth:
1058 DimValues[i] = pEngineChannel->ControllerTable[93];
1059 break;
1060 case ::gig::dimension_effect4depth:
1061 DimValues[i] = pEngineChannel->ControllerTable[94];
1062 break;
1063 case ::gig::dimension_effect5depth:
1064 DimValues[i] = pEngineChannel->ControllerTable[95];
1065 break;
1066 case ::gig::dimension_none:
1067 std::cerr << "gig::Engine::LaunchVoice() Error: dimension=none\n" << std::flush;
1068 break;
1069 default:
1070 std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;
1071 }
1072 }
1073
1074 // return if this is a release triggered voice and there is no
1075 // releasetrigger dimension (could happen if an instrument
1076 // change has occured between note on and off)
1077 if (ReleaseTriggerVoice && VoiceType != Voice::type_release_trigger) return Pool<Voice>::Iterator();
1078
1079 ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
1080
1081 // no need to continue if sample is silent
1082 if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator();
1083
1084 // allocate a new voice for the key
1085 Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();
1086 if (itNewVoice) {
1087 // launch the new voice
1088 if (itNewVoice->Trigger(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pDimRgn, VoiceType, iKeyGroup) < 0) {
1089 dmsg(4,("Voice not triggered\n"));
1090 pKey->pActiveVoices->free(itNewVoice);
1091 }
1092 else { // on success
1093 --VoiceSpawnsLeft;
1094 if (!pKey->Active) { // mark as active key
1095 pKey->Active = true;
1096 pKey->itSelf = pEngineChannel->pActiveKeys->allocAppend();
1097 *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
1098 }
1099 if (itNewVoice->KeyGroup) {
1100 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[itNewVoice->KeyGroup];
1101 *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group
1102 }
1103 if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
1104 return itNewVoice; // success
1105 }
1106 }
1107 else if (VoiceStealing) {
1108 // try to steal one voice
1109 int result = StealVoice(pEngineChannel, itNoteOnEvent);
1110 if (!result) { // voice stolen successfully
1111 // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
1112 RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
1113 if (itStealEvent) {
1114 *itStealEvent = *itNoteOnEvent; // copy event
1115 itStealEvent->Param.Note.Layer = iLayer;
1116 itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
1117 pKey->VoiceTheftsQueued++;
1118 }
1119 else dmsg(1,("Voice stealing queue full!\n"));
1120 }
1121 }
1122
1123 return Pool<Voice>::Iterator(); // no free voice or error
1124 }
1125
1126 /**
1127 * Will be called by LaunchVoice() method in case there are no free
1128 * voices left. This method will select and kill one old voice for
1129 * voice stealing and postpone the note-on event until the selected
1130 * voice actually died.
1131 *
1132 * @param pEngineChannel - engine channel on which this event occured on
1133 * @param itNoteOnEvent - key, velocity and time stamp of the event
1134 * @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
1135 */
1136 int Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1137 if (VoiceSpawnsLeft <= 0) {
1138 dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
1139 return -1;
1140 }
1141 if (!pEventPool->poolIsEmpty()) {
1142
1143 RTList<Voice>::Iterator itSelectedVoice;
1144
1145 // Select one voice for voice stealing
1146 switch (CONFIG_VOICE_STEAL_ALGO) {
1147
1148 // try to pick the oldest voice on the key where the new
1149 // voice should be spawned, if there is no voice on that
1150 // key, or no voice left to kill, then procceed with
1151 // 'oldestkey' algorithm
1152 case voice_steal_algo_oldestvoiceonkey: {
1153 midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
1154 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1155 // proceed iterating if voice was created in this fragment cycle
1156 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1157 // if we haven't found a voice then proceed with algorithm 'oldestkey'
1158 if (itSelectedVoice && itSelectedVoice->IsStealable()) break;
1159 } // no break - intentional !
1160
1161 // try to pick the oldest voice on the oldest active key
1162 // from the same engine channel
1163 // (caution: must stay after 'oldestvoiceonkey' algorithm !)
1164 case voice_steal_algo_oldestkey: {
1165 // if we already stole in this fragment, try to proceed on same key
1166 if (this->itLastStolenVoice) {
1167 itSelectedVoice = this->itLastStolenVoice;
1168 do {
1169 ++itSelectedVoice;
1170 } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1171 // found a "stealable" voice ?
1172 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1173 // remember which voice we stole, so we can simply proceed on next voice stealing
1174 this->itLastStolenVoice = itSelectedVoice;
1175 break; // selection succeeded
1176 }
1177 }
1178 // get (next) oldest key
1179 RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKey) ? ++this->iuiLastStolenKey : pEngineChannel->pActiveKeys->first();
1180 while (iuiSelectedKey) {
1181 midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];
1182 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1183 // proceed iterating if voice was created in this fragment cycle
1184 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1185 // found a "stealable" voice ?
1186 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1187 // remember which voice on which key we stole, so we can simply proceed on next voice stealing
1188 this->iuiLastStolenKey = iuiSelectedKey;
1189 this->itLastStolenVoice = itSelectedVoice;
1190 break; // selection succeeded
1191 }
1192 ++iuiSelectedKey; // get next oldest key
1193 }
1194 break;
1195 }
1196
1197 // don't steal anything
1198 case voice_steal_algo_none:
1199 default: {
1200 dmsg(1,("No free voice (voice stealing disabled)!\n"));
1201 return -1;
1202 }
1203 }
1204
1205 // if we couldn't steal a voice from the same engine channel then
1206 // steal oldest voice on the oldest key from any other engine channel
1207 // (the smaller engine channel number, the higher priority)
1208 if (!itSelectedVoice || !itSelectedVoice->IsStealable()) {
1209 EngineChannel* pSelectedChannel;
1210 int iChannelIndex;
1211 // select engine channel
1212 if (pLastStolenChannel) {
1213 pSelectedChannel = pLastStolenChannel;
1214 iChannelIndex = pSelectedChannel->iEngineIndexSelf;
1215 } else { // pick the engine channel followed by this engine channel
1216 iChannelIndex = (pEngineChannel->iEngineIndexSelf + 1) % engineChannels.size();
1217 pSelectedChannel = engineChannels[iChannelIndex];
1218 }
1219
1220 // if we already stole in this fragment, try to proceed on same key
1221 if (this->itLastStolenVoiceGlobally) {
1222 itSelectedVoice = this->itLastStolenVoiceGlobally;
1223 do {
1224 ++itSelectedVoice;
1225 } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1226 }
1227
1228 #if CONFIG_DEVMODE
1229 EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1230 #endif // CONFIG_DEVMODE
1231
1232 // did we find a 'stealable' voice?
1233 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1234 // remember which voice we stole, so we can simply proceed on next voice stealing
1235 this->itLastStolenVoiceGlobally = itSelectedVoice;
1236 } else while (true) { // iterate through engine channels
1237 // get (next) oldest key
1238 RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
1239 this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
1240 while (iuiSelectedKey) {
1241 midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1242 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1243 // proceed iterating if voice was created in this fragment cycle
1244 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1245 // found a "stealable" voice ?
1246 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1247 // remember which voice on which key on which engine channel we stole, so we can simply proceed on next voice stealing
1248 this->iuiLastStolenKeyGlobally = iuiSelectedKey;
1249 this->itLastStolenVoiceGlobally = itSelectedVoice;
1250 this->pLastStolenChannel = pSelectedChannel;
1251 goto stealable_voice_found; // selection succeeded
1252 }
1253 ++iuiSelectedKey; // get next key on current engine channel
1254 }
1255 // get next engine channel
1256 iChannelIndex = (iChannelIndex + 1) % engineChannels.size();
1257 pSelectedChannel = engineChannels[iChannelIndex];
1258
1259 #if CONFIG_DEVMODE
1260 if (pSelectedChannel == pBegin) {
1261 dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1262 dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1263 dmsg(1,("Exiting.\n"));
1264 exit(-1);
1265 }
1266 #endif // CONFIG_DEVMODE
1267 }
1268 }
1269
1270 // jump point if a 'stealable' voice was found
1271 stealable_voice_found:
1272
1273 #if CONFIG_DEVMODE
1274 if (!itSelectedVoice->IsActive()) {
1275 dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
1276 return -1;
1277 }
1278 #endif // CONFIG_DEVMODE
1279
1280 // now kill the selected voice
1281 itSelectedVoice->Kill(itNoteOnEvent);
1282
1283 --VoiceSpawnsLeft;
1284
1285 return 0; // success
1286 }
1287 else {
1288 dmsg(1,("Event pool emtpy!\n"));
1289 return -1;
1290 }
1291 }
1292
1293 /**
1294 * Removes the given voice from the MIDI key's list of active voices.
1295 * This method will be called when a voice went inactive, e.g. because
1296 * it finished to playback its sample, finished its release stage or
1297 * just was killed.
1298 *
1299 * @param pEngineChannel - engine channel on which this event occured on
1300 * @param itVoice - points to the voice to be freed
1301 */
1302 void Engine::FreeVoice(EngineChannel* pEngineChannel, Pool<Voice>::Iterator& itVoice) {
1303 if (itVoice) {
1304 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoice->MIDIKey];
1305
1306 uint keygroup = itVoice->KeyGroup;
1307
1308 // if the sample and dimension region belong to an
1309 // instrument that is unloaded, tell the disk thread to
1310 // release them
1311 if (itVoice->Orphan) {
1312 pDiskThread->OrderDeletionOfDimreg(itVoice->pDimRgn);
1313 }
1314
1315 // free the voice object
1316 pVoicePool->free(itVoice);
1317
1318 // if no other voices left and member of a key group, remove from key group
1319 if (pKey->pActiveVoices->isEmpty() && keygroup) {
1320 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[keygroup];
1321 if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group
1322 }
1323 }
1324 else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;
1325 }
1326
1327 /**
1328 * Called when there's no more voice left on a key, this call will
1329 * update the key info respectively.
1330 *
1331 * @param pEngineChannel - engine channel on which this event occured on
1332 * @param pKey - key which is now inactive
1333 */
1334 void Engine::FreeKey(EngineChannel* pEngineChannel, midi_key_info_t* pKey) {
1335 if (pKey->pActiveVoices->isEmpty()) {
1336 pKey->Active = false;
1337 pEngineChannel->pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
1338 pKey->itSelf = RTList<uint>::Iterator();
1339 pKey->ReleaseTrigger = false;
1340 pKey->pEvents->clear();
1341 dmsg(3,("Key has no more voices now\n"));
1342 }
1343 else dmsg(1,("gig::Engine: Oops, tried to free a key which contains voices.\n"));
1344 }
1345
1346 /**
1347 * Reacts on supported control change commands (e.g. pitch bend wheel,
1348 * modulation wheel, aftertouch).
1349 *
1350 * @param pEngineChannel - engine channel on which this event occured on
1351 * @param itControlChangeEvent - controller, value and time stamp of the event
1352 */
1353 void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {
1354 dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));
1355
1356 // update controller value in the engine channel's controller table
1357 pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1358
1359 // handle hard coded MIDI controllers
1360 switch (itControlChangeEvent->Param.CC.Controller) {
1361 case 5: { // portamento time
1362 pEngineChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
1363 break;
1364 }
1365 case 6: { // data entry (currently only used for RPN controllers)
1366 if (pEngineChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
1367 int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
1368 // limit to +- two octaves for now
1369 transpose = RTMath::Min(transpose, 24);
1370 transpose = RTMath::Max(transpose, -24);
1371 pEngineChannel->GlobalTranspose = transpose;
1372 // workaround, so we won't have hanging notes
1373 ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1374 }
1375 // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data
1376 pEngineChannel->ResetMidiRpnController();
1377 break;
1378 }
1379 case 7: { // volume
1380 //TODO: not sample accurate yet
1381 pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1382 pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1383 break;
1384 }
1385 case 10: { // panpot
1386 //TODO: not sample accurate yet
1387 pEngineChannel->GlobalPanLeft = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1388 pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value];
1389 break;
1390 }
1391 case 64: { // sustain
1392 if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1393 dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1394 pEngineChannel->SustainPedal = true;
1395
1396 #if !CONFIG_PROCESS_MUTED_CHANNELS
1397 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1398 #endif
1399
1400 // cancel release process of voices if necessary
1401 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1402 for (; iuiKey; ++iuiKey) {
1403 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1404 if (!pKey->KeyPressed) {
1405 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1406 if (itNewEvent) {
1407 *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1408 itNewEvent->Type = Event::type_cancel_release; // transform event type
1409 }
1410 else dmsg(1,("Event pool emtpy!\n"));
1411 }
1412 }
1413 }
1414 if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1415 dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1416 pEngineChannel->SustainPedal = false;
1417
1418 #if !CONFIG_PROCESS_MUTED_CHANNELS
1419 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1420 #endif
1421
1422 // release voices if their respective key is not pressed
1423 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1424 for (; iuiKey; ++iuiKey) {
1425 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1426 if (!pKey->KeyPressed && ShouldReleaseVoice(pEngineChannel, *iuiKey)) {
1427 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1428 if (itNewEvent) {
1429 *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1430 itNewEvent->Type = Event::type_release; // transform event type
1431 }
1432 else dmsg(1,("Event pool emtpy!\n"));
1433 }
1434 }
1435 }
1436 break;
1437 }
1438 case 65: { // portamento on / off
1439 KillAllVoices(pEngineChannel, itControlChangeEvent);
1440 pEngineChannel->PortamentoMode = itControlChangeEvent->Param.CC.Value >= 64;
1441 break;
1442 }
1443 case 66: { // sostenuto
1444 if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {
1445 dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1446 pEngineChannel->SostenutoPedal = true;
1447
1448 #if !CONFIG_PROCESS_MUTED_CHANNELS
1449 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1450 #endif
1451
1452 SostenutoKeyCount = 0;
1453 // Remeber the pressed keys
1454 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1455 for (; iuiKey; ++iuiKey) {
1456 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1457 if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
1458 }
1459 }
1460 if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SostenutoPedal) {
1461 dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1462 pEngineChannel->SostenutoPedal = false;
1463
1464 #if !CONFIG_PROCESS_MUTED_CHANNELS
1465 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1466 #endif
1467
1468 // release voices if the damper pedal is up and their respective key is not pressed
1469 for (int i = 0; i < SostenutoKeyCount; i++) {
1470 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[SostenutoKeys[i]];
1471 if (!pKey->KeyPressed && !pEngineChannel->SustainPedal) {
1472 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1473 if (itNewEvent) {
1474 *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1475 itNewEvent->Type = Event::type_release; // transform event type
1476 }
1477 else dmsg(1,("Event pool emtpy!\n"));
1478 }
1479 }
1480 }
1481 break;
1482 }
1483 case 100: { // RPN controller LSB
1484 pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1485 break;
1486 }
1487 case 101: { // RPN controller MSB
1488 pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1489 break;
1490 }
1491
1492
1493 // Channel Mode Messages
1494
1495 case 120: { // all sound off
1496 KillAllVoices(pEngineChannel, itControlChangeEvent);
1497 break;
1498 }
1499 case 121: { // reset all controllers
1500 pEngineChannel->ResetControllers();
1501 break;
1502 }
1503 case 123: { // all notes off
1504 #if CONFIG_PROCESS_ALL_NOTES_OFF
1505 ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1506 #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1507 break;
1508 }
1509 case 126: { // mono mode on
1510 KillAllVoices(pEngineChannel, itControlChangeEvent);
1511 pEngineChannel->SoloMode = true;
1512 break;
1513 }
1514 case 127: { // poly mode on
1515 KillAllVoices(pEngineChannel, itControlChangeEvent);
1516 pEngineChannel->SoloMode = false;
1517 break;
1518 }
1519 }
1520
1521 // handle FX send controllers
1522 if (!pEngineChannel->fxSends.empty()) {
1523 for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1524 FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1525 if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller)
1526 pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1527 }
1528 }
1529 }
1530
1531 /**
1532 * Reacts on MIDI system exclusive messages.
1533 *
1534 * @param itSysexEvent - sysex data size and time stamp of the sysex event
1535 */
1536 void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1537 RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1538
1539 uint8_t exclusive_status, id;
1540 if (!reader.pop(&exclusive_status)) goto free_sysex_data;
1541 if (!reader.pop(&id)) goto free_sysex_data;
1542 if (exclusive_status != 0xF0) goto free_sysex_data;
1543
1544 switch (id) {
1545 case 0x41: { // Roland
1546 dmsg(3,("Roland Sysex\n"));
1547 uint8_t device_id, model_id, cmd_id;
1548 if (!reader.pop(&device_id)) goto free_sysex_data;
1549 if (!reader.pop(&model_id)) goto free_sysex_data;
1550 if (!reader.pop(&cmd_id)) goto free_sysex_data;
1551 if (model_id != 0x42 /*GS*/) goto free_sysex_data;
1552 if (cmd_id != 0x12 /*DT1*/) goto free_sysex_data;
1553
1554 // command address
1555 uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
1556 const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
1557 if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1558 if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1559 dmsg(3,("\tSystem Parameter\n"));
1560 }
1561 else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
1562 dmsg(3,("\tCommon Parameter\n"));
1563 }
1564 else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
1565 dmsg(3,("\tPart Parameter\n"));
1566 switch (addr[2]) {
1567 case 0x40: { // scale tuning
1568 dmsg(3,("\t\tScale Tuning\n"));
1569 uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
1570 if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
1571 uint8_t checksum;
1572 if (!reader.pop(&checksum)) goto free_sysex_data;
1573 #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1574 if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
1575 #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1576 for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
1577 AdjustScale((int8_t*) scale_tunes);
1578 dmsg(3,("\t\t\tNew scale applied.\n"));
1579 break;
1580 }
1581 }
1582 }
1583 else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
1584 }
1585 else if (addr[0] == 0x41) { // Drum Setup Parameters
1586 }
1587 break;
1588 }
1589 }
1590
1591 free_sysex_data: // finally free sysex data
1592 pSysexBuffer->increment_read_ptr(itSysexEvent->Param.Sysex.Size);
1593 }
1594
1595 /**
1596 * Calculates the Roland GS sysex check sum.
1597 *
1598 * @param AddrReader - reader which currently points to the first GS
1599 * command address byte of the GS sysex message in
1600 * question
1601 * @param DataSize - size of the GS message data (in bytes)
1602 */
1603 uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {
1604 RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
1605 uint bytes = 3 /*addr*/ + DataSize;
1606 uint8_t addr_and_data[bytes];
1607 reader.read(&addr_and_data[0], bytes);
1608 uint8_t sum = 0;
1609 for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];
1610 return 128 - sum % 128;
1611 }
1612
1613 /**
1614 * Allows to tune each of the twelve semitones of an octave.
1615 *
1616 * @param ScaleTunes - detuning of all twelve semitones (in cents)
1617 */
1618 void Engine::AdjustScale(int8_t ScaleTunes[12]) {
1619 memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate
1620 }
1621
1622 /**
1623 * Releases all voices on an engine channel. All voices will go into
1624 * the release stage and thus it might take some time (e.g. dependant to
1625 * their envelope release time) until they actually die.
1626 *
1627 * @param pEngineChannel - engine channel on which all voices should be released
1628 * @param itReleaseEvent - event which caused this releasing of all voices
1629 */
1630 void Engine::ReleaseAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itReleaseEvent) {
1631 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1632 while (iuiKey) {
1633 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1634 ++iuiKey;
1635 // append a 'release' event to the key's own event list
1636 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1637 if (itNewEvent) {
1638 *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
1639 itNewEvent->Type = Event::type_release; // transform event type
1640 }
1641 else dmsg(1,("Event pool emtpy!\n"));
1642 }
1643 }
1644
1645 /**
1646 * Kills all voices on an engine channel as soon as possible. Voices
1647 * won't get into release state, their volume level will be ramped down
1648 * as fast as possible.
1649 *
1650 * @param pEngineChannel - engine channel on which all voices should be killed
1651 * @param itKillEvent - event which caused this killing of all voices
1652 */
1653 void Engine::KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
1654 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1655 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
1656 while (iuiKey != end) { // iterate through all active keys
1657 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1658 ++iuiKey;
1659 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
1660 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
1661 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
1662 itVoice->Kill(itKillEvent);
1663 --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
1664 }
1665 }
1666 }
1667
1668 /**
1669 * Determines whether the specified voice should be released.
1670 *
1671 * @param pEngineChannel - The engine channel on which the voice should be checked
1672 * @param Key - The key number
1673 * @returns true if the specified should be released, false otherwise.
1674 */
1675 bool Engine::ShouldReleaseVoice(EngineChannel* pEngineChannel, int Key) {
1676 if (pEngineChannel->SustainPedal) return false;
1677
1678 if (pEngineChannel->SostenutoPedal) {
1679 for (int i = 0; i < SostenutoKeyCount; i++)
1680 if (Key == SostenutoKeys[i]) return false;
1681 }
1682
1683 return true;
1684 }
1685
1686 uint Engine::VoiceCount() {
1687 return ActiveVoiceCount;
1688 }
1689
1690 uint Engine::VoiceCountMax() {
1691 return ActiveVoiceCountMax;
1692 }
1693
1694 bool Engine::DiskStreamSupported() {
1695 return true;
1696 }
1697
1698 uint Engine::DiskStreamCount() {
1699 return (pDiskThread) ? pDiskThread->ActiveStreamCount : 0;
1700 }
1701
1702 uint Engine::DiskStreamCountMax() {
1703 return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0;
1704 }
1705
1706 String Engine::DiskStreamBufferFillBytes() {
1707 return pDiskThread->GetBufferFillBytes();
1708 }
1709
1710 String Engine::DiskStreamBufferFillPercentage() {
1711 return pDiskThread->GetBufferFillPercentage();
1712 }
1713
1714 String Engine::EngineName() {
1715 return LS_GIG_ENGINE_NAME;
1716 }
1717
1718 String Engine::Description() {
1719 return "Gigasampler Engine";
1720 }
1721
1722 String Engine::Version() {
1723 String s = "$Revision: 1.75 $";
1724 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
1725 }
1726
1727 InstrumentManager* Engine::GetInstrumentManager() {
1728 return &instruments;
1729 }
1730
1731 // static constant initializers
1732 const float* Engine::VolumeCurve(InitVolumeCurve());
1733 const float* Engine::PanCurve(InitPanCurve());
1734 const float* Engine::CrossfadeCurve(InitCrossfadeCurve());
1735
1736 float* Engine::InitVolumeCurve() {
1737 // line-segment approximation
1738 const float segments[] = {
1739 0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
1740 64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
1741 };
1742 return InitCurve(segments);
1743 }
1744
1745 float* Engine::InitPanCurve() {
1746 // line-segment approximation
1747 const float segments[] = {
1748 0, 0, 1, 0,
1749 2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
1750 127, 1.41, 128, 1.41
1751 };
1752 return InitCurve(segments, 129);
1753 }
1754
1755 float* Engine::InitCrossfadeCurve() {
1756 // line-segment approximation
1757 const float segments[] = {
1758 0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
1759 };
1760 return InitCurve(segments);
1761 }
1762
1763 float* Engine::InitCurve(const float* segments, int size) {
1764 float* y = new float[size];
1765 for (int x = 0 ; x < size ; x++) {
1766 if (x > segments[2]) segments += 2;
1767 y[x] = segments[1] + (x - segments[0]) *
1768 (segments[3] - segments[1]) / (segments[2] - segments[0]);
1769 }
1770 return y;
1771 }
1772
1773 /**
1774 * Changes the instrument for an engine channel.
1775 *
1776 * @param pEngineChannel - engine channel on which the instrument
1777 * should be changed
1778 * @param pInstrument - new instrument
1779 * @returns a list of dimension regions from the old instrument
1780 * that are still in use
1781 */
1782 ::gig::DimensionRegion** Engine::ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument) {
1783 instrument_change_command_t command;
1784 command.pEngineChannel = pEngineChannel;
1785 command.pInstrument = pInstrument;
1786 InstrumentChangeQueue->push(&command);
1787
1788 // wait for the audio thread to confirm that the instrument
1789 // change has been done
1790 instrument_change_reply_t reply;
1791 while (InstrumentChangeReplyQueue->pop(&reply) == 0) {
1792 usleep(10000);
1793 }
1794 return pDimRegionsInUse;
1795 }
1796
1797 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC