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

Annotation of /linuxsampler/trunk/src/engines/AbstractEngine.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2611 - (hide annotations) (download)
Mon Jun 9 19:20:37 2014 UTC (9 years, 10 months ago) by schoenebeck
File size: 31505 byte(s)
* Fixed crash when loading an instrument script.
* Fixed "init" script handler only to be executed once:
  when the script was loaded.
* Fixed aftertouch script event which always had value zero
  and controller number was set to aftertouch value instead.
* gig Engine: Fixed handling of "smartmidi" dimension, which
  was recognized as "unknown" dimension.
* Fixed script function gig_set_dim_zone(): was accessing
  wrong event.
* ls_instr_script command line tool: is now not limited to
  core language scripts, but can now also parse sampler format
  dependent instrument scripts, with the respective specific
  built-in script variables and functions.
* ScriptVM: Fixed runtime behavior of "and" and "or" binary
  script expressions, which also evaluated the right hand side
  of the expression even if the left hand side already failed
  the overall expression semantic to become true.
* Bumped version (1.0.0.svn46).

1 iliev 2012 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck *
6 persson 2091 * Copyright (C) 2005-2008 Christian Schoenebeck *
7 schoenebeck 2500 * Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev *
8     * Copyright (C) 2013-2014 Christian Schoenebeck and Andreas Persson *
9 iliev 2012 * *
10     * This program is free software; you can redistribute it and/or modify *
11     * it under the terms of the GNU General Public License as published by *
12     * the Free Software Foundation; either version 2 of the License, or *
13     * (at your option) any later version. *
14     * *
15     * This program is distributed in the hope that it will be useful, *
16     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18     * GNU General Public License for more details. *
19     * *
20     * You should have received a copy of the GNU General Public License *
21     * along with this program; if not, write to the Free Software *
22     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
23     * MA 02111-1307 USA *
24     ***************************************************************************/
25    
26     #include "AbstractEngine.h"
27     #include "AbstractEngineChannel.h"
28     #include "EngineFactory.h"
29     #include "../common/global_private.h"
30 iliev 2296 #include "../effects/EffectFactory.h"
31 iliev 2012
32     namespace LinuxSampler {
33    
34     //InstrumentResourceManager Engine::instruments;
35    
36     std::map<AbstractEngine::Format, std::map<AudioOutputDevice*,AbstractEngine*> > AbstractEngine::engines;
37    
38     /**
39     * Get an AbstractEngine object for the given AbstractEngineChannel and the
40     * given AudioOutputDevice. All engine channels which are connected to
41     * the same audio output device will use the same engine instance. This
42     * method will be called by an EngineChannel whenever it's
43     * connecting to an audio output device.
44     *
45     * @param pChannel - engine channel which acquires an engine object
46     * @param pDevice - the audio output device \a pChannel is connected to
47     */
48     AbstractEngine* AbstractEngine::AcquireEngine(AbstractEngineChannel* pChannel, AudioOutputDevice* pDevice) {
49     AbstractEngine* pEngine = NULL;
50     // check if there's already an engine for the given audio output device
51     std::map<AbstractEngine::Format, std::map<AudioOutputDevice*,AbstractEngine*> >::iterator it;
52     it = engines.find(pChannel->GetEngineFormat());
53     if (it != engines.end() && (*it).second.count(pDevice)) {
54     dmsg(4,("Using existing Engine.\n"));
55     pEngine = (*it).second[pDevice];
56    
57     // Disable the engine while the new engine channel is
58     // added and initialized. The engine will be enabled again
59     // in EngineChannel::Connect.
60     pEngine->DisableAndLock();
61     } else { // create a new engine (and disk thread) instance for the given audio output device
62     dmsg(4,("Creating new Engine.\n"));
63     pEngine = (AbstractEngine*) EngineFactory::Create(pChannel->EngineName());
64 schoenebeck 2611 pEngine->CreateInstrumentScriptVM();
65 iliev 2012 pEngine->Connect(pDevice);
66     engines[pChannel->GetEngineFormat()][pDevice] = pEngine;
67     }
68     // register engine channel to the engine instance
69     pEngine->engineChannels.add(pChannel);
70     // remember index in the ArrayList
71     pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
72     dmsg(4,("This Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
73     return pEngine;
74     }
75    
76 schoenebeck 2611 AbstractEngine::AbstractEngine() {
77 iliev 2012 pAudioOutputDevice = NULL;
78     pEventGenerator = NULL;
79     pSysexBuffer = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);
80     pEventQueue = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
81     pEventPool = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
82     pGlobalEvents = new RTList<Event>(pEventPool);
83     FrameTime = 0;
84 persson 2091 RandomSeed = 0;
85 schoenebeck 2121 pDedicatedVoiceChannelLeft = pDedicatedVoiceChannelRight = NULL;
86 schoenebeck 2611 pScriptVM = NULL;
87 iliev 2012 }
88    
89     AbstractEngine::~AbstractEngine() {
90     if (pEventQueue) delete pEventQueue;
91     if (pEventPool) delete pEventPool;
92     if (pEventGenerator) delete pEventGenerator;
93     if (pGlobalEvents) delete pGlobalEvents;
94     if (pSysexBuffer) delete pSysexBuffer;
95 schoenebeck 2121 if (pDedicatedVoiceChannelLeft) delete pDedicatedVoiceChannelLeft;
96     if (pDedicatedVoiceChannelRight) delete pDedicatedVoiceChannelRight;
97 schoenebeck 2594 if (pScriptVM) delete pScriptVM;
98 iliev 2012 Unregister();
99     }
100    
101 schoenebeck 2611 void AbstractEngine::CreateInstrumentScriptVM() {
102     dmsg(2,("Created sampler format independent instrument script VM.\n"));
103     if (pScriptVM) return;
104     pScriptVM = new InstrumentScriptVM; // format independent script runner
105 schoenebeck 2600 }
106    
107     /**
108 iliev 2012 * Once an engine channel is disconnected from an audio output device,
109     * it will immediately call this method to unregister itself from the
110     * engine instance and if that engine instance is not used by any other
111     * engine channel anymore, then that engine instance will be destroyed.
112     *
113     * @param pChannel - engine channel which wants to disconnect from it's
114     * engine instance
115     * @param pDevice - audio output device \a pChannel was connected to
116     */
117     void AbstractEngine::FreeEngine(AbstractEngineChannel* pChannel, AudioOutputDevice* pDevice) {
118     dmsg(4,("Disconnecting EngineChannel from Engine.\n"));
119     AbstractEngine* pEngine = engines[pChannel->GetEngineFormat()][pDevice];
120     // unregister EngineChannel from the Engine instance
121     pEngine->engineChannels.remove(pChannel);
122     // if the used Engine instance is not used anymore, then destroy it
123     if (pEngine->engineChannels.empty()) {
124     pDevice->Disconnect(pEngine);
125     engines[pChannel->GetEngineFormat()].erase(pDevice);
126     delete pEngine;
127     dmsg(4,("Destroying Engine.\n"));
128     }
129     else dmsg(4,("This Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
130     }
131    
132     void AbstractEngine::Enable() {
133     dmsg(3,("AbstractEngine: enabling\n"));
134     EngineDisabled.PushAndUnlock(false, 2, 0, true); // set condition object 'EngineDisabled' to false (wait max. 2s)
135     dmsg(3,("AbstractEngine: enabled (val=%d)\n", EngineDisabled.GetUnsafe()));
136     }
137    
138     /**
139     * Temporarily stop the engine to not do anything. The engine will just be
140     * frozen during that time, that means after enabling it again it will
141     * continue where it was, with all its voices and playback state it had at
142     * the point of disabling. Notice that the engine's (audio) thread will
143     * continue to run, it just remains in an inactive loop during that time.
144     *
145     * If you need to be sure that all voices and disk streams are killed as
146     * well, use @c SuspendAll() instead.
147     *
148     * @see Enable(), SuspendAll()
149     */
150     void AbstractEngine::Disable() {
151     dmsg(3,("AbstractEngine: disabling\n"));
152     bool* pWasDisabled = EngineDisabled.PushAndUnlock(true, 2); // wait max. 2s
153     if (!pWasDisabled) dmsg(3,("AbstractEngine warning: Timeout waiting to disable engine.\n"));
154     }
155    
156     void AbstractEngine::DisableAndLock() {
157     dmsg(3,("AbstractEngine: disabling\n"));
158     bool* pWasDisabled = EngineDisabled.Push(true, 2); // wait max. 2s
159     if (!pWasDisabled) dmsg(3,("AbstractEngine warning: Timeout waiting to disable engine.\n"));
160     }
161    
162     /**
163     * Reset all voices and disk thread and clear input event queue and all
164     * control and status variables.
165     */
166     void AbstractEngine::Reset() {
167     DisableAndLock();
168     ResetInternal();
169     ResetScaleTuning();
170     Enable();
171     }
172    
173     /**
174     * Reset to normal, chromatic scale (means equal tempered).
175     */
176     void AbstractEngine::ResetScaleTuning() {
177     memset(&ScaleTuning[0], 0x00, 12);
178 schoenebeck 2448 ScaleTuningChanged.raise();
179 iliev 2012 }
180    
181     /**
182     * Copy all events from the engine's global input queue buffer to the
183     * engine's internal event list. This will be done at the beginning of
184     * each audio cycle (that is each RenderAudio() call) to distinguish
185     * all global events which have to be processed in the current audio
186     * cycle. These events are usually just SysEx messages. Every
187     * EngineChannel has it's own input event queue buffer and event list
188     * to handle common events like NoteOn, NoteOff and ControlChange
189     * events.
190     *
191     * @param Samples - number of sample points to be processed in the
192     * current audio cycle
193     */
194     void AbstractEngine::ImportEvents(uint Samples) {
195     RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
196     Event* pEvent;
197     while (true) {
198     // get next event from input event queue
199     if (!(pEvent = eventQueueReader.pop())) break;
200     // if younger event reached, ignore that and all subsequent ones for now
201     if (pEvent->FragmentPos() >= Samples) {
202     eventQueueReader--;
203     dmsg(2,("Younger Event, pos=%d ,Samples=%d!\n",pEvent->FragmentPos(),Samples));
204     pEvent->ResetFragmentPos();
205     break;
206     }
207     // copy event to internal event list
208     if (pGlobalEvents->poolIsEmpty()) {
209     dmsg(1,("Event pool emtpy!\n"));
210     break;
211     }
212     *pGlobalEvents->allocAppend() = *pEvent;
213     }
214     eventQueueReader.free(); // free all copied events from input queue
215     }
216    
217     /**
218     * Clear all engine global event lists.
219     */
220     void AbstractEngine::ClearEventLists() {
221     pGlobalEvents->clear();
222     }
223    
224     /**
225     * Will be called in case the respective engine channel sports FX send
226     * channels. In this particular case, engine channel local buffers are
227     * used to render and mix all voices to. This method is responsible for
228     * copying the audio data from those local buffers to the master audio
229     * output channels as well as to the FX send audio output channels with
230     * their respective FX send levels.
231     *
232     * @param pEngineChannel - engine channel from which audio should be
233     * routed
234     * @param Samples - amount of sample points to be routed in
235     * this audio fragment cycle
236     */
237     void AbstractEngine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
238     AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
239 schoenebeck 2121 AudioChannel* ppSource[2] = {
240     pChannel->pChannelLeft,
241     pChannel->pChannelRight
242     };
243 iliev 2012 // route dry signal
244     {
245     AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);
246     AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);
247 schoenebeck 2121 ppSource[0]->MixTo(pDstL, Samples);
248     ppSource[1]->MixTo(pDstR, Samples);
249 iliev 2012 }
250 schoenebeck 2121 // route FX send signal (wet)
251 iliev 2012 {
252     for (int iFxSend = 0; iFxSend < pChannel->GetFxSendCount(); iFxSend++) {
253     FxSend* pFxSend = pChannel->GetFxSend(iFxSend);
254 schoenebeck 2121 const bool success = RouteFxSend(pFxSend, ppSource, pFxSend->Level(), Samples);
255     if (!success) goto channel_cleanup;
256 iliev 2012 }
257     }
258     channel_cleanup:
259     // reset buffers with silence (zero out) for the next audio cycle
260 schoenebeck 2121 ppSource[0]->Clear();
261     ppSource[1]->Clear();
262 iliev 2012 }
263 schoenebeck 2121
264     /**
265     * Similar to RouteAudio(), but this method is even more special. It is
266     * only called by voices which have dedicated effect send(s) level(s). So
267     * such voices have to be routed separately apart from the other voices
268     * which can just be mixed together and routed afterwards in one turn.
269     */
270     void AbstractEngine::RouteDedicatedVoiceChannels(EngineChannel* pEngineChannel, optional<float> FxSendLevels[2], uint Samples) {
271     AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
272     AudioChannel* ppSource[2] = {
273     pDedicatedVoiceChannelLeft,
274     pDedicatedVoiceChannelRight
275     };
276     // route dry signal
277     {
278     AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);
279     AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);
280     ppSource[0]->MixTo(pDstL, Samples);
281     ppSource[1]->MixTo(pDstR, Samples);
282     }
283     // route FX send signals (wet)
284     // (we simply hard code the voices 'reverb send' to the 1st effect
285     // send bus, and the voioces 'chorus send' to the 2nd effect send bus)
286     {
287     for (int iFxSend = 0; iFxSend < 2 && iFxSend < pChannel->GetFxSendCount(); iFxSend++) {
288     // no voice specific FX send level defined for this effect?
289     if (!FxSendLevels[iFxSend]) continue; // ignore this effect then
290    
291     FxSend* pFxSend = pChannel->GetFxSend(iFxSend);
292     const bool success = RouteFxSend(pFxSend, ppSource, *FxSendLevels[iFxSend], Samples);
293     if (!success) goto channel_cleanup;
294     }
295     }
296     channel_cleanup:
297     // reset buffers with silence (zero out) for the next dedicated voice rendering/routing process
298     ppSource[0]->Clear();
299     ppSource[1]->Clear();
300     }
301    
302     /**
303     * Route the audio signal given by @a ppSource to the effect send bus
304     * defined by @a pFxSend (wet signal only).
305     *
306     * @param pFxSend - definition of effect send bus
307     * @param ppSource - the 2 channels of the audio signal to be routed
308     * @param FxSendLevel - the effect send level to by applied
309     * @param Samples - amount of sample points to be processed
310     * @returns true if signal was routed successfully, false on error
311     */
312     bool AbstractEngine::RouteFxSend(FxSend* pFxSend, AudioChannel* ppSource[2], float FxSendLevel, uint Samples) {
313     for (int iChan = 0; iChan < 2; ++iChan) {
314     const int iDstChan = pFxSend->DestinationChannel(iChan);
315     if (iDstChan < 0) {
316     dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
317     return false; // error
318     }
319     AudioChannel* pDstChan = NULL;
320 schoenebeck 2137 if (pFxSend->DestinationEffectChain() >= 0) { // fx send routed to an internal send effect
321 schoenebeck 2121 EffectChain* pEffectChain =
322 iliev 2198 pAudioOutputDevice->SendEffectChainByID(
323 schoenebeck 2137 pFxSend->DestinationEffectChain()
324 schoenebeck 2121 );
325     if (!pEffectChain) {
326 schoenebeck 2137 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChain()));
327 schoenebeck 2121 return false; // error
328     }
329     Effect* pEffect =
330     pEffectChain->GetEffect(
331 schoenebeck 2137 pFxSend->DestinationEffectChainPosition()
332 schoenebeck 2121 );
333     if (!pEffect) {
334 schoenebeck 2137 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChainPosition(), pFxSend->DestinationEffectChain()));
335 schoenebeck 2121 return false; // error
336     }
337     pDstChan = pEffect->InputChannel(iDstChan);
338     } else { // FX send routed directly to an audio output channel
339     pDstChan = pAudioOutputDevice->Channel(iDstChan);
340     }
341     if (!pDstChan) {
342     dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
343     return false; // error
344     }
345     ppSource[iChan]->MixTo(pDstChan, Samples, FxSendLevel);
346     }
347     return true; // success
348     }
349 iliev 2012
350     /**
351     * Calculates the Roland GS sysex check sum.
352     *
353     * @param AddrReader - reader which currently points to the first GS
354     * command address byte of the GS sysex message in
355     * question
356     * @param DataSize - size of the GS message data (in bytes)
357     */
358     uint8_t AbstractEngine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {
359     RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
360 schoenebeck 2500 uint bytes = 3 /*addr*/ + DataSize;
361 iliev 2012 uint8_t sum = 0;
362 schoenebeck 2500 uint8_t c;
363     for (uint i = 0; i < bytes; ++i) {
364     if (!reader.pop(&c)) break;
365     sum += c;
366     }
367 iliev 2012 return 128 - sum % 128;
368     }
369    
370     /**
371     * Allows to tune each of the twelve semitones of an octave.
372     *
373     * @param ScaleTunes - detuning of all twelve semitones (in cents)
374     */
375 schoenebeck 2448 void AbstractEngine::AdjustScaleTuning(const int8_t ScaleTunes[12]) {
376     memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12);
377     ScaleTuningChanged.raise();
378 iliev 2012 }
379 schoenebeck 2448
380     void AbstractEngine::GetScaleTuning(int8_t* pScaleTunes) {
381     memcpy(pScaleTunes, &this->ScaleTuning[0], 12);
382     }
383 iliev 2012
384     uint AbstractEngine::VoiceCount() {
385     return atomic_read(&ActiveVoiceCount);
386     }
387    
388     void AbstractEngine::SetVoiceCount(uint Count) {
389     atomic_set(&ActiveVoiceCount, Count);
390     }
391    
392     uint AbstractEngine::VoiceCountMax() {
393     return ActiveVoiceCountMax;
394     }
395    
396     /**
397 schoenebeck 2559 * Stores the latest pitchbend event as current pitchbend scalar value.
398 iliev 2012 *
399     * @param pEngineChannel - engine channel on which this event occured on
400     * @param itPitchbendEvent - absolute pitch value and time stamp of the event
401     */
402     void AbstractEngine::ProcessPitchbend(AbstractEngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
403     pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
404     }
405    
406     void AbstractEngine::ProcessFxSendControllers (
407     AbstractEngineChannel* pEngineChannel,
408     Pool<Event>::Iterator& itControlChangeEvent
409     ) {
410     if (!pEngineChannel->fxSends.empty()) {
411     for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
412     FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
413     if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller) {
414     pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
415     pFxSend->SetInfoChanged(true);
416     }
417     }
418     }
419     }
420    
421     /**
422     * Will be called by the MIDI input device whenever a MIDI system
423     * exclusive message has arrived.
424     *
425     * @param pData - pointer to sysex data
426     * @param Size - lenght of sysex data (in bytes)
427     * @param pSender - the MIDI input port on which the SysEx message was
428     * received
429     */
430     void AbstractEngine::SendSysex(void* pData, uint Size, MidiInputPort* pSender) {
431     Event event = pEventGenerator->CreateEvent();
432     event.Type = Event::type_sysex;
433     event.Param.Sysex.Size = Size;
434 persson 2606 memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
435 iliev 2012 event.pEngineChannel = NULL; // as Engine global event
436     event.pMidiInputPort = pSender;
437     if (pEventQueue->write_space() > 0) {
438     if (pSysexBuffer->write_space() >= Size) {
439     // copy sysex data to input buffer
440     uint toWrite = Size;
441     uint8_t* pPos = (uint8_t*) pData;
442     while (toWrite) {
443     const uint writeNow = RTMath::Min(toWrite, pSysexBuffer->write_space_to_end());
444     pSysexBuffer->write(pPos, writeNow);
445     toWrite -= writeNow;
446     pPos += writeNow;
447    
448     }
449     // finally place sysex event into input event queue
450     pEventQueue->push(&event);
451     }
452     else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,CONFIG_SYSEX_BUFFER_SIZE));
453     }
454     else dmsg(1,("Engine: Input event queue full!"));
455     }
456    
457     /**
458     * Reacts on MIDI system exclusive messages.
459     *
460     * @param itSysexEvent - sysex data size and time stamp of the sysex event
461     */
462     void AbstractEngine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
463     RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
464    
465     uint8_t exclusive_status, id;
466     if (!reader.pop(&exclusive_status)) goto free_sysex_data;
467     if (!reader.pop(&id)) goto free_sysex_data;
468     if (exclusive_status != 0xF0) goto free_sysex_data;
469    
470     switch (id) {
471     case 0x7f: { // (Realtime) Universal Sysex (GM Standard)
472     uint8_t sysex_channel, sub_id1, sub_id2, val_msb, val_lsb;;
473     if (!reader.pop(&sysex_channel)) goto free_sysex_data;
474     if (!reader.pop(&sub_id1)) goto free_sysex_data;
475     if (!reader.pop(&sub_id2)) goto free_sysex_data;
476     if (!reader.pop(&val_lsb)) goto free_sysex_data;
477     if (!reader.pop(&val_msb)) goto free_sysex_data;
478     //TODO: for now we simply ignore the sysex channel, seldom used anyway
479     switch (sub_id1) {
480     case 0x04: // Device Control
481     switch (sub_id2) {
482     case 0x01: { // Master Volume
483     const double volume =
484     double((uint(val_msb)<<7) | uint(val_lsb)) / 16383.0;
485     #if CONFIG_MASTER_VOLUME_SYSEX_BY_PORT
486     // apply volume to all sampler channels that
487     // are connected to the same MIDI input port
488     // this sysex message arrived on
489     for (int i = 0; i < engineChannels.size(); ++i) {
490     EngineChannel* pEngineChannel = engineChannels[i];
491     if (pEngineChannel->GetMidiInputPort() ==
492     itSysexEvent->pMidiInputPort)
493     {
494     pEngineChannel->Volume(volume);
495     }
496     }
497     #else
498     // apply volume globally to the whole sampler
499     GLOBAL_VOLUME = volume;
500     #endif // CONFIG_MASTER_VOLUME_SYSEX_BY_PORT
501     break;
502     }
503     }
504     break;
505     }
506     break;
507     }
508     case 0x41: { // Roland
509     dmsg(3,("Roland Sysex\n"));
510     uint8_t device_id, model_id, cmd_id;
511     if (!reader.pop(&device_id)) goto free_sysex_data;
512     if (!reader.pop(&model_id)) goto free_sysex_data;
513     if (!reader.pop(&cmd_id)) goto free_sysex_data;
514     if (model_id != 0x42 /*GS*/) goto free_sysex_data;
515     if (cmd_id != 0x12 /*DT1*/) goto free_sysex_data;
516    
517     // command address
518     uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
519     const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
520     if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
521     if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
522     dmsg(3,("\tSystem Parameter\n"));
523     if (addr[2] == 0x7f) { // GS reset
524     for (int i = 0; i < engineChannels.size(); ++i) {
525     AbstractEngineChannel* pEngineChannel
526     = static_cast<AbstractEngineChannel*>(engineChannels[i]);
527 schoenebeck 2500 Sync< ArrayList<MidiInputPort*> > midiInputs = pEngineChannel->midiInputs.front();
528     for (int k = 0; k < midiInputs->size(); ++k) {
529     if ((*midiInputs)[k] == itSysexEvent->pMidiInputPort) {
530     KillAllVoices(pEngineChannel, itSysexEvent);
531     pEngineChannel->ResetControllers();
532     break;
533     }
534 iliev 2012 }
535     }
536     }
537     }
538     else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
539     dmsg(3,("\tCommon Parameter\n"));
540     }
541     else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
542     dmsg(3,("\tPart Parameter\n"));
543     switch (addr[2]) {
544     case 0x40: { // scale tuning
545     dmsg(3,("\t\tScale Tuning\n"));
546     uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
547     if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
548     uint8_t checksum;
549     if (!reader.pop(&checksum)) goto free_sysex_data;
550     #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
551     if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
552     #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
553     for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
554 schoenebeck 2448 AdjustScaleTuning((int8_t*) scale_tunes);
555 iliev 2012 dmsg(3,("\t\t\tNew scale applied.\n"));
556     break;
557     }
558     case 0x15: { // chromatic / drumkit mode
559     dmsg(3,("\t\tMIDI Instrument Map Switch\n"));
560     uint8_t part = addr[1] & 0x0f;
561     uint8_t map;
562     if (!reader.pop(&map)) goto free_sysex_data;
563     for (int i = 0; i < engineChannels.size(); ++i) {
564     AbstractEngineChannel* pEngineChannel
565     = static_cast<AbstractEngineChannel*>(engineChannels[i]);
566 schoenebeck 2500 if (pEngineChannel->midiChannel == part ||
567     pEngineChannel->midiChannel == midi_chan_all)
568     {
569     Sync< ArrayList<MidiInputPort*> > midiInputs = pEngineChannel->midiInputs.front();
570     for (int k = 0; k < midiInputs->size(); ++k) {
571     if ((*midiInputs)[k] == itSysexEvent->pMidiInputPort) {
572     try {
573     pEngineChannel->SetMidiInstrumentMap(map);
574     } catch (Exception e) {
575     dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d: %s\n", map, part, e.Message().c_str()));
576     goto free_sysex_data;
577     } catch (...) {
578     dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part));
579     goto free_sysex_data;
580     }
581     break;
582     }
583 iliev 2012 }
584     }
585     }
586     dmsg(3,("\t\t\tApplied MIDI instrument map %d to part %d.\n", map, part));
587     break;
588     }
589     }
590     }
591     else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
592     }
593     else if (addr[0] == 0x41) { // Drum Setup Parameters
594     }
595     break;
596     }
597     }
598    
599     free_sysex_data: // finally free sysex data
600     pSysexBuffer->increment_read_ptr(itSysexEvent->Param.Sysex.Size);
601     }
602    
603     String AbstractEngine::GetFormatString(Format f) {
604     switch(f) {
605     case GIG: return "GIG";
606     case SF2: return "SF2";
607     case SFZ: return "SFZ";
608     default: return "UNKNOWN";
609     }
610     }
611    
612     String AbstractEngine::EngineName() {
613     return GetFormatString(GetEngineFormat());
614     }
615    
616     // static constant initializers
617     const AbstractEngine::FloatTable AbstractEngine::VolumeCurve(InitVolumeCurve());
618     const AbstractEngine::FloatTable AbstractEngine::PanCurve(InitPanCurve());
619     const AbstractEngine::FloatTable AbstractEngine::CrossfadeCurve(InitCrossfadeCurve());
620    
621     float* AbstractEngine::InitVolumeCurve() {
622     // line-segment approximation
623     const float segments[] = {
624     0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
625     64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
626     };
627     return InitCurve(segments);
628     }
629    
630     float* AbstractEngine::InitPanCurve() {
631     // line-segment approximation
632     const float segments[] = {
633     0, 0, 1, 0,
634     2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
635     127, 1.41, 128, 1.41
636     };
637     return InitCurve(segments, 129);
638     }
639    
640     float* AbstractEngine::InitCrossfadeCurve() {
641     // line-segment approximation
642     const float segments[] = {
643     0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
644     };
645     return InitCurve(segments);
646     }
647    
648     float* AbstractEngine::InitCurve(const float* segments, int size) {
649     float* y = new float[size];
650     for (int x = 0 ; x < size ; x++) {
651     if (x > segments[2]) segments += 2;
652     y[x] = segments[1] + (x - segments[0]) *
653     (segments[3] - segments[1]) / (segments[2] - segments[0]);
654     }
655     return y;
656     }
657    
658     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC