/[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 2931 - (show annotations) (download)
Sat Jul 9 14:38:33 2016 UTC (7 years, 9 months ago) by schoenebeck
File size: 32254 byte(s)
* Implemented built-in instrument script function "change_vol()".
* Implemented built-in instrument script function "change_tune()".
* Implemented built-in instrument script function "change_pan()".
* Bumped version (2.0.0.svn11).

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->CreateInstrumentScriptVM();
65 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 AbstractEngine::AbstractEngine() {
77 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 pEventPool->setPoolElementIDsReservedBits(INSTR_SCRIPT_EVENT_ID_RESERVED_BITS);
83 pGlobalEvents = new RTList<Event>(pEventPool);
84 FrameTime = 0;
85 RandomSeed = 0;
86 pDedicatedVoiceChannelLeft = pDedicatedVoiceChannelRight = NULL;
87 pScriptVM = NULL;
88 }
89
90 AbstractEngine::~AbstractEngine() {
91 if (pEventQueue) delete pEventQueue;
92 if (pEventPool) delete pEventPool;
93 if (pEventGenerator) delete pEventGenerator;
94 if (pGlobalEvents) delete pGlobalEvents;
95 if (pSysexBuffer) delete pSysexBuffer;
96 if (pDedicatedVoiceChannelLeft) delete pDedicatedVoiceChannelLeft;
97 if (pDedicatedVoiceChannelRight) delete pDedicatedVoiceChannelRight;
98 if (pScriptVM) delete pScriptVM;
99 Unregister();
100 }
101
102 void AbstractEngine::CreateInstrumentScriptVM() {
103 dmsg(2,("Created sampler format independent instrument script VM.\n"));
104 if (pScriptVM) return;
105 pScriptVM = new InstrumentScriptVM; // format independent script runner
106 }
107
108 /**
109 * Once an engine channel is disconnected from an audio output device,
110 * it will immediately call this method to unregister itself from the
111 * engine instance and if that engine instance is not used by any other
112 * engine channel anymore, then that engine instance will be destroyed.
113 *
114 * @param pChannel - engine channel which wants to disconnect from it's
115 * engine instance
116 * @param pDevice - audio output device \a pChannel was connected to
117 */
118 void AbstractEngine::FreeEngine(AbstractEngineChannel* pChannel, AudioOutputDevice* pDevice) {
119 dmsg(4,("Disconnecting EngineChannel from Engine.\n"));
120 AbstractEngine* pEngine = engines[pChannel->GetEngineFormat()][pDevice];
121 // unregister EngineChannel from the Engine instance
122 pEngine->engineChannels.remove(pChannel);
123 // if the used Engine instance is not used anymore, then destroy it
124 if (pEngine->engineChannels.empty()) {
125 pDevice->Disconnect(pEngine);
126 engines[pChannel->GetEngineFormat()].erase(pDevice);
127 delete pEngine;
128 dmsg(4,("Destroying Engine.\n"));
129 }
130 else dmsg(4,("This Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
131 }
132
133 void AbstractEngine::Enable() {
134 dmsg(3,("AbstractEngine: enabling\n"));
135 EngineDisabled.PushAndUnlock(false, 2, 0, true); // set condition object 'EngineDisabled' to false (wait max. 2s)
136 dmsg(3,("AbstractEngine: enabled (val=%d)\n", EngineDisabled.GetUnsafe()));
137 }
138
139 /**
140 * Temporarily stop the engine to not do anything. The engine will just be
141 * frozen during that time, that means after enabling it again it will
142 * continue where it was, with all its voices and playback state it had at
143 * the point of disabling. Notice that the engine's (audio) thread will
144 * continue to run, it just remains in an inactive loop during that time.
145 *
146 * If you need to be sure that all voices and disk streams are killed as
147 * well, use @c SuspendAll() instead.
148 *
149 * @see Enable(), SuspendAll()
150 */
151 void AbstractEngine::Disable() {
152 dmsg(3,("AbstractEngine: disabling\n"));
153 bool* pWasDisabled = EngineDisabled.PushAndUnlock(true, 2); // wait max. 2s
154 if (!pWasDisabled) dmsg(3,("AbstractEngine warning: Timeout waiting to disable engine.\n"));
155 }
156
157 void AbstractEngine::DisableAndLock() {
158 dmsg(3,("AbstractEngine: disabling\n"));
159 bool* pWasDisabled = EngineDisabled.Push(true, 2); // wait max. 2s
160 if (!pWasDisabled) dmsg(3,("AbstractEngine warning: Timeout waiting to disable engine.\n"));
161 }
162
163 /**
164 * Reset all voices and disk thread and clear input event queue and all
165 * control and status variables.
166 */
167 void AbstractEngine::Reset() {
168 DisableAndLock();
169 ResetInternal();
170 ResetScaleTuning();
171 Enable();
172 }
173
174 /**
175 * Reset to normal, chromatic scale (means equal tempered).
176 */
177 void AbstractEngine::ResetScaleTuning() {
178 memset(&ScaleTuning[0], 0x00, 12);
179 ScaleTuningChanged.raise();
180 }
181
182 /**
183 * Copy all events from the engine's global input queue buffer to the
184 * engine's internal event list. This will be done at the beginning of
185 * each audio cycle (that is each RenderAudio() call) to distinguish
186 * all global events which have to be processed in the current audio
187 * cycle. These events are usually just SysEx messages. Every
188 * EngineChannel has it's own input event queue buffer and event list
189 * to handle common events like NoteOn, NoteOff and ControlChange
190 * events.
191 *
192 * @param Samples - number of sample points to be processed in the
193 * current audio cycle
194 */
195 void AbstractEngine::ImportEvents(uint Samples) {
196 RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
197 Event* pEvent;
198 while (true) {
199 // get next event from input event queue
200 if (!(pEvent = eventQueueReader.pop())) break;
201 // if younger event reached, ignore that and all subsequent ones for now
202 if (pEvent->FragmentPos() >= Samples) {
203 eventQueueReader--;
204 dmsg(2,("Younger Event, pos=%d ,Samples=%d!\n",pEvent->FragmentPos(),Samples));
205 pEvent->ResetFragmentPos();
206 break;
207 }
208 // copy event to internal event list
209 if (pGlobalEvents->poolIsEmpty()) {
210 dmsg(1,("Event pool emtpy!\n"));
211 break;
212 }
213 *pGlobalEvents->allocAppend() = *pEvent;
214 }
215 eventQueueReader.free(); // free all copied events from input queue
216 }
217
218 /**
219 * Clear all engine global event lists.
220 */
221 void AbstractEngine::ClearEventLists() {
222 pGlobalEvents->clear();
223 }
224
225 /**
226 * Will be called in case the respective engine channel sports FX send
227 * channels. In this particular case, engine channel local buffers are
228 * used to render and mix all voices to. This method is responsible for
229 * copying the audio data from those local buffers to the master audio
230 * output channels as well as to the FX send audio output channels with
231 * their respective FX send levels.
232 *
233 * @param pEngineChannel - engine channel from which audio should be
234 * routed
235 * @param Samples - amount of sample points to be routed in
236 * this audio fragment cycle
237 */
238 void AbstractEngine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
239 AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
240 AudioChannel* ppSource[2] = {
241 pChannel->pChannelLeft,
242 pChannel->pChannelRight
243 };
244 // route dry signal
245 {
246 AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);
247 AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);
248 ppSource[0]->MixTo(pDstL, Samples);
249 ppSource[1]->MixTo(pDstR, Samples);
250 }
251 // route FX send signal (wet)
252 {
253 for (int iFxSend = 0; iFxSend < pChannel->GetFxSendCount(); iFxSend++) {
254 FxSend* pFxSend = pChannel->GetFxSend(iFxSend);
255 const bool success = RouteFxSend(pFxSend, ppSource, pFxSend->Level(), Samples);
256 if (!success) goto channel_cleanup;
257 }
258 }
259 channel_cleanup:
260 // reset buffers with silence (zero out) for the next audio cycle
261 ppSource[0]->Clear();
262 ppSource[1]->Clear();
263 }
264
265 /**
266 * Similar to RouteAudio(), but this method is even more special. It is
267 * only called by voices which have dedicated effect send(s) level(s). So
268 * such voices have to be routed separately apart from the other voices
269 * which can just be mixed together and routed afterwards in one turn.
270 */
271 void AbstractEngine::RouteDedicatedVoiceChannels(EngineChannel* pEngineChannel, optional<float> FxSendLevels[2], uint Samples) {
272 AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
273 AudioChannel* ppSource[2] = {
274 pDedicatedVoiceChannelLeft,
275 pDedicatedVoiceChannelRight
276 };
277 // route dry signal
278 {
279 AudioChannel* pDstL = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelLeft);
280 AudioChannel* pDstR = pAudioOutputDevice->Channel(pChannel->AudioDeviceChannelRight);
281 ppSource[0]->MixTo(pDstL, Samples);
282 ppSource[1]->MixTo(pDstR, Samples);
283 }
284 // route FX send signals (wet)
285 // (we simply hard code the voices 'reverb send' to the 1st effect
286 // send bus, and the voioces 'chorus send' to the 2nd effect send bus)
287 {
288 for (int iFxSend = 0; iFxSend < 2 && iFxSend < pChannel->GetFxSendCount(); iFxSend++) {
289 // no voice specific FX send level defined for this effect?
290 if (!FxSendLevels[iFxSend]) continue; // ignore this effect then
291
292 FxSend* pFxSend = pChannel->GetFxSend(iFxSend);
293 const bool success = RouteFxSend(pFxSend, ppSource, *FxSendLevels[iFxSend], Samples);
294 if (!success) goto channel_cleanup;
295 }
296 }
297 channel_cleanup:
298 // reset buffers with silence (zero out) for the next dedicated voice rendering/routing process
299 ppSource[0]->Clear();
300 ppSource[1]->Clear();
301 }
302
303 /**
304 * Route the audio signal given by @a ppSource to the effect send bus
305 * defined by @a pFxSend (wet signal only).
306 *
307 * @param pFxSend - definition of effect send bus
308 * @param ppSource - the 2 channels of the audio signal to be routed
309 * @param FxSendLevel - the effect send level to by applied
310 * @param Samples - amount of sample points to be processed
311 * @returns true if signal was routed successfully, false on error
312 */
313 bool AbstractEngine::RouteFxSend(FxSend* pFxSend, AudioChannel* ppSource[2], float FxSendLevel, uint Samples) {
314 for (int iChan = 0; iChan < 2; ++iChan) {
315 const int iDstChan = pFxSend->DestinationChannel(iChan);
316 if (iDstChan < 0) {
317 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
318 return false; // error
319 }
320 AudioChannel* pDstChan = NULL;
321 if (pFxSend->DestinationEffectChain() >= 0) { // fx send routed to an internal send effect
322 EffectChain* pEffectChain =
323 pAudioOutputDevice->SendEffectChainByID(
324 pFxSend->DestinationEffectChain()
325 );
326 if (!pEffectChain) {
327 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChain()));
328 return false; // error
329 }
330 Effect* pEffect =
331 pEffectChain->GetEffect(
332 pFxSend->DestinationEffectChainPosition()
333 );
334 if (!pEffect) {
335 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationEffectChainPosition(), pFxSend->DestinationEffectChain()));
336 return false; // error
337 }
338 pDstChan = pEffect->InputChannel(iDstChan);
339 } else { // FX send routed directly to an audio output channel
340 pDstChan = pAudioOutputDevice->Channel(iDstChan);
341 }
342 if (!pDstChan) {
343 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
344 return false; // error
345 }
346 ppSource[iChan]->MixTo(pDstChan, Samples, FxSendLevel);
347 }
348 return true; // success
349 }
350
351 /**
352 * Calculates the Roland GS sysex check sum.
353 *
354 * @param AddrReader - reader which currently points to the first GS
355 * command address byte of the GS sysex message in
356 * question
357 * @param DataSize - size of the GS message data (in bytes)
358 */
359 uint8_t AbstractEngine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {
360 RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
361 uint bytes = 3 /*addr*/ + DataSize;
362 uint8_t sum = 0;
363 uint8_t c;
364 for (uint i = 0; i < bytes; ++i) {
365 if (!reader.pop(&c)) break;
366 sum += c;
367 }
368 return 128 - sum % 128;
369 }
370
371 /**
372 * Allows to tune each of the twelve semitones of an octave.
373 *
374 * @param ScaleTunes - detuning of all twelve semitones (in cents)
375 */
376 void AbstractEngine::AdjustScaleTuning(const int8_t ScaleTunes[12]) {
377 memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12);
378 ScaleTuningChanged.raise();
379 }
380
381 void AbstractEngine::GetScaleTuning(int8_t* pScaleTunes) {
382 memcpy(pScaleTunes, &this->ScaleTuning[0], 12);
383 }
384
385 uint AbstractEngine::VoiceCount() {
386 return atomic_read(&ActiveVoiceCount);
387 }
388
389 void AbstractEngine::SetVoiceCount(uint Count) {
390 atomic_set(&ActiveVoiceCount, Count);
391 }
392
393 uint AbstractEngine::VoiceCountMax() {
394 return ActiveVoiceCountMax;
395 }
396
397 /**
398 * Stores the latest pitchbend event as current pitchbend scalar value.
399 *
400 * @param pEngineChannel - engine channel on which this event occured on
401 * @param itPitchbendEvent - absolute pitch value and time stamp of the event
402 */
403 void AbstractEngine::ProcessPitchbend(AbstractEngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
404 pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
405 }
406
407 void AbstractEngine::ProcessFxSendControllers (
408 AbstractEngineChannel* pEngineChannel,
409 Pool<Event>::Iterator& itControlChangeEvent
410 ) {
411 if (!pEngineChannel->fxSends.empty()) {
412 for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
413 FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
414 if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller) {
415 pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
416 pFxSend->SetInfoChanged(true);
417 }
418 }
419 }
420 }
421
422 /**
423 * Will be called by the MIDI input device whenever a MIDI system
424 * exclusive message has arrived.
425 *
426 * @param pData - pointer to sysex data
427 * @param Size - lenght of sysex data (in bytes)
428 * @param pSender - the MIDI input port on which the SysEx message was
429 * received
430 */
431 void AbstractEngine::SendSysex(void* pData, uint Size, MidiInputPort* pSender) {
432 Event event = pEventGenerator->CreateEvent();
433 event.Type = Event::type_sysex;
434 event.Param.Sysex.Size = Size;
435 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 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 }
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 AdjustScaleTuning((int8_t*) scale_tunes);
555 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 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 }
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 /**
659 * Returns the volume factor to be used for the requested signed,
660 * normalized @a pan value and audio @a channel index.
661 *
662 * @param pan - between -1.0 (most left) and +1.0 (most right)
663 * @param channel - 0: return value for left channel, 1: return value for right channel
664 * @returns final volume factor for the requested audio channel to be applied
665 */
666 float AbstractEngine::PanCurveValueNorm(float pan, int channel) {
667 float pan128 = (pan + 1.f) / 2.f * 128.f;
668 if (channel == 0) pan128 = 128 - pan128;
669 return PanCurve[pan128]; //TODO: interpolation should be done here (float type "pan" argument here allows a much more fine graded result value than those 129 steps of the PanCurve)
670 }
671
672 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC