/[svn]/linuxsampler/trunk/src/engines/gig/Engine.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/gig/Engine.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 705 - (hide annotations) (download)
Wed Jul 20 21:43:23 2005 UTC (18 years, 8 months ago) by schoenebeck
File size: 68582 byte(s)
* support for muting sampler channels and solo mode of the same, two new
  LSCP commands ("SET CHANNEL MUTE" and "SET CHANNEL SOLO") and two new
  fields ("MUTE" and "SOLO") for command "GET CHANNEL INFO" were
  introduced for this (patch by Grigor Iliev, a bit adjusted)

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 411 * Copyright (C) 2005 Christian Schoenebeck *
7 schoenebeck 53 * *
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 schoenebeck 285 #include "EGADSR.h"
28 schoenebeck 420 #include "../EngineFactory.h"
29 schoenebeck 53
30     #include "Engine.h"
31    
32 schoenebeck 361 #if defined(__APPLE__)
33     # include <stdlib.h>
34     #else
35     # include <malloc.h>
36     #endif
37    
38 schoenebeck 53 namespace LinuxSampler { namespace gig {
39    
40 schoenebeck 411 InstrumentResourceManager Engine::instruments;
41 schoenebeck 53
42 schoenebeck 411 std::map<AudioOutputDevice*,Engine*> Engine::engines;
43    
44 schoenebeck 412 /**
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 schoenebeck 411 Engine* Engine::AcquireEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
55 schoenebeck 412 Engine* pEngine = NULL;
56     // check if there's already an engine for the given audio output device
57 schoenebeck 411 if (engines.count(pDevice)) {
58 schoenebeck 412 dmsg(4,("Using existing gig::Engine.\n"));
59 persson 438 pEngine = engines[pDevice];
60 schoenebeck 412 } else { // create a new engine (and disk thread) instance for the given audio output device
61     dmsg(4,("Creating new gig::Engine.\n"));
62 schoenebeck 420 pEngine = (Engine*) EngineFactory::Create("gig");
63 schoenebeck 411 pEngine->Connect(pDevice);
64 persson 438 engines[pDevice] = pEngine;
65 schoenebeck 411 }
66 schoenebeck 412 // register engine channel to the engine instance
67 schoenebeck 460 pEngine->engineChannels.add(pChannel);
68     // remember index in the ArrayList
69     pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
70 schoenebeck 412 dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
71 schoenebeck 411 return pEngine;
72     }
73    
74 schoenebeck 412 /**
75     * Once an engine channel is disconnected from an audio output device,
76     * it wil immediately call this method to unregister itself from the
77     * engine instance and if that engine instance is not used by any other
78     * engine channel anymore, then that engine instance will be destroyed.
79     *
80     * @param pChannel - engine channel which wants to disconnect from it's
81     * engine instance
82     * @param pDevice - audio output device \a pChannel was connected to
83     */
84 schoenebeck 411 void Engine::FreeEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
85 schoenebeck 412 dmsg(4,("Disconnecting EngineChannel from gig::Engine.\n"));
86 schoenebeck 411 Engine* pEngine = engines[pDevice];
87 schoenebeck 412 // unregister EngineChannel from the Engine instance
88     pEngine->engineChannels.remove(pChannel);
89     // if the used Engine instance is not used anymore, then destroy it
90     if (pEngine->engineChannels.empty()) {
91     pDevice->Disconnect(pEngine);
92     engines.erase(pDevice);
93     delete pEngine;
94     dmsg(4,("Destroying gig::Engine.\n"));
95     }
96     else dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
97 schoenebeck 411 }
98    
99 schoenebeck 473 /**
100     * Constructor
101     */
102 schoenebeck 53 Engine::Engine() {
103     pAudioOutputDevice = NULL;
104     pDiskThread = NULL;
105     pEventGenerator = NULL;
106 schoenebeck 554 pSysexBuffer = new RingBuffer<uint8_t>(CONFIG_SYSEX_BUFFER_SIZE, 0);
107     pEventQueue = new RingBuffer<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
108     pEventPool = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
109     pVoicePool = new Pool<Voice>(CONFIG_MAX_VOICES);
110 schoenebeck 271 pVoiceStealingQueue = new RTList<Event>(pEventPool);
111 schoenebeck 460 pGlobalEvents = new RTList<Event>(pEventPool);
112 schoenebeck 271 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
113     iterVoice->SetEngine(this);
114 schoenebeck 53 }
115     pVoicePool->clear();
116    
117     pSynthesisParameters[0] = NULL; // we allocate when an audio device is connected
118 schoenebeck 80 pBasicFilterParameters = NULL;
119     pMainFilterParameters = NULL;
120 schoenebeck 123
121 schoenebeck 53 ResetInternal();
122 schoenebeck 659 ResetScaleTuning();
123 schoenebeck 53 }
124    
125 schoenebeck 473 /**
126     * Destructor
127     */
128 schoenebeck 53 Engine::~Engine() {
129     if (pDiskThread) {
130 senkov 329 dmsg(1,("Stopping disk thread..."));
131 schoenebeck 53 pDiskThread->StopThread();
132     delete pDiskThread;
133 senkov 329 dmsg(1,("OK\n"));
134 schoenebeck 53 }
135     if (pEventQueue) delete pEventQueue;
136     if (pEventPool) delete pEventPool;
137 schoenebeck 411 if (pVoicePool) {
138     pVoicePool->clear();
139     delete pVoicePool;
140     }
141 schoenebeck 53 if (pEventGenerator) delete pEventGenerator;
142 schoenebeck 80 if (pMainFilterParameters) delete[] pMainFilterParameters;
143     if (pBasicFilterParameters) delete[] pBasicFilterParameters;
144 schoenebeck 319 if (pSynthesisParameters[0]) free(pSynthesisParameters[0]);
145 schoenebeck 250 if (pVoiceStealingQueue) delete pVoiceStealingQueue;
146 schoenebeck 411 if (pSysexBuffer) delete pSysexBuffer;
147 schoenebeck 420 EngineFactory::Destroy(this);
148 schoenebeck 53 }
149    
150     void Engine::Enable() {
151     dmsg(3,("gig::Engine: enabling\n"));
152     EngineDisabled.PushAndUnlock(false, 2); // set condition object 'EngineDisabled' to false (wait max. 2s)
153 schoenebeck 64 dmsg(3,("gig::Engine: enabled (val=%d)\n", EngineDisabled.GetUnsafe()));
154 schoenebeck 53 }
155    
156     void Engine::Disable() {
157     dmsg(3,("gig::Engine: disabling\n"));
158     bool* pWasDisabled = EngineDisabled.PushAndUnlock(true, 2); // wait max. 2s
159     if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
160     }
161    
162     void Engine::DisableAndLock() {
163     dmsg(3,("gig::Engine: disabling\n"));
164     bool* pWasDisabled = EngineDisabled.Push(true, 2); // wait max. 2s
165     if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
166     }
167    
168     /**
169     * Reset all voices and disk thread and clear input event queue and all
170     * control and status variables.
171     */
172     void Engine::Reset() {
173     DisableAndLock();
174     ResetInternal();
175 schoenebeck 659 ResetScaleTuning();
176 schoenebeck 53 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 schoenebeck 250 // reset voice stealing parameters
188     pVoiceStealingQueue->clear();
189 schoenebeck 649 itLastStolenVoice = RTList<Voice>::Iterator();
190     itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
191     iuiLastStolenKey = RTList<uint>::Iterator();
192     iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
193     pLastStolenChannel = NULL;
194 schoenebeck 250
195 schoenebeck 53 // reset all voices
196 schoenebeck 271 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
197     iterVoice->Reset();
198 schoenebeck 53 }
199     pVoicePool->clear();
200    
201     // reset disk thread
202     if (pDiskThread) pDiskThread->Reset();
203    
204     // delete all input events
205     pEventQueue->init();
206 persson 438 }
207 schoenebeck 53
208 schoenebeck 473 /**
209 schoenebeck 659 * Reset to normal, chromatic scale (means equal tempered).
210     */
211     void Engine::ResetScaleTuning() {
212     memset(&ScaleTuning[0], 0x00, 12);
213     }
214    
215     /**
216 schoenebeck 473 * Connect this engine instance with the given audio output device.
217     * This method will be called when an Engine instance is created.
218     * All of the engine's data structures which are dependant to the used
219     * audio output device / driver will be (re)allocated and / or
220     * adjusted appropriately.
221     *
222     * @param pAudioOut - audio output device to connect to
223     */
224 schoenebeck 53 void Engine::Connect(AudioOutputDevice* pAudioOut) {
225     pAudioOutputDevice = pAudioOut;
226    
227     ResetInternal();
228    
229     // inform audio driver for the need of two channels
230     try {
231     pAudioOutputDevice->AcquireChannels(2); // gig engine only stereo
232     }
233     catch (AudioOutputException e) {
234     String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
235     throw LinuxSamplerException(msg);
236     }
237 persson 438
238 schoenebeck 460 this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
239     this->SampleRate = pAudioOutputDevice->SampleRate();
240 schoenebeck 225
241 schoenebeck 285 // FIXME: audio drivers with varying fragment sizes might be a problem here
242 schoenebeck 554 MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;
243 schoenebeck 688 if (MaxFadeOutPos < 0) {
244     std::cerr << "gig::Engine: WARNING, CONFIG_EG_MIN_RELEASE_TIME "
245     << "too big for current audio fragment size & sampling rate! "
246 schoenebeck 690 << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;
247 schoenebeck 688 // force volume ramp downs at the beginning of each fragment
248     MaxFadeOutPos = 0;
249     // lower minimum release time
250     const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
251     for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
252     iterVoice->pEG1->CalculateFadeOutCoeff(minReleaseTime, SampleRate);
253     }
254     pVoicePool->clear();
255     }
256 schoenebeck 285
257 schoenebeck 53 // (re)create disk thread
258     if (this->pDiskThread) {
259 senkov 329 dmsg(1,("Stopping disk thread..."));
260 schoenebeck 53 this->pDiskThread->StopThread();
261     delete this->pDiskThread;
262 senkov 329 dmsg(1,("OK\n"));
263 schoenebeck 53 }
264 schoenebeck 554 this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6); //FIXME: assuming stereo
265 schoenebeck 53 if (!pDiskThread) {
266     dmsg(0,("gig::Engine new diskthread = NULL\n"));
267     exit(EXIT_FAILURE);
268     }
269    
270 schoenebeck 271 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
271     iterVoice->pDiskThread = this->pDiskThread;
272 schoenebeck 53 dmsg(3,("d"));
273     }
274     pVoicePool->clear();
275    
276     // (re)create event generator
277     if (pEventGenerator) delete pEventGenerator;
278     pEventGenerator = new EventGenerator(pAudioOut->SampleRate());
279    
280     // (re)allocate synthesis parameter matrix
281 schoenebeck 319 if (pSynthesisParameters[0]) free(pSynthesisParameters[0]);
282 schoenebeck 361
283     #if defined(__APPLE__)
284     pSynthesisParameters[0] = (float *) malloc(Event::destination_count * sizeof(float) * pAudioOut->MaxSamplesPerCycle());
285     #else
286 schoenebeck 319 pSynthesisParameters[0] = (float *) memalign(16,(Event::destination_count * sizeof(float) * pAudioOut->MaxSamplesPerCycle()));
287 schoenebeck 361 #endif
288 schoenebeck 53 for (int dst = 1; dst < Event::destination_count; dst++)
289     pSynthesisParameters[dst] = pSynthesisParameters[dst - 1] + pAudioOut->MaxSamplesPerCycle();
290    
291 schoenebeck 80 // (re)allocate biquad filter parameter sequence
292     if (pBasicFilterParameters) delete[] pBasicFilterParameters;
293     if (pMainFilterParameters) delete[] pMainFilterParameters;
294     pBasicFilterParameters = new biquad_param_t[pAudioOut->MaxSamplesPerCycle()];
295     pMainFilterParameters = new biquad_param_t[pAudioOut->MaxSamplesPerCycle()];
296    
297 schoenebeck 53 dmsg(1,("Starting disk thread..."));
298     pDiskThread->StartThread();
299     dmsg(1,("OK\n"));
300    
301 schoenebeck 271 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
302     if (!iterVoice->pDiskThread) {
303 schoenebeck 53 dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
304     exit(EXIT_FAILURE);
305     }
306     }
307     }
308    
309 schoenebeck 473 /**
310     * Clear all engine global event lists.
311     */
312 schoenebeck 412 void Engine::ClearEventLists() {
313 schoenebeck 460 pGlobalEvents->clear();
314 schoenebeck 412 }
315    
316 schoenebeck 53 /**
317 schoenebeck 460 * Copy all events from the engine's global input queue buffer to the
318     * engine's internal event list. This will be done at the beginning of
319     * each audio cycle (that is each RenderAudio() call) to distinguish
320     * all global events which have to be processed in the current audio
321     * cycle. These events are usually just SysEx messages. Every
322     * EngineChannel has it's own input event queue buffer and event list
323     * to handle common events like NoteOn, NoteOff and ControlChange
324     * events.
325 schoenebeck 412 *
326 schoenebeck 460 * @param Samples - number of sample points to be processed in the
327     * current audio cycle
328 schoenebeck 412 */
329 schoenebeck 460 void Engine::ImportEvents(uint Samples) {
330 schoenebeck 412 RingBuffer<Event>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
331     Event* pEvent;
332     while (true) {
333     // get next event from input event queue
334     if (!(pEvent = eventQueueReader.pop())) break;
335     // if younger event reached, ignore that and all subsequent ones for now
336     if (pEvent->FragmentPos() >= Samples) {
337     eventQueueReader--;
338     dmsg(2,("Younger Event, pos=%d ,Samples=%d!\n",pEvent->FragmentPos(),Samples));
339     pEvent->ResetFragmentPos();
340     break;
341     }
342     // copy event to internal event list
343 schoenebeck 460 if (pGlobalEvents->poolIsEmpty()) {
344 schoenebeck 412 dmsg(1,("Event pool emtpy!\n"));
345     break;
346     }
347 schoenebeck 460 *pGlobalEvents->allocAppend() = *pEvent;
348 schoenebeck 412 }
349     eventQueueReader.free(); // free all copied events from input queue
350 persson 438 }
351 schoenebeck 412
352     /**
353 schoenebeck 53 * Let this engine proceed to render the given amount of sample points. The
354     * calculated audio data of all voices of this engine will be placed into
355     * the engine's audio sum buffer which has to be copied and eventually be
356     * converted to the appropriate value range by the audio output class (e.g.
357     * AlsaIO or JackIO) right after.
358     *
359     * @param Samples - number of sample points to be rendered
360     * @returns 0 on success
361     */
362 schoenebeck 412 int Engine::RenderAudio(uint Samples) {
363 schoenebeck 53 dmsg(5,("RenderAudio(Samples=%d)\n", Samples));
364    
365 schoenebeck 412 // return if engine disabled
366 schoenebeck 53 if (EngineDisabled.Pop()) {
367     dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
368     return 0;
369     }
370    
371 schoenebeck 293 // update time of start and end of this audio fragment (as events' time stamps relate to this)
372     pEventGenerator->UpdateFragmentTime(Samples);
373    
374 schoenebeck 663 // We only allow a maximum of CONFIG_MAX_VOICES voices to be spawned
375     // in each audio fragment. All subsequent request for spawning new
376     // voices in the same audio fragment will be ignored.
377     VoiceSpawnsLeft = CONFIG_MAX_VOICES;
378    
379 schoenebeck 412 // get all events from the engine's global input event queue which belong to the current fragment
380     // (these are usually just SysEx messages)
381 schoenebeck 460 ImportEvents(Samples);
382 schoenebeck 412
383     // process engine global events (these are currently only MIDI System Exclusive messages)
384     {
385 schoenebeck 460 RTList<Event>::Iterator itEvent = pGlobalEvents->first();
386     RTList<Event>::Iterator end = pGlobalEvents->end();
387 schoenebeck 412 for (; itEvent != end; ++itEvent) {
388     switch (itEvent->Type) {
389     case Event::type_sysex:
390     dmsg(5,("Engine: Sysex received\n"));
391     ProcessSysex(itEvent);
392     break;
393     }
394     }
395 schoenebeck 53 }
396 schoenebeck 412
397     // reset internal voice counter (just for statistic of active voices)
398     ActiveVoiceCountTemp = 0;
399    
400 schoenebeck 466 // handle events on all engine channels
401 schoenebeck 460 for (int i = 0; i < engineChannels.size(); i++) {
402     if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded
403     ProcessEvents(engineChannels[i], Samples);
404 schoenebeck 466 }
405    
406     // render all 'normal', active voices on all engine channels
407     for (int i = 0; i < engineChannels.size(); i++) {
408     if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded
409 schoenebeck 460 RenderActiveVoices(engineChannels[i], Samples);
410 schoenebeck 412 }
411    
412 schoenebeck 460 // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
413     RenderStolenVoices(Samples);
414    
415     // handle cleanup on all engine channels for the next audio fragment
416     for (int i = 0; i < engineChannels.size(); i++) {
417     if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded
418     PostProcess(engineChannels[i]);
419     }
420    
421    
422     // empty the engine's event list for the next audio fragment
423     ClearEventLists();
424    
425     // reset voice stealing for the next audio fragment
426     pVoiceStealingQueue->clear();
427    
428 schoenebeck 412 // just some statistics about this engine instance
429     ActiveVoiceCount = ActiveVoiceCountTemp;
430     if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
431    
432 persson 630 FrameTime += Samples;
433    
434 schoenebeck 412 return 0;
435     }
436    
437 schoenebeck 473 /**
438     * Dispatch and handle all events in this audio fragment for the given
439     * engine channel.
440     *
441     * @param pEngineChannel - engine channel on which events should be
442     * processed
443     * @param Samples - amount of sample points to be processed in
444     * this audio fragment cycle
445     */
446 schoenebeck 460 void Engine::ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
447 schoenebeck 412 // get all events from the engine channels's input event queue which belong to the current fragment
448     // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
449 schoenebeck 460 pEngineChannel->ImportEvents(Samples);
450 schoenebeck 53
451     // process events
452 schoenebeck 271 {
453 schoenebeck 460 RTList<Event>::Iterator itEvent = pEngineChannel->pEvents->first();
454     RTList<Event>::Iterator end = pEngineChannel->pEvents->end();
455 schoenebeck 271 for (; itEvent != end; ++itEvent) {
456     switch (itEvent->Type) {
457     case Event::type_note_on:
458     dmsg(5,("Engine: Note on received\n"));
459 schoenebeck 412 ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
460 schoenebeck 271 break;
461     case Event::type_note_off:
462     dmsg(5,("Engine: Note off received\n"));
463 schoenebeck 412 ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
464 schoenebeck 271 break;
465     case Event::type_control_change:
466     dmsg(5,("Engine: MIDI CC received\n"));
467 schoenebeck 412 ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
468 schoenebeck 271 break;
469     case Event::type_pitchbend:
470     dmsg(5,("Engine: Pitchbend received\n"));
471 schoenebeck 412 ProcessPitchbend((EngineChannel*)itEvent->pEngineChannel, itEvent);
472 schoenebeck 271 break;
473     }
474 schoenebeck 53 }
475     }
476 schoenebeck 649
477     // reset voice stealing for the next engine channel (or next audio fragment)
478     itLastStolenVoice = RTList<Voice>::Iterator();
479     itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
480     iuiLastStolenKey = RTList<uint>::Iterator();
481     iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
482     pLastStolenChannel = NULL;
483 schoenebeck 460 }
484 schoenebeck 53
485 schoenebeck 473 /**
486     * Render all 'normal' voices (that is voices which were not stolen in
487     * this fragment) on the given engine channel.
488     *
489     * @param pEngineChannel - engine channel on which audio should be
490     * rendered
491     * @param Samples - amount of sample points to be rendered in
492     * this audio fragment cycle
493     */
494 schoenebeck 460 void Engine::RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
495 schoenebeck 705 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
496    
497 schoenebeck 460 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
498     RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
499     while (iuiKey != end) { // iterate through all active keys
500     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
501     ++iuiKey;
502 schoenebeck 53
503 schoenebeck 460 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
504     RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
505     for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
506     // now render current voice
507     itVoice->Render(Samples);
508     if (itVoice->IsActive()) ActiveVoiceCountTemp++; // still active
509     else { // voice reached end, is now inactive
510     FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices
511 schoenebeck 53 }
512     }
513     }
514 schoenebeck 460 }
515 schoenebeck 53
516 schoenebeck 473 /**
517     * Render all stolen voices (only voices which were stolen in this
518     * fragment) on the given engine channel. Stolen voices are rendered
519     * after all normal voices have been rendered; this is needed to render
520     * audio of those voices which were selected for voice stealing until
521     * the point were the stealing (that is the take over of the voice)
522     * actually happened.
523     *
524     * @param pEngineChannel - engine channel on which audio should be
525     * rendered
526     * @param Samples - amount of sample points to be rendered in
527     * this audio fragment cycle
528     */
529 schoenebeck 460 void Engine::RenderStolenVoices(uint Samples) {
530     RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
531     RTList<Event>::Iterator end = pVoiceStealingQueue->end();
532     for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
533     EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
534     Pool<Voice>::Iterator itNewVoice =
535 schoenebeck 668 LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
536 schoenebeck 460 if (itNewVoice) {
537     itNewVoice->Render(Samples);
538     if (itNewVoice->IsActive()) ActiveVoiceCountTemp++; // still active
539     else { // voice reached end, is now inactive
540     FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices
541 schoenebeck 250 }
542     }
543 schoenebeck 460 else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));
544 schoenebeck 473
545     // we need to clear the key's event list explicitly here in case key was never active
546     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoiceStealEvent->Param.Note.Key];
547     pKey->VoiceTheftsQueued--;
548     if (!pKey->Active && !pKey->VoiceTheftsQueued) pKey->pEvents->clear();
549 schoenebeck 250 }
550 schoenebeck 460 }
551 schoenebeck 250
552 schoenebeck 473 /**
553     * Free all keys which have turned inactive in this audio fragment, from
554     * the list of active keys and clear all event lists on that engine
555     * channel.
556     *
557     * @param pEngineChannel - engine channel to cleanup
558     */
559 schoenebeck 460 void Engine::PostProcess(EngineChannel* pEngineChannel) {
560 schoenebeck 287 // free all keys which have no active voices left
561     {
562 schoenebeck 411 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
563     RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
564 schoenebeck 287 while (iuiKey != end) { // iterate through all active keys
565 schoenebeck 411 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
566 schoenebeck 287 ++iuiKey;
567 schoenebeck 411 if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);
568 schoenebeck 554 #if CONFIG_DEVMODE
569 schoenebeck 563 else { // just a sanity check for debugging
570 schoenebeck 287 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
571     RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
572     for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
573     if (itVoice->itKillEvent) {
574     dmsg(1,("gig::Engine: ERROR, killed voice survived !!!\n"));
575     }
576     }
577     }
578 schoenebeck 554 #endif // CONFIG_DEVMODE
579 schoenebeck 287 }
580     }
581 schoenebeck 460
582     // empty the engine channel's own event lists
583     pEngineChannel->ClearEventLists();
584 schoenebeck 412 }
585 schoenebeck 287
586 schoenebeck 53 /**
587 schoenebeck 244 * Will be called by the MIDI input device whenever a MIDI system
588     * exclusive message has arrived.
589     *
590     * @param pData - pointer to sysex data
591     * @param Size - lenght of sysex data (in bytes)
592     */
593     void Engine::SendSysex(void* pData, uint Size) {
594 schoenebeck 246 Event event = pEventGenerator->CreateEvent();
595     event.Type = Event::type_sysex;
596     event.Param.Sysex.Size = Size;
597 schoenebeck 412 event.pEngineChannel = NULL; // as Engine global event
598 schoenebeck 244 if (pEventQueue->write_space() > 0) {
599     if (pSysexBuffer->write_space() >= Size) {
600     // copy sysex data to input buffer
601     uint toWrite = Size;
602     uint8_t* pPos = (uint8_t*) pData;
603     while (toWrite) {
604     const uint writeNow = RTMath::Min(toWrite, pSysexBuffer->write_space_to_end());
605     pSysexBuffer->write(pPos, writeNow);
606     toWrite -= writeNow;
607     pPos += writeNow;
608    
609     }
610     // finally place sysex event into input event queue
611     pEventQueue->push(&event);
612     }
613 schoenebeck 554 else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,CONFIG_SYSEX_BUFFER_SIZE));
614 schoenebeck 244 }
615     else dmsg(1,("Engine: Input event queue full!"));
616     }
617    
618     /**
619 schoenebeck 53 * Assigns and triggers a new voice for the respective MIDI key.
620     *
621 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
622 schoenebeck 271 * @param itNoteOnEvent - key, velocity and time stamp of the event
623 schoenebeck 53 */
624 schoenebeck 411 void Engine::ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
625 schoenebeck 705 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
626 persson 438
627 schoenebeck 354 const int key = itNoteOnEvent->Param.Note.Key;
628    
629     // Change key dimension value if key is in keyswitching area
630 schoenebeck 411 {
631     const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
632     if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
633     pEngineChannel->CurrentKeyDimension = ((key - pInstrument->DimensionKeyRange.low) * 128) /
634     (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
635     }
636 schoenebeck 354
637 schoenebeck 411 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
638 schoenebeck 354
639 schoenebeck 53 pKey->KeyPressed = true; // the MIDI key was now pressed down
640 persson 630 pKey->Velocity = itNoteOnEvent->Param.Note.Velocity;
641     pKey->NoteOnTime = FrameTime + itNoteOnEvent->FragmentPos(); // will be used to calculate note length
642 schoenebeck 53
643     // cancel release process of voices on this key if needed
644 schoenebeck 411 if (pKey->Active && !pEngineChannel->SustainPedal) {
645 schoenebeck 271 RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
646     if (itCancelReleaseEvent) {
647     *itCancelReleaseEvent = *itNoteOnEvent; // copy event
648     itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
649 schoenebeck 239 }
650     else dmsg(1,("Event pool emtpy!\n"));
651 schoenebeck 53 }
652    
653 schoenebeck 271 // move note on event to the key's own event list
654     RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
655    
656 schoenebeck 460 // allocate and trigger new voice(s) for the key
657     {
658     // first, get total amount of required voices (dependant on amount of layers)
659     ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOnEventOnKeyList->Param.Note.Key);
660     if (pRegion) {
661     int voicesRequired = pRegion->Layers;
662     // now launch the required amount of voices
663     for (int i = 0; i < voicesRequired; i++)
664 schoenebeck 668 LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true, true);
665 schoenebeck 460 }
666     }
667 persson 438
668 schoenebeck 473 // if neither a voice was spawned or postponed then remove note on event from key again
669     if (!pKey->Active && !pKey->VoiceTheftsQueued)
670     pKey->pEvents->free(itNoteOnEventOnKeyList);
671    
672 persson 438 pKey->RoundRobinIndex++;
673 schoenebeck 53 }
674    
675     /**
676     * Releases the voices on the given key if sustain pedal is not pressed.
677     * If sustain is pressed, the release of the note will be postponed until
678     * sustain pedal will be released or voice turned inactive by itself (e.g.
679     * due to completion of sample playback).
680     *
681 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
682 schoenebeck 271 * @param itNoteOffEvent - key, velocity and time stamp of the event
683 schoenebeck 53 */
684 schoenebeck 411 void Engine::ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
685 schoenebeck 705 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
686    
687 schoenebeck 411 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itNoteOffEvent->Param.Note.Key];
688 schoenebeck 53 pKey->KeyPressed = false; // the MIDI key was now released
689    
690     // release voices on this key if needed
691 schoenebeck 411 if (pKey->Active && !pEngineChannel->SustainPedal) {
692 schoenebeck 271 itNoteOffEvent->Type = Event::type_release; // transform event type
693 schoenebeck 242
694 persson 497 // move event to the key's own event list
695     RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
696 schoenebeck 271
697 persson 497 // spawn release triggered voice(s) if needed
698 persson 630 if (pKey->ReleaseTrigger) {
699 persson 497 // first, get total amount of required voices (dependant on amount of layers)
700     ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
701     if (pRegion) {
702     int voicesRequired = pRegion->Layers;
703 persson 630
704     // MIDI note-on velocity is used instead of note-off velocity
705     itNoteOffEventOnKeyList->Param.Note.Velocity = pKey->Velocity;
706    
707 persson 497 // now launch the required amount of voices
708     for (int i = 0; i < voicesRequired; i++)
709 schoenebeck 668 LaunchVoice(pEngineChannel, itNoteOffEventOnKeyList, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples
710 persson 497 }
711     pKey->ReleaseTrigger = false;
712 schoenebeck 460 }
713 persson 497
714     // if neither a voice was spawned or postponed then remove note off event from key again
715     if (!pKey->Active && !pKey->VoiceTheftsQueued)
716     pKey->pEvents->free(itNoteOffEventOnKeyList);
717 schoenebeck 242 }
718 schoenebeck 53 }
719    
720     /**
721     * Moves pitchbend event from the general (input) event list to the pitch
722     * event list.
723     *
724 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
725 schoenebeck 271 * @param itPitchbendEvent - absolute pitch value and time stamp of the event
726 schoenebeck 53 */
727 schoenebeck 411 void Engine::ProcessPitchbend(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
728     pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
729 schoenebeck 460 itPitchbendEvent.moveToEndOf(pEngineChannel->pSynthesisEvents[Event::destination_vco]);
730 schoenebeck 53 }
731    
732     /**
733 schoenebeck 233 * Allocates and triggers a new voice. This method will usually be
734     * called by the ProcessNoteOn() method and by the voices itself
735     * (e.g. to spawn further voices on the same key for layered sounds).
736     *
737 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
738 schoenebeck 271 * @param itNoteOnEvent - key, velocity and time stamp of the event
739 schoenebeck 242 * @param iLayer - layer index for the new voice (optional - only
740     * in case of layered sounds of course)
741     * @param ReleaseTriggerVoice - if new voice is a release triggered voice
742     * (optional, default = false)
743 schoenebeck 250 * @param VoiceStealing - if voice stealing should be performed
744     * when there is no free voice
745     * (optional, default = true)
746 schoenebeck 668 * @param HandleKeyGroupConflicts - if voices should be killed due to a
747     * key group conflict
748 schoenebeck 250 * @returns pointer to new voice or NULL if there was no free voice or
749 schoenebeck 354 * if the voice wasn't triggered (for example when no region is
750     * defined for the given key).
751 schoenebeck 233 */
752 schoenebeck 668 Pool<Voice>::Iterator Engine::LaunchVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing, bool HandleKeyGroupConflicts) {
753 schoenebeck 669 int MIDIKey = itNoteOnEvent->Param.Note.Key;
754     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[MIDIKey];
755     ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(MIDIKey);
756 schoenebeck 233
757 schoenebeck 668 // if nothing defined for this key
758     if (!pRegion) return Pool<Voice>::Iterator(); // nothing to do
759    
760 schoenebeck 669 // only mark the first voice of a layered voice (group) to be in a
761     // key group, so the layered voices won't kill each other
762     int iKeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0;
763    
764 schoenebeck 668 // handle key group (a.k.a. exclusive group) conflicts
765     if (HandleKeyGroupConflicts) {
766     if (iKeyGroup) { // if this voice / key belongs to a key group
767     uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[iKeyGroup];
768     if (*ppKeyGroup) { // if there's already an active key in that key group
769     midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[**ppKeyGroup];
770     // kill all voices on the (other) key
771     RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
772     RTList<Voice>::Iterator end = pOtherKey->pActiveVoices->end();
773     for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
774     if (itVoiceToBeKilled->Type != Voice::type_release_trigger) {
775     itVoiceToBeKilled->Kill(itNoteOnEvent);
776     --VoiceSpawnsLeft; //FIXME: just a hack, we should better check in StealVoice() if the voice was killed due to key conflict
777     }
778     }
779     }
780     }
781     }
782    
783 schoenebeck 669 Voice::type_t VoiceType = Voice::type_normal;
784    
785     // get current dimension values to select the right dimension region
786     //TODO: for stolen voices this dimension region selection block is processed twice, this should be changed
787     //FIXME: controller values for selecting the dimension region here are currently not sample accurate
788     uint DimValues[8] = { 0 };
789     for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
790     switch (pRegion->pDimensionDefinitions[i].dimension) {
791     case ::gig::dimension_samplechannel:
792     DimValues[i] = 0; //TODO: we currently ignore this dimension
793     break;
794     case ::gig::dimension_layer:
795     DimValues[i] = iLayer;
796     break;
797     case ::gig::dimension_velocity:
798     DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
799     break;
800     case ::gig::dimension_channelaftertouch:
801     DimValues[i] = 0; //TODO: we currently ignore this dimension
802     break;
803     case ::gig::dimension_releasetrigger:
804     VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal;
805     DimValues[i] = (uint) ReleaseTriggerVoice;
806     break;
807     case ::gig::dimension_keyboard:
808     DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension;
809     break;
810     case ::gig::dimension_roundrobin:
811     DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
812     break;
813     case ::gig::dimension_random:
814     RandomSeed = RandomSeed * 1103515245 + 12345; // classic pseudo random number generator
815     DimValues[i] = (uint) RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random
816     break;
817     case ::gig::dimension_modwheel:
818     DimValues[i] = pEngineChannel->ControllerTable[1];
819     break;
820     case ::gig::dimension_breath:
821     DimValues[i] = pEngineChannel->ControllerTable[2];
822     break;
823     case ::gig::dimension_foot:
824     DimValues[i] = pEngineChannel->ControllerTable[4];
825     break;
826     case ::gig::dimension_portamentotime:
827     DimValues[i] = pEngineChannel->ControllerTable[5];
828     break;
829     case ::gig::dimension_effect1:
830     DimValues[i] = pEngineChannel->ControllerTable[12];
831     break;
832     case ::gig::dimension_effect2:
833     DimValues[i] = pEngineChannel->ControllerTable[13];
834     break;
835     case ::gig::dimension_genpurpose1:
836     DimValues[i] = pEngineChannel->ControllerTable[16];
837     break;
838     case ::gig::dimension_genpurpose2:
839     DimValues[i] = pEngineChannel->ControllerTable[17];
840     break;
841     case ::gig::dimension_genpurpose3:
842     DimValues[i] = pEngineChannel->ControllerTable[18];
843     break;
844     case ::gig::dimension_genpurpose4:
845     DimValues[i] = pEngineChannel->ControllerTable[19];
846     break;
847     case ::gig::dimension_sustainpedal:
848     DimValues[i] = pEngineChannel->ControllerTable[64];
849     break;
850     case ::gig::dimension_portamento:
851     DimValues[i] = pEngineChannel->ControllerTable[65];
852     break;
853     case ::gig::dimension_sostenutopedal:
854     DimValues[i] = pEngineChannel->ControllerTable[66];
855     break;
856     case ::gig::dimension_softpedal:
857     DimValues[i] = pEngineChannel->ControllerTable[67];
858     break;
859     case ::gig::dimension_genpurpose5:
860     DimValues[i] = pEngineChannel->ControllerTable[80];
861     break;
862     case ::gig::dimension_genpurpose6:
863     DimValues[i] = pEngineChannel->ControllerTable[81];
864     break;
865     case ::gig::dimension_genpurpose7:
866     DimValues[i] = pEngineChannel->ControllerTable[82];
867     break;
868     case ::gig::dimension_genpurpose8:
869     DimValues[i] = pEngineChannel->ControllerTable[83];
870     break;
871     case ::gig::dimension_effect1depth:
872     DimValues[i] = pEngineChannel->ControllerTable[91];
873     break;
874     case ::gig::dimension_effect2depth:
875     DimValues[i] = pEngineChannel->ControllerTable[92];
876     break;
877     case ::gig::dimension_effect3depth:
878     DimValues[i] = pEngineChannel->ControllerTable[93];
879     break;
880     case ::gig::dimension_effect4depth:
881     DimValues[i] = pEngineChannel->ControllerTable[94];
882     break;
883     case ::gig::dimension_effect5depth:
884     DimValues[i] = pEngineChannel->ControllerTable[95];
885     break;
886     case ::gig::dimension_none:
887     std::cerr << "gig::Engine::LaunchVoice() Error: dimension=none\n" << std::flush;
888     break;
889     default:
890     std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;
891     }
892     }
893     ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
894    
895     // no need to continue if sample is silent
896     if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator();
897    
898 schoenebeck 233 // allocate a new voice for the key
899 schoenebeck 271 Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();
900     if (itNewVoice) {
901 schoenebeck 233 // launch the new voice
902 schoenebeck 669 if (itNewVoice->Trigger(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pDimRgn, VoiceType, iKeyGroup) < 0) {
903 schoenebeck 354 dmsg(4,("Voice not triggered\n"));
904 schoenebeck 271 pKey->pActiveVoices->free(itNewVoice);
905 schoenebeck 233 }
906 schoenebeck 239 else { // on success
907 schoenebeck 663 --VoiceSpawnsLeft;
908 schoenebeck 239 if (!pKey->Active) { // mark as active key
909     pKey->Active = true;
910 schoenebeck 411 pKey->itSelf = pEngineChannel->pActiveKeys->allocAppend();
911 schoenebeck 271 *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
912 schoenebeck 239 }
913 schoenebeck 271 if (itNewVoice->KeyGroup) {
914 schoenebeck 668 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[itNewVoice->KeyGroup];
915 schoenebeck 271 *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group
916 schoenebeck 239 }
917 schoenebeck 271 if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
918     return itNewVoice; // success
919 schoenebeck 233 }
920     }
921 schoenebeck 285 else if (VoiceStealing) {
922 schoenebeck 460 // try to steal one voice
923 schoenebeck 473 int result = StealVoice(pEngineChannel, itNoteOnEvent);
924     if (!result) { // voice stolen successfully
925     // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
926     RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
927     if (itStealEvent) {
928     *itStealEvent = *itNoteOnEvent; // copy event
929     itStealEvent->Param.Note.Layer = iLayer;
930     itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
931     pKey->VoiceTheftsQueued++;
932     }
933     else dmsg(1,("Voice stealing queue full!\n"));
934 schoenebeck 285 }
935     }
936    
937 schoenebeck 271 return Pool<Voice>::Iterator(); // no free voice or error
938 schoenebeck 233 }
939    
940     /**
941 schoenebeck 250 * Will be called by LaunchVoice() method in case there are no free
942     * voices left. This method will select and kill one old voice for
943     * voice stealing and postpone the note-on event until the selected
944     * voice actually died.
945     *
946 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
947 schoenebeck 285 * @param itNoteOnEvent - key, velocity and time stamp of the event
948 schoenebeck 473 * @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
949 schoenebeck 250 */
950 schoenebeck 473 int Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
951 schoenebeck 663 if (VoiceSpawnsLeft <= 0) {
952 schoenebeck 554 dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
953 schoenebeck 473 return -1;
954 schoenebeck 460 }
955 schoenebeck 271 if (!pEventPool->poolIsEmpty()) {
956 schoenebeck 250
957 schoenebeck 460 RTList<Voice>::Iterator itSelectedVoice;
958 schoenebeck 250
959     // Select one voice for voice stealing
960 schoenebeck 554 switch (CONFIG_VOICE_STEAL_ALGO) {
961 schoenebeck 250
962     // try to pick the oldest voice on the key where the new
963     // voice should be spawned, if there is no voice on that
964 schoenebeck 563 // key, or no voice left to kill, then procceed with
965 schoenebeck 250 // 'oldestkey' algorithm
966 schoenebeck 460 case voice_steal_algo_oldestvoiceonkey: {
967     midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
968 schoenebeck 563 itSelectedVoice = pSelectedKey->pActiveVoices->first();
969     // proceed iterating if voice was created in this fragment cycle
970 schoenebeck 663 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
971 schoenebeck 563 // if we haven't found a voice then proceed with algorithm 'oldestkey'
972 schoenebeck 663 if (itSelectedVoice && itSelectedVoice->IsStealable()) break;
973 schoenebeck 250 } // no break - intentional !
974    
975     // try to pick the oldest voice on the oldest active key
976 schoenebeck 563 // from the same engine channel
977 schoenebeck 460 // (caution: must stay after 'oldestvoiceonkey' algorithm !)
978 schoenebeck 250 case voice_steal_algo_oldestkey: {
979 schoenebeck 649 // if we already stole in this fragment, try to proceed on same key
980 schoenebeck 460 if (this->itLastStolenVoice) {
981     itSelectedVoice = this->itLastStolenVoice;
982 schoenebeck 649 do {
983     ++itSelectedVoice;
984 schoenebeck 663 } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
985 schoenebeck 649 // found a "stealable" voice ?
986 schoenebeck 663 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
987 schoenebeck 649 // remember which voice we stole, so we can simply proceed on next voice stealing
988     this->itLastStolenVoice = itSelectedVoice;
989 schoenebeck 460 break; // selection succeeded
990 schoenebeck 250 }
991     }
992 schoenebeck 649 // get (next) oldest key
993     RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKey) ? ++this->iuiLastStolenKey : pEngineChannel->pActiveKeys->first();
994     while (iuiSelectedKey) {
995     midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];
996 schoenebeck 659 itSelectedVoice = pSelectedKey->pActiveVoices->first();
997 schoenebeck 649 // proceed iterating if voice was created in this fragment cycle
998 schoenebeck 663 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
999 schoenebeck 649 // found a "stealable" voice ?
1000 schoenebeck 663 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1001 schoenebeck 649 // remember which voice on which key we stole, so we can simply proceed on next voice stealing
1002     this->iuiLastStolenKey = iuiSelectedKey;
1003     this->itLastStolenVoice = itSelectedVoice;
1004     break; // selection succeeded
1005     }
1006     ++iuiSelectedKey; // get next oldest key
1007     }
1008 schoenebeck 250 break;
1009     }
1010    
1011     // don't steal anything
1012     case voice_steal_algo_none:
1013     default: {
1014     dmsg(1,("No free voice (voice stealing disabled)!\n"));
1015 schoenebeck 473 return -1;
1016 schoenebeck 250 }
1017     }
1018    
1019 schoenebeck 563 // if we couldn't steal a voice from the same engine channel then
1020     // steal oldest voice on the oldest key from any other engine channel
1021 schoenebeck 649 // (the smaller engine channel number, the higher priority)
1022 schoenebeck 663 if (!itSelectedVoice || !itSelectedVoice->IsStealable()) {
1023 schoenebeck 649 EngineChannel* pSelectedChannel;
1024     int iChannelIndex;
1025     // select engine channel
1026     if (pLastStolenChannel) {
1027     pSelectedChannel = pLastStolenChannel;
1028     iChannelIndex = pSelectedChannel->iEngineIndexSelf;
1029     } else { // pick the engine channel followed by this engine channel
1030     iChannelIndex = (pEngineChannel->iEngineIndexSelf + 1) % engineChannels.size();
1031     pSelectedChannel = engineChannels[iChannelIndex];
1032     }
1033 schoenebeck 663
1034     // if we already stole in this fragment, try to proceed on same key
1035     if (this->itLastStolenVoiceGlobally) {
1036     itSelectedVoice = this->itLastStolenVoiceGlobally;
1037     do {
1038     ++itSelectedVoice;
1039     } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1040     }
1041    
1042     #if CONFIG_DEVMODE
1043     EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1044     #endif // CONFIG_DEVMODE
1045    
1046     // did we find a 'stealable' voice?
1047     if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1048     // remember which voice we stole, so we can simply proceed on next voice stealing
1049     this->itLastStolenVoiceGlobally = itSelectedVoice;
1050     } else while (true) { // iterate through engine channels
1051 schoenebeck 649 // get (next) oldest key
1052 schoenebeck 663 RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
1053     this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
1054 schoenebeck 649 while (iuiSelectedKey) {
1055 schoenebeck 663 midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1056 schoenebeck 649 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1057     // proceed iterating if voice was created in this fragment cycle
1058 schoenebeck 663 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1059 schoenebeck 649 // found a "stealable" voice ?
1060 schoenebeck 663 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1061 schoenebeck 649 // remember which voice on which key on which engine channel we stole, so we can simply proceed on next voice stealing
1062     this->iuiLastStolenKeyGlobally = iuiSelectedKey;
1063     this->itLastStolenVoiceGlobally = itSelectedVoice;
1064     this->pLastStolenChannel = pSelectedChannel;
1065 schoenebeck 665 goto stealable_voice_found; // selection succeeded
1066 schoenebeck 649 }
1067     ++iuiSelectedKey; // get next key on current engine channel
1068     }
1069     // get next engine channel
1070 schoenebeck 460 iChannelIndex = (iChannelIndex + 1) % engineChannels.size();
1071 schoenebeck 649 pSelectedChannel = engineChannels[iChannelIndex];
1072 schoenebeck 663
1073     #if CONFIG_DEVMODE
1074     if (pSelectedChannel == pBegin) {
1075     dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1076     dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1077     dmsg(1,("Exiting.\n"));
1078     exit(-1);
1079     }
1080     #endif // CONFIG_DEVMODE
1081 schoenebeck 460 }
1082     }
1083    
1084 schoenebeck 665 // jump point if a 'stealable' voice was found
1085     stealable_voice_found:
1086    
1087 schoenebeck 563 #if CONFIG_DEVMODE
1088 schoenebeck 473 if (!itSelectedVoice->IsActive()) {
1089     dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
1090     return -1;
1091     }
1092 schoenebeck 563 #endif // CONFIG_DEVMODE
1093 schoenebeck 287
1094 schoenebeck 250 // now kill the selected voice
1095 schoenebeck 659 itSelectedVoice->Kill(itNoteOnEvent);
1096 schoenebeck 460
1097 schoenebeck 663 --VoiceSpawnsLeft;
1098 schoenebeck 473
1099     return 0; // success
1100 schoenebeck 250 }
1101 schoenebeck 473 else {
1102     dmsg(1,("Event pool emtpy!\n"));
1103     return -1;
1104     }
1105 schoenebeck 250 }
1106    
1107     /**
1108 schoenebeck 285 * Removes the given voice from the MIDI key's list of active voices.
1109     * This method will be called when a voice went inactive, e.g. because
1110     * it finished to playback its sample, finished its release stage or
1111     * just was killed.
1112 schoenebeck 53 *
1113 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
1114 schoenebeck 285 * @param itVoice - points to the voice to be freed
1115 schoenebeck 53 */
1116 schoenebeck 411 void Engine::FreeVoice(EngineChannel* pEngineChannel, Pool<Voice>::Iterator& itVoice) {
1117 schoenebeck 271 if (itVoice) {
1118 schoenebeck 411 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoice->MIDIKey];
1119 schoenebeck 53
1120 schoenebeck 271 uint keygroup = itVoice->KeyGroup;
1121    
1122 schoenebeck 53 // free the voice object
1123 schoenebeck 271 pVoicePool->free(itVoice);
1124 schoenebeck 53
1125 schoenebeck 287 // if no other voices left and member of a key group, remove from key group
1126     if (pKey->pActiveVoices->isEmpty() && keygroup) {
1127 schoenebeck 411 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[keygroup];
1128 schoenebeck 287 if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group
1129 schoenebeck 53 }
1130     }
1131 schoenebeck 285 else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;
1132 schoenebeck 53 }
1133    
1134     /**
1135 schoenebeck 287 * Called when there's no more voice left on a key, this call will
1136     * update the key info respectively.
1137     *
1138 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
1139 schoenebeck 287 * @param pKey - key which is now inactive
1140     */
1141 schoenebeck 411 void Engine::FreeKey(EngineChannel* pEngineChannel, midi_key_info_t* pKey) {
1142 schoenebeck 287 if (pKey->pActiveVoices->isEmpty()) {
1143     pKey->Active = false;
1144 schoenebeck 411 pEngineChannel->pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
1145 schoenebeck 287 pKey->itSelf = RTList<uint>::Iterator();
1146     pKey->ReleaseTrigger = false;
1147     pKey->pEvents->clear();
1148     dmsg(3,("Key has no more voices now\n"));
1149     }
1150     else dmsg(1,("gig::Engine: Oops, tried to free a key which contains voices.\n"));
1151     }
1152    
1153     /**
1154 schoenebeck 53 * Reacts on supported control change commands (e.g. pitch bend wheel,
1155     * modulation wheel, aftertouch).
1156     *
1157 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
1158 schoenebeck 271 * @param itControlChangeEvent - controller, value and time stamp of the event
1159 schoenebeck 53 */
1160 schoenebeck 411 void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {
1161 schoenebeck 271 dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));
1162 schoenebeck 53
1163 schoenebeck 473 // update controller value in the engine channel's controller table
1164     pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1165    
1166     // move event from the unsorted event list to the control change event list
1167     Pool<Event>::Iterator itControlChangeEventOnCCList = itControlChangeEvent.moveToEndOf(pEngineChannel->pCCEvents);
1168    
1169     switch (itControlChangeEventOnCCList->Param.CC.Controller) {
1170 schoenebeck 424 case 7: { // volume
1171     //TODO: not sample accurate yet
1172 schoenebeck 473 pEngineChannel->GlobalVolume = (float) itControlChangeEventOnCCList->Param.CC.Value / 127.0f;
1173 schoenebeck 660 pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1174 schoenebeck 424 break;
1175     }
1176     case 10: { // panpot
1177     //TODO: not sample accurate yet
1178 schoenebeck 473 const int pan = (int) itControlChangeEventOnCCList->Param.CC.Value - 64;
1179 schoenebeck 424 pEngineChannel->GlobalPanLeft = 1.0f - float(RTMath::Max(pan, 0)) / 63.0f;
1180     pEngineChannel->GlobalPanRight = 1.0f - float(RTMath::Min(pan, 0)) / -64.0f;
1181     break;
1182     }
1183     case 64: { // sustain
1184 schoenebeck 473 if (itControlChangeEventOnCCList->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1185 schoenebeck 53 dmsg(4,("PEDAL DOWN\n"));
1186 schoenebeck 411 pEngineChannel->SustainPedal = true;
1187 schoenebeck 53
1188 schoenebeck 705 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1189    
1190 schoenebeck 53 // cancel release process of voices if necessary
1191 schoenebeck 411 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1192 schoenebeck 473 for (; iuiKey; ++iuiKey) {
1193     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1194     if (!pKey->KeyPressed) {
1195     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1196     if (itNewEvent) {
1197     *itNewEvent = *itControlChangeEventOnCCList; // copy event to the key's own event list
1198     itNewEvent->Type = Event::type_cancel_release; // transform event type
1199 schoenebeck 53 }
1200 schoenebeck 473 else dmsg(1,("Event pool emtpy!\n"));
1201 schoenebeck 53 }
1202     }
1203     }
1204 schoenebeck 473 if (itControlChangeEventOnCCList->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1205 schoenebeck 53 dmsg(4,("PEDAL UP\n"));
1206 schoenebeck 411 pEngineChannel->SustainPedal = false;
1207 schoenebeck 53
1208 schoenebeck 705 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1209    
1210 schoenebeck 53 // release voices if their respective key is not pressed
1211 schoenebeck 411 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1212 schoenebeck 473 for (; iuiKey; ++iuiKey) {
1213     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1214     if (!pKey->KeyPressed) {
1215     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1216     if (itNewEvent) {
1217     *itNewEvent = *itControlChangeEventOnCCList; // copy event to the key's own event list
1218     itNewEvent->Type = Event::type_release; // transform event type
1219 schoenebeck 53 }
1220 schoenebeck 473 else dmsg(1,("Event pool emtpy!\n"));
1221 schoenebeck 53 }
1222     }
1223     }
1224     break;
1225     }
1226    
1227    
1228 schoenebeck 473 // Channel Mode Messages
1229    
1230     case 120: { // all sound off
1231     KillAllVoices(pEngineChannel, itControlChangeEventOnCCList);
1232     break;
1233     }
1234     case 121: { // reset all controllers
1235     pEngineChannel->ResetControllers();
1236     break;
1237     }
1238     case 123: { // all notes off
1239     ReleaseAllVoices(pEngineChannel, itControlChangeEventOnCCList);
1240     break;
1241     }
1242     }
1243 schoenebeck 53 }
1244    
1245     /**
1246 schoenebeck 244 * Reacts on MIDI system exclusive messages.
1247     *
1248 schoenebeck 271 * @param itSysexEvent - sysex data size and time stamp of the sysex event
1249 schoenebeck 244 */
1250 schoenebeck 271 void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1251 schoenebeck 244 RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1252    
1253     uint8_t exclusive_status, id;
1254     if (!reader.pop(&exclusive_status)) goto free_sysex_data;
1255     if (!reader.pop(&id)) goto free_sysex_data;
1256     if (exclusive_status != 0xF0) goto free_sysex_data;
1257    
1258     switch (id) {
1259     case 0x41: { // Roland
1260 schoenebeck 493 dmsg(3,("Roland Sysex\n"));
1261 schoenebeck 244 uint8_t device_id, model_id, cmd_id;
1262     if (!reader.pop(&device_id)) goto free_sysex_data;
1263     if (!reader.pop(&model_id)) goto free_sysex_data;
1264     if (!reader.pop(&cmd_id)) goto free_sysex_data;
1265     if (model_id != 0x42 /*GS*/) goto free_sysex_data;
1266     if (cmd_id != 0x12 /*DT1*/) goto free_sysex_data;
1267    
1268     // command address
1269     uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
1270     const RingBuffer<uint8_t>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
1271     if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1272     if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1273 schoenebeck 493 dmsg(3,("\tSystem Parameter\n"));
1274 schoenebeck 244 }
1275     else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
1276 schoenebeck 493 dmsg(3,("\tCommon Parameter\n"));
1277 schoenebeck 244 }
1278     else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
1279 schoenebeck 493 dmsg(3,("\tPart Parameter\n"));
1280     switch (addr[2]) {
1281 schoenebeck 244 case 0x40: { // scale tuning
1282 schoenebeck 493 dmsg(3,("\t\tScale Tuning\n"));
1283 schoenebeck 244 uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
1284     if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
1285     uint8_t checksum;
1286 schoenebeck 493 if (!reader.pop(&checksum)) goto free_sysex_data;
1287 schoenebeck 563 #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1288     if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
1289     #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1290 schoenebeck 244 for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
1291     AdjustScale((int8_t*) scale_tunes);
1292 schoenebeck 493 dmsg(3,("\t\t\tNew scale applied.\n"));
1293 schoenebeck 244 break;
1294     }
1295     }
1296     }
1297     else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
1298     }
1299     else if (addr[0] == 0x41) { // Drum Setup Parameters
1300     }
1301     break;
1302     }
1303     }
1304    
1305     free_sysex_data: // finally free sysex data
1306 schoenebeck 271 pSysexBuffer->increment_read_ptr(itSysexEvent->Param.Sysex.Size);
1307 schoenebeck 244 }
1308    
1309     /**
1310     * Calculates the Roland GS sysex check sum.
1311     *
1312     * @param AddrReader - reader which currently points to the first GS
1313     * command address byte of the GS sysex message in
1314     * question
1315     * @param DataSize - size of the GS message data (in bytes)
1316     */
1317     uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t>::NonVolatileReader AddrReader, uint DataSize) {
1318     RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;
1319     uint bytes = 3 /*addr*/ + DataSize;
1320     uint8_t addr_and_data[bytes];
1321     reader.read(&addr_and_data[0], bytes);
1322     uint8_t sum = 0;
1323     for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];
1324     return 128 - sum % 128;
1325     }
1326    
1327     /**
1328     * Allows to tune each of the twelve semitones of an octave.
1329     *
1330     * @param ScaleTunes - detuning of all twelve semitones (in cents)
1331     */
1332     void Engine::AdjustScale(int8_t ScaleTunes[12]) {
1333     memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate
1334     }
1335    
1336     /**
1337 schoenebeck 473 * Releases all voices on an engine channel. All voices will go into
1338     * the release stage and thus it might take some time (e.g. dependant to
1339     * their envelope release time) until they actually die.
1340     *
1341     * @param pEngineChannel - engine channel on which all voices should be released
1342     * @param itReleaseEvent - event which caused this releasing of all voices
1343     */
1344     void Engine::ReleaseAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itReleaseEvent) {
1345     RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1346     while (iuiKey) {
1347     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1348     ++iuiKey;
1349     // append a 'release' event to the key's own event list
1350     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1351     if (itNewEvent) {
1352     *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
1353     itNewEvent->Type = Event::type_release; // transform event type
1354     }
1355     else dmsg(1,("Event pool emtpy!\n"));
1356     }
1357     }
1358    
1359     /**
1360     * Kills all voices on an engine channel as soon as possible. Voices
1361     * won't get into release state, their volume level will be ramped down
1362     * as fast as possible.
1363     *
1364     * @param pEngineChannel - engine channel on which all voices should be killed
1365     * @param itKillEvent - event which caused this killing of all voices
1366     */
1367     void Engine::KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
1368     RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1369     RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
1370     while (iuiKey != end) { // iterate through all active keys
1371     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1372     ++iuiKey;
1373     RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
1374     RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
1375     for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
1376     itVoice->Kill(itKillEvent);
1377 schoenebeck 663 --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
1378 schoenebeck 473 }
1379     }
1380     }
1381    
1382     /**
1383 schoenebeck 53 * Initialize the parameter sequence for the modulation destination given by
1384     * by 'dst' with the constant value given by val.
1385     */
1386     void Engine::ResetSynthesisParameters(Event::destination_t dst, float val) {
1387     int maxsamples = pAudioOutputDevice->MaxSamplesPerCycle();
1388 schoenebeck 80 float* m = &pSynthesisParameters[dst][0];
1389     for (int i = 0; i < maxsamples; i += 4) {
1390     m[i] = val;
1391     m[i+1] = val;
1392     m[i+2] = val;
1393     m[i+3] = val;
1394     }
1395 persson 438 }
1396 schoenebeck 53
1397     uint Engine::VoiceCount() {
1398     return ActiveVoiceCount;
1399     }
1400    
1401     uint Engine::VoiceCountMax() {
1402     return ActiveVoiceCountMax;
1403     }
1404    
1405     bool Engine::DiskStreamSupported() {
1406     return true;
1407     }
1408    
1409     uint Engine::DiskStreamCount() {
1410     return (pDiskThread) ? pDiskThread->ActiveStreamCount : 0;
1411     }
1412    
1413     uint Engine::DiskStreamCountMax() {
1414     return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0;
1415     }
1416    
1417     String Engine::DiskStreamBufferFillBytes() {
1418     return pDiskThread->GetBufferFillBytes();
1419     }
1420    
1421     String Engine::DiskStreamBufferFillPercentage() {
1422     return pDiskThread->GetBufferFillPercentage();
1423     }
1424    
1425 senkov 112 String Engine::EngineName() {
1426 schoenebeck 475 return LS_GIG_ENGINE_NAME;
1427 senkov 112 }
1428    
1429 schoenebeck 53 String Engine::Description() {
1430     return "Gigasampler Engine";
1431     }
1432    
1433     String Engine::Version() {
1434 schoenebeck 705 String s = "$Revision: 1.50 $";
1435 schoenebeck 123 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
1436 schoenebeck 53 }
1437    
1438     }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC