/[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 424 - (show annotations) (download)
Fri Mar 4 22:54:11 2005 UTC (19 years ago) by schoenebeck
File size: 48076 byte(s)
* implemented MIDI Control Change 7 (Volume)
* implemented MIDI Control Change 10 (Panpot)

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

  ViewVC Help
Powered by ViewVC