/[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 411 - (show annotations) (download)
Sat Feb 26 02:01:14 2005 UTC (14 years, 7 months ago) by schoenebeck
File size: 42975 byte(s)
* design change: using now one sampler engine instance and one disk thread
  instance for all sampler channels that are connected to the same audio
  output device (and are using the same engine type of course)
* added EngineFactory / EngineChannelFactory to remove the annoying build
  dependencies e.g. of the lscpserver to the actual sampler engine
  implementations
* bumped version to 0.3.0 (current CVS state is still quite broken,
  previous, stable CVS version was tagged as "v0_2_0" and is also available
  as source tarball)

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

  ViewVC Help
Powered by ViewVC