/[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 738 - (show annotations) (download)
Tue Aug 16 17:14:25 2005 UTC (18 years, 7 months ago) by schoenebeck
File size: 67028 byte(s)
* extensive synthesis optimization: reimplementation of EGs and LFO(s),
  removed synthesis parameter prerendering and the synthesis parameter
  matrix in general, splitting each audio fragment into subfragments now
  where each subfragment uses constant synthesis parameters
  (everything's still very buggy ATM)

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 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 } else { // create a new engine (and disk thread) instance for the given audio output device
55 dmsg(4,("Creating new gig::Engine.\n"));
56 pEngine = (Engine*) EngineFactory::Create("gig");
57 pEngine->Connect(pDevice);
58 engines[pDevice] = pEngine;
59 }
60 // register engine channel to the engine instance
61 pEngine->engineChannels.add(pChannel);
62 // remember index in the ArrayList
63 pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
64 dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
65 return pEngine;
66 }
67
68 /**
69 * Once an engine channel is disconnected from an audio output device,
70 * it wil immediately call this method to unregister itself from the
71 * engine instance and if that engine instance is not used by any other
72 * engine channel anymore, then that engine instance will be destroyed.
73 *
74 * @param pChannel - engine channel which wants to disconnect from it's
75 * engine instance
76 * @param pDevice - audio output device \a pChannel was connected to
77 */
78 void Engine::FreeEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
79 dmsg(4,("Disconnecting EngineChannel from gig::Engine.\n"));
80 Engine* pEngine = engines[pDevice];
81 // unregister EngineChannel from the Engine instance
82 pEngine->engineChannels.remove(pChannel);
83 // if the used Engine instance is not used anymore, then destroy it
84 if (pEngine->engineChannels.empty()) {
85 pDevice->Disconnect(pEngine);
86 engines.erase(pDevice);
87 delete pEngine;
88 dmsg(4,("Destroying gig::Engine.\n"));
89 }
90 else dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
91 }
92
93 /**
94 * Constructor
95 */
96 Engine::Engine() {
97 pAudioOutputDevice = NULL;
98 pDiskThread = NULL;
99 pEventGenerator = NULL;
100 pSysexBuffer = new RingBuffer<uint8_t>(CONFIG_SYSEX_BUFFER_SIZE, 0);
101 pEventQueue = new RingBuffer<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
102 pEventPool = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
103 pVoicePool = new Pool<Voice>(CONFIG_MAX_VOICES);
104 pVoiceStealingQueue = new RTList<Event>(pEventPool);
105 pGlobalEvents = new RTList<Event>(pEventPool);
106 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
107 iterVoice->SetEngine(this);
108 }
109 pVoicePool->clear();
110
111 ResetInternal();
112 ResetScaleTuning();
113 }
114
115 /**
116 * Destructor
117 */
118 Engine::~Engine() {
119 if (pDiskThread) {
120 dmsg(1,("Stopping disk thread..."));
121 pDiskThread->StopThread();
122 delete pDiskThread;
123 dmsg(1,("OK\n"));
124 }
125 if (pEventQueue) delete pEventQueue;
126 if (pEventPool) delete pEventPool;
127 if (pVoicePool) {
128 pVoicePool->clear();
129 delete pVoicePool;
130 }
131 if (pEventGenerator) delete pEventGenerator;
132 if (pVoiceStealingQueue) delete pVoiceStealingQueue;
133 if (pSysexBuffer) delete pSysexBuffer;
134 EngineFactory::Destroy(this);
135 }
136
137 void Engine::Enable() {
138 dmsg(3,("gig::Engine: enabling\n"));
139 EngineDisabled.PushAndUnlock(false, 2); // set condition object 'EngineDisabled' to false (wait max. 2s)
140 dmsg(3,("gig::Engine: enabled (val=%d)\n", EngineDisabled.GetUnsafe()));
141 }
142
143 void Engine::Disable() {
144 dmsg(3,("gig::Engine: disabling\n"));
145 bool* pWasDisabled = EngineDisabled.PushAndUnlock(true, 2); // wait max. 2s
146 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
147 }
148
149 void Engine::DisableAndLock() {
150 dmsg(3,("gig::Engine: disabling\n"));
151 bool* pWasDisabled = EngineDisabled.Push(true, 2); // wait max. 2s
152 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
153 }
154
155 /**
156 * Reset all voices and disk thread and clear input event queue and all
157 * control and status variables.
158 */
159 void Engine::Reset() {
160 DisableAndLock();
161 ResetInternal();
162 ResetScaleTuning();
163 Enable();
164 }
165
166 /**
167 * Reset all voices and disk thread and clear input event queue and all
168 * control and status variables. This method is not thread safe!
169 */
170 void Engine::ResetInternal() {
171 ActiveVoiceCount = 0;
172 ActiveVoiceCountMax = 0;
173
174 // reset voice stealing parameters
175 pVoiceStealingQueue->clear();
176 itLastStolenVoice = RTList<Voice>::Iterator();
177 itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
178 iuiLastStolenKey = RTList<uint>::Iterator();
179 iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
180 pLastStolenChannel = NULL;
181
182 // reset all voices
183 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
184 iterVoice->Reset();
185 }
186 pVoicePool->clear();
187
188 // reset disk thread
189 if (pDiskThread) pDiskThread->Reset();
190
191 // delete all input events
192 pEventQueue->init();
193 }
194
195 /**
196 * Reset to normal, chromatic scale (means equal tempered).
197 */
198 void Engine::ResetScaleTuning() {
199 memset(&ScaleTuning[0], 0x00, 12);
200 }
201
202 /**
203 * Connect this engine instance with the given audio output device.
204 * This method will be called when an Engine instance is created.
205 * All of the engine's data structures which are dependant to the used
206 * audio output device / driver will be (re)allocated and / or
207 * adjusted appropriately.
208 *
209 * @param pAudioOut - audio output device to connect to
210 */
211 void Engine::Connect(AudioOutputDevice* pAudioOut) {
212 pAudioOutputDevice = pAudioOut;
213
214 ResetInternal();
215
216 // inform audio driver for the need of two channels
217 try {
218 pAudioOutputDevice->AcquireChannels(2); // gig engine only stereo
219 }
220 catch (AudioOutputException e) {
221 String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
222 throw LinuxSamplerException(msg);
223 }
224
225 this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
226 this->SampleRate = pAudioOutputDevice->SampleRate();
227
228 // FIXME: audio drivers with varying fragment sizes might be a problem here
229 MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;
230 if (MaxFadeOutPos < 0) {
231 std::cerr << "gig::Engine: WARNING, CONFIG_EG_MIN_RELEASE_TIME "
232 << "too big for current audio fragment size & sampling rate! "
233 << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;
234 // force volume ramp downs at the beginning of each fragment
235 MaxFadeOutPos = 0;
236 // lower minimum release time
237 const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
238 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
239 iterVoice->EG1.CalculateFadeOutCoeff(minReleaseTime, SampleRate);
240 }
241 pVoicePool->clear();
242 }
243
244 // (re)create disk thread
245 if (this->pDiskThread) {
246 dmsg(1,("Stopping disk thread..."));
247 this->pDiskThread->StopThread();
248 delete this->pDiskThread;
249 dmsg(1,("OK\n"));
250 }
251 this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6); //FIXME: assuming stereo
252 if (!pDiskThread) {
253 dmsg(0,("gig::Engine new diskthread = NULL\n"));
254 exit(EXIT_FAILURE);
255 }
256
257 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
258 iterVoice->pDiskThread = this->pDiskThread;
259 dmsg(3,("d"));
260 }
261 pVoicePool->clear();
262
263 // (re)create event generator
264 if (pEventGenerator) delete pEventGenerator;
265 pEventGenerator = new EventGenerator(pAudioOut->SampleRate());
266
267 dmsg(1,("Starting disk thread..."));
268 pDiskThread->StartThread();
269 dmsg(1,("OK\n"));
270
271 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
272 if (!iterVoice->pDiskThread) {
273 dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
274 exit(EXIT_FAILURE);
275 }
276 }
277 }
278
279 /**
280 * Clear all engine global event lists.
281 */
282 void Engine::ClearEventLists() {
283 pGlobalEvents->clear();
284 }
285
286 /**
287 * Copy all events from the engine's global input queue buffer to the
288 * engine's internal event list. This will be done at the beginning of
289 * each audio cycle (that is each RenderAudio() call) to distinguish
290 * all global events which have to be processed in the current audio
291 * cycle. These events are usually just SysEx messages. Every
292 * EngineChannel has it's own input event queue buffer and event list
293 * to handle common events like NoteOn, NoteOff and ControlChange
294 * events.
295 *
296 * @param Samples - number of sample points to be processed in the
297 * current audio cycle
298 */
299 void Engine::ImportEvents(uint Samples) {
300 RingBuffer<Event>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
301 Event* pEvent;
302 while (true) {
303 // get next event from input event queue
304 if (!(pEvent = eventQueueReader.pop())) break;
305 // if younger event reached, ignore that and all subsequent ones for now
306 if (pEvent->FragmentPos() >= Samples) {
307 eventQueueReader--;
308 dmsg(2,("Younger Event, pos=%d ,Samples=%d!\n",pEvent->FragmentPos(),Samples));
309 pEvent->ResetFragmentPos();
310 break;
311 }
312 // copy event to internal event list
313 if (pGlobalEvents->poolIsEmpty()) {
314 dmsg(1,("Event pool emtpy!\n"));
315 break;
316 }
317 *pGlobalEvents->allocAppend() = *pEvent;
318 }
319 eventQueueReader.free(); // free all copied events from input queue
320 }
321
322 /**
323 * Let this engine proceed to render the given amount of sample points. The
324 * calculated audio data of all voices of this engine will be placed into
325 * the engine's audio sum buffer which has to be copied and eventually be
326 * converted to the appropriate value range by the audio output class (e.g.
327 * AlsaIO or JackIO) right after.
328 *
329 * @param Samples - number of sample points to be rendered
330 * @returns 0 on success
331 */
332 int Engine::RenderAudio(uint Samples) {
333 dmsg(5,("RenderAudio(Samples=%d)\n", Samples));
334
335 // return if engine disabled
336 if (EngineDisabled.Pop()) {
337 dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
338 return 0;
339 }
340
341 // update time of start and end of this audio fragment (as events' time stamps relate to this)
342 pEventGenerator->UpdateFragmentTime(Samples);
343
344 // We only allow a maximum of CONFIG_MAX_VOICES voices to be spawned
345 // in each audio fragment. All subsequent request for spawning new
346 // voices in the same audio fragment will be ignored.
347 VoiceSpawnsLeft = CONFIG_MAX_VOICES;
348
349 // get all events from the engine's global input event queue which belong to the current fragment
350 // (these are usually just SysEx messages)
351 ImportEvents(Samples);
352
353 // process engine global events (these are currently only MIDI System Exclusive messages)
354 {
355 RTList<Event>::Iterator itEvent = pGlobalEvents->first();
356 RTList<Event>::Iterator end = pGlobalEvents->end();
357 for (; itEvent != end; ++itEvent) {
358 switch (itEvent->Type) {
359 case Event::type_sysex:
360 dmsg(5,("Engine: Sysex received\n"));
361 ProcessSysex(itEvent);
362 break;
363 }
364 }
365 }
366
367 // reset internal voice counter (just for statistic of active voices)
368 ActiveVoiceCountTemp = 0;
369
370 // handle events on all engine channels
371 for (int i = 0; i < engineChannels.size(); i++) {
372 if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded
373 ProcessEvents(engineChannels[i], Samples);
374 }
375
376 // render all 'normal', active voices on all engine channels
377 for (int i = 0; i < engineChannels.size(); i++) {
378 if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded
379 RenderActiveVoices(engineChannels[i], Samples);
380 }
381
382 // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
383 RenderStolenVoices(Samples);
384
385 // handle cleanup on all engine channels for the next audio fragment
386 for (int i = 0; i < engineChannels.size(); i++) {
387 if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded
388 PostProcess(engineChannels[i]);
389 }
390
391
392 // empty the engine's event list for the next audio fragment
393 ClearEventLists();
394
395 // reset voice stealing for the next audio fragment
396 pVoiceStealingQueue->clear();
397
398 // just some statistics about this engine instance
399 ActiveVoiceCount = ActiveVoiceCountTemp;
400 if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
401
402 FrameTime += Samples;
403
404 return 0;
405 }
406
407 /**
408 * Dispatch and handle all events in this audio fragment for the given
409 * engine channel.
410 *
411 * @param pEngineChannel - engine channel on which events should be
412 * processed
413 * @param Samples - amount of sample points to be processed in
414 * this audio fragment cycle
415 */
416 void Engine::ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
417 // get all events from the engine channels's input event queue which belong to the current fragment
418 // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
419 pEngineChannel->ImportEvents(Samples);
420
421 // process events
422 {
423 RTList<Event>::Iterator itEvent = pEngineChannel->pEvents->first();
424 RTList<Event>::Iterator end = pEngineChannel->pEvents->end();
425 for (; itEvent != end; ++itEvent) {
426 switch (itEvent->Type) {
427 case Event::type_note_on:
428 dmsg(5,("Engine: Note on received\n"));
429 ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
430 break;
431 case Event::type_note_off:
432 dmsg(5,("Engine: Note off received\n"));
433 ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
434 break;
435 case Event::type_control_change:
436 dmsg(5,("Engine: MIDI CC received\n"));
437 ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
438 break;
439 case Event::type_pitchbend:
440 dmsg(5,("Engine: Pitchbend received\n"));
441 ProcessPitchbend((EngineChannel*)itEvent->pEngineChannel, itEvent);
442 break;
443 }
444 }
445 }
446
447 // reset voice stealing for the next engine channel (or next audio fragment)
448 itLastStolenVoice = RTList<Voice>::Iterator();
449 itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
450 iuiLastStolenKey = RTList<uint>::Iterator();
451 iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
452 pLastStolenChannel = NULL;
453 }
454
455 /**
456 * Render all 'normal' voices (that is voices which were not stolen in
457 * this fragment) on the given engine channel.
458 *
459 * @param pEngineChannel - engine channel on which audio should be
460 * rendered
461 * @param Samples - amount of sample points to be rendered in
462 * this audio fragment cycle
463 */
464 void Engine::RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
465 #if !CONFIG_PROCESS_MUTED_CHANNELS
466 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
467 #endif
468
469 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
470 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
471 while (iuiKey != end) { // iterate through all active keys
472 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
473 ++iuiKey;
474
475 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
476 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
477 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
478 // now render current voice
479 itVoice->Render(Samples);
480 if (itVoice->IsActive()) ActiveVoiceCountTemp++; // still active
481 else { // voice reached end, is now inactive
482 FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices
483 }
484 }
485 }
486 }
487
488 /**
489 * Render all stolen voices (only voices which were stolen in this
490 * fragment) on the given engine channel. Stolen voices are rendered
491 * after all normal voices have been rendered; this is needed to render
492 * audio of those voices which were selected for voice stealing until
493 * the point were the stealing (that is the take over of the voice)
494 * actually happened.
495 *
496 * @param pEngineChannel - engine channel on which audio should be
497 * rendered
498 * @param Samples - amount of sample points to be rendered in
499 * this audio fragment cycle
500 */
501 void Engine::RenderStolenVoices(uint Samples) {
502 RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
503 RTList<Event>::Iterator end = pVoiceStealingQueue->end();
504 for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
505 EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
506 Pool<Voice>::Iterator itNewVoice =
507 LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
508 if (itNewVoice) {
509 itNewVoice->Render(Samples);
510 if (itNewVoice->IsActive()) ActiveVoiceCountTemp++; // still active
511 else { // voice reached end, is now inactive
512 FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices
513 }
514 }
515 else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));
516
517 // we need to clear the key's event list explicitly here in case key was never active
518 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoiceStealEvent->Param.Note.Key];
519 pKey->VoiceTheftsQueued--;
520 if (!pKey->Active && !pKey->VoiceTheftsQueued) pKey->pEvents->clear();
521 }
522 }
523
524 /**
525 * Free all keys which have turned inactive in this audio fragment, from
526 * the list of active keys and clear all event lists on that engine
527 * channel.
528 *
529 * @param pEngineChannel - engine channel to cleanup
530 */
531 void Engine::PostProcess(EngineChannel* pEngineChannel) {
532 // free all keys which have no active voices left
533 {
534 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
535 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
536 while (iuiKey != end) { // iterate through all active keys
537 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
538 ++iuiKey;
539 if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);
540 #if CONFIG_DEVMODE
541 else { // just a sanity check for debugging
542 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
543 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
544 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
545 if (itVoice->itKillEvent) {
546 dmsg(1,("gig::Engine: ERROR, killed voice survived !!!\n"));
547 }
548 }
549 }
550 #endif // CONFIG_DEVMODE
551 }
552 }
553
554 // empty the engine channel's own event lists
555 pEngineChannel->ClearEventLists();
556 }
557
558 /**
559 * Will be called by the MIDI input device whenever a MIDI system
560 * exclusive message has arrived.
561 *
562 * @param pData - pointer to sysex data
563 * @param Size - lenght of sysex data (in bytes)
564 */
565 void Engine::SendSysex(void* pData, uint Size) {
566 Event event = pEventGenerator->CreateEvent();
567 event.Type = Event::type_sysex;
568 event.Param.Sysex.Size = Size;
569 event.pEngineChannel = NULL; // as Engine global event
570 if (pEventQueue->write_space() > 0) {
571 if (pSysexBuffer->write_space() >= Size) {
572 // copy sysex data to input buffer
573 uint toWrite = Size;
574 uint8_t* pPos = (uint8_t*) pData;
575 while (toWrite) {
576 const uint writeNow = RTMath::Min(toWrite, pSysexBuffer->write_space_to_end());
577 pSysexBuffer->write(pPos, writeNow);
578 toWrite -= writeNow;
579 pPos += writeNow;
580
581 }
582 // finally place sysex event into input event queue
583 pEventQueue->push(&event);
584 }
585 else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,CONFIG_SYSEX_BUFFER_SIZE));
586 }
587 else dmsg(1,("Engine: Input event queue full!"));
588 }
589
590 /**
591 * Assigns and triggers a new voice for the respective MIDI key.
592 *
593 * @param pEngineChannel - engine channel on which this event occured on
594 * @param itNoteOnEvent - key, velocity and time stamp of the event
595 */
596 void Engine::ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
597 #if !CONFIG_PROCESS_MUTED_CHANNELS
598 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
599 #endif
600
601 const int key = itNoteOnEvent->Param.Note.Key;
602
603 // Change key dimension value if key is in keyswitching area
604 {
605 const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
606 if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
607 pEngineChannel->CurrentKeyDimension = ((key - pInstrument->DimensionKeyRange.low) * 128) /
608 (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
609 }
610
611 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
612
613 pKey->KeyPressed = true; // the MIDI key was now pressed down
614 pKey->Velocity = itNoteOnEvent->Param.Note.Velocity;
615 pKey->NoteOnTime = FrameTime + itNoteOnEvent->FragmentPos(); // will be used to calculate note length
616
617 // cancel release process of voices on this key if needed
618 if (pKey->Active && !pEngineChannel->SustainPedal) {
619 RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
620 if (itCancelReleaseEvent) {
621 *itCancelReleaseEvent = *itNoteOnEvent; // copy event
622 itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
623 }
624 else dmsg(1,("Event pool emtpy!\n"));
625 }
626
627 // move note on event to the key's own event list
628 RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
629
630 // allocate and trigger new voice(s) for the key
631 {
632 // first, get total amount of required voices (dependant on amount of layers)
633 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOnEventOnKeyList->Param.Note.Key);
634 if (pRegion) {
635 int voicesRequired = pRegion->Layers;
636 // now launch the required amount of voices
637 for (int i = 0; i < voicesRequired; i++)
638 LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true, true);
639 }
640 }
641
642 // if neither a voice was spawned or postponed then remove note on event from key again
643 if (!pKey->Active && !pKey->VoiceTheftsQueued)
644 pKey->pEvents->free(itNoteOnEventOnKeyList);
645
646 pKey->RoundRobinIndex++;
647 }
648
649 /**
650 * Releases the voices on the given key if sustain pedal is not pressed.
651 * If sustain is pressed, the release of the note will be postponed until
652 * sustain pedal will be released or voice turned inactive by itself (e.g.
653 * due to completion of sample playback).
654 *
655 * @param pEngineChannel - engine channel on which this event occured on
656 * @param itNoteOffEvent - key, velocity and time stamp of the event
657 */
658 void Engine::ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
659 #if !CONFIG_PROCESS_MUTED_CHANNELS
660 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
661 #endif
662
663 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itNoteOffEvent->Param.Note.Key];
664 pKey->KeyPressed = false; // the MIDI key was now released
665
666 // release voices on this key if needed
667 if (pKey->Active && !pEngineChannel->SustainPedal) {
668 itNoteOffEvent->Type = Event::type_release; // transform event type
669
670 // move event to the key's own event list
671 RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
672
673 // spawn release triggered voice(s) if needed
674 if (pKey->ReleaseTrigger) {
675 // first, get total amount of required voices (dependant on amount of layers)
676 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
677 if (pRegion) {
678 int voicesRequired = pRegion->Layers;
679
680 // MIDI note-on velocity is used instead of note-off velocity
681 itNoteOffEventOnKeyList->Param.Note.Velocity = pKey->Velocity;
682
683 // now launch the required amount of voices
684 for (int i = 0; i < voicesRequired; i++)
685 LaunchVoice(pEngineChannel, itNoteOffEventOnKeyList, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples
686 }
687 pKey->ReleaseTrigger = false;
688 }
689
690 // if neither a voice was spawned or postponed then remove note off event from key again
691 if (!pKey->Active && !pKey->VoiceTheftsQueued)
692 pKey->pEvents->free(itNoteOffEventOnKeyList);
693 }
694 }
695
696 /**
697 * Moves pitchbend event from the general (input) event list to the engine
698 * channel's event list. It will actually processed later by the
699 * respective voice.
700 *
701 * @param pEngineChannel - engine channel on which this event occured on
702 * @param itPitchbendEvent - absolute pitch value and time stamp of the event
703 */
704 void Engine::ProcessPitchbend(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
705 pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
706 itPitchbendEvent.moveToEndOf(pEngineChannel->pEvents);
707 }
708
709 /**
710 * Allocates and triggers a new voice. This method will usually be
711 * called by the ProcessNoteOn() method and by the voices itself
712 * (e.g. to spawn further voices on the same key for layered sounds).
713 *
714 * @param pEngineChannel - engine channel on which this event occured on
715 * @param itNoteOnEvent - key, velocity and time stamp of the event
716 * @param iLayer - layer index for the new voice (optional - only
717 * in case of layered sounds of course)
718 * @param ReleaseTriggerVoice - if new voice is a release triggered voice
719 * (optional, default = false)
720 * @param VoiceStealing - if voice stealing should be performed
721 * when there is no free voice
722 * (optional, default = true)
723 * @param HandleKeyGroupConflicts - if voices should be killed due to a
724 * key group conflict
725 * @returns pointer to new voice or NULL if there was no free voice or
726 * if the voice wasn't triggered (for example when no region is
727 * defined for the given key).
728 */
729 Pool<Voice>::Iterator Engine::LaunchVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing, bool HandleKeyGroupConflicts) {
730 int MIDIKey = itNoteOnEvent->Param.Note.Key;
731 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[MIDIKey];
732 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(MIDIKey);
733
734 // if nothing defined for this key
735 if (!pRegion) return Pool<Voice>::Iterator(); // nothing to do
736
737 // only mark the first voice of a layered voice (group) to be in a
738 // key group, so the layered voices won't kill each other
739 int iKeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0;
740
741 // handle key group (a.k.a. exclusive group) conflicts
742 if (HandleKeyGroupConflicts) {
743 if (iKeyGroup) { // if this voice / key belongs to a key group
744 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[iKeyGroup];
745 if (*ppKeyGroup) { // if there's already an active key in that key group
746 midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[**ppKeyGroup];
747 // kill all voices on the (other) key
748 RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
749 RTList<Voice>::Iterator end = pOtherKey->pActiveVoices->end();
750 for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
751 if (itVoiceToBeKilled->Type != Voice::type_release_trigger) {
752 itVoiceToBeKilled->Kill(itNoteOnEvent);
753 --VoiceSpawnsLeft; //FIXME: just a hack, we should better check in StealVoice() if the voice was killed due to key conflict
754 }
755 }
756 }
757 }
758 }
759
760 Voice::type_t VoiceType = Voice::type_normal;
761
762 // get current dimension values to select the right dimension region
763 //TODO: for stolen voices this dimension region selection block is processed twice, this should be changed
764 //FIXME: controller values for selecting the dimension region here are currently not sample accurate
765 uint DimValues[8] = { 0 };
766 for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
767 switch (pRegion->pDimensionDefinitions[i].dimension) {
768 case ::gig::dimension_samplechannel:
769 DimValues[i] = 0; //TODO: we currently ignore this dimension
770 break;
771 case ::gig::dimension_layer:
772 DimValues[i] = iLayer;
773 break;
774 case ::gig::dimension_velocity:
775 DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
776 break;
777 case ::gig::dimension_channelaftertouch:
778 DimValues[i] = 0; //TODO: we currently ignore this dimension
779 break;
780 case ::gig::dimension_releasetrigger:
781 VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal;
782 DimValues[i] = (uint) ReleaseTriggerVoice;
783 break;
784 case ::gig::dimension_keyboard:
785 DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension;
786 break;
787 case ::gig::dimension_roundrobin:
788 DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
789 break;
790 case ::gig::dimension_random:
791 RandomSeed = RandomSeed * 1103515245 + 12345; // classic pseudo random number generator
792 DimValues[i] = (uint) RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random
793 break;
794 case ::gig::dimension_modwheel:
795 DimValues[i] = pEngineChannel->ControllerTable[1];
796 break;
797 case ::gig::dimension_breath:
798 DimValues[i] = pEngineChannel->ControllerTable[2];
799 break;
800 case ::gig::dimension_foot:
801 DimValues[i] = pEngineChannel->ControllerTable[4];
802 break;
803 case ::gig::dimension_portamentotime:
804 DimValues[i] = pEngineChannel->ControllerTable[5];
805 break;
806 case ::gig::dimension_effect1:
807 DimValues[i] = pEngineChannel->ControllerTable[12];
808 break;
809 case ::gig::dimension_effect2:
810 DimValues[i] = pEngineChannel->ControllerTable[13];
811 break;
812 case ::gig::dimension_genpurpose1:
813 DimValues[i] = pEngineChannel->ControllerTable[16];
814 break;
815 case ::gig::dimension_genpurpose2:
816 DimValues[i] = pEngineChannel->ControllerTable[17];
817 break;
818 case ::gig::dimension_genpurpose3:
819 DimValues[i] = pEngineChannel->ControllerTable[18];
820 break;
821 case ::gig::dimension_genpurpose4:
822 DimValues[i] = pEngineChannel->ControllerTable[19];
823 break;
824 case ::gig::dimension_sustainpedal:
825 DimValues[i] = pEngineChannel->ControllerTable[64];
826 break;
827 case ::gig::dimension_portamento:
828 DimValues[i] = pEngineChannel->ControllerTable[65];
829 break;
830 case ::gig::dimension_sostenutopedal:
831 DimValues[i] = pEngineChannel->ControllerTable[66];
832 break;
833 case ::gig::dimension_softpedal:
834 DimValues[i] = pEngineChannel->ControllerTable[67];
835 break;
836 case ::gig::dimension_genpurpose5:
837 DimValues[i] = pEngineChannel->ControllerTable[80];
838 break;
839 case ::gig::dimension_genpurpose6:
840 DimValues[i] = pEngineChannel->ControllerTable[81];
841 break;
842 case ::gig::dimension_genpurpose7:
843 DimValues[i] = pEngineChannel->ControllerTable[82];
844 break;
845 case ::gig::dimension_genpurpose8:
846 DimValues[i] = pEngineChannel->ControllerTable[83];
847 break;
848 case ::gig::dimension_effect1depth:
849 DimValues[i] = pEngineChannel->ControllerTable[91];
850 break;
851 case ::gig::dimension_effect2depth:
852 DimValues[i] = pEngineChannel->ControllerTable[92];
853 break;
854 case ::gig::dimension_effect3depth:
855 DimValues[i] = pEngineChannel->ControllerTable[93];
856 break;
857 case ::gig::dimension_effect4depth:
858 DimValues[i] = pEngineChannel->ControllerTable[94];
859 break;
860 case ::gig::dimension_effect5depth:
861 DimValues[i] = pEngineChannel->ControllerTable[95];
862 break;
863 case ::gig::dimension_none:
864 std::cerr << "gig::Engine::LaunchVoice() Error: dimension=none\n" << std::flush;
865 break;
866 default:
867 std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;
868 }
869 }
870 ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
871
872 // no need to continue if sample is silent
873 if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator();
874
875 // allocate a new voice for the key
876 Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();
877 if (itNewVoice) {
878 // launch the new voice
879 if (itNewVoice->Trigger(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pDimRgn, VoiceType, iKeyGroup) < 0) {
880 dmsg(4,("Voice not triggered\n"));
881 pKey->pActiveVoices->free(itNewVoice);
882 }
883 else { // on success
884 --VoiceSpawnsLeft;
885 if (!pKey->Active) { // mark as active key
886 pKey->Active = true;
887 pKey->itSelf = pEngineChannel->pActiveKeys->allocAppend();
888 *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
889 }
890 if (itNewVoice->KeyGroup) {
891 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[itNewVoice->KeyGroup];
892 *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group
893 }
894 if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
895 return itNewVoice; // success
896 }
897 }
898 else if (VoiceStealing) {
899 // try to steal one voice
900 int result = StealVoice(pEngineChannel, itNoteOnEvent);
901 if (!result) { // voice stolen successfully
902 // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
903 RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
904 if (itStealEvent) {
905 *itStealEvent = *itNoteOnEvent; // copy event
906 itStealEvent->Param.Note.Layer = iLayer;
907 itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
908 pKey->VoiceTheftsQueued++;
909 }
910 else dmsg(1,("Voice stealing queue full!\n"));
911 }
912 }
913
914 return Pool<Voice>::Iterator(); // no free voice or error
915 }
916
917 /**
918 * Will be called by LaunchVoice() method in case there are no free
919 * voices left. This method will select and kill one old voice for
920 * voice stealing and postpone the note-on event until the selected
921 * voice actually died.
922 *
923 * @param pEngineChannel - engine channel on which this event occured on
924 * @param itNoteOnEvent - key, velocity and time stamp of the event
925 * @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
926 */
927 int Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
928 if (VoiceSpawnsLeft <= 0) {
929 dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
930 return -1;
931 }
932 if (!pEventPool->poolIsEmpty()) {
933
934 RTList<Voice>::Iterator itSelectedVoice;
935
936 // Select one voice for voice stealing
937 switch (CONFIG_VOICE_STEAL_ALGO) {
938
939 // try to pick the oldest voice on the key where the new
940 // voice should be spawned, if there is no voice on that
941 // key, or no voice left to kill, then procceed with
942 // 'oldestkey' algorithm
943 case voice_steal_algo_oldestvoiceonkey: {
944 midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
945 itSelectedVoice = pSelectedKey->pActiveVoices->first();
946 // proceed iterating if voice was created in this fragment cycle
947 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
948 // if we haven't found a voice then proceed with algorithm 'oldestkey'
949 if (itSelectedVoice && itSelectedVoice->IsStealable()) break;
950 } // no break - intentional !
951
952 // try to pick the oldest voice on the oldest active key
953 // from the same engine channel
954 // (caution: must stay after 'oldestvoiceonkey' algorithm !)
955 case voice_steal_algo_oldestkey: {
956 // if we already stole in this fragment, try to proceed on same key
957 if (this->itLastStolenVoice) {
958 itSelectedVoice = this->itLastStolenVoice;
959 do {
960 ++itSelectedVoice;
961 } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
962 // found a "stealable" voice ?
963 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
964 // remember which voice we stole, so we can simply proceed on next voice stealing
965 this->itLastStolenVoice = itSelectedVoice;
966 break; // selection succeeded
967 }
968 }
969 // get (next) oldest key
970 RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKey) ? ++this->iuiLastStolenKey : pEngineChannel->pActiveKeys->first();
971 while (iuiSelectedKey) {
972 midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];
973 itSelectedVoice = pSelectedKey->pActiveVoices->first();
974 // proceed iterating if voice was created in this fragment cycle
975 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
976 // found a "stealable" voice ?
977 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
978 // remember which voice on which key we stole, so we can simply proceed on next voice stealing
979 this->iuiLastStolenKey = iuiSelectedKey;
980 this->itLastStolenVoice = itSelectedVoice;
981 break; // selection succeeded
982 }
983 ++iuiSelectedKey; // get next oldest key
984 }
985 break;
986 }
987
988 // don't steal anything
989 case voice_steal_algo_none:
990 default: {
991 dmsg(1,("No free voice (voice stealing disabled)!\n"));
992 return -1;
993 }
994 }
995
996 // if we couldn't steal a voice from the same engine channel then
997 // steal oldest voice on the oldest key from any other engine channel
998 // (the smaller engine channel number, the higher priority)
999 if (!itSelectedVoice || !itSelectedVoice->IsStealable()) {
1000 EngineChannel* pSelectedChannel;
1001 int iChannelIndex;
1002 // select engine channel
1003 if (pLastStolenChannel) {
1004 pSelectedChannel = pLastStolenChannel;
1005 iChannelIndex = pSelectedChannel->iEngineIndexSelf;
1006 } else { // pick the engine channel followed by this engine channel
1007 iChannelIndex = (pEngineChannel->iEngineIndexSelf + 1) % engineChannels.size();
1008 pSelectedChannel = engineChannels[iChannelIndex];
1009 }
1010
1011 // if we already stole in this fragment, try to proceed on same key
1012 if (this->itLastStolenVoiceGlobally) {
1013 itSelectedVoice = this->itLastStolenVoiceGlobally;
1014 do {
1015 ++itSelectedVoice;
1016 } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1017 }
1018
1019 #if CONFIG_DEVMODE
1020 EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1021 #endif // CONFIG_DEVMODE
1022
1023 // did we find a 'stealable' voice?
1024 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1025 // remember which voice we stole, so we can simply proceed on next voice stealing
1026 this->itLastStolenVoiceGlobally = itSelectedVoice;
1027 } else while (true) { // iterate through engine channels
1028 // get (next) oldest key
1029 RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
1030 this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
1031 while (iuiSelectedKey) {
1032 midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1033 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1034 // proceed iterating if voice was created in this fragment cycle
1035 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1036 // found a "stealable" voice ?
1037 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1038 // remember which voice on which key on which engine channel we stole, so we can simply proceed on next voice stealing
1039 this->iuiLastStolenKeyGlobally = iuiSelectedKey;
1040 this->itLastStolenVoiceGlobally = itSelectedVoice;
1041 this->pLastStolenChannel = pSelectedChannel;
1042 goto stealable_voice_found; // selection succeeded
1043 }
1044 ++iuiSelectedKey; // get next key on current engine channel
1045 }
1046 // get next engine channel
1047 iChannelIndex = (iChannelIndex + 1) % engineChannels.size();
1048 pSelectedChannel = engineChannels[iChannelIndex];
1049
1050 #if CONFIG_DEVMODE
1051 if (pSelectedChannel == pBegin) {
1052 dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1053 dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1054 dmsg(1,("Exiting.\n"));
1055 exit(-1);
1056 }
1057 #endif // CONFIG_DEVMODE
1058 }
1059 }
1060
1061 // jump point if a 'stealable' voice was found
1062 stealable_voice_found:
1063
1064 #if CONFIG_DEVMODE
1065 if (!itSelectedVoice->IsActive()) {
1066 dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
1067 return -1;
1068 }
1069 #endif // CONFIG_DEVMODE
1070
1071 // now kill the selected voice
1072 itSelectedVoice->Kill(itNoteOnEvent);
1073
1074 --VoiceSpawnsLeft;
1075
1076 return 0; // success
1077 }
1078 else {
1079 dmsg(1,("Event pool emtpy!\n"));
1080 return -1;
1081 }
1082 }
1083
1084 /**
1085 * Removes the given voice from the MIDI key's list of active voices.
1086 * This method will be called when a voice went inactive, e.g. because
1087 * it finished to playback its sample, finished its release stage or
1088 * just was killed.
1089 *
1090 * @param pEngineChannel - engine channel on which this event occured on
1091 * @param itVoice - points to the voice to be freed
1092 */
1093 void Engine::FreeVoice(EngineChannel* pEngineChannel, Pool<Voice>::Iterator& itVoice) {
1094 if (itVoice) {
1095 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoice->MIDIKey];
1096
1097 uint keygroup = itVoice->KeyGroup;
1098
1099 // free the voice object
1100 pVoicePool->free(itVoice);
1101
1102 // if no other voices left and member of a key group, remove from key group
1103 if (pKey->pActiveVoices->isEmpty() && keygroup) {
1104 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[keygroup];
1105 if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group
1106 }
1107 }
1108 else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;
1109 }
1110
1111 /**
1112 * Called when there's no more voice left on a key, this call will
1113 * update the key info respectively.
1114 *
1115 * @param pEngineChannel - engine channel on which this event occured on
1116 * @param pKey - key which is now inactive
1117 */
1118 void Engine::FreeKey(EngineChannel* pEngineChannel, midi_key_info_t* pKey) {
1119 if (pKey->pActiveVoices->isEmpty()) {
1120 pKey->Active = false;
1121 pEngineChannel->pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
1122 pKey->itSelf = RTList<uint>::Iterator();
1123 pKey->ReleaseTrigger = false;
1124 pKey->pEvents->clear();
1125 dmsg(3,("Key has no more voices now\n"));
1126 }
1127 else dmsg(1,("gig::Engine: Oops, tried to free a key which contains voices.\n"));
1128 }
1129
1130 /**
1131 * Reacts on supported control change commands (e.g. pitch bend wheel,
1132 * modulation wheel, aftertouch).
1133 *
1134 * @param pEngineChannel - engine channel on which this event occured on
1135 * @param itControlChangeEvent - controller, value and time stamp of the event
1136 */
1137 void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {
1138 dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));
1139
1140 // update controller value in the engine channel's controller table
1141 pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1142
1143 // move event from the import event list to the engine channel's CC and pitchbend event list
1144 Pool<Event>::Iterator itControlChangeEventOnCCList = itControlChangeEvent.moveToEndOf(pEngineChannel->pEvents);
1145
1146 switch (itControlChangeEventOnCCList->Param.CC.Controller) {
1147 case 7: { // volume
1148 //TODO: not sample accurate yet
1149 pEngineChannel->GlobalVolume = (float) itControlChangeEventOnCCList->Param.CC.Value / 127.0f;
1150 pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1151 break;
1152 }
1153 case 10: { // panpot
1154 //TODO: not sample accurate yet
1155 const int pan = (int) itControlChangeEventOnCCList->Param.CC.Value - 64;
1156 pEngineChannel->GlobalPanLeft = 1.0f - float(RTMath::Max(pan, 0)) / 63.0f;
1157 pEngineChannel->GlobalPanRight = 1.0f - float(RTMath::Min(pan, 0)) / -64.0f;
1158 break;
1159 }
1160 case 64: { // sustain
1161 if (itControlChangeEventOnCCList->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1162 dmsg(4,("PEDAL DOWN\n"));
1163 pEngineChannel->SustainPedal = true;
1164
1165 #if !CONFIG_PROCESS_MUTED_CHANNELS
1166 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1167 #endif
1168
1169 // cancel release process of voices if necessary
1170 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1171 for (; iuiKey; ++iuiKey) {
1172 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1173 if (!pKey->KeyPressed) {
1174 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1175 if (itNewEvent) {
1176 *itNewEvent = *itControlChangeEventOnCCList; // copy event to the key's own event list
1177 itNewEvent->Type = Event::type_cancel_release; // transform event type
1178 }
1179 else dmsg(1,("Event pool emtpy!\n"));
1180 }
1181 }
1182 }
1183 if (itControlChangeEventOnCCList->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1184 dmsg(4,("PEDAL UP\n"));
1185 pEngineChannel->SustainPedal = false;
1186
1187 #if !CONFIG_PROCESS_MUTED_CHANNELS
1188 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1189 #endif
1190
1191 // release voices if their respective key is not pressed
1192 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1193 for (; iuiKey; ++iuiKey) {
1194 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1195 if (!pKey->KeyPressed) {
1196 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1197 if (itNewEvent) {
1198 *itNewEvent = *itControlChangeEventOnCCList; // copy event to the key's own event list
1199 itNewEvent->Type = Event::type_release; // transform event type
1200 }
1201 else dmsg(1,("Event pool emtpy!\n"));
1202 }
1203 }
1204 }
1205 break;
1206 }
1207
1208
1209 // Channel Mode Messages
1210
1211 case 120: { // all sound off
1212 KillAllVoices(pEngineChannel, itControlChangeEventOnCCList);
1213 break;
1214 }
1215 case 121: { // reset all controllers
1216 pEngineChannel->ResetControllers();
1217 break;
1218 }
1219 case 123: { // all notes off
1220 ReleaseAllVoices(pEngineChannel, itControlChangeEventOnCCList);
1221 break;
1222 }
1223 }
1224 }
1225
1226 /**
1227 * Reacts on MIDI system exclusive messages.
1228 *
1229 * @param itSysexEvent - sysex data size and time stamp of the sysex event
1230 */
1231 void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1232 RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1233
1234 uint8_t exclusive_status, id;
1235 if (!reader.pop(&exclusive_status)) goto free_sysex_data;
1236 if (!reader.pop(&id)) goto free_sysex_data;
1237 if (exclusive_status != 0xF0) goto free_sysex_data;
1238
1239 switch (id) {
1240 case 0x41: { // Roland
1241 dmsg(3,("Roland Sysex\n"));
1242 uint8_t device_id, model_id, cmd_id;
1243 if (!reader.pop(&device_id)) goto free_sysex_data;
1244 if (!reader.pop(&model_id)) goto free_sysex_data;
1245 if (!reader.pop(&cmd_id)) goto free_sysex_data;
1246 if (model_id != 0x42 /*GS*/) goto free_sysex_data;
1247 if (cmd_id != 0x12 /*DT1*/) goto free_sysex_data;
1248
1249 // command address
1250 uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
1251 const RingBuffer<uint8_t>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
1252 if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1253 if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1254 dmsg(3,("\tSystem Parameter\n"));
1255 }
1256 else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
1257 dmsg(3,("\tCommon Parameter\n"));
1258 }
1259 else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
1260 dmsg(3,("\tPart Parameter\n"));
1261 switch (addr[2]) {
1262 case 0x40: { // scale tuning
1263 dmsg(3,("\t\tScale Tuning\n"));
1264 uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
1265 if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
1266 uint8_t checksum;
1267 if (!reader.pop(&checksum)) goto free_sysex_data;
1268 #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1269 if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
1270 #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1271 for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
1272 AdjustScale((int8_t*) scale_tunes);
1273 dmsg(3,("\t\t\tNew scale applied.\n"));
1274 break;
1275 }
1276 }
1277 }
1278 else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
1279 }
1280 else if (addr[0] == 0x41) { // Drum Setup Parameters
1281 }
1282 break;
1283 }
1284 }
1285
1286 free_sysex_data: // finally free sysex data
1287 pSysexBuffer->increment_read_ptr(itSysexEvent->Param.Sysex.Size);
1288 }
1289
1290 /**
1291 * Calculates the Roland GS sysex check sum.
1292 *
1293 * @param AddrReader - reader which currently points to the first GS
1294 * command address byte of the GS sysex message in
1295 * question
1296 * @param DataSize - size of the GS message data (in bytes)
1297 */
1298 uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t>::NonVolatileReader AddrReader, uint DataSize) {
1299 RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;
1300 uint bytes = 3 /*addr*/ + DataSize;
1301 uint8_t addr_and_data[bytes];
1302 reader.read(&addr_and_data[0], bytes);
1303 uint8_t sum = 0;
1304 for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];
1305 return 128 - sum % 128;
1306 }
1307
1308 /**
1309 * Allows to tune each of the twelve semitones of an octave.
1310 *
1311 * @param ScaleTunes - detuning of all twelve semitones (in cents)
1312 */
1313 void Engine::AdjustScale(int8_t ScaleTunes[12]) {
1314 memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate
1315 }
1316
1317 /**
1318 * Releases all voices on an engine channel. All voices will go into
1319 * the release stage and thus it might take some time (e.g. dependant to
1320 * their envelope release time) until they actually die.
1321 *
1322 * @param pEngineChannel - engine channel on which all voices should be released
1323 * @param itReleaseEvent - event which caused this releasing of all voices
1324 */
1325 void Engine::ReleaseAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itReleaseEvent) {
1326 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1327 while (iuiKey) {
1328 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1329 ++iuiKey;
1330 // append a 'release' event to the key's own event list
1331 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1332 if (itNewEvent) {
1333 *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
1334 itNewEvent->Type = Event::type_release; // transform event type
1335 }
1336 else dmsg(1,("Event pool emtpy!\n"));
1337 }
1338 }
1339
1340 /**
1341 * Kills all voices on an engine channel as soon as possible. Voices
1342 * won't get into release state, their volume level will be ramped down
1343 * as fast as possible.
1344 *
1345 * @param pEngineChannel - engine channel on which all voices should be killed
1346 * @param itKillEvent - event which caused this killing of all voices
1347 */
1348 void Engine::KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
1349 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1350 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
1351 while (iuiKey != end) { // iterate through all active keys
1352 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1353 ++iuiKey;
1354 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
1355 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
1356 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
1357 itVoice->Kill(itKillEvent);
1358 --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
1359 }
1360 }
1361 }
1362
1363 uint Engine::VoiceCount() {
1364 return ActiveVoiceCount;
1365 }
1366
1367 uint Engine::VoiceCountMax() {
1368 return ActiveVoiceCountMax;
1369 }
1370
1371 bool Engine::DiskStreamSupported() {
1372 return true;
1373 }
1374
1375 uint Engine::DiskStreamCount() {
1376 return (pDiskThread) ? pDiskThread->ActiveStreamCount : 0;
1377 }
1378
1379 uint Engine::DiskStreamCountMax() {
1380 return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0;
1381 }
1382
1383 String Engine::DiskStreamBufferFillBytes() {
1384 return pDiskThread->GetBufferFillBytes();
1385 }
1386
1387 String Engine::DiskStreamBufferFillPercentage() {
1388 return pDiskThread->GetBufferFillPercentage();
1389 }
1390
1391 String Engine::EngineName() {
1392 return LS_GIG_ENGINE_NAME;
1393 }
1394
1395 String Engine::Description() {
1396 return "Gigasampler Engine";
1397 }
1398
1399 String Engine::Version() {
1400 String s = "$Revision: 1.52 $";
1401 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
1402 }
1403
1404 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC