/[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 376 - (hide annotations) (download)
Sat Feb 12 23:48:50 2005 UTC (19 years, 1 month ago) by senkov
File size: 51328 byte(s)
* Added INSTRUMENT_NAME to GET CHANNEL INFO command result set

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

  ViewVC Help
Powered by ViewVC