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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2559 - (show annotations) (download)
Sun May 18 17:38:25 2014 UTC (9 years, 11 months ago) by schoenebeck
File size: 31031 byte(s)
* Aftertouch: extended API to explicitly handle channel pressure and
  polyphonic key pressure events (so far polyphonic pressure was not
  supported at all, and channel pressure was rerouted as CC128 but not
  used so far).
* Gig Engine: Fixed support for 'aftertouch' attenuation controller.
* Bumped version (1.0.0.svn39).

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

  ViewVC Help
Powered by ViewVC