/[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 412 - (show annotations) (download)
Sat Feb 26 22:44:51 2005 UTC (19 years, 1 month ago) by schoenebeck
File size: 47365 byte(s)
* gig::Engine: fixed silence (engine channels' events were not imported
  into the engine, fixed undesired creation of new gig::Engine instances
  (and disk threads)
* AudioOutputDevice: reverted behavior to render per Engine instance (and
  not per EngineChannel instance)

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

  ViewVC Help
Powered by ViewVC