/[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 250 - (show annotations) (download)
Mon Sep 20 00:31:13 2004 UTC (19 years, 6 months ago) by schoenebeck
File size: 46019 byte(s)
* added first two experimental voice stealing algorithms ('oldestkey' -
which just steals the oldest voice on the oldest key and 'keymask' - which
tries to pick the oldest voice on the same key where the new voice should
be spawned, if it fails it behaves like 'oldestkey'), the desired algorithm
can be selected at compile time (see Engine.h) will be configurable via
LSCP soon though

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #include <sstream>
24 #include "DiskThread.h"
25 #include "Voice.h"
26
27 #include "Engine.h"
28
29 namespace LinuxSampler { namespace gig {
30
31 InstrumentResourceManager Engine::Instruments;
32
33 Engine::Engine() {
34 pRIFF = NULL;
35 pGig = NULL;
36 pInstrument = NULL;
37 pAudioOutputDevice = NULL;
38 pDiskThread = NULL;
39 pEventGenerator = NULL;
40 pSysexBuffer = new RingBuffer<uint8_t>(SYSEX_BUFFER_SIZE, 0);
41 pEventQueue = new RingBuffer<Event>(MAX_EVENTS_PER_FRAGMENT, 0);
42 pEventPool = new RTELMemoryPool<Event>(MAX_EVENTS_PER_FRAGMENT);
43 pVoicePool = new RTELMemoryPool<Voice>(MAX_AUDIO_VOICES);
44 pActiveKeys = new RTELMemoryPool<uint>(128);
45 pVoiceStealingQueue = new RTEList<Event>(pEventPool);
46 pEvents = new RTEList<Event>(pEventPool);
47 pCCEvents = new RTEList<Event>(pEventPool);
48 for (uint i = 0; i < Event::destination_count; i++) {
49 pSynthesisEvents[i] = new RTEList<Event>(pEventPool);
50 }
51 for (uint i = 0; i < 128; i++) {
52 pMIDIKeyInfo[i].pActiveVoices = new RTEList<Voice>(pVoicePool);
53 pMIDIKeyInfo[i].KeyPressed = false;
54 pMIDIKeyInfo[i].Active = false;
55 pMIDIKeyInfo[i].ReleaseTrigger = false;
56 pMIDIKeyInfo[i].pSelf = NULL;
57 pMIDIKeyInfo[i].pEvents = new RTEList<Event>(pEventPool);
58 }
59 for (Voice* pVoice = pVoicePool->alloc(); pVoice; pVoice = pVoicePool->alloc()) {
60 pVoice->SetEngine(this);
61 }
62 pVoicePool->clear();
63
64 pSynthesisParameters[0] = NULL; // we allocate when an audio device is connected
65 pBasicFilterParameters = NULL;
66 pMainFilterParameters = NULL;
67
68 InstrumentIdx = -1;
69 InstrumentStat = -1;
70
71 AudioDeviceChannelLeft = -1;
72 AudioDeviceChannelRight = -1;
73
74 ResetInternal();
75 }
76
77 Engine::~Engine() {
78 if (pDiskThread) {
79 pDiskThread->StopThread();
80 delete pDiskThread;
81 }
82 if (pGig) delete pGig;
83 if (pRIFF) delete pRIFF;
84 for (uint i = 0; i < 128; i++) {
85 if (pMIDIKeyInfo[i].pActiveVoices) delete pMIDIKeyInfo[i].pActiveVoices;
86 if (pMIDIKeyInfo[i].pEvents) delete pMIDIKeyInfo[i].pEvents;
87 }
88 for (uint i = 0; i < Event::destination_count; i++) {
89 if (pSynthesisEvents[i]) delete pSynthesisEvents[i];
90 }
91 delete[] pSynthesisEvents;
92 if (pEvents) delete pEvents;
93 if (pCCEvents) delete pCCEvents;
94 if (pEventQueue) delete pEventQueue;
95 if (pEventPool) delete pEventPool;
96 if (pVoicePool) delete pVoicePool;
97 if (pActiveKeys) delete pActiveKeys;
98 if (pSysexBuffer) delete pSysexBuffer;
99 if (pEventGenerator) delete pEventGenerator;
100 if (pMainFilterParameters) delete[] pMainFilterParameters;
101 if (pBasicFilterParameters) delete[] pBasicFilterParameters;
102 if (pSynthesisParameters[0]) delete[] pSynthesisParameters[0];
103 if (pVoiceStealingQueue) delete pVoiceStealingQueue;
104 }
105
106 void Engine::Enable() {
107 dmsg(3,("gig::Engine: enabling\n"));
108 EngineDisabled.PushAndUnlock(false, 2); // set condition object 'EngineDisabled' to false (wait max. 2s)
109 dmsg(3,("gig::Engine: enabled (val=%d)\n", EngineDisabled.GetUnsafe()));
110 }
111
112 void Engine::Disable() {
113 dmsg(3,("gig::Engine: disabling\n"));
114 bool* pWasDisabled = EngineDisabled.PushAndUnlock(true, 2); // wait max. 2s
115 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
116 }
117
118 void Engine::DisableAndLock() {
119 dmsg(3,("gig::Engine: disabling\n"));
120 bool* pWasDisabled = EngineDisabled.Push(true, 2); // wait max. 2s
121 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
122 }
123
124 /**
125 * Reset all voices and disk thread and clear input event queue and all
126 * control and status variables.
127 */
128 void Engine::Reset() {
129 DisableAndLock();
130
131 //if (pAudioOutputDevice->IsPlaying()) { // if already running
132 /*
133 // signal audio thread not to enter render part anymore
134 SuspensionRequested = true;
135 // sleep until wakened by audio thread
136 pthread_mutex_lock(&__render_state_mutex);
137 pthread_cond_wait(&__render_exit_condition, &__render_state_mutex);
138 pthread_mutex_unlock(&__render_state_mutex);
139 */
140 //}
141
142 //if (wasplaying) pAudioOutputDevice->Stop();
143
144 ResetInternal();
145
146 // signal audio thread to continue with rendering
147 //SuspensionRequested = false;
148 Enable();
149 }
150
151 /**
152 * Reset all voices and disk thread and clear input event queue and all
153 * control and status variables. This method is not thread safe!
154 */
155 void Engine::ResetInternal() {
156 Pitch = 0;
157 SustainPedal = false;
158 ActiveVoiceCount = 0;
159 ActiveVoiceCountMax = 0;
160 GlobalVolume = 1.0;
161
162 // reset voice stealing parameters
163 pLastStolenVoice = NULL;
164 puiLastStolenKey = NULL;
165 pVoiceStealingQueue->clear();
166
167 // reset to normal chromatic scale (means equal temper)
168 memset(&ScaleTuning[0], 0x00, 12);
169
170 // set all MIDI controller values to zero
171 memset(ControllerTable, 0x00, 128);
172
173 // reset key info
174 for (uint i = 0; i < 128; i++) {
175 pMIDIKeyInfo[i].pActiveVoices->clear();
176 pMIDIKeyInfo[i].pEvents->clear();
177 pMIDIKeyInfo[i].KeyPressed = false;
178 pMIDIKeyInfo[i].Active = false;
179 pMIDIKeyInfo[i].ReleaseTrigger = false;
180 pMIDIKeyInfo[i].pSelf = NULL;
181 }
182
183 // reset all key groups
184 map<uint,uint*>::iterator iter = ActiveKeyGroups.begin();
185 for (; iter != ActiveKeyGroups.end(); iter++) iter->second = NULL;
186
187 // reset all voices
188 for (Voice* pVoice = pVoicePool->alloc(); pVoice; pVoice = pVoicePool->alloc()) {
189 pVoice->Reset();
190 }
191 pVoicePool->clear();
192
193 // free all active keys
194 pActiveKeys->clear();
195
196 // reset disk thread
197 if (pDiskThread) pDiskThread->Reset();
198
199 // delete all input events
200 pEventQueue->init();
201 }
202
203 /**
204 * Load an instrument from a .gig file.
205 *
206 * @param FileName - file name of the Gigasampler instrument file
207 * @param Instrument - index of the instrument in the .gig file
208 * @throws LinuxSamplerException on error
209 * @returns detailed description of the method call result
210 */
211 void Engine::LoadInstrument(const char* FileName, uint Instrument) {
212
213 DisableAndLock();
214
215 ResetInternal(); // reset engine
216
217 // free old instrument
218 if (pInstrument) {
219 // give old instrument back to instrument manager
220 Instruments.HandBack(pInstrument, this);
221 }
222
223 InstrumentFile = FileName;
224 InstrumentIdx = Instrument;
225 InstrumentStat = 0;
226
227 // delete all key groups
228 ActiveKeyGroups.clear();
229
230 // request gig instrument from instrument manager
231 try {
232 instrument_id_t instrid;
233 instrid.FileName = FileName;
234 instrid.iInstrument = Instrument;
235 pInstrument = Instruments.Borrow(instrid, this);
236 if (!pInstrument) {
237 InstrumentStat = -1;
238 dmsg(1,("no instrument loaded!!!\n"));
239 exit(EXIT_FAILURE);
240 }
241 }
242 catch (RIFF::Exception e) {
243 InstrumentStat = -2;
244 String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message;
245 throw LinuxSamplerException(msg);
246 }
247 catch (InstrumentResourceManagerException e) {
248 InstrumentStat = -3;
249 String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message();
250 throw LinuxSamplerException(msg);
251 }
252 catch (...) {
253 InstrumentStat = -4;
254 throw LinuxSamplerException("gig::Engine error: Failed to load instrument, cause: Unknown exception while trying to parse gig file.");
255 }
256
257 // rebuild ActiveKeyGroups map with key groups of current instrument
258 for (::gig::Region* pRegion = pInstrument->GetFirstRegion(); pRegion; pRegion = pInstrument->GetNextRegion())
259 if (pRegion->KeyGroup) ActiveKeyGroups[pRegion->KeyGroup] = NULL;
260
261 InstrumentStat = 100;
262
263 // inform audio driver for the need of two channels
264 try {
265 if (pAudioOutputDevice) pAudioOutputDevice->AcquireChannels(2); // gig Engine only stereo
266 }
267 catch (AudioOutputException e) {
268 String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
269 throw LinuxSamplerException(msg);
270 }
271
272 Enable();
273 }
274
275 /**
276 * Will be called by the InstrumentResourceManager when the instrument
277 * we are currently using in this engine is going to be updated, so we
278 * can stop playback before that happens.
279 */
280 void Engine::ResourceToBeUpdated(::gig::Instrument* pResource, void*& pUpdateArg) {
281 dmsg(3,("gig::Engine: Received instrument update message.\n"));
282 DisableAndLock();
283 ResetInternal();
284 this->pInstrument = NULL;
285 }
286
287 /**
288 * Will be called by the InstrumentResourceManager when the instrument
289 * update process was completed, so we can continue with playback.
290 */
291 void Engine::ResourceUpdated(::gig::Instrument* pOldResource, ::gig::Instrument* pNewResource, void* pUpdateArg) {
292 this->pInstrument = pNewResource; //TODO: there are couple of engine parameters we should update here as well if the instrument was updated (see LoadInstrument())
293 Enable();
294 }
295
296 void Engine::Connect(AudioOutputDevice* pAudioOut) {
297 pAudioOutputDevice = pAudioOut;
298
299 ResetInternal();
300
301 // inform audio driver for the need of two channels
302 try {
303 pAudioOutputDevice->AcquireChannels(2); // gig engine only stereo
304 }
305 catch (AudioOutputException e) {
306 String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
307 throw LinuxSamplerException(msg);
308 }
309
310 this->AudioDeviceChannelLeft = 0;
311 this->AudioDeviceChannelRight = 1;
312 this->pOutputLeft = pAudioOutputDevice->Channel(0)->Buffer();
313 this->pOutputRight = pAudioOutputDevice->Channel(1)->Buffer();
314 this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
315 this->SampleRate = pAudioOutputDevice->SampleRate();
316
317 // (re)create disk thread
318 if (this->pDiskThread) {
319 this->pDiskThread->StopThread();
320 delete this->pDiskThread;
321 }
322 this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << MAX_PITCH) << 1) + 6); //FIXME: assuming stereo
323 if (!pDiskThread) {
324 dmsg(0,("gig::Engine new diskthread = NULL\n"));
325 exit(EXIT_FAILURE);
326 }
327
328 for (Voice* pVoice = pVoicePool->alloc(); pVoice; pVoice = pVoicePool->alloc()) {
329 pVoice->pDiskThread = this->pDiskThread;
330 dmsg(3,("d"));
331 }
332 pVoicePool->clear();
333
334 // (re)create event generator
335 if (pEventGenerator) delete pEventGenerator;
336 pEventGenerator = new EventGenerator(pAudioOut->SampleRate());
337
338 // (re)allocate synthesis parameter matrix
339 if (pSynthesisParameters[0]) delete[] pSynthesisParameters[0];
340 pSynthesisParameters[0] = new float[Event::destination_count * pAudioOut->MaxSamplesPerCycle()];
341 for (int dst = 1; dst < Event::destination_count; dst++)
342 pSynthesisParameters[dst] = pSynthesisParameters[dst - 1] + pAudioOut->MaxSamplesPerCycle();
343
344 // (re)allocate biquad filter parameter sequence
345 if (pBasicFilterParameters) delete[] pBasicFilterParameters;
346 if (pMainFilterParameters) delete[] pMainFilterParameters;
347 pBasicFilterParameters = new biquad_param_t[pAudioOut->MaxSamplesPerCycle()];
348 pMainFilterParameters = new biquad_param_t[pAudioOut->MaxSamplesPerCycle()];
349
350 dmsg(1,("Starting disk thread..."));
351 pDiskThread->StartThread();
352 dmsg(1,("OK\n"));
353
354 for (Voice* pVoice = pVoicePool->first(); pVoice; pVoice = pVoicePool->next()) {
355 if (!pVoice->pDiskThread) {
356 dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
357 exit(EXIT_FAILURE);
358 }
359 }
360 }
361
362 void Engine::DisconnectAudioOutputDevice() {
363 if (pAudioOutputDevice) { // if clause to prevent disconnect loops
364 AudioOutputDevice* olddevice = pAudioOutputDevice;
365 pAudioOutputDevice = NULL;
366 olddevice->Disconnect(this);
367 AudioDeviceChannelLeft = -1;
368 AudioDeviceChannelRight = -1;
369 }
370 }
371
372 /**
373 * Let this engine proceed to render the given amount of sample points. The
374 * calculated audio data of all voices of this engine will be placed into
375 * the engine's audio sum buffer which has to be copied and eventually be
376 * converted to the appropriate value range by the audio output class (e.g.
377 * AlsaIO or JackIO) right after.
378 *
379 * @param Samples - number of sample points to be rendered
380 * @returns 0 on success
381 */
382 int Engine::RenderAudio(uint Samples) {
383 dmsg(5,("RenderAudio(Samples=%d)\n", Samples));
384
385 // return if no instrument loaded or engine disabled
386 if (EngineDisabled.Pop()) {
387 dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
388 return 0;
389 }
390 if (!pInstrument) {
391 dmsg(5,("gig::Engine: no instrument loaded\n"));
392 return 0;
393 }
394
395
396 // empty the event lists for the new fragment
397 pEvents->clear();
398 pCCEvents->clear();
399 for (uint i = 0; i < Event::destination_count; i++) {
400 pSynthesisEvents[i]->clear();
401 }
402 for (uint* puiKey = pActiveKeys->first(); puiKey; puiKey = pActiveKeys->next()) {
403 midi_key_info_t* pKey = &pMIDIKeyInfo[*puiKey];
404 pKey->pEvents->clear(); // free all events on the key
405 }
406
407 // read and copy events from input queue
408 Event event = pEventGenerator->CreateEvent();
409 while (true) {
410 if (!pEventQueue->pop(&event)) break;
411 pEvents->alloc_assign(event);
412 }
413
414
415 // update time of start and end of this audio fragment (as events' time stamps relate to this)
416 pEventGenerator->UpdateFragmentTime(Samples);
417
418
419 // process events
420 Event* pNextEvent = pEvents->first();
421 while (pNextEvent) {
422 Event* pEvent = pNextEvent;
423 pEvents->set_current(pEvent);
424 pNextEvent = pEvents->next();
425 switch (pEvent->Type) {
426 case Event::type_note_on:
427 dmsg(5,("Engine: Note on received\n"));
428 ProcessNoteOn(pEvent);
429 break;
430 case Event::type_note_off:
431 dmsg(5,("Engine: Note off received\n"));
432 ProcessNoteOff(pEvent);
433 break;
434 case Event::type_control_change:
435 dmsg(5,("Engine: MIDI CC received\n"));
436 ProcessControlChange(pEvent);
437 break;
438 case Event::type_pitchbend:
439 dmsg(5,("Engine: Pitchbend received\n"));
440 ProcessPitchbend(pEvent);
441 break;
442 case Event::type_sysex:
443 dmsg(5,("Engine: Sysex received\n"));
444 ProcessSysex(pEvent);
445 break;
446 }
447 }
448
449
450 // render audio from all active voices
451 int active_voices = 0;
452 uint* piKey = pActiveKeys->first();
453 while (piKey) { // iterate through all active keys
454 midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
455 pActiveKeys->set_current(piKey);
456 piKey = pActiveKeys->next();
457
458 Voice* pVoiceNext = pKey->pActiveVoices->first();
459 while (pVoiceNext) { // iterate through all voices on this key
460 // already get next voice on key
461 Voice* pVoice = pVoiceNext;
462 pKey->pActiveVoices->set_current(pVoice);
463 pVoiceNext = pKey->pActiveVoices->next();
464
465 // now render current voice
466 pVoice->Render(Samples);
467 if (pVoice->IsActive()) active_voices++; // still active
468 else { // voice reached end, is now inactive
469 KillVoiceImmediately(pVoice); // remove voice from the list of active voices
470 }
471 }
472 }
473
474
475 // now render all postponed voices from voice stealing
476 Event* pVoiceStealEvent = pVoiceStealingQueue->first();
477 while (pVoiceStealEvent) {
478 Voice* pNewVoice = LaunchVoice(pVoiceStealEvent, pVoiceStealEvent->Param.Note.Layer, pVoiceStealEvent->Param.Note.ReleaseTrigger, false);
479 if (pNewVoice) {
480 pNewVoice->Render(Samples);
481 if (pNewVoice->IsActive()) active_voices++; // still active
482 else { // voice reached end, is now inactive
483 KillVoiceImmediately(pNewVoice); // remove voice from the list of active voices
484 }
485 }
486 else dmsg(1,("Ouch, voice stealing didn't work out!\n"));
487 pVoiceStealEvent = pVoiceStealingQueue->next();
488 }
489 // reset voice stealing for the new fragment
490 pVoiceStealingQueue->clear();
491 pLastStolenVoice = NULL;
492 puiLastStolenKey = NULL;
493
494
495 // write that to the disk thread class so that it can print it
496 // on the console for debugging purposes
497 ActiveVoiceCount = active_voices;
498 if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
499
500
501 return 0;
502 }
503
504 /**
505 * Will be called by the MIDIIn Thread to let the audio thread trigger a new
506 * voice for the given key.
507 *
508 * @param Key - MIDI key number of the triggered key
509 * @param Velocity - MIDI velocity value of the triggered key
510 */
511 void Engine::SendNoteOn(uint8_t Key, uint8_t Velocity) {
512 Event event = pEventGenerator->CreateEvent();
513 event.Type = Event::type_note_on;
514 event.Param.Note.Key = Key;
515 event.Param.Note.Velocity = Velocity;
516 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
517 else dmsg(1,("Engine: Input event queue full!"));
518 }
519
520 /**
521 * Will be called by the MIDIIn Thread to signal the audio thread to release
522 * voice(s) on the given key.
523 *
524 * @param Key - MIDI key number of the released key
525 * @param Velocity - MIDI release velocity value of the released key
526 */
527 void Engine::SendNoteOff(uint8_t Key, uint8_t Velocity) {
528 Event event = pEventGenerator->CreateEvent();
529 event.Type = Event::type_note_off;
530 event.Param.Note.Key = Key;
531 event.Param.Note.Velocity = Velocity;
532 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
533 else dmsg(1,("Engine: Input event queue full!"));
534 }
535
536 /**
537 * Will be called by the MIDIIn Thread to signal the audio thread to change
538 * the pitch value for all voices.
539 *
540 * @param Pitch - MIDI pitch value (-8192 ... +8191)
541 */
542 void Engine::SendPitchbend(int Pitch) {
543 Event event = pEventGenerator->CreateEvent();
544 event.Type = Event::type_pitchbend;
545 event.Param.Pitch.Pitch = Pitch;
546 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
547 else dmsg(1,("Engine: Input event queue full!"));
548 }
549
550 /**
551 * Will be called by the MIDIIn Thread to signal the audio thread that a
552 * continuous controller value has changed.
553 *
554 * @param Controller - MIDI controller number of the occured control change
555 * @param Value - value of the control change
556 */
557 void Engine::SendControlChange(uint8_t Controller, uint8_t Value) {
558 Event event = pEventGenerator->CreateEvent();
559 event.Type = Event::type_control_change;
560 event.Param.CC.Controller = Controller;
561 event.Param.CC.Value = Value;
562 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
563 else dmsg(1,("Engine: Input event queue full!"));
564 }
565
566 /**
567 * Will be called by the MIDI input device whenever a MIDI system
568 * exclusive message has arrived.
569 *
570 * @param pData - pointer to sysex data
571 * @param Size - lenght of sysex data (in bytes)
572 */
573 void Engine::SendSysex(void* pData, uint Size) {
574 Event event = pEventGenerator->CreateEvent();
575 event.Type = Event::type_sysex;
576 event.Param.Sysex.Size = Size;
577 if (pEventQueue->write_space() > 0) {
578 if (pSysexBuffer->write_space() >= Size) {
579 // copy sysex data to input buffer
580 uint toWrite = Size;
581 uint8_t* pPos = (uint8_t*) pData;
582 while (toWrite) {
583 const uint writeNow = RTMath::Min(toWrite, pSysexBuffer->write_space_to_end());
584 pSysexBuffer->write(pPos, writeNow);
585 toWrite -= writeNow;
586 pPos += writeNow;
587
588 }
589 // finally place sysex event into input event queue
590 pEventQueue->push(&event);
591 }
592 else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,SYSEX_BUFFER_SIZE));
593 }
594 else dmsg(1,("Engine: Input event queue full!"));
595 }
596
597 /**
598 * Assigns and triggers a new voice for the respective MIDI key.
599 *
600 * @param pNoteOnEvent - key, velocity and time stamp of the event
601 */
602 void Engine::ProcessNoteOn(Event* pNoteOnEvent) {
603 midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Param.Note.Key];
604
605 pKey->KeyPressed = true; // the MIDI key was now pressed down
606
607 // cancel release process of voices on this key if needed
608 if (pKey->Active && !SustainPedal) {
609 Event* pCancelReleaseEvent = pKey->pEvents->alloc();
610 if (pCancelReleaseEvent) {
611 *pCancelReleaseEvent = *pNoteOnEvent;
612 pCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
613 }
614 else dmsg(1,("Event pool emtpy!\n"));
615 }
616
617 // allocate and trigger a new voice for the key
618 LaunchVoice(pNoteOnEvent);
619
620 // finally move note on event to the key's own event list
621 pEvents->move(pNoteOnEvent, pKey->pEvents);
622 }
623
624 /**
625 * Releases the voices on the given key if sustain pedal is not pressed.
626 * If sustain is pressed, the release of the note will be postponed until
627 * sustain pedal will be released or voice turned inactive by itself (e.g.
628 * due to completion of sample playback).
629 *
630 * @param pNoteOffEvent - key, velocity and time stamp of the event
631 */
632 void Engine::ProcessNoteOff(Event* pNoteOffEvent) {
633 midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOffEvent->Param.Note.Key];
634
635 pKey->KeyPressed = false; // the MIDI key was now released
636
637 // release voices on this key if needed
638 if (pKey->Active && !SustainPedal) {
639 pNoteOffEvent->Type = Event::type_release; // transform event type
640 }
641
642 // spawn release triggered voice(s) if needed
643 if (pKey->ReleaseTrigger) {
644 LaunchVoice(pNoteOffEvent, 0, true);
645 pKey->ReleaseTrigger = false;
646 }
647
648 // move event to the key's own event list
649 pEvents->move(pNoteOffEvent, pKey->pEvents);
650 }
651
652 /**
653 * Moves pitchbend event from the general (input) event list to the pitch
654 * event list.
655 *
656 * @param pPitchbendEvent - absolute pitch value and time stamp of the event
657 */
658 void Engine::ProcessPitchbend(Event* pPitchbendEvent) {
659 this->Pitch = pPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
660 pEvents->move(pPitchbendEvent, pSynthesisEvents[Event::destination_vco]);
661 }
662
663 /**
664 * Allocates and triggers a new voice. This method will usually be
665 * called by the ProcessNoteOn() method and by the voices itself
666 * (e.g. to spawn further voices on the same key for layered sounds).
667 *
668 * @param pNoteOnEvent - key, velocity and time stamp of the event
669 * @param iLayer - layer index for the new voice (optional - only
670 * in case of layered sounds of course)
671 * @param ReleaseTriggerVoice - if new voice is a release triggered voice
672 * (optional, default = false)
673 * @param VoiceStealing - if voice stealing should be performed
674 * when there is no free voice
675 * (optional, default = true)
676 * @returns pointer to new voice or NULL if there was no free voice or
677 * if an error occured while trying to trigger the new voice
678 */
679 Voice* Engine::LaunchVoice(Event* pNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {
680 midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Param.Note.Key];
681
682 // allocate a new voice for the key
683 Voice* pNewVoice = pKey->pActiveVoices->alloc();
684 if (pNewVoice) {
685 // launch the new voice
686 if (pNewVoice->Trigger(pNoteOnEvent, this->Pitch, this->pInstrument, iLayer, ReleaseTriggerVoice) < 0) {
687 dmsg(1,("Triggering new voice failed!\n"));
688 pKey->pActiveVoices->free(pNewVoice);
689 }
690 else { // on success
691 uint** ppKeyGroup = NULL;
692 if (pNewVoice->KeyGroup) { // if this voice / key belongs to a key group
693 ppKeyGroup = &ActiveKeyGroups[pNewVoice->KeyGroup];
694 if (*ppKeyGroup) { // if there's already an active key in that key group
695 midi_key_info_t* pOtherKey = &pMIDIKeyInfo[**ppKeyGroup];
696 // kill all voices on the (other) key
697 Voice* pVoiceToBeKilled = pOtherKey->pActiveVoices->first();
698 while (pVoiceToBeKilled) {
699 Voice* pVoiceToBeKilledNext = pOtherKey->pActiveVoices->next();
700 if (pVoiceToBeKilled->Type != Voice::type_release_trigger) pVoiceToBeKilled->Kill(pNoteOnEvent);
701 pOtherKey->pActiveVoices->set_current(pVoiceToBeKilled);
702 pVoiceToBeKilled = pVoiceToBeKilledNext;
703 }
704 }
705 }
706 if (!pKey->Active) { // mark as active key
707 pKey->Active = true;
708 pKey->pSelf = pActiveKeys->alloc();
709 *pKey->pSelf = pNoteOnEvent->Param.Note.Key;
710 }
711 if (pNewVoice->KeyGroup) {
712 *ppKeyGroup = pKey->pSelf; // put key as the (new) active key to its key group
713 }
714 if (pNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
715 return pNewVoice; // success
716 }
717 }
718 else if (VoiceStealing) StealVoice(pNoteOnEvent, iLayer, ReleaseTriggerVoice); // no free voice left, so steal one
719
720 return NULL; // no free voice or error
721 }
722
723 /**
724 * Will be called by LaunchVoice() method in case there are no free
725 * voices left. This method will select and kill one old voice for
726 * voice stealing and postpone the note-on event until the selected
727 * voice actually died.
728 *
729 * @param pNoteOnEvent - key, velocity and time stamp of the event
730 * @param iLayer - layer index for the new voice
731 * @param ReleaseTriggerVoice - if new voice is a release triggered voice
732 */
733 void Engine::StealVoice(Event* pNoteOnEvent, int iLayer, bool ReleaseTriggerVoice) {
734 if (!pEventPool->pool_is_empty()) {
735
736 uint* puiOldestKey;
737 Voice* pOldestVoice;
738
739 // Select one voice for voice stealing
740 switch (VOICE_STEAL_ALGORITHM) {
741
742 // try to pick the oldest voice on the key where the new
743 // voice should be spawned, if there is no voice on that
744 // key, or no voice left to kill there, then procceed with
745 // 'oldestkey' algorithm
746 case voice_steal_algo_keymask: {
747 midi_key_info_t* pOldestKey = &pMIDIKeyInfo[pNoteOnEvent->Param.Note.Key];
748 if (pLastStolenVoice) {
749 pOldestKey->pActiveVoices->set_current(pLastStolenVoice);
750 pOldestVoice = pOldestKey->pActiveVoices->next();
751 }
752 else { // no voice stolen in this audio fragment cycle yet
753 pOldestVoice = pOldestKey->pActiveVoices->first();
754 }
755 if (pOldestVoice) {
756 puiOldestKey = pOldestKey->pSelf;
757 break; // selection succeeded
758 }
759 } // no break - intentional !
760
761 // try to pick the oldest voice on the oldest active key
762 // (caution: must stay after 'keymask' algorithm !)
763 case voice_steal_algo_oldestkey: {
764 if (pLastStolenVoice) {
765 midi_key_info_t* pOldestKey = &pMIDIKeyInfo[*puiLastStolenKey];
766 pOldestKey->pActiveVoices->set_current(pLastStolenVoice);
767 pOldestVoice = pOldestKey->pActiveVoices->next();
768 if (!pOldestVoice) {
769 pActiveKeys->set_current(puiLastStolenKey);
770 puiOldestKey = pActiveKeys->next();
771 if (puiOldestKey) {
772 midi_key_info_t* pOldestKey = &pMIDIKeyInfo[*puiOldestKey];
773 pOldestVoice = pOldestKey->pActiveVoices->first();
774 }
775 else { // too less voices, even for voice stealing
776 dmsg(1,("Voice overflow! - You might recompile with higher MAX_AUDIO_VOICES!\n"));
777 return;
778 }
779 }
780 else puiOldestKey = puiLastStolenKey;
781 }
782 else { // no voice stolen in this audio fragment cycle yet
783 puiOldestKey = pActiveKeys->first();
784 midi_key_info_t* pOldestKey = &pMIDIKeyInfo[*puiOldestKey];
785 pOldestVoice = pOldestKey->pActiveVoices->first();
786 }
787 break;
788 }
789
790 // don't steal anything
791 case voice_steal_algo_none:
792 default: {
793 dmsg(1,("No free voice (voice stealing disabled)!\n"));
794 return;
795 }
796 }
797
798 // now kill the selected voice
799 pOldestVoice->Kill(pNoteOnEvent);
800 // remember which voice on which key we stole, so we can simply proceed for the next voice stealing
801 this->pLastStolenVoice = pOldestVoice;
802 this->puiLastStolenKey = puiOldestKey;
803 // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
804 Event* pStealEvent = pVoiceStealingQueue->alloc();
805 *pStealEvent = *pNoteOnEvent;
806 pStealEvent->Param.Note.Layer = iLayer;
807 pStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
808 }
809 else dmsg(1,("Event pool emtpy!\n"));
810 }
811
812 /**
813 * Immediately kills the voice given with pVoice (no matter if sustain is
814 * pressed or not) and removes it from the MIDI key's list of active voice.
815 * This method will e.g. be called if a voice went inactive by itself.
816 *
817 * @param pVoice - points to the voice to be killed
818 */
819 void Engine::KillVoiceImmediately(Voice* pVoice) {
820 if (pVoice) {
821 if (pVoice->IsActive()) pVoice->KillImmediately();
822
823 midi_key_info_t* pKey = &pMIDIKeyInfo[pVoice->MIDIKey];
824
825 // free the voice object
826 pVoicePool->free(pVoice);
827
828 // check if there are no voices left on the MIDI key and update the key info if so
829 if (pKey->pActiveVoices->is_empty()) {
830 if (pVoice->KeyGroup) { // if voice / key belongs to a key group
831 uint** ppKeyGroup = &ActiveKeyGroups[pVoice->KeyGroup];
832 if (*ppKeyGroup == pKey->pSelf) *ppKeyGroup = NULL; // remove key from key group
833 }
834 pKey->Active = false;
835 pActiveKeys->free(pKey->pSelf); // remove key from list of active keys
836 pKey->pSelf = NULL;
837 pKey->ReleaseTrigger = false;
838 pKey->pEvents->clear();
839 dmsg(3,("Key has no more voices now\n"));
840 }
841 }
842 else std::cerr << "Couldn't release voice! (pVoice == NULL)\n" << std::flush;
843 }
844
845 /**
846 * Reacts on supported control change commands (e.g. pitch bend wheel,
847 * modulation wheel, aftertouch).
848 *
849 * @param pControlChangeEvent - controller, value and time stamp of the event
850 */
851 void Engine::ProcessControlChange(Event* pControlChangeEvent) {
852 dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", pControlChangeEvent->Param.CC.Controller, pControlChangeEvent->Param.CC.Value));
853
854 switch (pControlChangeEvent->Param.CC.Controller) {
855 case 64: {
856 if (pControlChangeEvent->Param.CC.Value >= 64 && !SustainPedal) {
857 dmsg(4,("PEDAL DOWN\n"));
858 SustainPedal = true;
859
860 // cancel release process of voices if necessary
861 uint* piKey = pActiveKeys->first();
862 if (piKey) {
863 pControlChangeEvent->Type = Event::type_cancel_release; // transform event type
864 while (piKey) {
865 midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
866 pActiveKeys->set_current(piKey);
867 piKey = pActiveKeys->next();
868 if (!pKey->KeyPressed) {
869 Event* pNewEvent = pKey->pEvents->alloc();
870 if (pNewEvent) *pNewEvent = *pControlChangeEvent; // copy event to the key's own event list
871 else dmsg(1,("Event pool emtpy!\n"));
872 }
873 }
874 }
875 }
876 if (pControlChangeEvent->Param.CC.Value < 64 && SustainPedal) {
877 dmsg(4,("PEDAL UP\n"));
878 SustainPedal = false;
879
880 // release voices if their respective key is not pressed
881 uint* piKey = pActiveKeys->first();
882 if (piKey) {
883 pControlChangeEvent->Type = Event::type_release; // transform event type
884 while (piKey) {
885 midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
886 pActiveKeys->set_current(piKey);
887 piKey = pActiveKeys->next();
888 if (!pKey->KeyPressed) {
889 Event* pNewEvent = pKey->pEvents->alloc();
890 if (pNewEvent) *pNewEvent = *pControlChangeEvent; // copy event to the key's own event list
891 else dmsg(1,("Event pool emtpy!\n"));
892 }
893 }
894 }
895 }
896 break;
897 }
898 }
899
900 // update controller value in the engine's controller table
901 ControllerTable[pControlChangeEvent->Param.CC.Controller] = pControlChangeEvent->Param.CC.Value;
902
903 // move event from the unsorted event list to the control change event list
904 pEvents->move(pControlChangeEvent, pCCEvents);
905 }
906
907 /**
908 * Reacts on MIDI system exclusive messages.
909 *
910 * @param pSysexEvent - sysex data size and time stamp of the sysex event
911 */
912 void Engine::ProcessSysex(Event* pSysexEvent) {
913 RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
914
915 uint8_t exclusive_status, id;
916 if (!reader.pop(&exclusive_status)) goto free_sysex_data;
917 if (!reader.pop(&id)) goto free_sysex_data;
918 if (exclusive_status != 0xF0) goto free_sysex_data;
919
920 switch (id) {
921 case 0x41: { // Roland
922 uint8_t device_id, model_id, cmd_id;
923 if (!reader.pop(&device_id)) goto free_sysex_data;
924 if (!reader.pop(&model_id)) goto free_sysex_data;
925 if (!reader.pop(&cmd_id)) goto free_sysex_data;
926 if (model_id != 0x42 /*GS*/) goto free_sysex_data;
927 if (cmd_id != 0x12 /*DT1*/) goto free_sysex_data;
928
929 // command address
930 uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
931 const RingBuffer<uint8_t>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
932 if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
933 if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
934 }
935 else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
936 }
937 else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
938 switch (addr[3]) {
939 case 0x40: { // scale tuning
940 uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
941 if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
942 uint8_t checksum;
943 if (!reader.pop(&checksum)) goto free_sysex_data;
944 if (GSCheckSum(checksum_reader, 12) != checksum) goto free_sysex_data;
945 for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
946 AdjustScale((int8_t*) scale_tunes);
947 break;
948 }
949 }
950 }
951 else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
952 }
953 else if (addr[0] == 0x41) { // Drum Setup Parameters
954 }
955 break;
956 }
957 }
958
959 free_sysex_data: // finally free sysex data
960 pSysexBuffer->increment_read_ptr(pSysexEvent->Param.Sysex.Size);
961 }
962
963 /**
964 * Calculates the Roland GS sysex check sum.
965 *
966 * @param AddrReader - reader which currently points to the first GS
967 * command address byte of the GS sysex message in
968 * question
969 * @param DataSize - size of the GS message data (in bytes)
970 */
971 uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t>::NonVolatileReader AddrReader, uint DataSize) {
972 RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;
973 uint bytes = 3 /*addr*/ + DataSize;
974 uint8_t addr_and_data[bytes];
975 reader.read(&addr_and_data[0], bytes);
976 uint8_t sum = 0;
977 for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];
978 return 128 - sum % 128;
979 }
980
981 /**
982 * Allows to tune each of the twelve semitones of an octave.
983 *
984 * @param ScaleTunes - detuning of all twelve semitones (in cents)
985 */
986 void Engine::AdjustScale(int8_t ScaleTunes[12]) {
987 memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate
988 }
989
990 /**
991 * Initialize the parameter sequence for the modulation destination given by
992 * by 'dst' with the constant value given by val.
993 */
994 void Engine::ResetSynthesisParameters(Event::destination_t dst, float val) {
995 int maxsamples = pAudioOutputDevice->MaxSamplesPerCycle();
996 float* m = &pSynthesisParameters[dst][0];
997 for (int i = 0; i < maxsamples; i += 4) {
998 m[i] = val;
999 m[i+1] = val;
1000 m[i+2] = val;
1001 m[i+3] = val;
1002 }
1003 }
1004
1005 float Engine::Volume() {
1006 return GlobalVolume;
1007 }
1008
1009 void Engine::Volume(float f) {
1010 GlobalVolume = f;
1011 }
1012
1013 uint Engine::Channels() {
1014 return 2;
1015 }
1016
1017 void Engine::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {
1018 AudioChannel* pChannel = pAudioOutputDevice->Channel(AudioDeviceChannel);
1019 if (!pChannel) throw AudioOutputException("Invalid audio output device channel " + ToString(AudioDeviceChannel));
1020 switch (EngineAudioChannel) {
1021 case 0: // left output channel
1022 pOutputLeft = pChannel->Buffer();
1023 AudioDeviceChannelLeft = AudioDeviceChannel;
1024 break;
1025 case 1: // right output channel
1026 pOutputRight = pChannel->Buffer();
1027 AudioDeviceChannelRight = AudioDeviceChannel;
1028 break;
1029 default:
1030 throw AudioOutputException("Invalid engine audio channel " + ToString(EngineAudioChannel));
1031 }
1032 }
1033
1034 int Engine::OutputChannel(uint EngineAudioChannel) {
1035 switch (EngineAudioChannel) {
1036 case 0: // left channel
1037 return AudioDeviceChannelLeft;
1038 case 1: // right channel
1039 return AudioDeviceChannelRight;
1040 default:
1041 throw AudioOutputException("Invalid engine audio channel " + ToString(EngineAudioChannel));
1042 }
1043 }
1044
1045 uint Engine::VoiceCount() {
1046 return ActiveVoiceCount;
1047 }
1048
1049 uint Engine::VoiceCountMax() {
1050 return ActiveVoiceCountMax;
1051 }
1052
1053 bool Engine::DiskStreamSupported() {
1054 return true;
1055 }
1056
1057 uint Engine::DiskStreamCount() {
1058 return (pDiskThread) ? pDiskThread->ActiveStreamCount : 0;
1059 }
1060
1061 uint Engine::DiskStreamCountMax() {
1062 return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0;
1063 }
1064
1065 String Engine::DiskStreamBufferFillBytes() {
1066 return pDiskThread->GetBufferFillBytes();
1067 }
1068
1069 String Engine::DiskStreamBufferFillPercentage() {
1070 return pDiskThread->GetBufferFillPercentage();
1071 }
1072
1073 String Engine::EngineName() {
1074 return "GigEngine";
1075 }
1076
1077 String Engine::InstrumentFileName() {
1078 return InstrumentFile;
1079 }
1080
1081 int Engine::InstrumentIndex() {
1082 return InstrumentIdx;
1083 }
1084
1085 int Engine::InstrumentStatus() {
1086 return InstrumentStat;
1087 }
1088
1089 String Engine::Description() {
1090 return "Gigasampler Engine";
1091 }
1092
1093 String Engine::Version() {
1094 String s = "$Revision: 1.14 $";
1095 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
1096 }
1097
1098 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC