/[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 239 - (show annotations) (download)
Sun Sep 12 14:48:19 2004 UTC (16 years, 1 month ago) by schoenebeck
File size: 32886 byte(s)
* implemented key groups (a.k.a exclusive groups) which is important for
  drum patches and monphonic instruments
* src/engines/gig/Engine.cpp: bugfix in ProcessNoteOn() - did not always
  stick the note on event to the respective key's own event list although
  e.g. the EGADRS expects it to find there

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 pEventQueue = new RingBuffer<Event>(MAX_EVENTS_PER_FRAGMENT);
41 pEventPool = new RTELMemoryPool<Event>(MAX_EVENTS_PER_FRAGMENT);
42 pVoicePool = new RTELMemoryPool<Voice>(MAX_AUDIO_VOICES);
43 pActiveKeys = new RTELMemoryPool<uint>(128);
44 pEvents = new RTEList<Event>(pEventPool);
45 pCCEvents = new RTEList<Event>(pEventPool);
46 for (uint i = 0; i < Event::destination_count; i++) {
47 pSynthesisEvents[i] = new RTEList<Event>(pEventPool);
48 }
49 for (uint i = 0; i < 128; i++) {
50 pMIDIKeyInfo[i].pActiveVoices = new RTEList<Voice>(pVoicePool);
51 pMIDIKeyInfo[i].KeyPressed = false;
52 pMIDIKeyInfo[i].Active = false;
53 pMIDIKeyInfo[i].pSelf = NULL;
54 pMIDIKeyInfo[i].pEvents = new RTEList<Event>(pEventPool);
55 }
56 for (Voice* pVoice = pVoicePool->alloc(); pVoice; pVoice = pVoicePool->alloc()) {
57 pVoice->SetEngine(this);
58 }
59 pVoicePool->clear();
60
61 pSynthesisParameters[0] = NULL; // we allocate when an audio device is connected
62 pBasicFilterParameters = NULL;
63 pMainFilterParameters = NULL;
64
65 InstrumentIdx = -1;
66 InstrumentStat = -1;
67
68 AudioDeviceChannelLeft = -1;
69 AudioDeviceChannelRight = -1;
70
71 ResetInternal();
72 }
73
74 Engine::~Engine() {
75 if (pDiskThread) {
76 pDiskThread->StopThread();
77 delete pDiskThread;
78 }
79 if (pGig) delete pGig;
80 if (pRIFF) delete pRIFF;
81 for (uint i = 0; i < 128; i++) {
82 if (pMIDIKeyInfo[i].pActiveVoices) delete pMIDIKeyInfo[i].pActiveVoices;
83 if (pMIDIKeyInfo[i].pEvents) delete pMIDIKeyInfo[i].pEvents;
84 }
85 for (uint i = 0; i < Event::destination_count; i++) {
86 if (pSynthesisEvents[i]) delete pSynthesisEvents[i];
87 }
88 delete[] pSynthesisEvents;
89 if (pEvents) delete pEvents;
90 if (pCCEvents) delete pCCEvents;
91 if (pEventQueue) delete pEventQueue;
92 if (pEventPool) delete pEventPool;
93 if (pVoicePool) delete pVoicePool;
94 if (pActiveKeys) delete pActiveKeys;
95 if (pEventGenerator) delete pEventGenerator;
96 if (pMainFilterParameters) delete[] pMainFilterParameters;
97 if (pBasicFilterParameters) delete[] pBasicFilterParameters;
98 if (pSynthesisParameters[0]) delete[] pSynthesisParameters[0];
99 }
100
101 void Engine::Enable() {
102 dmsg(3,("gig::Engine: enabling\n"));
103 EngineDisabled.PushAndUnlock(false, 2); // set condition object 'EngineDisabled' to false (wait max. 2s)
104 dmsg(3,("gig::Engine: enabled (val=%d)\n", EngineDisabled.GetUnsafe()));
105 }
106
107 void Engine::Disable() {
108 dmsg(3,("gig::Engine: disabling\n"));
109 bool* pWasDisabled = EngineDisabled.PushAndUnlock(true, 2); // wait max. 2s
110 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
111 }
112
113 void Engine::DisableAndLock() {
114 dmsg(3,("gig::Engine: disabling\n"));
115 bool* pWasDisabled = EngineDisabled.Push(true, 2); // wait max. 2s
116 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
117 }
118
119 /**
120 * Reset all voices and disk thread and clear input event queue and all
121 * control and status variables.
122 */
123 void Engine::Reset() {
124 DisableAndLock();
125
126 //if (pAudioOutputDevice->IsPlaying()) { // if already running
127 /*
128 // signal audio thread not to enter render part anymore
129 SuspensionRequested = true;
130 // sleep until wakened by audio thread
131 pthread_mutex_lock(&__render_state_mutex);
132 pthread_cond_wait(&__render_exit_condition, &__render_state_mutex);
133 pthread_mutex_unlock(&__render_state_mutex);
134 */
135 //}
136
137 //if (wasplaying) pAudioOutputDevice->Stop();
138
139 ResetInternal();
140
141 // signal audio thread to continue with rendering
142 //SuspensionRequested = false;
143 Enable();
144 }
145
146 /**
147 * Reset all voices and disk thread and clear input event queue and all
148 * control and status variables. This method is not thread safe!
149 */
150 void Engine::ResetInternal() {
151 Pitch = 0;
152 SustainPedal = false;
153 ActiveVoiceCount = 0;
154 ActiveVoiceCountMax = 0;
155 GlobalVolume = 1.0;
156
157 // set all MIDI controller values to zero
158 memset(ControllerTable, 0x00, 128);
159
160 // reset key info
161 for (uint i = 0; i < 128; i++) {
162 pMIDIKeyInfo[i].pActiveVoices->clear();
163 pMIDIKeyInfo[i].pEvents->clear();
164 pMIDIKeyInfo[i].KeyPressed = false;
165 pMIDIKeyInfo[i].Active = false;
166 pMIDIKeyInfo[i].pSelf = NULL;
167 }
168
169 // reset all key groups
170 map<uint,uint*>::iterator iter = ActiveKeyGroups.begin();
171 for (; iter != ActiveKeyGroups.end(); iter++) iter->second = NULL;
172
173 // reset all voices
174 for (Voice* pVoice = pVoicePool->alloc(); pVoice; pVoice = pVoicePool->alloc()) {
175 pVoice->Reset();
176 }
177 pVoicePool->clear();
178
179 // free all active keys
180 pActiveKeys->clear();
181
182 // reset disk thread
183 if (pDiskThread) pDiskThread->Reset();
184
185 // delete all input events
186 pEventQueue->init();
187 }
188
189 /**
190 * Load an instrument from a .gig file.
191 *
192 * @param FileName - file name of the Gigasampler instrument file
193 * @param Instrument - index of the instrument in the .gig file
194 * @throws LinuxSamplerException on error
195 * @returns detailed description of the method call result
196 */
197 void Engine::LoadInstrument(const char* FileName, uint Instrument) {
198
199 DisableAndLock();
200
201 ResetInternal(); // reset engine
202
203 // free old instrument
204 if (pInstrument) {
205 // give old instrument back to instrument manager
206 Instruments.HandBack(pInstrument, this);
207 }
208
209 InstrumentFile = FileName;
210 InstrumentIdx = Instrument;
211 InstrumentStat = 0;
212
213 // delete all key groups
214 ActiveKeyGroups.clear();
215
216 // request gig instrument from instrument manager
217 try {
218 instrument_id_t instrid;
219 instrid.FileName = FileName;
220 instrid.iInstrument = Instrument;
221 pInstrument = Instruments.Borrow(instrid, this);
222 if (!pInstrument) {
223 InstrumentStat = -1;
224 dmsg(1,("no instrument loaded!!!\n"));
225 exit(EXIT_FAILURE);
226 }
227 }
228 catch (RIFF::Exception e) {
229 InstrumentStat = -2;
230 String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message;
231 throw LinuxSamplerException(msg);
232 }
233 catch (InstrumentResourceManagerException e) {
234 InstrumentStat = -3;
235 String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message();
236 throw LinuxSamplerException(msg);
237 }
238 catch (...) {
239 InstrumentStat = -4;
240 throw LinuxSamplerException("gig::Engine error: Failed to load instrument, cause: Unknown exception while trying to parse gig file.");
241 }
242
243 // rebuild ActiveKeyGroups map with key groups of current instrument
244 for (::gig::Region* pRegion = pInstrument->GetFirstRegion(); pRegion; pRegion = pInstrument->GetNextRegion())
245 if (pRegion->KeyGroup) ActiveKeyGroups[pRegion->KeyGroup] = NULL;
246
247 InstrumentStat = 100;
248
249 // inform audio driver for the need of two channels
250 try {
251 if (pAudioOutputDevice) pAudioOutputDevice->AcquireChannels(2); // gig Engine only stereo
252 }
253 catch (AudioOutputException e) {
254 String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
255 throw LinuxSamplerException(msg);
256 }
257
258 Enable();
259 }
260
261 /**
262 * Will be called by the InstrumentResourceManager when the instrument
263 * we are currently using in this engine is going to be updated, so we
264 * can stop playback before that happens.
265 */
266 void Engine::ResourceToBeUpdated(::gig::Instrument* pResource, void*& pUpdateArg) {
267 dmsg(3,("gig::Engine: Received instrument update message.\n"));
268 DisableAndLock();
269 ResetInternal();
270 this->pInstrument = NULL;
271 }
272
273 /**
274 * Will be called by the InstrumentResourceManager when the instrument
275 * update process was completed, so we can continue with playback.
276 */
277 void Engine::ResourceUpdated(::gig::Instrument* pOldResource, ::gig::Instrument* pNewResource, void* pUpdateArg) {
278 this->pInstrument = pNewResource; //TODO: there are couple of engine parameters we should update here as well if the instrument was updated (see LoadInstrument())
279 Enable();
280 }
281
282 void Engine::Connect(AudioOutputDevice* pAudioOut) {
283 pAudioOutputDevice = pAudioOut;
284
285 ResetInternal();
286
287 // inform audio driver for the need of two channels
288 try {
289 pAudioOutputDevice->AcquireChannels(2); // gig engine only stereo
290 }
291 catch (AudioOutputException e) {
292 String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
293 throw LinuxSamplerException(msg);
294 }
295
296 this->AudioDeviceChannelLeft = 0;
297 this->AudioDeviceChannelRight = 1;
298 this->pOutputLeft = pAudioOutputDevice->Channel(0)->Buffer();
299 this->pOutputRight = pAudioOutputDevice->Channel(1)->Buffer();
300 this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
301 this->SampleRate = pAudioOutputDevice->SampleRate();
302
303 // (re)create disk thread
304 if (this->pDiskThread) {
305 this->pDiskThread->StopThread();
306 delete this->pDiskThread;
307 }
308 this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << MAX_PITCH) << 1) + 6); //FIXME: assuming stereo
309 if (!pDiskThread) {
310 dmsg(0,("gig::Engine new diskthread = NULL\n"));
311 exit(EXIT_FAILURE);
312 }
313
314 for (Voice* pVoice = pVoicePool->alloc(); pVoice; pVoice = pVoicePool->alloc()) {
315 pVoice->pDiskThread = this->pDiskThread;
316 dmsg(3,("d"));
317 }
318 pVoicePool->clear();
319
320 // (re)create event generator
321 if (pEventGenerator) delete pEventGenerator;
322 pEventGenerator = new EventGenerator(pAudioOut->SampleRate());
323
324 // (re)allocate synthesis parameter matrix
325 if (pSynthesisParameters[0]) delete[] pSynthesisParameters[0];
326 pSynthesisParameters[0] = new float[Event::destination_count * pAudioOut->MaxSamplesPerCycle()];
327 for (int dst = 1; dst < Event::destination_count; dst++)
328 pSynthesisParameters[dst] = pSynthesisParameters[dst - 1] + pAudioOut->MaxSamplesPerCycle();
329
330 // (re)allocate biquad filter parameter sequence
331 if (pBasicFilterParameters) delete[] pBasicFilterParameters;
332 if (pMainFilterParameters) delete[] pMainFilterParameters;
333 pBasicFilterParameters = new biquad_param_t[pAudioOut->MaxSamplesPerCycle()];
334 pMainFilterParameters = new biquad_param_t[pAudioOut->MaxSamplesPerCycle()];
335
336 dmsg(1,("Starting disk thread..."));
337 pDiskThread->StartThread();
338 dmsg(1,("OK\n"));
339
340 for (Voice* pVoice = pVoicePool->first(); pVoice; pVoice = pVoicePool->next()) {
341 if (!pVoice->pDiskThread) {
342 dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
343 exit(EXIT_FAILURE);
344 }
345 }
346 }
347
348 void Engine::DisconnectAudioOutputDevice() {
349 if (pAudioOutputDevice) { // if clause to prevent disconnect loops
350 AudioOutputDevice* olddevice = pAudioOutputDevice;
351 pAudioOutputDevice = NULL;
352 olddevice->Disconnect(this);
353 AudioDeviceChannelLeft = -1;
354 AudioDeviceChannelRight = -1;
355 }
356 }
357
358 /**
359 * Let this engine proceed to render the given amount of sample points. The
360 * calculated audio data of all voices of this engine will be placed into
361 * the engine's audio sum buffer which has to be copied and eventually be
362 * converted to the appropriate value range by the audio output class (e.g.
363 * AlsaIO or JackIO) right after.
364 *
365 * @param Samples - number of sample points to be rendered
366 * @returns 0 on success
367 */
368 int Engine::RenderAudio(uint Samples) {
369 dmsg(5,("RenderAudio(Samples=%d)\n", Samples));
370
371 // return if no instrument loaded or engine disabled
372 if (EngineDisabled.Pop()) {
373 dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
374 return 0;
375 }
376 if (!pInstrument) {
377 dmsg(5,("gig::Engine: no instrument loaded\n"));
378 return 0;
379 }
380
381
382 // empty the event lists for the new fragment
383 pEvents->clear();
384 pCCEvents->clear();
385 for (uint i = 0; i < Event::destination_count; i++) {
386 pSynthesisEvents[i]->clear();
387 }
388
389 // read and copy events from input queue
390 Event event = pEventGenerator->CreateEvent();
391 while (true) {
392 if (!pEventQueue->pop(&event)) break;
393 pEvents->alloc_assign(event);
394 }
395
396
397 // update time of start and end of this audio fragment (as events' time stamps relate to this)
398 pEventGenerator->UpdateFragmentTime(Samples);
399
400
401 // process events
402 Event* pNextEvent = pEvents->first();
403 while (pNextEvent) {
404 Event* pEvent = pNextEvent;
405 pEvents->set_current(pEvent);
406 pNextEvent = pEvents->next();
407 switch (pEvent->Type) {
408 case Event::type_note_on:
409 dmsg(5,("Audio Thread: Note on received\n"));
410 ProcessNoteOn(pEvent);
411 break;
412 case Event::type_note_off:
413 dmsg(5,("Audio Thread: Note off received\n"));
414 ProcessNoteOff(pEvent);
415 break;
416 case Event::type_control_change:
417 dmsg(5,("Audio Thread: MIDI CC received\n"));
418 ProcessControlChange(pEvent);
419 break;
420 case Event::type_pitchbend:
421 dmsg(5,("Audio Thread: Pitchbend received\n"));
422 ProcessPitchbend(pEvent);
423 break;
424 }
425 }
426
427
428 // render audio from all active voices
429 int active_voices = 0;
430 uint* piKey = pActiveKeys->first();
431 while (piKey) { // iterate through all active keys
432 midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
433 pActiveKeys->set_current(piKey);
434 piKey = pActiveKeys->next();
435
436 Voice* pVoiceNext = pKey->pActiveVoices->first();
437 while (pVoiceNext) { // iterate through all voices on this key
438 // already get next voice on key
439 Voice* pVoice = pVoiceNext;
440 pKey->pActiveVoices->set_current(pVoice);
441 pVoiceNext = pKey->pActiveVoices->next();
442
443 // now render current voice
444 pVoice->Render(Samples);
445 if (pVoice->IsActive()) active_voices++; // still active
446 else { // voice reached end, is now inactive
447 KillVoiceImmediately(pVoice); // remove voice from the list of active voices
448 }
449 }
450 pKey->pEvents->clear(); // free all events on the key
451 }
452
453
454 // write that to the disk thread class so that it can print it
455 // on the console for debugging purposes
456 ActiveVoiceCount = active_voices;
457 if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
458
459
460 return 0;
461 }
462
463 /**
464 * Will be called by the MIDIIn Thread to let the audio thread trigger a new
465 * voice for the given key.
466 *
467 * @param Key - MIDI key number of the triggered key
468 * @param Velocity - MIDI velocity value of the triggered key
469 */
470 void Engine::SendNoteOn(uint8_t Key, uint8_t Velocity) {
471 Event event = pEventGenerator->CreateEvent();
472 event.Type = Event::type_note_on;
473 event.Key = Key;
474 event.Velocity = Velocity;
475 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
476 else dmsg(1,("Engine: Input event queue full!"));
477 }
478
479 /**
480 * Will be called by the MIDIIn Thread to signal the audio thread to release
481 * voice(s) on the given key.
482 *
483 * @param Key - MIDI key number of the released key
484 * @param Velocity - MIDI release velocity value of the released key
485 */
486 void Engine::SendNoteOff(uint8_t Key, uint8_t Velocity) {
487 Event event = pEventGenerator->CreateEvent();
488 event.Type = Event::type_note_off;
489 event.Key = Key;
490 event.Velocity = Velocity;
491 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
492 else dmsg(1,("Engine: Input event queue full!"));
493 }
494
495 /**
496 * Will be called by the MIDIIn Thread to signal the audio thread to change
497 * the pitch value for all voices.
498 *
499 * @param Pitch - MIDI pitch value (-8192 ... +8191)
500 */
501 void Engine::SendPitchbend(int Pitch) {
502 Event event = pEventGenerator->CreateEvent();
503 event.Type = Event::type_pitchbend;
504 event.Pitch = Pitch;
505 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
506 else dmsg(1,("Engine: Input event queue full!"));
507 }
508
509 /**
510 * Will be called by the MIDIIn Thread to signal the audio thread that a
511 * continuous controller value has changed.
512 *
513 * @param Controller - MIDI controller number of the occured control change
514 * @param Value - value of the control change
515 */
516 void Engine::SendControlChange(uint8_t Controller, uint8_t Value) {
517 Event event = pEventGenerator->CreateEvent();
518 event.Type = Event::type_control_change;
519 event.Controller = Controller;
520 event.Value = Value;
521 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
522 else dmsg(1,("Engine: Input event queue full!"));
523 }
524
525 /**
526 * Assigns and triggers a new voice for the respective MIDI key.
527 *
528 * @param pNoteOnEvent - key, velocity and time stamp of the event
529 */
530 void Engine::ProcessNoteOn(Event* pNoteOnEvent) {
531 midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Key];
532
533 pKey->KeyPressed = true; // the MIDI key was now pressed down
534
535 // cancel release process of voices on this key if needed
536 if (pKey->Active && !SustainPedal) {
537 Event* pCancelReleaseEvent = pKey->pEvents->alloc();
538 if (pCancelReleaseEvent) {
539 *pCancelReleaseEvent = *pNoteOnEvent;
540 pCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
541 }
542 else dmsg(1,("Event pool emtpy!\n"));
543 }
544
545 // allocate and trigger a new voice for the key
546 LaunchVoice(pNoteOnEvent);
547
548 // finally move note on event to the key's own event list
549 pEvents->move(pNoteOnEvent, pKey->pEvents);
550 }
551
552 /**
553 * Releases the voices on the given key if sustain pedal is not pressed.
554 * If sustain is pressed, the release of the note will be postponed until
555 * sustain pedal will be released or voice turned inactive by itself (e.g.
556 * due to completion of sample playback).
557 *
558 * @param pNoteOffEvent - key, velocity and time stamp of the event
559 */
560 void Engine::ProcessNoteOff(Event* pNoteOffEvent) {
561 midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOffEvent->Key];
562
563 pKey->KeyPressed = false; // the MIDI key was now released
564
565 // release voices on this key if needed
566 if (pKey->Active && !SustainPedal) {
567 pNoteOffEvent->Type = Event::type_release; // transform event type
568 pEvents->move(pNoteOffEvent, pKey->pEvents); // move event to the key's own event list
569 }
570 }
571
572 /**
573 * Moves pitchbend event from the general (input) event list to the pitch
574 * event list.
575 *
576 * @param pPitchbendEvent - absolute pitch value and time stamp of the event
577 */
578 void Engine::ProcessPitchbend(Event* pPitchbendEvent) {
579 this->Pitch = pPitchbendEvent->Pitch; // store current pitch value
580 pEvents->move(pPitchbendEvent, pSynthesisEvents[Event::destination_vco]);
581 }
582
583 /**
584 * Allocates and triggers a new voice. This method will usually be
585 * called by the ProcessNoteOn() method and by the voices itself
586 * (e.g. to spawn further voices on the same key for layered sounds).
587 *
588 * @param pNoteOnEvent - key, velocity and time stamp of the event
589 * @param iLayer - layer index for the new voice (optional - only
590 * in case of layered sounds of course)
591 */
592 void Engine::LaunchVoice(Event* pNoteOnEvent, int iLayer) {
593 midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Key];
594
595 // allocate a new voice for the key
596 Voice* pNewVoice = pKey->pActiveVoices->alloc();
597 if (pNewVoice) {
598 // launch the new voice
599 if (pNewVoice->Trigger(pNoteOnEvent, this->Pitch, this->pInstrument, iLayer) < 0) {
600 dmsg(1,("Triggering new voice failed!\n"));
601 pKey->pActiveVoices->free(pNewVoice);
602 }
603 else { // on success
604 uint** ppKeyGroup = NULL;
605 if (pNewVoice->KeyGroup) { // if this voice / key belongs to a key group
606 ppKeyGroup = &ActiveKeyGroups[pNewVoice->KeyGroup];
607 if (*ppKeyGroup) { // if there's already an active key in that key group
608 midi_key_info_t* pOtherKey = &pMIDIKeyInfo[**ppKeyGroup];
609 // kill all voices on the (other) key
610 Voice* pVoiceToBeKilled = pOtherKey->pActiveVoices->first();
611 for (; pVoiceToBeKilled; pVoiceToBeKilled = pOtherKey->pActiveVoices->next())
612 if (pVoiceToBeKilled != pNewVoice) pVoiceToBeKilled->Kill(pNoteOnEvent);
613 }
614 }
615 if (!pKey->Active) { // mark as active key
616 pKey->Active = true;
617 pKey->pSelf = pActiveKeys->alloc();
618 *pKey->pSelf = pNoteOnEvent->Key;
619 }
620 if (pNewVoice->KeyGroup) {
621 *ppKeyGroup = pKey->pSelf; // put key as the (new) active key to its key group
622 }
623 }
624 }
625 else std::cerr << "No free voice!" << std::endl << std::flush;
626 }
627
628 /**
629 * Immediately kills the voice given with pVoice (no matter if sustain is
630 * pressed or not) and removes it from the MIDI key's list of active voice.
631 * This method will e.g. be called if a voice went inactive by itself.
632 *
633 * @param pVoice - points to the voice to be killed
634 */
635 void Engine::KillVoiceImmediately(Voice* pVoice) {
636 if (pVoice) {
637 if (pVoice->IsActive()) pVoice->KillImmediately();
638
639 midi_key_info_t* pKey = &pMIDIKeyInfo[pVoice->MIDIKey];
640
641 // free the voice object
642 pVoicePool->free(pVoice);
643
644 // check if there are no voices left on the MIDI key and update the key info if so
645 if (pKey->pActiveVoices->is_empty()) {
646 if (pVoice->KeyGroup) { // if voice / key belongs to a key group
647 uint** ppKeyGroup = &ActiveKeyGroups[pVoice->KeyGroup];
648 if (*ppKeyGroup == pKey->pSelf) *ppKeyGroup = NULL; // remove key from key group
649 }
650 pKey->Active = false;
651 pActiveKeys->free(pKey->pSelf); // remove key from list of active keys
652 pKey->pSelf = NULL;
653 dmsg(3,("Key has no more voices now\n"));
654 }
655 }
656 else std::cerr << "Couldn't release voice! (pVoice == NULL)\n" << std::flush;
657 }
658
659 /**
660 * Reacts on supported control change commands (e.g. pitch bend wheel,
661 * modulation wheel, aftertouch).
662 *
663 * @param pControlChangeEvent - controller, value and time stamp of the event
664 */
665 void Engine::ProcessControlChange(Event* pControlChangeEvent) {
666 dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", pControlChangeEvent->Controller, pControlChangeEvent->Value));
667
668 switch (pControlChangeEvent->Controller) {
669 case 64: {
670 if (pControlChangeEvent->Value >= 64 && !SustainPedal) {
671 dmsg(4,("PEDAL DOWN\n"));
672 SustainPedal = true;
673
674 // cancel release process of voices if necessary
675 uint* piKey = pActiveKeys->first();
676 if (piKey) {
677 pControlChangeEvent->Type = Event::type_cancel_release; // transform event type
678 while (piKey) {
679 midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
680 pActiveKeys->set_current(piKey);
681 piKey = pActiveKeys->next();
682 if (!pKey->KeyPressed) {
683 Event* pNewEvent = pKey->pEvents->alloc();
684 if (pNewEvent) *pNewEvent = *pControlChangeEvent; // copy event to the key's own event list
685 else dmsg(1,("Event pool emtpy!\n"));
686 }
687 }
688 }
689 }
690 if (pControlChangeEvent->Value < 64 && SustainPedal) {
691 dmsg(4,("PEDAL UP\n"));
692 SustainPedal = false;
693
694 // release voices if their respective key is not pressed
695 uint* piKey = pActiveKeys->first();
696 if (piKey) {
697 pControlChangeEvent->Type = Event::type_release; // transform event type
698 while (piKey) {
699 midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
700 pActiveKeys->set_current(piKey);
701 piKey = pActiveKeys->next();
702 if (!pKey->KeyPressed) {
703 Event* pNewEvent = pKey->pEvents->alloc();
704 if (pNewEvent) *pNewEvent = *pControlChangeEvent; // copy event to the key's own event list
705 else dmsg(1,("Event pool emtpy!\n"));
706 }
707 }
708 }
709 }
710 break;
711 }
712 }
713
714 // update controller value in the engine's controller table
715 ControllerTable[pControlChangeEvent->Controller] = pControlChangeEvent->Value;
716
717 // move event from the unsorted event list to the control change event list
718 pEvents->move(pControlChangeEvent, pCCEvents);
719 }
720
721 /**
722 * Initialize the parameter sequence for the modulation destination given by
723 * by 'dst' with the constant value given by val.
724 */
725 void Engine::ResetSynthesisParameters(Event::destination_t dst, float val) {
726 int maxsamples = pAudioOutputDevice->MaxSamplesPerCycle();
727 float* m = &pSynthesisParameters[dst][0];
728 for (int i = 0; i < maxsamples; i += 4) {
729 m[i] = val;
730 m[i+1] = val;
731 m[i+2] = val;
732 m[i+3] = val;
733 }
734 }
735
736 float Engine::Volume() {
737 return GlobalVolume;
738 }
739
740 void Engine::Volume(float f) {
741 GlobalVolume = f;
742 }
743
744 uint Engine::Channels() {
745 return 2;
746 }
747
748 void Engine::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {
749 AudioChannel* pChannel = pAudioOutputDevice->Channel(AudioDeviceChannel);
750 if (!pChannel) throw AudioOutputException("Invalid audio output device channel " + ToString(AudioDeviceChannel));
751 switch (EngineAudioChannel) {
752 case 0: // left output channel
753 pOutputLeft = pChannel->Buffer();
754 AudioDeviceChannelLeft = AudioDeviceChannel;
755 break;
756 case 1: // right output channel
757 pOutputRight = pChannel->Buffer();
758 AudioDeviceChannelRight = AudioDeviceChannel;
759 break;
760 default:
761 throw AudioOutputException("Invalid engine audio channel " + ToString(EngineAudioChannel));
762 }
763 }
764
765 int Engine::OutputChannel(uint EngineAudioChannel) {
766 switch (EngineAudioChannel) {
767 case 0: // left channel
768 return AudioDeviceChannelLeft;
769 case 1: // right channel
770 return AudioDeviceChannelRight;
771 default:
772 throw AudioOutputException("Invalid engine audio channel " + ToString(EngineAudioChannel));
773 }
774 }
775
776 uint Engine::VoiceCount() {
777 return ActiveVoiceCount;
778 }
779
780 uint Engine::VoiceCountMax() {
781 return ActiveVoiceCountMax;
782 }
783
784 bool Engine::DiskStreamSupported() {
785 return true;
786 }
787
788 uint Engine::DiskStreamCount() {
789 return (pDiskThread) ? pDiskThread->ActiveStreamCount : 0;
790 }
791
792 uint Engine::DiskStreamCountMax() {
793 return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0;
794 }
795
796 String Engine::DiskStreamBufferFillBytes() {
797 return pDiskThread->GetBufferFillBytes();
798 }
799
800 String Engine::DiskStreamBufferFillPercentage() {
801 return pDiskThread->GetBufferFillPercentage();
802 }
803
804 String Engine::EngineName() {
805 return "GigEngine";
806 }
807
808 String Engine::InstrumentFileName() {
809 return InstrumentFile;
810 }
811
812 int Engine::InstrumentIndex() {
813 return InstrumentIdx;
814 }
815
816 int Engine::InstrumentStatus() {
817 return InstrumentStat;
818 }
819
820 String Engine::Description() {
821 return "Gigasampler Engine";
822 }
823
824 String Engine::Version() {
825 String s = "$Revision: 1.10 $";
826 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
827 }
828
829 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC