/[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 244 - (hide annotations) (download)
Fri Sep 17 01:01:11 2004 UTC (19 years, 6 months ago) by schoenebeck
File size: 39318 byte(s)
* added support for scale tuning via MIDI GS system exclusive message

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

  ViewVC Help
Powered by ViewVC