/[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 460 - (show annotations) (download)
Mon Mar 14 22:35:44 2005 UTC (19 years ago) by schoenebeck
File size: 48605 byte(s)
* spawning layered voices now within a loop instead of recursively (fixes
  segmentation fault under heavy voice count load and reduces stress on the
  stack)
* voice stealing operates on all engine channels now
* limit voice stealing to MAX_AUDIO_VOICES thefts per audio fragment cycle
* fixed keygroup handling (layered voices could kill each other)

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 #if defined(__APPLE__)
33 # include <stdlib.h>
34 #else
35 # include <malloc.h>
36 #endif
37
38 namespace LinuxSampler { namespace gig {
39
40 InstrumentResourceManager Engine::instruments;
41
42 std::map<AudioOutputDevice*,Engine*> Engine::engines;
43
44 /**
45 * Get a gig::Engine object for the given gig::EngineChannel and the
46 * given AudioOutputDevice. All engine channels which are connected to
47 * the same audio output device will use the same engine instance. This
48 * method will be called by a gig::EngineChannel whenever it's
49 * connecting to a audio output device.
50 *
51 * @param pChannel - engine channel which acquires an engine object
52 * @param pDevice - the audio output device \a pChannel is connected to
53 */
54 Engine* Engine::AcquireEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
55 Engine* pEngine = NULL;
56 // check if there's already an engine for the given audio output device
57 if (engines.count(pDevice)) {
58 dmsg(4,("Using existing gig::Engine.\n"));
59 pEngine = engines[pDevice];
60 } else { // create a new engine (and disk thread) instance for the given audio output device
61 dmsg(4,("Creating new gig::Engine.\n"));
62 pEngine = (Engine*) EngineFactory::Create("gig");
63 pEngine->Connect(pDevice);
64 engines[pDevice] = pEngine;
65 }
66 // register engine channel to the engine instance
67 pEngine->engineChannels.add(pChannel);
68 // remember index in the ArrayList
69 pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
70 dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
71 return pEngine;
72 }
73
74 /**
75 * Once an engine channel is disconnected from an audio output device,
76 * it wil immediately call this method to unregister itself from the
77 * engine instance and if that engine instance is not used by any other
78 * engine channel anymore, then that engine instance will be destroyed.
79 *
80 * @param pChannel - engine channel which wants to disconnect from it's
81 * engine instance
82 * @param pDevice - audio output device \a pChannel was connected to
83 */
84 void Engine::FreeEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
85 dmsg(4,("Disconnecting EngineChannel from gig::Engine.\n"));
86 Engine* pEngine = engines[pDevice];
87 // unregister EngineChannel from the Engine instance
88 pEngine->engineChannels.remove(pChannel);
89 // if the used Engine instance is not used anymore, then destroy it
90 if (pEngine->engineChannels.empty()) {
91 pDevice->Disconnect(pEngine);
92 engines.erase(pDevice);
93 delete pEngine;
94 dmsg(4,("Destroying gig::Engine.\n"));
95 }
96 else dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
97 }
98
99 Engine::Engine() {
100 pAudioOutputDevice = NULL;
101 pDiskThread = NULL;
102 pEventGenerator = NULL;
103 pSysexBuffer = new RingBuffer<uint8_t>(SYSEX_BUFFER_SIZE, 0);
104 pEventQueue = new RingBuffer<Event>(MAX_EVENTS_PER_FRAGMENT, 0);
105 pEventPool = new Pool<Event>(MAX_EVENTS_PER_FRAGMENT);
106 pVoicePool = new Pool<Voice>(MAX_AUDIO_VOICES);
107 pVoiceStealingQueue = new RTList<Event>(pEventPool);
108 pGlobalEvents = new RTList<Event>(pEventPool);
109 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
110 iterVoice->SetEngine(this);
111 }
112 pVoicePool->clear();
113
114 pSynthesisParameters[0] = NULL; // we allocate when an audio device is connected
115 pBasicFilterParameters = NULL;
116 pMainFilterParameters = NULL;
117
118 ResetInternal();
119 }
120
121 Engine::~Engine() {
122 if (pDiskThread) {
123 dmsg(1,("Stopping disk thread..."));
124 pDiskThread->StopThread();
125 delete pDiskThread;
126 dmsg(1,("OK\n"));
127 }
128 if (pEventQueue) delete pEventQueue;
129 if (pEventPool) delete pEventPool;
130 if (pVoicePool) {
131 pVoicePool->clear();
132 delete pVoicePool;
133 }
134 if (pEventGenerator) delete pEventGenerator;
135 if (pMainFilterParameters) delete[] pMainFilterParameters;
136 if (pBasicFilterParameters) delete[] pBasicFilterParameters;
137 if (pSynthesisParameters[0]) free(pSynthesisParameters[0]);
138 if (pVoiceStealingQueue) delete pVoiceStealingQueue;
139 if (pSysexBuffer) delete pSysexBuffer;
140 EngineFactory::Destroy(this);
141 }
142
143 void Engine::Enable() {
144 dmsg(3,("gig::Engine: enabling\n"));
145 EngineDisabled.PushAndUnlock(false, 2); // set condition object 'EngineDisabled' to false (wait max. 2s)
146 dmsg(3,("gig::Engine: enabled (val=%d)\n", EngineDisabled.GetUnsafe()));
147 }
148
149 void Engine::Disable() {
150 dmsg(3,("gig::Engine: disabling\n"));
151 bool* pWasDisabled = EngineDisabled.PushAndUnlock(true, 2); // wait max. 2s
152 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
153 }
154
155 void Engine::DisableAndLock() {
156 dmsg(3,("gig::Engine: disabling\n"));
157 bool* pWasDisabled = EngineDisabled.Push(true, 2); // wait max. 2s
158 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
159 }
160
161 /**
162 * Reset all voices and disk thread and clear input event queue and all
163 * control and status variables.
164 */
165 void Engine::Reset() {
166 DisableAndLock();
167 ResetInternal();
168 Enable();
169 }
170
171 /**
172 * Reset all voices and disk thread and clear input event queue and all
173 * control and status variables. This method is not thread safe!
174 */
175 void Engine::ResetInternal() {
176 ActiveVoiceCount = 0;
177 ActiveVoiceCountMax = 0;
178
179 // reset voice stealing parameters
180 pVoiceStealingQueue->clear();
181 itLastStolenVoice = RTList<Voice>::Iterator();
182 iuiLastStolenKey = RTList<uint>::Iterator();
183 pLastStolenChannel = NULL;
184
185 // reset to normal chromatic scale (means equal temper)
186 memset(&ScaleTuning[0], 0x00, 12);
187
188 // reset all voices
189 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
190 iterVoice->Reset();
191 }
192 pVoicePool->clear();
193
194 // reset disk thread
195 if (pDiskThread) pDiskThread->Reset();
196
197 // delete all input events
198 pEventQueue->init();
199 }
200
201 void Engine::Connect(AudioOutputDevice* pAudioOut) {
202 pAudioOutputDevice = pAudioOut;
203
204 ResetInternal();
205
206 // inform audio driver for the need of two channels
207 try {
208 pAudioOutputDevice->AcquireChannels(2); // gig engine only stereo
209 }
210 catch (AudioOutputException e) {
211 String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
212 throw LinuxSamplerException(msg);
213 }
214
215 this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
216 this->SampleRate = pAudioOutputDevice->SampleRate();
217
218 // FIXME: audio drivers with varying fragment sizes might be a problem here
219 MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * EG_MIN_RELEASE_TIME) - 1;
220 if (MaxFadeOutPos < 0)
221 throw LinuxSamplerException("EG_MIN_RELEASE_TIME in EGADSR.h too big for current audio fragment size / sampling rate!");
222
223 // (re)create disk thread
224 if (this->pDiskThread) {
225 dmsg(1,("Stopping disk thread..."));
226 this->pDiskThread->StopThread();
227 delete this->pDiskThread;
228 dmsg(1,("OK\n"));
229 }
230 this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << MAX_PITCH) << 1) + 6); //FIXME: assuming stereo
231 if (!pDiskThread) {
232 dmsg(0,("gig::Engine new diskthread = NULL\n"));
233 exit(EXIT_FAILURE);
234 }
235
236 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
237 iterVoice->pDiskThread = this->pDiskThread;
238 dmsg(3,("d"));
239 }
240 pVoicePool->clear();
241
242 // (re)create event generator
243 if (pEventGenerator) delete pEventGenerator;
244 pEventGenerator = new EventGenerator(pAudioOut->SampleRate());
245
246 // (re)allocate synthesis parameter matrix
247 if (pSynthesisParameters[0]) free(pSynthesisParameters[0]);
248
249 #if defined(__APPLE__)
250 pSynthesisParameters[0] = (float *) malloc(Event::destination_count * sizeof(float) * pAudioOut->MaxSamplesPerCycle());
251 #else
252 pSynthesisParameters[0] = (float *) memalign(16,(Event::destination_count * sizeof(float) * pAudioOut->MaxSamplesPerCycle()));
253 #endif
254 for (int dst = 1; dst < Event::destination_count; dst++)
255 pSynthesisParameters[dst] = pSynthesisParameters[dst - 1] + pAudioOut->MaxSamplesPerCycle();
256
257 // (re)allocate biquad filter parameter sequence
258 if (pBasicFilterParameters) delete[] pBasicFilterParameters;
259 if (pMainFilterParameters) delete[] pMainFilterParameters;
260 pBasicFilterParameters = new biquad_param_t[pAudioOut->MaxSamplesPerCycle()];
261 pMainFilterParameters = new biquad_param_t[pAudioOut->MaxSamplesPerCycle()];
262
263 dmsg(1,("Starting disk thread..."));
264 pDiskThread->StartThread();
265 dmsg(1,("OK\n"));
266
267 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
268 if (!iterVoice->pDiskThread) {
269 dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
270 exit(EXIT_FAILURE);
271 }
272 }
273 }
274
275 void Engine::ClearEventLists() {
276 pGlobalEvents->clear();
277 }
278
279 /**
280 * Copy all events from the engine's global input queue buffer to the
281 * engine's internal event list. This will be done at the beginning of
282 * each audio cycle (that is each RenderAudio() call) to distinguish
283 * all global events which have to be processed in the current audio
284 * cycle. These events are usually just SysEx messages. Every
285 * EngineChannel has it's own input event queue buffer and event list
286 * to handle common events like NoteOn, NoteOff and ControlChange
287 * events.
288 *
289 * @param Samples - number of sample points to be processed in the
290 * current audio cycle
291 */
292 void Engine::ImportEvents(uint Samples) {
293 RingBuffer<Event>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
294 Event* pEvent;
295 while (true) {
296 // get next event from input event queue
297 if (!(pEvent = eventQueueReader.pop())) break;
298 // if younger event reached, ignore that and all subsequent ones for now
299 if (pEvent->FragmentPos() >= Samples) {
300 eventQueueReader--;
301 dmsg(2,("Younger Event, pos=%d ,Samples=%d!\n",pEvent->FragmentPos(),Samples));
302 pEvent->ResetFragmentPos();
303 break;
304 }
305 // copy event to internal event list
306 if (pGlobalEvents->poolIsEmpty()) {
307 dmsg(1,("Event pool emtpy!\n"));
308 break;
309 }
310 *pGlobalEvents->allocAppend() = *pEvent;
311 }
312 eventQueueReader.free(); // free all copied events from input queue
313 }
314
315 /**
316 * Let this engine proceed to render the given amount of sample points. The
317 * calculated audio data of all voices of this engine will be placed into
318 * the engine's audio sum buffer which has to be copied and eventually be
319 * converted to the appropriate value range by the audio output class (e.g.
320 * AlsaIO or JackIO) right after.
321 *
322 * @param Samples - number of sample points to be rendered
323 * @returns 0 on success
324 */
325 int Engine::RenderAudio(uint Samples) {
326 dmsg(5,("RenderAudio(Samples=%d)\n", Samples));
327
328 // return if engine disabled
329 if (EngineDisabled.Pop()) {
330 dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
331 return 0;
332 }
333
334 // update time of start and end of this audio fragment (as events' time stamps relate to this)
335 pEventGenerator->UpdateFragmentTime(Samples);
336
337 // get all events from the engine's global input event queue which belong to the current fragment
338 // (these are usually just SysEx messages)
339 ImportEvents(Samples);
340
341 // process engine global events (these are currently only MIDI System Exclusive messages)
342 {
343 RTList<Event>::Iterator itEvent = pGlobalEvents->first();
344 RTList<Event>::Iterator end = pGlobalEvents->end();
345 for (; itEvent != end; ++itEvent) {
346 switch (itEvent->Type) {
347 case Event::type_sysex:
348 dmsg(5,("Engine: Sysex received\n"));
349 ProcessSysex(itEvent);
350 break;
351 }
352 }
353 }
354
355 // We only allow a maximum of MAX_AUDIO_VOICES voices to be stolen
356 // in each audio fragment. All subsequent request for spawning new
357 // voices in the same audio fragment will be ignored.
358 VoiceTheftsLeft = MAX_AUDIO_VOICES;
359
360 // reset internal voice counter (just for statistic of active voices)
361 ActiveVoiceCountTemp = 0;
362
363
364 // render audio on all engine channels
365 for (int i = 0; i < engineChannels.size(); i++) {
366 if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded
367 // handle events on that engine channel
368 ProcessEvents(engineChannels[i], Samples);
369 // render all 'normal', active voices
370 RenderActiveVoices(engineChannels[i], Samples);
371 }
372
373 // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
374 RenderStolenVoices(Samples);
375
376 // handle cleanup on all engine channels for the next audio fragment
377 for (int i = 0; i < engineChannels.size(); i++) {
378 if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded
379 PostProcess(engineChannels[i]);
380 }
381
382
383 // empty the engine's event list for the next audio fragment
384 ClearEventLists();
385
386 // reset voice stealing for the next audio fragment
387 pVoiceStealingQueue->clear();
388 itLastStolenVoice = RTList<Voice>::Iterator();
389 iuiLastStolenKey = RTList<uint>::Iterator();
390 pLastStolenChannel = NULL;
391
392 // just some statistics about this engine instance
393 ActiveVoiceCount = ActiveVoiceCountTemp;
394 if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
395
396 return 0;
397 }
398
399 void Engine::ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
400 // get all events from the engine channels's input event queue which belong to the current fragment
401 // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
402 pEngineChannel->ImportEvents(Samples);
403
404 // process events
405 {
406 RTList<Event>::Iterator itEvent = pEngineChannel->pEvents->first();
407 RTList<Event>::Iterator end = pEngineChannel->pEvents->end();
408 for (; itEvent != end; ++itEvent) {
409 switch (itEvent->Type) {
410 case Event::type_note_on:
411 dmsg(5,("Engine: Note on received\n"));
412 ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
413 break;
414 case Event::type_note_off:
415 dmsg(5,("Engine: Note off received\n"));
416 ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
417 break;
418 case Event::type_control_change:
419 dmsg(5,("Engine: MIDI CC received\n"));
420 ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
421 break;
422 case Event::type_pitchbend:
423 dmsg(5,("Engine: Pitchbend received\n"));
424 ProcessPitchbend((EngineChannel*)itEvent->pEngineChannel, itEvent);
425 break;
426 }
427 }
428 }
429 }
430
431 void Engine::RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
432 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
433 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
434 while (iuiKey != end) { // iterate through all active keys
435 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
436 ++iuiKey;
437
438 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
439 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
440 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
441 // now render current voice
442 itVoice->Render(Samples);
443 if (itVoice->IsActive()) ActiveVoiceCountTemp++; // still active
444 else { // voice reached end, is now inactive
445 FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices
446 }
447 }
448 }
449 }
450
451 void Engine::RenderStolenVoices(uint Samples) {
452 RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
453 RTList<Event>::Iterator end = pVoiceStealingQueue->end();
454 for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
455 EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
456 Pool<Voice>::Iterator itNewVoice =
457 LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false);
458 if (itNewVoice) {
459 itNewVoice->Render(Samples);
460 if (itNewVoice->IsActive()) ActiveVoiceCountTemp++; // still active
461 else { // voice reached end, is now inactive
462 FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices
463 }
464 }
465 else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));
466 }
467 }
468
469 void Engine::PostProcess(EngineChannel* pEngineChannel) {
470 // free all keys which have no active voices left
471 {
472 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
473 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
474 while (iuiKey != end) { // iterate through all active keys
475 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
476 ++iuiKey;
477 if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);
478 #if DEVMODE
479 else { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)
480 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
481 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
482 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
483 if (itVoice->itKillEvent) {
484 dmsg(1,("gig::Engine: ERROR, killed voice survived !!!\n"));
485 }
486 }
487 }
488 #endif // DEVMODE
489 }
490 }
491
492 // empty the engine channel's own event lists
493 pEngineChannel->ClearEventLists();
494 }
495
496 /**
497 * Will be called by the MIDI input device whenever a MIDI system
498 * exclusive message has arrived.
499 *
500 * @param pData - pointer to sysex data
501 * @param Size - lenght of sysex data (in bytes)
502 */
503 void Engine::SendSysex(void* pData, uint Size) {
504 Event event = pEventGenerator->CreateEvent();
505 event.Type = Event::type_sysex;
506 event.Param.Sysex.Size = Size;
507 event.pEngineChannel = NULL; // as Engine global event
508 if (pEventQueue->write_space() > 0) {
509 if (pSysexBuffer->write_space() >= Size) {
510 // copy sysex data to input buffer
511 uint toWrite = Size;
512 uint8_t* pPos = (uint8_t*) pData;
513 while (toWrite) {
514 const uint writeNow = RTMath::Min(toWrite, pSysexBuffer->write_space_to_end());
515 pSysexBuffer->write(pPos, writeNow);
516 toWrite -= writeNow;
517 pPos += writeNow;
518
519 }
520 // finally place sysex event into input event queue
521 pEventQueue->push(&event);
522 }
523 else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,SYSEX_BUFFER_SIZE));
524 }
525 else dmsg(1,("Engine: Input event queue full!"));
526 }
527
528 /**
529 * Assigns and triggers a new voice for the respective MIDI key.
530 *
531 * @param pEngineChannel - engine channel on which this event occured on
532 * @param itNoteOnEvent - key, velocity and time stamp of the event
533 */
534 void Engine::ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
535
536 const int key = itNoteOnEvent->Param.Note.Key;
537
538 // Change key dimension value if key is in keyswitching area
539 {
540 const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
541 if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
542 pEngineChannel->CurrentKeyDimension = ((key - pInstrument->DimensionKeyRange.low) * 128) /
543 (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
544 }
545
546 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
547
548 pKey->KeyPressed = true; // the MIDI key was now pressed down
549
550 // cancel release process of voices on this key if needed
551 if (pKey->Active && !pEngineChannel->SustainPedal) {
552 RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
553 if (itCancelReleaseEvent) {
554 *itCancelReleaseEvent = *itNoteOnEvent; // copy event
555 itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
556 }
557 else dmsg(1,("Event pool emtpy!\n"));
558 }
559
560 // move note on event to the key's own event list
561 RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
562
563 // allocate and trigger new voice(s) for the key
564 {
565 // first, get total amount of required voices (dependant on amount of layers)
566 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOnEventOnKeyList->Param.Note.Key);
567 if (pRegion) {
568 int voicesRequired = pRegion->Layers;
569 // now launch the required amount of voices
570 for (int i = 0; i < voicesRequired; i++)
571 LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true);
572 }
573 }
574
575 pKey->RoundRobinIndex++;
576 }
577
578 /**
579 * Releases the voices on the given key if sustain pedal is not pressed.
580 * If sustain is pressed, the release of the note will be postponed until
581 * sustain pedal will be released or voice turned inactive by itself (e.g.
582 * due to completion of sample playback).
583 *
584 * @param pEngineChannel - engine channel on which this event occured on
585 * @param itNoteOffEvent - key, velocity and time stamp of the event
586 */
587 void Engine::ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
588 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itNoteOffEvent->Param.Note.Key];
589
590 pKey->KeyPressed = false; // the MIDI key was now released
591
592 // release voices on this key if needed
593 if (pKey->Active && !pEngineChannel->SustainPedal) {
594 itNoteOffEvent->Type = Event::type_release; // transform event type
595 }
596
597 // move event to the key's own event list
598 RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
599
600 // spawn release triggered voice(s) if needed
601 if (pKey->ReleaseTrigger) {
602 // first, get total amount of required voices (dependant on amount of layers)
603 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
604 if (pRegion) {
605 int voicesRequired = pRegion->Layers;
606 // now launch the required amount of voices
607 for (int i = 0; i < voicesRequired; i++)
608 LaunchVoice(pEngineChannel, itNoteOffEventOnKeyList, i, true, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples
609 }
610 pKey->ReleaseTrigger = false;
611 }
612 }
613
614 /**
615 * Moves pitchbend event from the general (input) event list to the pitch
616 * event list.
617 *
618 * @param pEngineChannel - engine channel on which this event occured on
619 * @param itPitchbendEvent - absolute pitch value and time stamp of the event
620 */
621 void Engine::ProcessPitchbend(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
622 pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
623 itPitchbendEvent.moveToEndOf(pEngineChannel->pSynthesisEvents[Event::destination_vco]);
624 }
625
626 /**
627 * Allocates and triggers a new voice. This method will usually be
628 * called by the ProcessNoteOn() method and by the voices itself
629 * (e.g. to spawn further voices on the same key for layered sounds).
630 *
631 * @param pEngineChannel - engine channel on which this event occured on
632 * @param itNoteOnEvent - key, velocity and time stamp of the event
633 * @param iLayer - layer index for the new voice (optional - only
634 * in case of layered sounds of course)
635 * @param ReleaseTriggerVoice - if new voice is a release triggered voice
636 * (optional, default = false)
637 * @param VoiceStealing - if voice stealing should be performed
638 * when there is no free voice
639 * (optional, default = true)
640 * @returns pointer to new voice or NULL if there was no free voice or
641 * if the voice wasn't triggered (for example when no region is
642 * defined for the given key).
643 */
644 Pool<Voice>::Iterator Engine::LaunchVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {
645 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
646
647 // allocate a new voice for the key
648 Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();
649 if (itNewVoice) {
650 // launch the new voice
651 if (itNewVoice->Trigger(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pEngineChannel->pInstrument, iLayer, ReleaseTriggerVoice, VoiceStealing) < 0) {
652 dmsg(4,("Voice not triggered\n"));
653 pKey->pActiveVoices->free(itNewVoice);
654 }
655 else { // on success
656 uint** ppKeyGroup = NULL;
657 if (itNewVoice->KeyGroup) { // if this voice / key belongs to a key group
658 ppKeyGroup = &pEngineChannel->ActiveKeyGroups[itNewVoice->KeyGroup];
659 if (*ppKeyGroup) { // if there's already an active key in that key group
660 midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[**ppKeyGroup];
661 // kill all voices on the (other) key
662 RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
663 RTList<Voice>::Iterator end = pOtherKey->pActiveVoices->end();
664 for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
665 if (itVoiceToBeKilled->Type != Voice::type_release_trigger) itVoiceToBeKilled->Kill(itNoteOnEvent);
666 }
667 }
668 }
669 if (!pKey->Active) { // mark as active key
670 pKey->Active = true;
671 pKey->itSelf = pEngineChannel->pActiveKeys->allocAppend();
672 *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
673 }
674 if (itNewVoice->KeyGroup) {
675 *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group
676 }
677 if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
678 return itNewVoice; // success
679 }
680 }
681 else if (VoiceStealing) {
682
683 // try to steal one voice
684 StealVoice(pEngineChannel, itNoteOnEvent);
685
686 // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
687 RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
688 if (itStealEvent) {
689 *itStealEvent = *itNoteOnEvent; // copy event
690 itStealEvent->Param.Note.Layer = iLayer;
691 itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
692 }
693 else dmsg(1,("Voice stealing queue full!\n"));
694 }
695
696 return Pool<Voice>::Iterator(); // no free voice or error
697 }
698
699 /**
700 * Will be called by LaunchVoice() method in case there are no free
701 * voices left. This method will select and kill one old voice for
702 * voice stealing and postpone the note-on event until the selected
703 * voice actually died.
704 *
705 * @param pEngineChannel - engine channel on which this event occured on
706 * @param itNoteOnEvent - key, velocity and time stamp of the event
707 */
708 void Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
709 if (!VoiceTheftsLeft) {
710 dmsg(1,("Max. voice thefts per audio fragment reached (you may raise MAX_AUDIO_VOICES).\n"));
711 return;
712 }
713 if (!pEventPool->poolIsEmpty()) {
714
715 RTList<Voice>::Iterator itSelectedVoice;
716
717 // Select one voice for voice stealing
718 switch (VOICE_STEAL_ALGORITHM) {
719
720 // try to pick the oldest voice on the key where the new
721 // voice should be spawned, if there is no voice on that
722 // key, or no voice left to kill there, then procceed with
723 // 'oldestkey' algorithm
724 case voice_steal_algo_oldestvoiceonkey: {
725 #if 0 // FIXME: broken
726 midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
727 if (this->itLastStolenVoice) {
728 itSelectedVoice = this->itLastStolenVoice;
729 ++itSelectedVoice;
730 }
731 else { // no voice stolen in this audio fragment cycle yet
732 itSelectedVoice = pSelectedKey->pActiveVoices->first();
733 }
734 if (itSelectedVoice) {
735 iuiSelectedKey = pSelectedKey->itSelf;
736 break; // selection succeeded
737 }
738 #endif
739 } // no break - intentional !
740
741 // try to pick the oldest voice on the oldest active key
742 // (caution: must stay after 'oldestvoiceonkey' algorithm !)
743 case voice_steal_algo_oldestkey: {
744 if (this->itLastStolenVoice) {
745 itSelectedVoice = this->itLastStolenVoice;
746 ++itSelectedVoice;
747 if (itSelectedVoice) break; // selection succeeded
748 RTList<uint>::Iterator iuiSelectedKey = this->iuiLastStolenKey;
749 ++iuiSelectedKey;
750 if (iuiSelectedKey) {
751 this->iuiLastStolenKey = iuiSelectedKey;
752 midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];
753 itSelectedVoice = pSelectedKey->pActiveVoices->first();
754 break; // selection succeeded
755 }
756 }
757 break;
758 }
759
760 // don't steal anything
761 case voice_steal_algo_none:
762 default: {
763 dmsg(1,("No free voice (voice stealing disabled)!\n"));
764 return;
765 }
766 }
767
768 // steal oldest voice on the oldest key from this or any other engine channel
769 if (!itSelectedVoice) {
770 EngineChannel* pSelectedChannel = (pLastStolenChannel) ? pLastStolenChannel : pEngineChannel;
771 int iChannelIndex = pSelectedChannel->iEngineIndexSelf;
772 while (true) {
773 RTList<uint>::Iterator iuiSelectedKey = pSelectedChannel->pActiveKeys->first();
774 if (iuiSelectedKey) {
775 midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
776 itSelectedVoice = pSelectedKey->pActiveVoices->first();
777 iuiLastStolenKey = iuiSelectedKey;
778 pLastStolenChannel = pSelectedChannel;
779 break; // selection succeeded
780 }
781 iChannelIndex = (iChannelIndex + 1) % engineChannels.size();
782 pSelectedChannel = engineChannels[iChannelIndex];
783 }
784 }
785
786 //FIXME: can be removed, just a sanity check for debugging
787 if (!itSelectedVoice->IsActive()) dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
788
789 // now kill the selected voice
790 itSelectedVoice->Kill(itNoteOnEvent);
791
792 // remember which voice we stole, so we can simply proceed for the next voice stealing
793 itLastStolenVoice = itSelectedVoice;
794
795 --VoiceTheftsLeft;
796 }
797 else dmsg(1,("Event pool emtpy!\n"));
798 }
799
800 /**
801 * Removes the given voice from the MIDI key's list of active voices.
802 * This method will be called when a voice went inactive, e.g. because
803 * it finished to playback its sample, finished its release stage or
804 * just was killed.
805 *
806 * @param pEngineChannel - engine channel on which this event occured on
807 * @param itVoice - points to the voice to be freed
808 */
809 void Engine::FreeVoice(EngineChannel* pEngineChannel, Pool<Voice>::Iterator& itVoice) {
810 if (itVoice) {
811 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoice->MIDIKey];
812
813 uint keygroup = itVoice->KeyGroup;
814
815 // free the voice object
816 pVoicePool->free(itVoice);
817
818 // if no other voices left and member of a key group, remove from key group
819 if (pKey->pActiveVoices->isEmpty() && keygroup) {
820 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[keygroup];
821 if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group
822 }
823 }
824 else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;
825 }
826
827 /**
828 * Called when there's no more voice left on a key, this call will
829 * update the key info respectively.
830 *
831 * @param pEngineChannel - engine channel on which this event occured on
832 * @param pKey - key which is now inactive
833 */
834 void Engine::FreeKey(EngineChannel* pEngineChannel, midi_key_info_t* pKey) {
835 if (pKey->pActiveVoices->isEmpty()) {
836 pKey->Active = false;
837 pEngineChannel->pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
838 pKey->itSelf = RTList<uint>::Iterator();
839 pKey->ReleaseTrigger = false;
840 pKey->pEvents->clear();
841 dmsg(3,("Key has no more voices now\n"));
842 }
843 else dmsg(1,("gig::Engine: Oops, tried to free a key which contains voices.\n"));
844 }
845
846 /**
847 * Reacts on supported control change commands (e.g. pitch bend wheel,
848 * modulation wheel, aftertouch).
849 *
850 * @param pEngineChannel - engine channel on which this event occured on
851 * @param itControlChangeEvent - controller, value and time stamp of the event
852 */
853 void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {
854 dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));
855
856 switch (itControlChangeEvent->Param.CC.Controller) {
857 case 7: { // volume
858 //TODO: not sample accurate yet
859 pEngineChannel->GlobalVolume = (float) itControlChangeEvent->Param.CC.Value / 127.0f;
860 break;
861 }
862 case 10: { // panpot
863 //TODO: not sample accurate yet
864 const int pan = (int) itControlChangeEvent->Param.CC.Value - 64;
865 pEngineChannel->GlobalPanLeft = 1.0f - float(RTMath::Max(pan, 0)) / 63.0f;
866 pEngineChannel->GlobalPanRight = 1.0f - float(RTMath::Min(pan, 0)) / -64.0f;
867 break;
868 }
869 case 64: { // sustain
870 if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
871 dmsg(4,("PEDAL DOWN\n"));
872 pEngineChannel->SustainPedal = true;
873
874 // cancel release process of voices if necessary
875 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
876 if (iuiKey) {
877 itControlChangeEvent->Type = Event::type_cancel_release; // transform event type
878 while (iuiKey) {
879 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
880 ++iuiKey;
881 if (!pKey->KeyPressed) {
882 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
883 if (itNewEvent) *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
884 else dmsg(1,("Event pool emtpy!\n"));
885 }
886 }
887 }
888 }
889 if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
890 dmsg(4,("PEDAL UP\n"));
891 pEngineChannel->SustainPedal = false;
892
893 // release voices if their respective key is not pressed
894 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
895 if (iuiKey) {
896 itControlChangeEvent->Type = Event::type_release; // transform event type
897 while (iuiKey) {
898 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
899 ++iuiKey;
900 if (!pKey->KeyPressed) {
901 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
902 if (itNewEvent) *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
903 else dmsg(1,("Event pool emtpy!\n"));
904 }
905 }
906 }
907 }
908 break;
909 }
910 }
911
912 // update controller value in the engine's controller table
913 pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
914
915 // move event from the unsorted event list to the control change event list
916 itControlChangeEvent.moveToEndOf(pEngineChannel->pCCEvents);
917 }
918
919 /**
920 * Reacts on MIDI system exclusive messages.
921 *
922 * @param itSysexEvent - sysex data size and time stamp of the sysex event
923 */
924 void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
925 RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
926
927 uint8_t exclusive_status, id;
928 if (!reader.pop(&exclusive_status)) goto free_sysex_data;
929 if (!reader.pop(&id)) goto free_sysex_data;
930 if (exclusive_status != 0xF0) goto free_sysex_data;
931
932 switch (id) {
933 case 0x41: { // Roland
934 uint8_t device_id, model_id, cmd_id;
935 if (!reader.pop(&device_id)) goto free_sysex_data;
936 if (!reader.pop(&model_id)) goto free_sysex_data;
937 if (!reader.pop(&cmd_id)) goto free_sysex_data;
938 if (model_id != 0x42 /*GS*/) goto free_sysex_data;
939 if (cmd_id != 0x12 /*DT1*/) goto free_sysex_data;
940
941 // command address
942 uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
943 const RingBuffer<uint8_t>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
944 if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
945 if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
946 }
947 else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
948 }
949 else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
950 switch (addr[3]) {
951 case 0x40: { // scale tuning
952 uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
953 if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
954 uint8_t checksum;
955 if (!reader.pop(&checksum)) goto free_sysex_data;
956 if (GSCheckSum(checksum_reader, 12) != checksum) goto free_sysex_data;
957 for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
958 AdjustScale((int8_t*) scale_tunes);
959 break;
960 }
961 }
962 }
963 else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
964 }
965 else if (addr[0] == 0x41) { // Drum Setup Parameters
966 }
967 break;
968 }
969 }
970
971 free_sysex_data: // finally free sysex data
972 pSysexBuffer->increment_read_ptr(itSysexEvent->Param.Sysex.Size);
973 }
974
975 /**
976 * Calculates the Roland GS sysex check sum.
977 *
978 * @param AddrReader - reader which currently points to the first GS
979 * command address byte of the GS sysex message in
980 * question
981 * @param DataSize - size of the GS message data (in bytes)
982 */
983 uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t>::NonVolatileReader AddrReader, uint DataSize) {
984 RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;
985 uint bytes = 3 /*addr*/ + DataSize;
986 uint8_t addr_and_data[bytes];
987 reader.read(&addr_and_data[0], bytes);
988 uint8_t sum = 0;
989 for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];
990 return 128 - sum % 128;
991 }
992
993 /**
994 * Allows to tune each of the twelve semitones of an octave.
995 *
996 * @param ScaleTunes - detuning of all twelve semitones (in cents)
997 */
998 void Engine::AdjustScale(int8_t ScaleTunes[12]) {
999 memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate
1000 }
1001
1002 /**
1003 * Initialize the parameter sequence for the modulation destination given by
1004 * by 'dst' with the constant value given by val.
1005 */
1006 void Engine::ResetSynthesisParameters(Event::destination_t dst, float val) {
1007 int maxsamples = pAudioOutputDevice->MaxSamplesPerCycle();
1008 float* m = &pSynthesisParameters[dst][0];
1009 for (int i = 0; i < maxsamples; i += 4) {
1010 m[i] = val;
1011 m[i+1] = val;
1012 m[i+2] = val;
1013 m[i+3] = val;
1014 }
1015 }
1016
1017 uint Engine::VoiceCount() {
1018 return ActiveVoiceCount;
1019 }
1020
1021 uint Engine::VoiceCountMax() {
1022 return ActiveVoiceCountMax;
1023 }
1024
1025 bool Engine::DiskStreamSupported() {
1026 return true;
1027 }
1028
1029 uint Engine::DiskStreamCount() {
1030 return (pDiskThread) ? pDiskThread->ActiveStreamCount : 0;
1031 }
1032
1033 uint Engine::DiskStreamCountMax() {
1034 return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0;
1035 }
1036
1037 String Engine::DiskStreamBufferFillBytes() {
1038 return pDiskThread->GetBufferFillBytes();
1039 }
1040
1041 String Engine::DiskStreamBufferFillPercentage() {
1042 return pDiskThread->GetBufferFillPercentage();
1043 }
1044
1045 String Engine::EngineName() {
1046 return "GigEngine";
1047 }
1048
1049 String Engine::Description() {
1050 return "Gigasampler Engine";
1051 }
1052
1053 String Engine::Version() {
1054 String s = "$Revision: 1.31 $";
1055 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
1056 }
1057
1058 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC