/[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 271 - (show annotations) (download)
Fri Oct 8 20:51:39 2004 UTC (19 years, 5 months ago) by schoenebeck
File size: 47022 byte(s)
* libgig: fixed panorama value in DimensionRegion (invalid conversion
  from signed 7 bit to signed 8 bit)
* src/linuxsampler.cpp: stacktrace is now automatically shown on fatal
  errors (that is  segmentation faults, etc.), gdb should be installed for
  this to work
* gig::Voice: tiny accuracy fix of pan calculation
* replaced old pool classes by completely new ones which now offer
  Iterator abstraction

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

  ViewVC Help
Powered by ViewVC