/[svn]/linuxsampler/trunk/src/engines/EngineBase.h
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/EngineBase.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3246 - (hide annotations) (download) (as text)
Sun May 28 22:22:56 2017 UTC (6 years, 10 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 125692 byte(s)
* NKSP: Implemented built-in script function "change_vol_curve()".
* NKSP: Implemented built-in script function "change_tune_curve()".
* NKSP: Added built-in script constant "$NKSP_LINEAR".
* NKSP: Added built-in script constant "$NKSP_EASE_IN_EASE_OUT".
* Bumped version (2.0.0.svn54).

1 iliev 2012 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck *
6 persson 2055 * Copyright (C) 2005-2008 Christian Schoenebeck *
7 schoenebeck 2871 * Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev *
8 schoenebeck 3073 * Copyright (C) 2012-2017 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     #ifndef __LS_ENGINEBASE_H__
27     #define __LS_ENGINEBASE_H__
28    
29     #include "AbstractEngine.h"
30     #include "EngineChannelBase.h"
31     #include "common/DiskThreadBase.h"
32     #include "common/MidiKeyboardManager.h"
33     #include "InstrumentManager.h"
34     #include "../common/global_private.h"
35    
36 schoenebeck 2879 // a bit headroom over CONFIG_MAX_VOICES to avoid minor complications i.e. under voice stealing conditions
37     #define MAX_NOTES_HEADROOM 3
38     #define GLOBAL_MAX_NOTES (GLOBAL_MAX_VOICES * MAX_NOTES_HEADROOM)
39 iliev 2012
40     namespace LinuxSampler {
41    
42     class AbstractEngineChannel;
43    
44     template <
45     class V /* Voice */,
46     class RR /* Root Region */,
47     class R /* Region */,
48     class D /* Disk Thread */,
49     class IM /* Instrument Manager */,
50     class I /* Instrument */
51     >
52 schoenebeck 2879 class EngineBase: public AbstractEngine, public RegionPools<R>, public NotePool<V> {
53 iliev 2012
54     public:
55 schoenebeck 2879 typedef typename RTList< Note<V> >::Iterator NoteIterator;
56 iliev 2012 typedef typename RTList<V>::Iterator VoiceIterator;
57     typedef typename Pool<V>::Iterator PoolVoiceIterator;
58     typedef typename RTList<RR*>::Iterator RootRegionIterator;
59     typedef typename MidiKeyboardManager<V>::MidiKey MidiKey;
60    
61 schoenebeck 3034 EngineBase() : noteIDPool(GLOBAL_MAX_NOTES), SuspendedRegions(128) {
62 iliev 2012 pDiskThread = NULL;
63 schoenebeck 2879 pNotePool = new Pool< Note<V> >(GLOBAL_MAX_NOTES);
64     pNotePool->setPoolElementIDsReservedBits(INSTR_SCRIPT_EVENT_ID_RESERVED_BITS);
65 iliev 2012 pVoicePool = new Pool<V>(GLOBAL_MAX_VOICES);
66     pRegionPool[0] = new Pool<R*>(GLOBAL_MAX_VOICES);
67     pRegionPool[1] = new Pool<R*>(GLOBAL_MAX_VOICES);
68     pVoiceStealingQueue = new RTList<Event>(pEventPool);
69     iMaxDiskStreams = GLOBAL_MAX_STREAMS;
70    
71 schoenebeck 2879 // init all Voice objects in voice pool
72     for (VoiceIterator iterVoice = pVoicePool->allocAppend();
73     iterVoice; iterVoice = pVoicePool->allocAppend())
74     {
75 iliev 2012 iterVoice->SetEngine(this);
76     }
77     pVoicePool->clear();
78    
79 schoenebeck 2879 // init all Note objects in note pool
80     for (NoteIterator itNote = pNotePool->allocAppend(); itNote;
81     itNote = pNotePool->allocAppend())
82     {
83     itNote->init(pVoicePool, &noteIDPool);
84     }
85     pNotePool->clear();
86    
87 iliev 2012 ResetInternal();
88     ResetScaleTuning();
89     ResetSuspendedRegions();
90     }
91    
92     virtual ~EngineBase() {
93     if (pDiskThread) {
94     dmsg(1,("Stopping disk thread..."));
95     pDiskThread->StopThread();
96     delete pDiskThread;
97     dmsg(1,("OK\n"));
98     }
99    
100 schoenebeck 2879 if (pNotePool) {
101     pNotePool->clear();
102     delete pNotePool;
103     }
104    
105 iliev 2012 if (pVoicePool) {
106     pVoicePool->clear();
107     delete pVoicePool;
108     }
109    
110     if (pVoiceStealingQueue) delete pVoiceStealingQueue;
111    
112     if (pRegionPool[0]) delete pRegionPool[0];
113     if (pRegionPool[1]) delete pRegionPool[1];
114     ResetSuspendedRegions();
115     }
116    
117     // implementation of abstract methods derived from class 'LinuxSampler::Engine'
118    
119     /**
120     * Let this engine proceed to render the given amount of sample points.
121     * The engine will iterate through all engine channels and render audio
122     * for each engine channel independently. The calculated audio data of
123     * all voices of each engine channel will be placed into the audio sum
124     * buffers of the respective audio output device, connected to the
125     * respective engine channel.
126     *
127     * @param Samples - number of sample points to be rendered
128     * @returns 0 on success
129     */
130 schoenebeck 2434 virtual int RenderAudio(uint Samples) OVERRIDE {
131 iliev 2012 dmsg(8,("RenderAudio(Samples=%d)\n", Samples));
132    
133     // return if engine disabled
134     if (EngineDisabled.Pop()) {
135     dmsg(5,("EngineBase: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
136     EngineDisabled.RttDone();
137     return 0;
138     }
139    
140     // process requests for suspending / resuming regions (i.e. to avoid
141     // crashes while these regions are modified by an instrument editor)
142     ProcessSuspensionsChanges();
143    
144     // update time of start and end of this audio fragment (as events' time stamps relate to this)
145     pEventGenerator->UpdateFragmentTime(Samples);
146    
147     // We only allow the given maximum number of voices to be spawned
148     // in each audio fragment. All subsequent request for spawning new
149     // voices in the same audio fragment will be ignored.
150     VoiceSpawnsLeft = MaxVoices();
151    
152     // get all events from the engine's global input event queue which belong to the current fragment
153     // (these are usually just SysEx messages)
154     ImportEvents(Samples);
155    
156     // process engine global events (these are currently only MIDI System Exclusive messages)
157     {
158     RTList<Event>::Iterator itEvent = pGlobalEvents->first();
159     RTList<Event>::Iterator end = pGlobalEvents->end();
160     for (; itEvent != end; ++itEvent) {
161     switch (itEvent->Type) {
162     case Event::type_sysex:
163     dmsg(5,("Engine: Sysex received\n"));
164     ProcessSysex(itEvent);
165     break;
166 schoenebeck 3034 default: ; // noop
167 iliev 2012 }
168     }
169     }
170 schoenebeck 2448
171     // In case scale tuning has been changed, recalculate pitch for
172     // all active voices.
173     ProcessScaleTuningChange();
174 iliev 2012
175     // reset internal voice counter (just for statistic of active voices)
176     ActiveVoiceCountTemp = 0;
177    
178     HandleInstrumentChanges();
179    
180     // handle events on all engine channels
181     for (int i = 0; i < engineChannels.size(); i++) {
182     ProcessEvents(engineChannels[i], Samples);
183     }
184    
185     // render all 'normal', active voices on all engine channels
186     for (int i = 0; i < engineChannels.size(); i++) {
187     RenderActiveVoices(engineChannels[i], Samples);
188     }
189    
190     // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
191     RenderStolenVoices(Samples);
192    
193     // handle audio routing for engine channels with FX sends
194     for (int i = 0; i < engineChannels.size(); i++) {
195     AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(engineChannels[i]);
196     if (pChannel->fxSends.empty()) continue; // ignore if no FX sends
197     RouteAudio(engineChannels[i], Samples);
198     }
199    
200     // handle cleanup on all engine channels for the next audio fragment
201     for (int i = 0; i < engineChannels.size(); i++) {
202     PostProcess(engineChannels[i]);
203     }
204    
205    
206     // empty the engine's event list for the next audio fragment
207     ClearEventLists();
208    
209     // reset voice stealing for the next audio fragment
210     pVoiceStealingQueue->clear();
211    
212     // just some statistics about this engine instance
213     SetVoiceCount(ActiveVoiceCountTemp);
214     if (VoiceCount() > ActiveVoiceCountMax) ActiveVoiceCountMax = VoiceCount();
215    
216     // in case regions were previously suspended and we killed voices
217     // with disk streams due to that, check if those streams have finally
218     // been deleted by the disk thread
219     if (iPendingStreamDeletions) ProcessPendingStreamDeletions();
220    
221 persson 2162 // Release the instrument change command. (This has to
222     // be done after all voices have been rendered and not
223     // in HandleInstrumentChanges, as the RegionsInUse
224     // list has been built up by the voice renderers.)
225     for (int i = 0; i < engineChannels.size(); i++) {
226     EngineChannelBase<V, R, I>* channel =
227     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
228     channel->InstrumentChangeCommandReader.Unlock();
229     }
230 iliev 2012 FrameTime += Samples;
231    
232     EngineDisabled.RttDone();
233     return 0;
234     }
235    
236 schoenebeck 2434 virtual int MaxVoices() OVERRIDE { return pVoicePool->poolSize(); }
237 iliev 2012
238 schoenebeck 2434 virtual void SetMaxVoices(int iVoices) throw (Exception) OVERRIDE {
239 iliev 2012 if (iVoices < 1)
240     throw Exception("Maximum voices for an engine cannot be set lower than 1");
241    
242     SuspendAll();
243    
244     // NOTE: we need to clear pRegionsInUse before deleting pDimRegionPool,
245     // otherwise memory corruption will occur if there are active voices (see bug #118)
246     for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
247     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannel]);
248     pChannel->ClearRegionsInUse();
249     }
250    
251     if (pRegionPool[0]) delete pRegionPool[0];
252     if (pRegionPool[1]) delete pRegionPool[1];
253    
254     pRegionPool[0] = new Pool<R*>(iVoices);
255     pRegionPool[1] = new Pool<R*>(iVoices);
256    
257     for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
258     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannel]);
259     pChannel->ResetRegionsInUse(pRegionPool);
260     }
261    
262 schoenebeck 2879 // FIXME: Shouldn't all those pool elements be freed before resizing the pools?
263 iliev 2012 try {
264     pVoicePool->resizePool(iVoices);
265 schoenebeck 2879 pNotePool->resizePool(iVoices * MAX_NOTES_HEADROOM);
266     noteIDPool.resizePool(iVoices * MAX_NOTES_HEADROOM);
267 iliev 2012 } catch (...) {
268     throw Exception("FATAL: Could not resize voice pool!");
269     }
270    
271 schoenebeck 2879 for (VoiceIterator iterVoice = pVoicePool->allocAppend();
272     iterVoice; iterVoice = pVoicePool->allocAppend())
273     {
274 iliev 2012 iterVoice->SetEngine(this);
275     iterVoice->pDiskThread = this->pDiskThread;
276     }
277     pVoicePool->clear();
278    
279 schoenebeck 2879 for (NoteIterator itNote = pNotePool->allocAppend(); itNote;
280     itNote = pNotePool->allocAppend())
281     {
282     itNote->init(pVoicePool, &noteIDPool);
283     }
284     pNotePool->clear();
285    
286 iliev 2244 PostSetMaxVoices(iVoices);
287 iliev 2012 ResumeAll();
288     }
289 iliev 2244
290     /** Called after the new max number of voices is set and before resuming the engine. */
291     virtual void PostSetMaxVoices(int iVoices) { }
292 iliev 2012
293 schoenebeck 2434 virtual uint DiskStreamCount() OVERRIDE { return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0; }
294     virtual uint DiskStreamCountMax() OVERRIDE { return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0; }
295     virtual int MaxDiskStreams() OVERRIDE { return iMaxDiskStreams; }
296 iliev 2012
297 schoenebeck 2434 virtual void SetMaxDiskStreams(int iStreams) throw (Exception) OVERRIDE {
298 iliev 2012 if (iStreams < 0)
299     throw Exception("Maximum disk streams for an engine cannot be set lower than 0");
300    
301     SuspendAll();
302    
303     iMaxDiskStreams = iStreams;
304    
305     // reconnect to audio output device, because that will automatically
306     // recreate the disk thread with the required amount of streams
307     if (pAudioOutputDevice) Connect(pAudioOutputDevice);
308    
309     ResumeAll();
310     }
311    
312 schoenebeck 2434 virtual String DiskStreamBufferFillBytes() OVERRIDE { return (pDiskThread) ? pDiskThread->GetBufferFillBytes() : ""; }
313     virtual String DiskStreamBufferFillPercentage() OVERRIDE { return (pDiskThread) ? pDiskThread->GetBufferFillPercentage() : ""; }
314     virtual InstrumentManager* GetInstrumentManager() OVERRIDE { return &instruments; }
315 iliev 2012
316     /**
317     * Connect this engine instance with the given audio output device.
318     * This method will be called when an Engine instance is created.
319     * All of the engine's data structures which are dependant to the used
320     * audio output device / driver will be (re)allocated and / or
321     * adjusted appropriately.
322     *
323     * @param pAudioOut - audio output device to connect to
324     */
325 schoenebeck 2434 virtual void Connect(AudioOutputDevice* pAudioOut) OVERRIDE {
326 iliev 2012 // caution: don't ignore if connecting to the same device here,
327     // because otherwise SetMaxDiskStreams() implementation won't work anymore!
328    
329     pAudioOutputDevice = pAudioOut;
330    
331     ResetInternal();
332    
333     // inform audio driver for the need of two channels
334     try {
335     pAudioOutputDevice->AcquireChannels(2); // default stereo
336     }
337     catch (AudioOutputException e) {
338     String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
339     throw Exception(msg);
340     }
341    
342     this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
343     this->SampleRate = pAudioOutputDevice->SampleRate();
344    
345     MinFadeOutSamples = int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;
346     if (MaxSamplesPerCycle < MinFadeOutSamples) {
347     std::cerr << "EngineBase: WARNING, CONFIG_EG_MIN_RELEASE_TIME "
348     << "too big for current audio fragment size & sampling rate! "
349     << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;
350     // force volume ramp downs at the beginning of each fragment
351     MinFadeOutSamples = MaxSamplesPerCycle;
352     // lower minimum release time
353     const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
354 schoenebeck 2879 pVoicePool->clear();
355 iliev 2012 for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
356 persson 2327 iterVoice->CalculateFadeOutCoeff(minReleaseTime, SampleRate);
357 iliev 2012 }
358     pVoicePool->clear();
359     }
360    
361     // (re)create disk thread
362     if (this->pDiskThread) {
363     dmsg(1,("Stopping disk thread..."));
364     this->pDiskThread->StopThread();
365     delete this->pDiskThread;
366     dmsg(1,("OK\n"));
367     }
368     this->pDiskThread = CreateDiskThread();
369    
370     if (!pDiskThread) {
371     dmsg(0,("EngineBase new diskthread = NULL\n"));
372     exit(EXIT_FAILURE);
373     }
374    
375 schoenebeck 2879 pVoicePool->clear();
376 iliev 2012 for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
377     iterVoice->pDiskThread = this->pDiskThread;
378     dmsg(3,("d"));
379     }
380     pVoicePool->clear();
381    
382     // (re)create event generator
383     if (pEventGenerator) delete pEventGenerator;
384     pEventGenerator = new EventGenerator(pAudioOut->SampleRate());
385    
386     dmsg(1,("Starting disk thread..."));
387     pDiskThread->StartThread();
388     dmsg(1,("OK\n"));
389    
390 iliev 2298 bool printEqInfo = true;
391 iliev 2012 for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
392     if (!iterVoice->pDiskThread) {
393     dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
394     exit(EXIT_FAILURE);
395     }
396 iliev 2298
397     iterVoice->CreateEq();
398    
399     if(printEqInfo) {
400     iterVoice->PrintEqInfo();
401     printEqInfo = false;
402     }
403 iliev 2012 }
404     pVoicePool->clear();
405 schoenebeck 2121
406     // (re)create dedicated voice audio buffers
407     //TODO: we could optimize resource usage a bit by just allocating these dedicated voice buffers when there is at least one engine channel with FX sends, because only in this case those special buffers are used actually, but since it would usually only save couple bytes in total, its probably not worth it
408     if (pDedicatedVoiceChannelLeft) delete pDedicatedVoiceChannelLeft;
409     if (pDedicatedVoiceChannelRight) delete pDedicatedVoiceChannelRight;
410     pDedicatedVoiceChannelLeft = new AudioChannel(0, MaxSamplesPerCycle);
411     pDedicatedVoiceChannelRight = new AudioChannel(1, MaxSamplesPerCycle);
412 iliev 2012 }
413 schoenebeck 2410
414     // Implementattion for abstract method derived from Engine.
415 schoenebeck 2434 virtual void ReconnectAudioOutputDevice() OVERRIDE {
416 schoenebeck 2410 SuspendAll();
417     if (pAudioOutputDevice) Connect(pAudioOutputDevice);
418     ResumeAll();
419     }
420 iliev 2012
421     /**
422     * Similar to @c Disable() but this method additionally kills all voices
423     * and disk streams and blocks until all voices and disk streams are actually
424     * killed / deleted.
425     *
426     * @e Note: only the original calling thread is able to re-enable the
427     * engine afterwards by calling @c ResumeAll() later on!
428     */
429     virtual void SuspendAll() {
430     dmsg(2,("Engine: Suspending all ...\n"));
431     // stop the engine, so we can safely modify the engine's
432     // data structures from this foreign thread
433     DisableAndLock();
434     // we could also use the respective class member variable here,
435     // but this is probably safer and cleaner
436     int iPendingStreamDeletions = 0;
437     // kill all voices on all engine channels the *die hard* way
438     for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
439     EngineChannelBase<V, R, I>* pEngineChannel =
440     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannel]);
441    
442     iPendingStreamDeletions += pEngineChannel->KillAllVoicesImmediately();
443     }
444     // wait until all streams were actually deleted by the disk thread
445     while (iPendingStreamDeletions) {
446     while (
447     iPendingStreamDeletions &&
448     pDiskThread->AskForDeletedStream() != Stream::INVALID_HANDLE
449     ) iPendingStreamDeletions--;
450     if (!iPendingStreamDeletions) break;
451     usleep(10000); // sleep for 10ms
452     }
453     dmsg(2,("EngineBase: Everything suspended.\n"));
454     }
455    
456     /**
457     * At the moment same as calling @c Enable() directly, but this might
458     * change in future, so better call this method as counterpart to
459     * @c SuspendAll() instead of @c Enable() !
460     */
461     virtual void ResumeAll() { Enable(); }
462    
463     /**
464     * Order the engine to stop rendering audio for the given region.
465     * Additionally this method will block until all voices and their disk
466     * streams associated with that region are actually killed / deleted, so
467     * one can i.e. safely modify the region with an instrument editor after
468     * returning from this method.
469     *
470     * @param pRegion - region the engine shall stop using
471     */
472     virtual void Suspend(RR* pRegion) {
473 persson 2837 dmsg(2,("EngineBase: Suspending Region %p ...\n",(void*)pRegion));
474 persson 2427 {
475     LockGuard lock(SuspendedRegionsMutex);
476     SuspensionChangeOngoing.Set(true);
477     pPendingRegionSuspension = pRegion;
478     SuspensionChangeOngoing.WaitAndUnlockIf(true);
479     }
480 persson 2837 dmsg(2,("EngineBase: Region %p suspended.",(void*)pRegion));
481 iliev 2012 }
482    
483     /**
484     * Orders the engine to resume playing back the given region, previously
485     * suspended with @c Suspend() .
486     *
487     * @param pRegion - region the engine shall be allowed to use again
488     */
489     virtual void Resume(RR* pRegion) {
490 persson 2837 dmsg(2,("EngineBase: Resuming Region %p ...\n",(void*)pRegion));
491 persson 2427 {
492     LockGuard lock(SuspendedRegionsMutex);
493     SuspensionChangeOngoing.Set(true);
494     pPendingRegionResumption = pRegion;
495     SuspensionChangeOngoing.WaitAndUnlockIf(true);
496     }
497 persson 2837 dmsg(2,("EngineBase: Region %p resumed.\n",(void*)pRegion));
498 iliev 2012 }
499    
500     virtual void ResetSuspendedRegions() {
501     SuspendedRegions.clear();
502     iPendingStreamDeletions = 0;
503     pPendingRegionSuspension = pPendingRegionResumption = NULL;
504     SuspensionChangeOngoing.Set(false);
505     }
506    
507     /**
508     * Called by the engine's (audio) thread once per cycle to process requests
509     * from the outer world to suspend or resume a given @c gig::Region .
510     */
511     virtual void ProcessSuspensionsChanges() {
512     // process request for suspending one region
513     if (pPendingRegionSuspension) {
514     // kill all voices on all engine channels that use this region
515     for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
516     EngineChannelBase<V, R, I>* pEngineChannel =
517     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannel]);
518     SuspensionVoiceHandler handler(pPendingRegionSuspension);
519     pEngineChannel->ProcessActiveVoices(&handler);
520     iPendingStreamDeletions += handler.PendingStreamDeletions;
521     }
522     // make sure the region is not yet on the list
523     bool bAlreadySuspended = false;
524     RootRegionIterator iter = SuspendedRegions.first();
525     RootRegionIterator end = SuspendedRegions.end();
526     for (; iter != end; ++iter) { // iterate through all suspended regions
527     if (*iter == pPendingRegionSuspension) { // found
528     bAlreadySuspended = true;
529     dmsg(1,("EngineBase: attempt to suspend an already suspended region !!!\n"));
530     break;
531     }
532     }
533     if (!bAlreadySuspended) {
534     // put the region on the list of suspended regions
535     RootRegionIterator iter = SuspendedRegions.allocAppend();
536     if (iter) {
537     *iter = pPendingRegionSuspension;
538     } else std::cerr << "EngineBase: Could not suspend Region, list is full. This is a bug!!!\n" << std::flush;
539     }
540     // free request slot for next caller (and to make sure that
541     // we're not going to process the same request in the next cycle)
542     pPendingRegionSuspension = NULL;
543     // if no disk stream deletions are pending, awaken other side, as
544     // we're done in this case
545     if (!iPendingStreamDeletions) SuspensionChangeOngoing.Set(false);
546     }
547    
548     // process request for resuming one region
549     if (pPendingRegionResumption) {
550     // remove region from the list of suspended regions
551     RootRegionIterator iter = SuspendedRegions.first();
552     RootRegionIterator end = SuspendedRegions.end();
553     for (; iter != end; ++iter) { // iterate through all suspended regions
554     if (*iter == pPendingRegionResumption) { // found
555     SuspendedRegions.free(iter);
556     break; // done
557     }
558     }
559     // free request slot for next caller
560     pPendingRegionResumption = NULL;
561     // awake other side as we're done
562     SuspensionChangeOngoing.Set(false);
563     }
564     }
565    
566     /**
567     * Called by the engine's (audio) thread once per cycle to check if
568     * streams of voices that were killed due to suspension request have
569     * finally really been deleted by the disk thread.
570     */
571     virtual void ProcessPendingStreamDeletions() {
572     if (!iPendingStreamDeletions) return;
573     //TODO: or shall we better store a list with stream handles instead of a scalar amount of streams to be deleted? might be safer
574     while (
575     iPendingStreamDeletions &&
576     pDiskThread->AskForDeletedStream() != Stream::INVALID_HANDLE
577     ) iPendingStreamDeletions--;
578     // just for safety ...
579     while (pDiskThread->AskForDeletedStream() != Stream::INVALID_HANDLE);
580     // now that all disk streams are deleted, awake other side as
581     // we're finally done with suspending the requested region
582     if (!iPendingStreamDeletions) SuspensionChangeOngoing.Set(false);
583     }
584    
585     /**
586     * Returns @c true if the given region is currently set to be suspended
587     * from being used, @c false otherwise.
588     */
589     virtual bool RegionSuspended(RR* pRegion) {
590     if (SuspendedRegions.isEmpty()) return false;
591     //TODO: or shall we use a sorted container instead of the RTList? might be faster ... or trivial ;-)
592     RootRegionIterator iter = SuspendedRegions.first();
593     RootRegionIterator end = SuspendedRegions.end();
594     for (; iter != end; ++iter) // iterate through all suspended regions
595     if (*iter == pRegion) return true;
596     return false;
597     }
598    
599     // implementation of abstract method derived from class 'LinuxSampler::RegionPools'
600 schoenebeck 3054 virtual Pool<R*>* GetRegionPool(int index) OVERRIDE {
601 iliev 2012 if (index < 0 || index > 1) throw Exception("Index out of bounds");
602     return pRegionPool[index];
603     }
604    
605 schoenebeck 2879 // implementation of abstract methods derived from class 'LinuxSampler::NotePool'
606     virtual Pool<V>* GetVoicePool() OVERRIDE { return pVoicePool; }
607     virtual Pool< Note<V> >* GetNotePool() OVERRIDE { return pNotePool; }
608 schoenebeck 3073 virtual Pool<note_id_t>* GetNoteIDPool() OVERRIDE { return &noteIDPool; }
609 iliev 2012
610     D* GetDiskThread() { return pDiskThread; }
611    
612     //friend class EngineChannelBase<V, R, I>;
613    
614 persson 2127 static IM instruments;
615    
616 iliev 2012 protected:
617     class SuspensionVoiceHandler : public MidiKeyboardManager<V>::VoiceHandler {
618     public:
619     int PendingStreamDeletions;
620     RR* pPendingRegionSuspension;
621 schoenebeck 2434
622 iliev 2012 SuspensionVoiceHandler(RR* pPendingRegionSuspension) {
623     PendingStreamDeletions = 0;
624     this->pPendingRegionSuspension = pPendingRegionSuspension;
625     }
626    
627 schoenebeck 2434 virtual bool Process(MidiKey* pMidiKey) OVERRIDE {
628 schoenebeck 2879 NoteIterator itNote = pMidiKey->pActiveNotes->first();
629     VoiceIterator itVoice = itNote->pActiveVoices->first();
630 iliev 2012 // if current key is not associated with this region, skip this key
631     if (itVoice->GetRegion()->GetParent() != pPendingRegionSuspension) return false;
632    
633     return true;
634     }
635    
636 schoenebeck 2434 virtual void Process(VoiceIterator& itVoice) OVERRIDE {
637 iliev 2012 // request a notification from disk thread side for stream deletion
638     const Stream::Handle hStream = itVoice->KillImmediately(true);
639     if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream
640     PendingStreamDeletions++;
641     }
642     //NOTE: maybe we should call FreeVoice() here, shouldn't cause a harm though I think, since the voices should be freed by RenderActiveVoices() in the render loop, they are probably just freed a bit later than they could/should be
643     }
644     };
645    
646     Pool<R*>* pRegionPool[2]; ///< Double buffered pool, used by the engine channels to keep track of regions in use.
647     int MinFadeOutSamples; ///< The number of samples needed to make an instant fade out (e.g. for voice stealing) without leading to clicks.
648     D* pDiskThread;
649    
650     int ActiveVoiceCountTemp; ///< number of currently active voices (for internal usage, will be used for incrementation)
651     VoiceIterator itLastStolenVoice; ///< Only for voice stealing: points to the last voice which was theft in current audio fragment, NULL otherwise.
652 schoenebeck 2879 NoteIterator itLastStolenNote; ///< Only for voice stealing: points to the last note from which was theft in current audio fragment, NULL otherwise.
653 iliev 2012 RTList<uint>::Iterator iuiLastStolenKey; ///< Only for voice stealing: key number of last key on which the last voice was theft in current audio fragment, NULL otherwise.
654     EngineChannelBase<V, R, I>* pLastStolenChannel; ///< Only for voice stealing: points to the engine channel on which the previous voice was stolen in this audio fragment.
655     VoiceIterator itLastStolenVoiceGlobally; ///< Same as itLastStolenVoice, but engine globally
656 schoenebeck 2879 NoteIterator itLastStolenNoteGlobally; ///< Same as itLastStolenNote, but engine globally
657 iliev 2012 RTList<uint>::Iterator iuiLastStolenKeyGlobally; ///< Same as iuiLastStolenKey, but engine globally
658     RTList<Event>* pVoiceStealingQueue; ///< All voice-launching events which had to be postponed due to free voice shortage.
659     Mutex ResetInternalMutex; ///< Mutex to protect the ResetInternal function for concurrent usage (e.g. by the lscp and instrument loader threads).
660     int iMaxDiskStreams;
661    
662 schoenebeck 2879 NoteBase* NoteByID(note_id_t id) OVERRIDE {
663     NoteIterator itNote = GetNotePool()->fromID(id);
664     if (!itNote) return NULL;
665     return &*itNote;
666     }
667    
668 iliev 2012 /**
669 schoenebeck 2879 * Gets a new @c Note object from the note pool, initializes it
670     * appropriately, links it with requested parent note (if
671     * requested), moves it to the appropriate key's list of active
672     * notes it, and sticks the new note's unique ID to the
673     * passed @a pNoteOnEvent.
674     *
675     * @param pEngineChannel - engine channel on which this event happened
676     * @param pNoteOnEvent - event which caused this
677     * @returns new note's unique ID (or zero on error)
678     */
679 schoenebeck 3205 note_id_t LaunchNewNote(LinuxSampler::EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) OVERRIDE {
680 schoenebeck 2879 EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
681     Pool< Note<V> >* pNotePool = GetNotePool();
682    
683     if (pNotePool->poolIsEmpty()) {
684     dmsg(1,("Engine: Could not launch new note; Note pool empty!\n"));
685     return 0; // error
686     }
687    
688     // create a new note (for new voices to be assigned to)
689     //NoteIterator itNewNote = pKey->pActiveNotes->allocAppend();
690     NoteIterator itNewNote = pNotePool->allocAppend();
691     const note_id_t newNoteID = pNotePool->getID(itNewNote);
692    
693 schoenebeck 2962 // remember the engine's time when this note was triggered exactly
694 schoenebeck 3205 itNewNote->triggerSchedTime = itNoteOnEvent->SchedTime();
695 schoenebeck 2962
696 schoenebeck 2879 // usually the new note (and its subsequent voices) will be
697     // allocated on the key provided by the event's note number,
698     // however if this new note is requested not to be a regular
699     // note, but rather a child note, then this new note will be
700     // allocated on the parent note's key instead in order to
701     // release the child note simultaniously with its parent note
702 schoenebeck 3205 itNewNote->hostKey = itNoteOnEvent->Param.Note.Key;
703 schoenebeck 2879
704     // in case this new note was requested to be a child note,
705     // then retrieve its parent note and link them with each other
706 schoenebeck 3205 const note_id_t parentNoteID = itNoteOnEvent->Param.Note.ParentNoteID;
707 schoenebeck 2879 if (parentNoteID) {
708     NoteIterator itParentNote = pNotePool->fromID(parentNoteID);
709     if (itParentNote) {
710     RTList<note_id_t>::Iterator itChildNoteID = itParentNote->pChildNotes->allocAppend();
711     if (itChildNoteID) {
712     // link parent and child note with each other
713     *itChildNoteID = newNoteID;
714     itNewNote->parentNoteID = parentNoteID;
715     itNewNote->hostKey = itParentNote->hostKey;
716     } else {
717     dmsg(1,("Engine: Could not assign new note as child note; Note ID pool empty!\n"));
718     pNotePool->free(itNewNote);
719     return 0; // error
720     }
721     } else {
722     // the parent note was apparently released already, so
723     // free the new note again and inform caller that it
724     // should drop the event
725     dmsg(3,("Engine: Could not assign new note as child note; Parent note is gone!\n"));
726     pNotePool->free(itNewNote);
727     return 0; // error
728     }
729     }
730    
731     dmsg(2,("Launched new note on host key %d\n", itNewNote->hostKey));
732    
733     // copy event which caused this note
734 schoenebeck 3205 itNewNote->cause = *itNoteOnEvent;
735     itNewNote->eventID = pEventPool->getID(itNoteOnEvent);
736     if (!itNewNote->eventID) {
737     dmsg(0,("Engine: No valid event ID resolved for note. This is a bug!!!\n"));
738     }
739 schoenebeck 2879
740     // move new note to its host key
741     MidiKey* pKey = &pChannel->pMIDIKeyInfo[itNewNote->hostKey];
742     itNewNote.moveToEndOf(pKey->pActiveNotes);
743    
744     // assign unique note ID of this new note to the original note on event
745 schoenebeck 3205 itNoteOnEvent->Param.Note.ID = newNoteID;
746 schoenebeck 2879
747     return newNoteID; // success
748     }
749    
750     /**
751 iliev 2012 * Dispatch and handle all events in this audio fragment for the given
752     * engine channel.
753     *
754     * @param pEngineChannel - engine channel on which events should be
755     * processed
756     * @param Samples - amount of sample points to be processed in
757     * this audio fragment cycle
758     */
759     void ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
760     // get all events from the engine channels's input event queue which belong to the current fragment
761     // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
762     AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
763     pChannel->ImportEvents(Samples);
764    
765 schoenebeck 2594 // if a valid real-time instrument script is loaded, pre-process
766     // the event list by running the script now, since the script
767     // might filter events or add new ones for this cycle
768 schoenebeck 2659 if (pChannel->pScript) {
769 schoenebeck 2871 const sched_time_t fragmentEndTime = pEventGenerator->schedTimeAtCurrentFragmentEnd();
770 schoenebeck 2594
771 schoenebeck 2871 // resume suspended script executions been scheduled for
772     // this audio fragment cycle (which were suspended in a
773     // previous audio fragment cycle)
774     ProcessSuspendedScriptEvents(pChannel, fragmentEndTime);
775    
776 schoenebeck 2594 // spawn new script executions for the new MIDI events of
777     // this audio fragment cycle
778 schoenebeck 2871 //
779     // FIXME: it would probably be better to just schedule newly spawned script executions here and then execute them altogether with already suspended ones all at once in order of all their scheduled timing
780 schoenebeck 2594 for (RTList<Event>::Iterator itEvent = pChannel->pEvents->first(),
781 schoenebeck 2884 end = pChannel->pEvents->end(); itEvent != end; )
782 schoenebeck 2594 {
783 schoenebeck 2884 //HACK: avoids iterator invalidation which might happen below since an instrument script might drop an event by direct raw pointer access (it would be considerable to extend the Iterator class to detect and circumvent this case by checking the "reincarnation" member variable).
784     RTList<Event>::Iterator itNext = itEvent;
785     ++itNext;
786    
787 schoenebeck 2594 switch (itEvent->Type) {
788     case Event::type_note_on:
789 schoenebeck 2611 if (pChannel->pScript->handlerNote)
790     ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerNote);
791 schoenebeck 2594 break;
792     case Event::type_note_off:
793 schoenebeck 2611 if (pChannel->pScript->handlerRelease)
794     ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerRelease);
795 schoenebeck 2594 break;
796     case Event::type_control_change:
797     case Event::type_channel_pressure:
798     case Event::type_pitchbend:
799 schoenebeck 2611 if (pChannel->pScript->handlerController)
800     ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerController);
801 schoenebeck 2594 break;
802     case Event::type_note_pressure:
803     //TODO: ...
804     break;
805 schoenebeck 3034
806     case Event::type_sysex:
807     //TODO: ...
808     break;
809    
810     case Event::type_cancel_release_key:
811     case Event::type_release_key:
812     case Event::type_release_note:
813     case Event::type_play_note:
814     case Event::type_stop_note:
815 schoenebeck 3188 case Event::type_kill_note:
816 schoenebeck 3034 case Event::type_note_synth_param:
817     break; // noop
818 schoenebeck 2594 }
819 schoenebeck 2884
820     // see HACK comment above
821     itEvent = itNext;
822 schoenebeck 2594 }
823 schoenebeck 2871
824     // this has to be run again, since the newly spawned scripts
825     // above may have cause suspended scripts that must be
826     // resumed within this same audio fragment cycle
827     //
828     // FIXME: see FIXME comment above
829     ProcessSuspendedScriptEvents(pChannel, fragmentEndTime);
830 schoenebeck 2594 }
831    
832 schoenebeck 2871 // if there are any delayed events scheduled for the current
833     // audio fragment cycle, then move and sort them into the main
834     // event list
835     if (!pChannel->delayedEvents.queue.isEmpty()) {
836     dmsg(5,("Engine: There are delayed MIDI events (total queue size: %d) ...\n", pChannel->delayedEvents.queue.size()));
837     const sched_time_t fragmentEndTime = pEventGenerator->schedTimeAtCurrentFragmentEnd();
838     RTList<Event>::Iterator itEvent = pChannel->pEvents->first();
839     while (true) {
840     RTList<ScheduledEvent>::Iterator itDelayedEventNode =
841     pEventGenerator->popNextScheduledEvent(
842     pChannel->delayedEvents.queue,
843     pChannel->delayedEvents.schedulerNodes,
844     fragmentEndTime
845     );
846     if (!itDelayedEventNode) break;
847     // get the actual delayed event object and free the used scheduler node
848     RTList<Event>::Iterator itDelayedEvent = itDelayedEventNode->itEvent;
849     pChannel->delayedEvents.schedulerNodes.free(itDelayedEventNode);
850     if (!itDelayedEvent) { // should never happen, but just to be sure ...
851     dmsg(1,("Engine: Oops, invalid delayed event!\n"));
852     continue;
853     }
854     // skip all events on main event list which have a time
855     // before (or equal to) the delayed event to be inserted
856     for (; itEvent && itEvent->FragmentPos() <= itDelayedEvent->FragmentPos();
857     ++itEvent);
858     // now move delayed event from delayedEvents.pList to
859     // the current position on the main event list
860     itEvent = itDelayedEvent.moveBefore(itEvent);
861     dmsg(5,("Engine: Inserted event of type %d into main event list (queue size: %d).\n", itEvent->Type, pChannel->delayedEvents.queue.size()));
862     }
863     dmsg(5,("Engine: End of delayed events (total queue size: %d).\n", pChannel->delayedEvents.queue.size()));
864     }
865    
866 schoenebeck 2594 // now process all events regularly
867 iliev 2012 {
868     RTList<Event>::Iterator itEvent = pChannel->pEvents->first();
869     RTList<Event>::Iterator end = pChannel->pEvents->end();
870     for (; itEvent != end; ++itEvent) {
871     switch (itEvent->Type) {
872     case Event::type_note_on:
873     dmsg(5,("Engine: Note on received\n"));
874     ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
875     break;
876 schoenebeck 2938 case Event::type_play_note:
877     dmsg(5,("Engine: Play Note received\n"));
878     ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
879     break;
880 iliev 2012 case Event::type_note_off:
881     dmsg(5,("Engine: Note off received\n"));
882     ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
883     break;
884 schoenebeck 2938 case Event::type_stop_note:
885     dmsg(5,("Engine: Stop Note received\n"));
886     ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
887     break;
888 schoenebeck 3188 case Event::type_kill_note:
889     dmsg(5,("Engine: Kill Note received\n"));
890     ProcessKillNote((EngineChannel*)itEvent->pEngineChannel, itEvent);
891     break;
892 iliev 2012 case Event::type_control_change:
893     dmsg(5,("Engine: MIDI CC received\n"));
894     ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
895     break;
896 schoenebeck 2559 case Event::type_channel_pressure:
897     dmsg(5,("Engine: MIDI Chan. Pressure received\n"));
898     ProcessChannelPressure((EngineChannel*)itEvent->pEngineChannel, itEvent);
899     break;
900     case Event::type_note_pressure:
901     dmsg(5,("Engine: MIDI Note Pressure received\n"));
902     ProcessPolyphonicKeyPressure((EngineChannel*)itEvent->pEngineChannel, itEvent);
903     break;
904 iliev 2012 case Event::type_pitchbend:
905     dmsg(5,("Engine: Pitchbend received\n"));
906     ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);
907     break;
908 schoenebeck 2931 case Event::type_note_synth_param:
909     dmsg(5,("Engine: Note Synth Param received\n"));
910     ProcessNoteSynthParam(itEvent->pEngineChannel, itEvent);
911     break;
912 schoenebeck 3034 case Event::type_sysex:
913     break; // TODO ...
914    
915     case Event::type_cancel_release_key:
916     case Event::type_release_key:
917     case Event::type_release_note:
918     break; // noop
919 iliev 2012 }
920     }
921     }
922    
923     // reset voice stealing for the next engine channel (or next audio fragment)
924     itLastStolenVoice = VoiceIterator();
925     itLastStolenVoiceGlobally = VoiceIterator();
926 schoenebeck 2879 itLastStolenNote = NoteIterator();
927     itLastStolenNoteGlobally = NoteIterator();
928 iliev 2012 iuiLastStolenKey = RTList<uint>::Iterator();
929     iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
930     pLastStolenChannel = NULL;
931     }
932    
933 schoenebeck 2871 /**
934     * Run all suspended script execution instances which are scheduled
935     * to be resumed for the current audio fragment cycle.
936     *
937     * @param pChannel - engine channel on which suspended events occurred
938     */
939     void ProcessSuspendedScriptEvents(AbstractEngineChannel* pChannel, const sched_time_t fragmentEndTime) {
940     while (true) {
941     RTList<ScriptEvent>::Iterator itEvent =
942     pEventGenerator->popNextScheduledScriptEvent(
943     pChannel->pScript->suspendedEvents,
944     *pChannel->pScript->pEvents, fragmentEndTime
945     );
946     if (!itEvent) break;
947     ResumeScriptEvent(pChannel, itEvent);
948     }
949     }
950    
951 schoenebeck 2594 /** @brief Call instrument script's event handler for this event.
952     *
953     * Causes a new execution instance of the currently loaded real-time
954     * instrument script's event handler (callback) to be spawned for
955     * the given MIDI event.
956     *
957 schoenebeck 2871 * @param pChannel - engine channel on which the MIDI event occurred
958 schoenebeck 2594 * @param itEvent - MIDI event that causes this new script execution
959     * @param pEventHandler - script's event handler to be executed
960     */
961     void ProcessEventByScript(AbstractEngineChannel* pChannel, RTList<Event>::Iterator& itEvent, VMEventHandler* pEventHandler) {
962 schoenebeck 2645 const int key = itEvent->Param.Note.Key; // even if this is not a note on/off event, accessing it does not mean any harm
963     // check if polyphonic data is passed from "note" to "release"
964     // script event handlers
965     if (pEventHandler == pChannel->pScript->handlerRelease &&
966     pChannel->pScript->handlerNote &&
967     pChannel->pScript->handlerNote->isPolyphonic() &&
968     pChannel->pScript->handlerRelease->isPolyphonic() &&
969     !pChannel->pScript->pKeyEvents[key]->isEmpty())
970     {
971     // polyphonic variable data is used/passed from "note" to
972     // "release" script callback, so we have to recycle the
973     // original "note on" script event(s)
974     RTList<ScriptEvent>::Iterator it = pChannel->pScript->pKeyEvents[key]->first();
975     RTList<ScriptEvent>::Iterator end = pChannel->pScript->pKeyEvents[key]->end();
976     for (; it != end; ++it) {
977     ProcessScriptEvent(
978     pChannel, itEvent, pEventHandler, it
979     );
980     }
981     } else {
982     // no polyphonic data is used/passed from "note" to
983     // "release" script callback, so just use a new fresh
984     // script event object
985     RTList<ScriptEvent>::Iterator itScriptEvent =
986     pChannel->pScript->pEvents->allocAppend();
987 schoenebeck 3207 // if event handler uses polyphonic variables, reset them
988     // to zero values before starting to execute the handler
989     if (pEventHandler->isPolyphonic())
990     itScriptEvent->execCtx->resetPolyphonicData();
991 schoenebeck 2645 ProcessScriptEvent(
992     pChannel, itEvent, pEventHandler, itScriptEvent
993     );
994     }
995     }
996 schoenebeck 2594
997 schoenebeck 2871 /** @brief Spawn new execution instance of an instrument script handler.
998     *
999     * Will be called to initiate a new execution of a real-time
1000     * instrument script event right from the start of the script's
1001     * respective handler. If script execution did not complete after
1002     * calling this method, the respective script exeuction is then
1003     * suspended and a call to ResumeScriptEvent() will be used next
1004     * time to continue its execution.
1005     *
1006     * @param pChannel - engine channel this script is running for
1007     * @param itEvent - event which caused execution of this script
1008     * event handler
1009     * @param pEventHandler - VM representation of event handler to be
1010     * executed
1011     * @param itScriptEvent - script event that shall be processed
1012     */
1013 schoenebeck 2645 void ProcessScriptEvent(AbstractEngineChannel* pChannel, RTList<Event>::Iterator& itEvent, VMEventHandler* pEventHandler, RTList<ScriptEvent>::Iterator& itScriptEvent) {
1014     if (!itScriptEvent) return; // not a valid script event (i.e. because no free script event was left in the script event pool)
1015 schoenebeck 2594
1016     // fill the list of script handlers to be executed by this event
1017     int i = 0;
1018     itScriptEvent->handlers[i++] = pEventHandler; // actual event handler (i.e. note, controller)
1019     itScriptEvent->handlers[i] = NULL; // NULL termination of list
1020    
1021     // initialize/reset other members
1022     itScriptEvent->cause = *itEvent;
1023 schoenebeck 3205 itScriptEvent->scheduleTime = itEvent->SchedTime();
1024 schoenebeck 2594 itScriptEvent->currentHandler = 0;
1025     itScriptEvent->executionSlices = 0;
1026 schoenebeck 2948 itScriptEvent->ignoreAllWaitCalls = false;
1027     itScriptEvent->handlerType = pEventHandler->eventHandlerType();
1028 schoenebeck 2879 // this is the native representation of the $EVENT_ID script variable
1029     itScriptEvent->id =
1030     (itEvent->Type == Event::type_note_on)
1031     ? ScriptID::fromNoteID( itEvent->Param.Note.ID )
1032     : ScriptID::fromEventID( pEventPool->getID(itEvent) );
1033 schoenebeck 2594
1034     // run script handler(s)
1035     VMExecStatus_t res = pScriptVM->exec(
1036 schoenebeck 2611 pChannel->pScript->parserContext, &*itScriptEvent
1037 schoenebeck 2594 );
1038    
1039 schoenebeck 2871 // was the script suspended?
1040     if (res & VM_EXEC_SUSPENDED) { // script was suspended ...
1041     // in case the script was suspended, keep it on the allocated
1042     // ScriptEvent list to be resume at the scheduled time in future,
1043     // additionally insert it into a sorted time queue
1044     pEventGenerator->scheduleAheadMicroSec(
1045     pChannel->pScript->suspendedEvents, // scheduler queue
1046     *itScriptEvent, // script event
1047     itScriptEvent->cause.FragmentPos(), // current time of script event (basis for its next execution)
1048     itScriptEvent->execCtx->suspensionTimeMicroseconds() // how long shall it be suspended
1049     );
1050     } else { // script execution has finished without 'suspended' status ...
1051 schoenebeck 2645 // if "polyphonic" variable data is passed from script's
1052     // "note" event handler to its "release" event handler, then
1053     // the script event must be kept and recycled for the later
1054     // occuring "release" script event ...
1055     if (pEventHandler == pChannel->pScript->handlerNote &&
1056     pChannel->pScript->handlerRelease &&
1057     pChannel->pScript->handlerNote->isPolyphonic() &&
1058     pChannel->pScript->handlerRelease->isPolyphonic())
1059     {
1060     const int key = itEvent->Param.Note.Key;
1061     itScriptEvent.moveToEndOf(pChannel->pScript->pKeyEvents[key & 127]);
1062     } else {
1063     // ... otherwise if no polyphonic data is passed and
1064     // script's execution has finished without suspension
1065     // status, then free the script event for a new future
1066     // script event to be triggered from start
1067     pChannel->pScript->pEvents->free(itScriptEvent);
1068     }
1069     }
1070 schoenebeck 2594 }
1071    
1072     /** @brief Resume execution of instrument script.
1073     *
1074     * Will be called to resume execution of a real-time instrument
1075 schoenebeck 2879 * script event which has been suspended previously.
1076 schoenebeck 2594 *
1077     * Script execution might be suspended for various reasons. Usually
1078     * a script will be suspended if the script called the built-in
1079     * "wait()" function, but it might also be suspended automatically
1080     * if the script took too much execution time in an audio fragment
1081     * cycle. So in the latter case automatic suspension is performed in
1082     * order to avoid harm for the sampler's overall real-time
1083     * requirements.
1084     *
1085     * @param pChannel - engine channel this script is running for
1086     * @param itScriptEvent - script execution that shall be resumed
1087     */
1088     void ResumeScriptEvent(AbstractEngineChannel* pChannel, RTList<ScriptEvent>::Iterator& itScriptEvent) {
1089 schoenebeck 2645 VMEventHandler* handler = itScriptEvent->handlers[itScriptEvent->currentHandler];
1090    
1091 schoenebeck 2594 // run script
1092     VMExecStatus_t res = pScriptVM->exec(
1093 schoenebeck 2611 pChannel->pScript->parserContext, &*itScriptEvent
1094 schoenebeck 2594 );
1095 schoenebeck 2645
1096 schoenebeck 2871 // was the script suspended?
1097     if (res & VM_EXEC_SUSPENDED) {
1098     // in case the script was suspended, keep it on the allocated
1099     // ScriptEvent list to be resume at the scheduled time in future,
1100     // additionally insert it into a sorted time queue
1101     pEventGenerator->scheduleAheadMicroSec(
1102     pChannel->pScript->suspendedEvents, // scheduler queue
1103     *itScriptEvent, // script event
1104     itScriptEvent->cause.FragmentPos(), // current time of script event (basis for its next execution)
1105     itScriptEvent->execCtx->suspensionTimeMicroseconds() // how long shall it be suspended
1106     );
1107     } else { // script execution has finished without 'suspended' status ...
1108 schoenebeck 2645 // if "polyphonic" variable data is passed from script's
1109     // "note" event handler to its "release" event handler, then
1110     // the script event must be kept and recycled for the later
1111     // occuring "release" script event ...
1112     if (handler && handler == pChannel->pScript->handlerNote &&
1113     pChannel->pScript->handlerRelease &&
1114     pChannel->pScript->handlerNote->isPolyphonic() &&
1115     pChannel->pScript->handlerRelease->isPolyphonic())
1116     {
1117     const int key = itScriptEvent->cause.Param.Note.Key;
1118     itScriptEvent.moveToEndOf(pChannel->pScript->pKeyEvents[key & 127]);
1119     } else {
1120     // ... otherwise if no polyphonic data is passed and
1121     // script's execution has finished without suspension
1122     // status, then free the script event for a new future
1123     // script event to be triggered from start
1124     pChannel->pScript->pEvents->free(itScriptEvent);
1125     }
1126     }
1127 schoenebeck 2594 }
1128    
1129 iliev 2012 /**
1130     * Will be called by LaunchVoice() method in case there are no free
1131     * voices left. This method will select and kill one old voice for
1132     * voice stealing and postpone the note-on event until the selected
1133     * voice actually died.
1134     *
1135 schoenebeck 2871 * @param pEngineChannel - engine channel on which this event occurred on
1136 iliev 2012 * @param itNoteOnEvent - key, velocity and time stamp of the event
1137     * @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
1138     */
1139 schoenebeck 2879 int StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1140 iliev 2012 if (VoiceSpawnsLeft <= 0) {
1141     dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
1142     return -1;
1143     }
1144    
1145     EngineChannelBase<V, R, I>* pEngineChn = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1146    
1147 schoenebeck 2879 if (pEventPool->poolIsEmpty()) {
1148     dmsg(1,("Event pool emtpy!\n"));
1149     return -1;
1150     }
1151 iliev 2012
1152 schoenebeck 2879 if (!pEngineChn->StealVoice(itNoteOnEvent, &itLastStolenVoice, &itLastStolenNote, &iuiLastStolenKey)) {
1153     --VoiceSpawnsLeft;
1154     return 0;
1155     }
1156 iliev 2012
1157 schoenebeck 2879 // if we couldn't steal a voice from the same engine channel then
1158     // steal oldest voice on the oldest key from any other engine channel
1159     // (the smaller engine channel number, the higher priority)
1160     EngineChannelBase<V, R, I>* pSelectedChannel;
1161     int iChannelIndex;
1162     VoiceIterator itSelectedVoice;
1163 iliev 2012
1164 schoenebeck 2879 // select engine channel
1165     if (pLastStolenChannel) {
1166     pSelectedChannel = pLastStolenChannel;
1167     iChannelIndex = pSelectedChannel->iEngineIndexSelf;
1168     } else { // pick the engine channel followed by this engine channel
1169     iChannelIndex = (pEngineChn->iEngineIndexSelf + 1) % engineChannels.size();
1170     pSelectedChannel = static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannelIndex]);
1171     }
1172 iliev 2012
1173 schoenebeck 2879 // if we already stole in this fragment, try to proceed on same note
1174     if (this->itLastStolenVoiceGlobally) {
1175     itSelectedVoice = this->itLastStolenVoiceGlobally;
1176     do {
1177     ++itSelectedVoice;
1178     } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1179     }
1180     // did we find a 'stealable' voice?
1181     if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1182     // remember which voice we stole, so we can simply proceed on next voice stealing
1183     this->itLastStolenVoiceGlobally = itSelectedVoice;
1184     // done
1185     goto stealable_voice_found;
1186     }
1187    
1188     // get (next) oldest note
1189     if (this->itLastStolenNoteGlobally) {
1190     for (NoteIterator itNote = ++this->itLastStolenNoteGlobally;
1191     itNote; ++itNote)
1192     {
1193     for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice) {
1194     // proceed iterating if voice was created in this audio fragment cycle
1195     if (itSelectedVoice->IsStealable()) {
1196     // remember which voice of which note we stole, so we can simply proceed on next voice stealing
1197     this->itLastStolenNoteGlobally = itNote;
1198     this->itLastStolenVoiceGlobally = itSelectedVoice;
1199     goto stealable_voice_found; // selection succeeded
1200     }
1201     }
1202 iliev 2012 }
1203 schoenebeck 2879 }
1204 iliev 2012
1205 schoenebeck 2879 #if CONFIG_DEVMODE
1206     EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1207     #endif // CONFIG_DEVMODE
1208 iliev 2012
1209 schoenebeck 2879 while (true) { // iterate through engine channels
1210     // get (next) oldest key
1211     RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
1212     this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
1213     while (iuiSelectedKey) {
1214     MidiKey* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1215    
1216     for (NoteIterator itNote = pSelectedKey->pActiveNotes->first(),
1217     itNotesEnd = pSelectedKey->pActiveNotes->end();
1218     itNote != itNotesEnd; ++itNote)
1219     {
1220     itSelectedVoice = itNote->pActiveVoices->first();
1221 iliev 2012 // proceed iterating if voice was created in this fragment cycle
1222     while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1223     // found a "stealable" voice ?
1224     if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1225 schoenebeck 2879 // remember which voice of which note on which key on which engine channel we stole, so we can simply proceed on next voice stealing
1226 iliev 2012 this->iuiLastStolenKeyGlobally = iuiSelectedKey;
1227 schoenebeck 2879 this->itLastStolenNoteGlobally = itNote;
1228 iliev 2012 this->itLastStolenVoiceGlobally = itSelectedVoice;
1229     this->pLastStolenChannel = pSelectedChannel;
1230     goto stealable_voice_found; // selection succeeded
1231     }
1232     }
1233 schoenebeck 2879 ++iuiSelectedKey; // get next key on current engine channel
1234 iliev 2012 }
1235 schoenebeck 2879 // get next engine channel
1236     iChannelIndex = (iChannelIndex + 1) % engineChannels.size();
1237     pSelectedChannel = static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannelIndex]);
1238 iliev 2012
1239     #if CONFIG_DEVMODE
1240 schoenebeck 2879 if (pSelectedChannel == pBegin) {
1241     dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1242     dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1243     dmsg(1,("Exiting.\n"));
1244     exit(-1);
1245 iliev 2012 }
1246     #endif // CONFIG_DEVMODE
1247 schoenebeck 2879 }
1248 iliev 2012
1249 schoenebeck 2879 // jump point if a 'stealable' voice was found
1250     stealable_voice_found:
1251 iliev 2012
1252 schoenebeck 2879 #if CONFIG_DEVMODE
1253     if (!itSelectedVoice->IsActive()) {
1254     dmsg(1,("EngineBase: ERROR, tried to steal a voice which was not active !!!\n"));
1255 iliev 2012 return -1;
1256     }
1257 schoenebeck 2879 #endif // CONFIG_DEVMODE
1258    
1259     // now kill the selected voice
1260     itSelectedVoice->Kill(itNoteOnEvent);
1261    
1262     --VoiceSpawnsLeft;
1263    
1264     return 0; // success
1265 iliev 2012 }
1266    
1267     void HandleInstrumentChanges() {
1268     bool instrumentChanged = false;
1269     for (int i = 0; i < engineChannels.size(); i++) {
1270     EngineChannelBase<V, R, I>* pEngineChannel =
1271     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
1272    
1273     // as we're going to (carefully) write some status to the
1274     // synchronized struct, we cast away the const
1275     InstrumentChangeCmd<R, I>& cmd =
1276     const_cast<InstrumentChangeCmd<R, I>&>(pEngineChannel->InstrumentChangeCommandReader.Lock());
1277    
1278     pEngineChannel->pRegionsInUse = cmd.pRegionsInUse;
1279     pEngineChannel->pRegionsInUse->clear();
1280    
1281     if (cmd.bChangeInstrument) {
1282     // change instrument
1283     dmsg(5,("Engine: instrument change command received\n"));
1284     cmd.bChangeInstrument = false;
1285     pEngineChannel->pInstrument = cmd.pInstrument;
1286 schoenebeck 2659 pEngineChannel->pScript =
1287     cmd.pScript->bHasValidScript ? cmd.pScript : NULL;
1288 iliev 2012 instrumentChanged = true;
1289    
1290     pEngineChannel->MarkAllActiveVoicesAsOrphans();
1291 schoenebeck 2611
1292     // the script's "init" event handler is only executed
1293     // once (when the script is loaded or reloaded)
1294     if (pEngineChannel->pScript && pEngineChannel->pScript->handlerInit) {
1295 schoenebeck 2972 dmsg(5,("Engine: exec handlerInit %p\n", pEngineChannel->pScript->handlerInit));
1296 schoenebeck 2611 RTList<ScriptEvent>::Iterator itScriptEvent =
1297     pEngineChannel->pScript->pEvents->allocAppend();
1298    
1299 schoenebeck 2614 itScriptEvent->cause.pEngineChannel = pEngineChannel;
1300 schoenebeck 2618 itScriptEvent->handlers[0] = pEngineChannel->pScript->handlerInit;
1301     itScriptEvent->handlers[1] = NULL;
1302 schoenebeck 2972 itScriptEvent->currentHandler = 0;
1303     itScriptEvent->executionSlices = 0;
1304     itScriptEvent->ignoreAllWaitCalls = false;
1305     itScriptEvent->handlerType = VM_EVENT_HANDLER_INIT;
1306 schoenebeck 2614
1307 schoenebeck 3221 VMExecStatus_t res;
1308     size_t instructionsCount = 0;
1309     const size_t maxInstructions = 200000; // aiming approx. 1 second max. (based on very roughly 5us / instruction)
1310     bool bWarningShown = false;
1311     do {
1312     res = pScriptVM->exec(
1313     pEngineChannel->pScript->parserContext, &*itScriptEvent
1314     );
1315     instructionsCount += itScriptEvent->execCtx->instructionsPerformed();
1316     if (instructionsCount > maxInstructions && !bWarningShown) {
1317     bWarningShown = true;
1318     dmsg(0,("[ScriptVM] WARNING: \"init\" event handler of instrument script executing for long time!\n"));
1319     }
1320     } while (res & VM_EXEC_SUSPENDED && !(res & VM_EXEC_ERROR));
1321 schoenebeck 2611
1322     pEngineChannel->pScript->pEvents->free(itScriptEvent);
1323     }
1324 iliev 2012 }
1325     }
1326    
1327     if (instrumentChanged) {
1328     //TODO: this is a lazy solution ATM and not safe in case somebody is currently editing the instrument we're currently switching to (we should store all suspended regions on instrument manager side and when switching to another instrument copy that list to the engine's local list of suspensions
1329     ResetSuspendedRegions();
1330     }
1331     }
1332    
1333     /**
1334     * Render all 'normal' voices (that is voices which were not stolen in
1335     * this fragment) on the given engine channel.
1336     *
1337     * @param pEngineChannel - engine channel on which audio should be
1338     * rendered
1339     * @param Samples - amount of sample points to be rendered in
1340     * this audio fragment cycle
1341     */
1342     void RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
1343     #if !CONFIG_PROCESS_MUTED_CHANNELS
1344     if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1345     #endif
1346    
1347     EngineChannelBase<V, R, I>* pChannel =
1348     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1349     pChannel->RenderActiveVoices(Samples);
1350    
1351     ActiveVoiceCountTemp += pEngineChannel->GetVoiceCount();
1352     }
1353    
1354     /**
1355     * Render all stolen voices (only voices which were stolen in this
1356     * fragment) on the given engine channel. Stolen voices are rendered
1357     * after all normal voices have been rendered; this is needed to render
1358     * audio of those voices which were selected for voice stealing until
1359     * the point were the stealing (that is the take over of the voice)
1360     * actually happened.
1361     *
1362     * @param pEngineChannel - engine channel on which audio should be
1363     * rendered
1364     * @param Samples - amount of sample points to be rendered in
1365     * this audio fragment cycle
1366     */
1367     void RenderStolenVoices(uint Samples) {
1368     RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
1369     RTList<Event>::Iterator end = pVoiceStealingQueue->end();
1370     for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
1371     EngineChannelBase<V, R, I>* pEngineChannel =
1372     static_cast<EngineChannelBase<V, R, I>*>(itVoiceStealEvent->pEngineChannel);;
1373     if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
1374 schoenebeck 2879
1375 iliev 2012 PoolVoiceIterator itNewVoice =
1376     LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
1377     if (itNewVoice) {
1378 schoenebeck 2879 // usually there should already be a new Note object
1379     NoteIterator itNote = GetNotePool()->fromID(itVoiceStealEvent->Param.Note.ID);
1380     if (!itNote) { // should not happen, but just to be sure ...
1381 schoenebeck 3205 const note_id_t noteID = LaunchNewNote(pEngineChannel, itVoiceStealEvent);
1382 schoenebeck 2879 if (!noteID) {
1383     dmsg(1,("Engine: Voice stealing failed; No Note object and Note pool empty!\n"));
1384     continue;
1385     }
1386     itNote = GetNotePool()->fromID(noteID);
1387     }
1388     // move voice from whereever it was, to the new note's list of active voices
1389     itNewVoice = itNewVoice.moveToEndOf(itNote->pActiveVoices);
1390     // render audio of this new voice for the first time
1391 iliev 2012 itNewVoice->Render(Samples);
1392     if (itNewVoice->IsActive()) { // still active
1393     *(pEngineChannel->pRegionsInUse->allocAppend()) = itNewVoice->GetRegion();
1394     ActiveVoiceCountTemp++;
1395     pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);
1396    
1397     if (itNewVoice->PlaybackState == Voice::playback_state_disk) {
1398     if (itNewVoice->DiskStreamRef.State != Stream::state_unused) {
1399     pEngineChannel->SetDiskStreamCount(pEngineChannel->GetDiskStreamCount() + 1);
1400     }
1401     }
1402     } else { // voice reached end, is now inactive
1403     pEngineChannel->FreeVoice(itNewVoice); // remove voice from the list of active voices
1404     }
1405     }
1406     else dmsg(1,("EngineBase: ERROR, voice stealing didn't work out!\n"));
1407    
1408     // we need to clear the key's event list explicitly here in case key was never active
1409     MidiKey* pKey = &pEngineChannel->pMIDIKeyInfo[itVoiceStealEvent->Param.Note.Key];
1410     pKey->VoiceTheftsQueued--;
1411     if (!pKey->Active && !pKey->VoiceTheftsQueued) pKey->pEvents->clear();
1412     }
1413     }
1414    
1415     /**
1416     * Free all keys which have turned inactive in this audio fragment, from
1417     * the list of active keys and clear all event lists on that engine
1418     * channel.
1419     *
1420     * @param pEngineChannel - engine channel to cleanup
1421     */
1422     void PostProcess(EngineChannel* pEngineChannel) {
1423     EngineChannelBase<V, R, I>* pChannel =
1424     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1425     pChannel->FreeAllInactiveKyes();
1426    
1427     // empty the engine channel's own event lists
1428 schoenebeck 2871 // (only events of the current audio fragment cycle)
1429     pChannel->ClearEventListsOfCurrentFragment();
1430 iliev 2012 }
1431    
1432 schoenebeck 2121 /**
1433     * Process MIDI control change events with hard coded behavior,
1434     * that is controllers whose behavior is defined independently
1435     * of the actual sampler engine type and instrument.
1436     *
1437     * @param pEngineChannel - engine channel on which the MIDI CC event was received
1438     * @param itControlChangeEvent - the actual MIDI CC event
1439     */
1440 iliev 2012 void ProcessHardcodedControllers (
1441     EngineChannel* pEngineChannel,
1442     Pool<Event>::Iterator& itControlChangeEvent
1443     ) {
1444     EngineChannelBase<V, R, I>* pChannel =
1445     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1446    
1447     switch (itControlChangeEvent->Param.CC.Controller) {
1448     case 5: { // portamento time
1449     pChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
1450     break;
1451     }
1452 schoenebeck 2121 case 6: { // data entry (currently only used for RPN and NRPN controllers)
1453     //dmsg(1,("DATA ENTRY %d\n", itControlChangeEvent->Param.CC.Value));
1454     if (pChannel->GetMidiRpnController() >= 0) { // RPN controller number was sent previously ...
1455     dmsg(4,("Guess it's an RPN ...\n"));
1456     if (pChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
1457     int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
1458     // limit to +- two octaves for now
1459     transpose = RTMath::Min(transpose, 24);
1460     transpose = RTMath::Max(transpose, -24);
1461     pChannel->GlobalTranspose = transpose;
1462     // workaround, so we won't have hanging notes
1463     pChannel->ReleaseAllVoices(itControlChangeEvent);
1464     }
1465     // to prevent other MIDI CC #6 messages to be misenterpreted as RPN controller data
1466     pChannel->ResetMidiRpnController();
1467     } else if (pChannel->GetMidiNrpnController() >= 0) { // NRPN controller number was sent previously ...
1468     dmsg(4,("Guess it's an NRPN ...\n"));
1469     const int NrpnCtrlMSB = pChannel->GetMidiNrpnController() >> 8;
1470     const int NrpnCtrlLSB = pChannel->GetMidiNrpnController() & 0xff;
1471     dmsg(4,("NRPN MSB=%d LSB=%d Data=%d\n", NrpnCtrlMSB, NrpnCtrlLSB, itControlChangeEvent->Param.CC.Value));
1472     switch (NrpnCtrlMSB) {
1473     case 0x1a: { // volume level of note (Roland GS NRPN)
1474     const uint note = NrpnCtrlLSB;
1475     const uint vol = itControlChangeEvent->Param.CC.Value;
1476     dmsg(4,("Note Volume NRPN received (note=%d,vol=%d).\n", note, vol));
1477     if (note < 128 && vol < 128)
1478     pChannel->pMIDIKeyInfo[note].Volume = VolumeCurve[vol];
1479     break;
1480     }
1481     case 0x1c: { // panpot of note (Roland GS NRPN)
1482     const uint note = NrpnCtrlLSB;
1483     const uint pan = itControlChangeEvent->Param.CC.Value;
1484     dmsg(4,("Note Pan NRPN received (note=%d,pan=%d).\n", note, pan));
1485     if (note < 128 && pan < 128) {
1486     pChannel->pMIDIKeyInfo[note].PanLeft = PanCurve[128 - pan];
1487     pChannel->pMIDIKeyInfo[note].PanRight = PanCurve[pan];
1488     }
1489     break;
1490     }
1491     case 0x1d: { // reverb send of note (Roland GS NRPN)
1492     const uint note = NrpnCtrlLSB;
1493     const float reverb = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
1494 persson 2837 dmsg(4,("Note Reverb Send NRPN received (note=%d,send=%f).\n", note, reverb));
1495 schoenebeck 2121 if (note < 128)
1496     pChannel->pMIDIKeyInfo[note].ReverbSend = reverb;
1497     break;
1498     }
1499     case 0x1e: { // chorus send of note (Roland GS NRPN)
1500     const uint note = NrpnCtrlLSB;
1501     const float chorus = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
1502 persson 2837 dmsg(4,("Note Chorus Send NRPN received (note=%d,send=%f).\n", note, chorus));
1503 schoenebeck 2121 if (note < 128)
1504     pChannel->pMIDIKeyInfo[note].ChorusSend = chorus;
1505     break;
1506     }
1507     }
1508     // to prevent other MIDI CC #6 messages to be misenterpreted as NRPN controller data
1509     pChannel->ResetMidiNrpnController();
1510 iliev 2012 }
1511     break;
1512     }
1513     case 7: { // volume
1514     //TODO: not sample accurate yet
1515     pChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1516     pChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1517     break;
1518     }
1519     case 10: { // panpot
1520     //TODO: not sample accurate yet
1521     pChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;
1522     break;
1523     }
1524     case 64: { // sustain
1525     if (itControlChangeEvent->Param.CC.Value >= 64 && !pChannel->SustainPedal) {
1526     dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1527     pChannel->SustainPedal = true;
1528     pChannel->listeners.PreProcessSustainPedalDown();
1529    
1530     #if !CONFIG_PROCESS_MUTED_CHANNELS
1531     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1532     pChannel->listeners.PostProcessSustainPedalDown();
1533     return;
1534     }
1535     #endif
1536    
1537     pChannel->ProcessSustainPedalDown(itControlChangeEvent);
1538     pChannel->listeners.PostProcessSustainPedalDown();
1539     }
1540     if (itControlChangeEvent->Param.CC.Value < 64 && pChannel->SustainPedal) {
1541     dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1542     pChannel->SustainPedal = false;
1543     pChannel->listeners.PreProcessSustainPedalUp();
1544    
1545     #if !CONFIG_PROCESS_MUTED_CHANNELS
1546     if (pChannel->GetMute()) { // skip if sampler channel is muted
1547     pChannel->listeners.PostProcessSustainPedalUp();
1548     return;
1549     }
1550     #endif
1551    
1552     pChannel->ProcessSustainPedalUp(itControlChangeEvent);
1553     pChannel->listeners.PostProcessSustainPedalUp();
1554     }
1555     break;
1556     }
1557     case 65: { // portamento on / off
1558     const bool bPortamento = itControlChangeEvent->Param.CC.Value >= 64;
1559     if (bPortamento != pChannel->PortamentoMode)
1560     KillAllVoices(pChannel, itControlChangeEvent);
1561     pChannel->PortamentoMode = bPortamento;
1562     break;
1563     }
1564     case 66: { // sostenuto
1565     if (itControlChangeEvent->Param.CC.Value >= 64 && !pChannel->SostenutoPedal) {
1566     dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1567     pChannel->SostenutoPedal = true;
1568     pChannel->listeners.PreProcessSostenutoPedalDown();
1569    
1570     #if !CONFIG_PROCESS_MUTED_CHANNELS
1571     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1572     pChannel->listeners.PostProcessSostenutoPedalDown();
1573     return;
1574     }
1575     #endif
1576    
1577     pChannel->ProcessSostenutoPedalDown();
1578     pChannel->listeners.PostProcessSostenutoPedalDown();
1579     }
1580     if (itControlChangeEvent->Param.CC.Value < 64 && pChannel->SostenutoPedal) {
1581     dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1582     pChannel->SostenutoPedal = false;
1583     pChannel->listeners.PreProcessSostenutoPedalUp();
1584    
1585     #if !CONFIG_PROCESS_MUTED_CHANNELS
1586     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1587     pChannel->listeners.PostProcessSostenutoPedalUp();
1588     return;
1589     }
1590     #endif
1591    
1592     pChannel->ProcessSostenutoPedalUp(itControlChangeEvent);
1593     pChannel->listeners.PostProcessSostenutoPedalUp();
1594     }
1595     break;
1596     }
1597 schoenebeck 2121 case 98: { // NRPN controller LSB
1598     dmsg(4,("NRPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1599     pEngineChannel->SetMidiNrpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1600     break;
1601     }
1602     case 99: { // NRPN controller MSB
1603     dmsg(4,("NRPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1604     pEngineChannel->SetMidiNrpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1605     break;
1606     }
1607 iliev 2012 case 100: { // RPN controller LSB
1608 schoenebeck 2121 dmsg(4,("RPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1609 iliev 2012 pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1610     break;
1611     }
1612     case 101: { // RPN controller MSB
1613 schoenebeck 2121 dmsg(4,("RPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1614 iliev 2012 pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1615     break;
1616     }
1617    
1618    
1619     // Channel Mode Messages
1620    
1621     case 120: { // all sound off
1622     KillAllVoices(pEngineChannel, itControlChangeEvent);
1623     break;
1624     }
1625     case 121: { // reset all controllers
1626     pChannel->ResetControllers();
1627     break;
1628     }
1629     case 123: { // all notes off
1630     #if CONFIG_PROCESS_ALL_NOTES_OFF
1631     pChannel->ReleaseAllVoices(itControlChangeEvent);
1632     #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1633     break;
1634     }
1635     case 126: { // mono mode on
1636     if (!pChannel->SoloMode)
1637     KillAllVoices(pEngineChannel, itControlChangeEvent);
1638     pChannel->SoloMode = true;
1639     break;
1640     }
1641     case 127: { // poly mode on
1642     if (pChannel->SoloMode)
1643     KillAllVoices(pEngineChannel, itControlChangeEvent);
1644     pChannel->SoloMode = false;
1645     break;
1646     }
1647     }
1648     }
1649    
1650     virtual D* CreateDiskThread() = 0;
1651    
1652     /**
1653     * Assigns and triggers a new voice for the respective MIDI key.
1654     *
1655 schoenebeck 2871 * @param pEngineChannel - engine channel on which this event occurred on
1656 iliev 2012 * @param itNoteOnEvent - key, velocity and time stamp of the event
1657     */
1658 schoenebeck 3054 virtual void ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) OVERRIDE {
1659 iliev 2012 EngineChannelBase<V, R, I>* pChannel =
1660     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1661    
1662 schoenebeck 2879 const int key = itNoteOnEvent->Param.Note.Key;
1663     const int vel = itNoteOnEvent->Param.Note.Velocity;
1664     if (key < 0 || key > 127) return; // ignore event, key outside allowed key range
1665 iliev 2012
1666     MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];
1667    
1668 schoenebeck 2938 // There are real MIDI note-on events (Event::type_note_on) and
1669     // programmatically spawned notes (Event::type_play_note). We have
1670     // to distinguish between them, since certain processing below
1671     // must only be done on real MIDI note-on events (i.e. for
1672     // correctly updating which MIDI keys are currently pressed down).
1673     const bool isRealMIDINoteOnEvent = itNoteOnEvent->Type == Event::type_note_on;
1674    
1675     if (isRealMIDINoteOnEvent)
1676     pChannel->listeners.PreProcessNoteOn(key, vel);
1677    
1678 iliev 2012 #if !CONFIG_PROCESS_MUTED_CHANNELS
1679     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1680 schoenebeck 2938 if (isRealMIDINoteOnEvent)
1681     pChannel->listeners.PostProcessNoteOn(key, vel);
1682 iliev 2012 return;
1683     }
1684     #endif
1685    
1686     if (!pChannel->pInstrument) {
1687 schoenebeck 2938 if (isRealMIDINoteOnEvent)
1688     pChannel->listeners.PostProcessNoteOn(key, vel);
1689 iliev 2012 return; // ignore if no instrument loaded
1690     }
1691    
1692     // move note on event to the key's own event list
1693     RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
1694    
1695     // if Solo Mode then kill all already active voices
1696 schoenebeck 2938 if (pChannel->SoloMode && isRealMIDINoteOnEvent) {
1697 iliev 2012 Pool<uint>::Iterator itYoungestKey = pChannel->pActiveKeys->last();
1698     if (itYoungestKey) {
1699     const int iYoungestKey = *itYoungestKey;
1700     const MidiKey* pOtherKey = &pChannel->pMIDIKeyInfo[iYoungestKey];
1701     if (pOtherKey->Active) {
1702     // get final portamento position of currently active voice
1703     if (pChannel->PortamentoMode) {
1704 schoenebeck 2879 NoteIterator itNote = pOtherKey->pActiveNotes->last();
1705     if (itNote) {
1706     VoiceIterator itVoice = itNote->pActiveVoices->last();
1707     if (itVoice) itVoice->UpdatePortamentoPos(itNoteOnEventOnKeyList);
1708     }
1709 iliev 2012 }
1710     // kill all voices on the (other) key
1711 schoenebeck 2879 for (NoteIterator itNote = pOtherKey->pActiveNotes->first(); itNote; ++itNote) {
1712     VoiceIterator itVoiceToBeKilled = itNote->pActiveVoices->first();
1713     VoiceIterator end = itNote->pActiveVoices->end();
1714     for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1715     if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1716     itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
1717     }
1718 iliev 2012 }
1719     }
1720     }
1721     // set this key as 'currently active solo key'
1722     pChannel->SoloKey = key;
1723     }
1724    
1725 schoenebeck 2938 if (isRealMIDINoteOnEvent) {
1726     pChannel->ProcessKeySwitchChange(key);
1727 iliev 2012
1728 schoenebeck 2938 pKey->KeyPressed = true; // the MIDI key was now pressed down
1729     pChannel->KeyDown[key] = true; // just used as built-in %KEY_DOWN script variable
1730     pKey->Velocity = itNoteOnEventOnKeyList->Param.Note.Velocity;
1731     pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
1732     }
1733 iliev 2012
1734     // cancel release process of voices on this key if needed
1735 schoenebeck 2938 if (pKey->Active && !pChannel->SustainPedal && isRealMIDINoteOnEvent) {
1736 iliev 2012 RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
1737     if (itCancelReleaseEvent) {
1738     *itCancelReleaseEvent = *itNoteOnEventOnKeyList; // copy event
1739 schoenebeck 2938 itCancelReleaseEvent->Type = Event::type_cancel_release_key; // transform event type
1740 iliev 2012 }
1741     else dmsg(1,("Event pool emtpy!\n"));
1742     }
1743    
1744     TriggerNewVoices(pEngineChannel, itNoteOnEventOnKeyList);
1745    
1746     // if neither a voice was spawned or postponed then remove note on event from key again
1747     if (!pKey->Active && !pKey->VoiceTheftsQueued)
1748     pKey->pEvents->free(itNoteOnEventOnKeyList);
1749    
1750 schoenebeck 2938 if (isRealMIDINoteOnEvent && (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f))
1751     pChannel->PortamentoPos = (float) key;
1752    
1753     //NOTE: Hmm, I guess its a matter of taste whether round robin should be advanced only on real MIDI note-on events, isn't it?
1754 persson 2043 if (pKey->pRoundRobinIndex) {
1755     (*pKey->pRoundRobinIndex)++; // counter specific for the key or region
1756     pChannel->RoundRobinIndex++; // common counter for the channel
1757     }
1758 schoenebeck 2938
1759     if (isRealMIDINoteOnEvent)
1760     pChannel->listeners.PostProcessNoteOn(key, vel);
1761 iliev 2012 }
1762    
1763     /**
1764     * Allocate and trigger new voice(s) for the key.
1765     */
1766     virtual void TriggerNewVoices (
1767     EngineChannel* pEngineChannel,
1768     RTList<Event>::Iterator& itNoteOnEvent,
1769     bool HandleKeyGroupConflicts = true
1770     ) = 0;
1771    
1772     /**
1773     * Allocate and trigger release voice(s) for the key.
1774     */
1775     virtual void TriggerReleaseVoices (
1776     EngineChannel* pEngineChannel,
1777     RTList<Event>::Iterator& itNoteOffEvent
1778     ) = 0;
1779    
1780     /**
1781     * Releases the voices on the given key if sustain pedal is not pressed.
1782     * If sustain is pressed, the release of the note will be postponed until
1783     * sustain pedal will be released or voice turned inactive by itself (e.g.
1784     * due to completion of sample playback).
1785     *
1786 schoenebeck 2871 * @param pEngineChannel - engine channel on which this event occurred on
1787 iliev 2012 * @param itNoteOffEvent - key, velocity and time stamp of the event
1788     */
1789 schoenebeck 3054 virtual void ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) OVERRIDE {
1790 iliev 2012 EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1791    
1792 schoenebeck 2879 const int iKey = itNoteOffEvent->Param.Note.Key;
1793     const int vel = itNoteOffEvent->Param.Note.Velocity;
1794     if (iKey < 0 || iKey > 127) return; // ignore event, key outside allowed key range
1795 iliev 2012
1796     MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];
1797    
1798 schoenebeck 2938 // There are real MIDI note-off events (Event::type_note_off) and
1799     // programmatically spawned notes (Event::type_stop_note). We have
1800     // to distinguish between them, since certain processing below
1801     // must only be done on real MIDI note-off events (i.e. for
1802     // correctly updating which MIDI keys are currently pressed down),
1803     // plus a stop-note event just releases voices of one particular
1804     // note, whereas a note-off event releases all voices on a
1805     // particular MIDI key instead.
1806     const bool isRealMIDINoteOffEvent = itNoteOffEvent->Type == Event::type_note_off;
1807 iliev 2012
1808 schoenebeck 2938 if (isRealMIDINoteOffEvent)
1809     pChannel->listeners.PreProcessNoteOff(iKey, vel);
1810    
1811 iliev 2012 #if !CONFIG_PROCESS_MUTED_CHANNELS
1812     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1813 schoenebeck 2938 if (isRealMIDINoteOffEvent)
1814     pChannel->listeners.PostProcessNoteOff(iKey, vel);
1815 iliev 2012 return;
1816     }
1817     #endif
1818    
1819 schoenebeck 2938 if (isRealMIDINoteOffEvent) {
1820     pKey->KeyPressed = false; // the MIDI key was now released
1821     pChannel->KeyDown[iKey] = false; // just used as built-in %KEY_DOWN script variable
1822     }
1823 iliev 2012
1824     // move event to the key's own event list
1825     RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
1826    
1827 schoenebeck 2938 if (isRealMIDINoteOffEvent) {
1828     bool bShouldRelease = pKey->Active && pChannel->ShouldReleaseVoice(itNoteOffEventOnKeyList->Param.Note.Key);
1829 iliev 2012
1830 schoenebeck 2938 // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
1831     if (pChannel->SoloMode && pChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
1832     bool bOtherKeysPressed = false;
1833     if (iKey == pChannel->SoloKey) {
1834     pChannel->SoloKey = -1;
1835     // if there's still a key pressed down, respawn a voice (group) on the highest key
1836     for (int i = 127; i > 0; i--) {
1837     MidiKey* pOtherKey = &pChannel->pMIDIKeyInfo[i];
1838     if (pOtherKey->KeyPressed) {
1839     bOtherKeysPressed = true;
1840     // make the other key the new 'currently active solo key'
1841     pChannel->SoloKey = i;
1842     // get final portamento position of currently active voice
1843     if (pChannel->PortamentoMode) {
1844     NoteIterator itNote = pKey->pActiveNotes->first();
1845     VoiceIterator itVoice = itNote->pActiveVoices->first();
1846     if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);
1847 schoenebeck 2879 }
1848 schoenebeck 2938 // create a pseudo note on event
1849     RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
1850     if (itPseudoNoteOnEvent) {
1851     // copy event
1852     *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
1853     // transform event to a note on event
1854     itPseudoNoteOnEvent->Type = Event::type_note_on; //FIXME: should probably use Event::type_play_note instead (to avoid i.e. hanging notes)
1855     itPseudoNoteOnEvent->Param.Note.Key = i;
1856     itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
1857     // assign a new note to this note-on event
1858 schoenebeck 3205 if (LaunchNewNote(pChannel, itPseudoNoteOnEvent)) {
1859 schoenebeck 2938 // allocate and trigger new voice(s) for the other key
1860     TriggerNewVoices(pChannel, itPseudoNoteOnEvent, false);
1861     }
1862     // if neither a voice was spawned or postponed then remove note on event from key again
1863     if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
1864     pOtherKey->pEvents->free(itPseudoNoteOnEvent);
1865 iliev 2012
1866 schoenebeck 2938 } else dmsg(1,("Could not respawn voice, no free event left\n"));
1867     break; // done
1868     }
1869 iliev 2012 }
1870     }
1871 schoenebeck 2938 if (bOtherKeysPressed) {
1872     if (pKey->Active) { // kill all voices on this key
1873     bShouldRelease = false; // no need to release, as we kill it here
1874     for (NoteIterator itNote = pKey->pActiveNotes->first(); itNote; ++itNote) {
1875     VoiceIterator itVoiceToBeKilled = itNote->pActiveVoices->first();
1876     VoiceIterator end = itNote->pActiveVoices->end();
1877     for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1878     if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1879     itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1880     }
1881 schoenebeck 2879 }
1882 iliev 2012 }
1883 schoenebeck 2938 } else pChannel->PortamentoPos = -1.0f;
1884     }
1885 iliev 2012
1886 schoenebeck 2938 // if no solo mode (the usual case) or if solo mode and no other key pressed, then release voices on this key if needed
1887     if (bShouldRelease) {
1888     itNoteOffEventOnKeyList->Type = Event::type_release_key; // transform event type
1889     // spawn release triggered voice(s) if needed
1890     ProcessReleaseTrigger(pChannel, itNoteOffEventOnKeyList, pKey);
1891     }
1892     } else if (itNoteOffEventOnKeyList->Type == Event::type_stop_note) {
1893     // This programmatically caused event is caused by a call to
1894     // the built-in instrument script function note_off(). In
1895     // contrast to a real MIDI note-off event the stop-note
1896     // event just intends to release voices of one particular note.
1897     NoteBase* pNote = pChannel->pEngine->NoteByID( itNoteOffEventOnKeyList->Param.Note.ID );
1898     if (pNote) { // the requested note is still alive ...
1899     itNoteOffEventOnKeyList->Type = Event::type_release_note; // transform event type
1900     } else { // note is dead and gone ..
1901     pKey->pEvents->free(itNoteOffEventOnKeyList); // remove stop-note event from key again
1902     return; // prevent event to be removed a 2nd time below
1903     }
1904 iliev 2012 }
1905    
1906     // if neither a voice was spawned or postponed on this key then remove note off event from key again
1907     if (!pKey->Active && !pKey->VoiceTheftsQueued)
1908     pKey->pEvents->free(itNoteOffEventOnKeyList);
1909    
1910 schoenebeck 2938 if (isRealMIDINoteOffEvent)
1911     pChannel->listeners.PostProcessNoteOff(iKey, vel);
1912 iliev 2012 }
1913    
1914     /**
1915 schoenebeck 2927 * Called on sustain pedal up events to check and if required,
1916     * launch release trigger voices on the respective active key.
1917     *
1918     * @param pEngineChannel - engine channel on which this event occurred on
1919     * @param itEvent - release trigger event (contains note number)
1920     */
1921     virtual void ProcessReleaseTrigger(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) OVERRIDE {
1922     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1923    
1924     const int iKey = itEvent->Param.Note.Key;
1925     if (iKey < 0 || iKey > 127) return; // ignore event, key outside allowed key range
1926    
1927     MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];
1928    
1929     ProcessReleaseTrigger(pChannel, itEvent, pKey);
1930     }
1931    
1932     /**
1933     * Called on note-off and sustain pedal up events to check and if
1934     * required, launch release trigger voices on the respective active
1935     * key.
1936     *
1937     * @param pEngineChannel - engine channel on which this event occurred on
1938     * @param itEvent - note off event / release trigger event
1939     * @param pKey - key on which the release trigger voices shall be spawned
1940     */
1941     inline void ProcessReleaseTrigger(EngineChannelBase<V, R, I>* pChannel, RTList<Event>::Iterator& itEvent, MidiKey* pKey) {
1942     // spawn release triggered voice(s) if needed
1943     if (pKey->ReleaseTrigger && pChannel->pInstrument) {
1944     // assign a new note to this release event
1945 schoenebeck 3205 if (LaunchNewNote(pChannel, itEvent)) {
1946 schoenebeck 2927 // allocate and trigger new release voice(s)
1947     TriggerReleaseVoices(pChannel, itEvent);
1948     }
1949     pKey->ReleaseTrigger = false;
1950     }
1951     }
1952    
1953     /**
1954 schoenebeck 3188 * Called on "kill note" events, which currently only happens on
1955     * built-in real-time instrument script function fade_out(). This
1956     * method only fulfills one task: moving the even to the Note's own
1957     * event list so that its voices can process the kill event sample
1958     * accurately.
1959     */
1960     void ProcessKillNote(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) {
1961     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1962    
1963     NoteBase* pNote = pChannel->pEngine->NoteByID( itEvent->Param.Note.ID );
1964     if (!pNote || pNote->hostKey < 0 || pNote->hostKey >= 128) return;
1965    
1966     // move note kill event to its MIDI key
1967     MidiKey* pKey = &pChannel->pMIDIKeyInfo[pNote->hostKey];
1968     itEvent.moveToEndOf(pKey->pEvents);
1969     }
1970    
1971     /**
1972 schoenebeck 2931 * Called on note synthesis parameter change events. These are
1973     * internal events caused by calling built-in real-time instrument
1974 schoenebeck 3188 * script functions like change_vol(), change_tune(), etc.
1975 schoenebeck 2931 *
1976     * This method performs two tasks:
1977     *
1978     * - It converts the event's relative values changes (Deltas) to
1979     * the respective final new synthesis parameter value (AbsValue),
1980     * for that particular moment of the event that is.
1981     *
1982     * - It moves the individual events to the Note's own event list
1983     * (or actually to the event list of the MIDI key), so that
1984     * voices can process those events sample accurately.
1985     *
1986     * @param pEngineChannel - engine channel on which this event occurred on
1987     * @param itEvent - note synthesis parameter change event
1988     */
1989 persson 2952 virtual void ProcessNoteSynthParam(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) {
1990 schoenebeck 2931 EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1991    
1992     NoteBase* pNote = pChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID );
1993     if (!pNote || pNote->hostKey < 0 || pNote->hostKey >= 128) return;
1994    
1995     const bool& relative = itEvent->Param.NoteSynthParam.Relative;
1996    
1997     switch (itEvent->Param.NoteSynthParam.Type) {
1998     case Event::synth_param_volume:
1999     if (relative)
2000     pNote->Override.Volume *= itEvent->Param.NoteSynthParam.Delta;
2001     else
2002     pNote->Override.Volume = itEvent->Param.NoteSynthParam.Delta;
2003     itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Volume;
2004     break;
2005 schoenebeck 3188 case Event::synth_param_volume_time:
2006     pNote->Override.VolumeTime = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2007     break;
2008 schoenebeck 3246 case Event::synth_param_volume_curve:
2009     itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2010     pNote->Override.VolumeCurve = (fade_curve_t) itEvent->Param.NoteSynthParam.AbsValue;
2011     break;
2012 schoenebeck 2931 case Event::synth_param_pitch:
2013     if (relative)
2014     pNote->Override.Pitch *= itEvent->Param.NoteSynthParam.Delta;
2015     else
2016     pNote->Override.Pitch = itEvent->Param.NoteSynthParam.Delta;
2017     itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Pitch;
2018     break;
2019 schoenebeck 3188 case Event::synth_param_pitch_time:
2020     pNote->Override.PitchTime = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2021     break;
2022 schoenebeck 3246 case Event::synth_param_pitch_curve:
2023     itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2024     pNote->Override.PitchCurve = (fade_curve_t) itEvent->Param.NoteSynthParam.AbsValue;
2025     break;
2026 schoenebeck 2931 case Event::synth_param_pan:
2027     if (relative) {
2028     pNote->Override.Pan = RTMath::RelativeSummedAvg(pNote->Override.Pan, itEvent->Param.NoteSynthParam.Delta, ++pNote->Override.PanSources);
2029     } else {
2030     pNote->Override.Pan = itEvent->Param.NoteSynthParam.Delta;
2031     pNote->Override.PanSources = 1; // only relevant on subsequent change_pan() instrument script calls on same note with 'relative' argument being set
2032     }
2033     itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Pan;
2034     break;
2035 schoenebeck 2935 case Event::synth_param_cutoff:
2036     pNote->Override.Cutoff = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2037     break;
2038     case Event::synth_param_resonance:
2039     pNote->Override.Resonance = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2040     break;
2041 schoenebeck 2953 case Event::synth_param_attack:
2042     pNote->Override.Attack = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2043     break;
2044     case Event::synth_param_decay:
2045     pNote->Override.Decay = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2046     break;
2047     case Event::synth_param_release:
2048     pNote->Override.Release = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2049     break;
2050 schoenebeck 3118 case Event::synth_param_amp_lfo_depth:
2051     pNote->Override.AmpLFODepth = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2052     break;
2053     case Event::synth_param_amp_lfo_freq:
2054     pNote->Override.AmpLFOFreq = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2055     break;
2056     case Event::synth_param_pitch_lfo_depth:
2057     pNote->Override.PitchLFODepth = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2058     break;
2059     case Event::synth_param_pitch_lfo_freq:
2060     pNote->Override.PitchLFOFreq = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
2061     break;
2062 schoenebeck 2931 }
2063    
2064     // move note parameter event to its MIDI key
2065     MidiKey* pKey = &pChannel->pMIDIKeyInfo[pNote->hostKey];
2066     itEvent.moveToEndOf(pKey->pEvents);
2067     }
2068    
2069     /**
2070 iliev 2012 * Reset all voices and disk thread and clear input event queue and all
2071     * control and status variables. This method is protected by a mutex.
2072     */
2073 schoenebeck 3054 virtual void ResetInternal() OVERRIDE {
2074 persson 2427 LockGuard lock(ResetInternalMutex);
2075 iliev 2012
2076     // make sure that the engine does not get any sysex messages
2077     // while it's reseting
2078     bool sysexDisabled = MidiInputPort::RemoveSysexListener(this);
2079     SetVoiceCount(0);
2080     ActiveVoiceCountMax = 0;
2081    
2082     // reset voice stealing parameters
2083     pVoiceStealingQueue->clear();
2084     itLastStolenVoice = VoiceIterator();
2085     itLastStolenVoiceGlobally = VoiceIterator();
2086 schoenebeck 2879 itLastStolenNote = NoteIterator();
2087     itLastStolenNoteGlobally = NoteIterator();
2088 iliev 2012 iuiLastStolenKey = RTList<uint>::Iterator();
2089     iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
2090     pLastStolenChannel = NULL;
2091    
2092 schoenebeck 2879 // reset all notes
2093     pNotePool->clear();
2094     for (NoteIterator itNote = pNotePool->allocAppend(); itNote;
2095     itNote = pNotePool->allocAppend())
2096     {
2097     itNote->reset();
2098     }
2099     pNotePool->clear();
2100    
2101 iliev 2012 // reset all voices
2102 schoenebeck 2879 pVoicePool->clear();
2103 iliev 2012 for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
2104     iterVoice->Reset();
2105     }
2106     pVoicePool->clear();
2107    
2108 schoenebeck 2871 // reset all engine channels
2109     for (int i = 0; i < engineChannels.size(); i++) {
2110     AbstractEngineChannel* pEngineChannel =
2111     static_cast<AbstractEngineChannel*>(engineChannels[i]);
2112     pEngineChannel->ResetInternal(false/*don't reset engine*/);
2113     }
2114    
2115 iliev 2012 // reset disk thread
2116     if (pDiskThread) pDiskThread->Reset();
2117    
2118     // delete all input events
2119     pEventQueue->init();
2120     pSysexBuffer->init();
2121     if (sysexDisabled) MidiInputPort::AddSysexListener(this);
2122     }
2123    
2124     /**
2125     * Kills all voices on an engine channel as soon as possible. Voices
2126     * won't get into release state, their volume level will be ramped down
2127     * as fast as possible.
2128     *
2129     * @param pEngineChannel - engine channel on which all voices should be killed
2130     * @param itKillEvent - event which caused this killing of all voices
2131     */
2132 schoenebeck 3054 virtual void KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) OVERRIDE {
2133 iliev 2012 EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
2134     int count = pChannel->KillAllVoices(itKillEvent);
2135     VoiceSpawnsLeft -= count; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
2136     }
2137    
2138     /**
2139     * Allocates and triggers a new voice. This method will usually be
2140     * called by the ProcessNoteOn() method and by the voices itself
2141     * (e.g. to spawn further voices on the same key for layered sounds).
2142     *
2143 schoenebeck 2871 * @param pEngineChannel - engine channel on which this event occurred on
2144 iliev 2012 * @param itNoteOnEvent - key, velocity and time stamp of the event
2145     * @param iLayer - layer index for the new voice (optional - only
2146     * in case of layered sounds of course)
2147     * @param ReleaseTriggerVoice - if new voice is a release triggered voice
2148     * (optional, default = false)
2149     * @param VoiceStealing - if voice stealing should be performed
2150     * when there is no free voice
2151     * (optional, default = true)
2152     * @param HandleKeyGroupConflicts - if voices should be killed due to a
2153     * key group conflict
2154     * @returns pointer to new voice or NULL if there was no free voice or
2155     * if the voice wasn't triggered (for example when no region is
2156     * defined for the given key).
2157     */
2158     virtual PoolVoiceIterator LaunchVoice (
2159     EngineChannel* pEngineChannel,
2160     Pool<Event>::Iterator& itNoteOnEvent,
2161     int iLayer,
2162     bool ReleaseTriggerVoice,
2163     bool VoiceStealing,
2164     bool HandleKeyGroupConflicts
2165     ) = 0;
2166    
2167 schoenebeck 3054 virtual int GetMinFadeOutSamples() OVERRIDE { return MinFadeOutSamples; }
2168 iliev 2015
2169 iliev 2027 int InitNewVoice (
2170     EngineChannelBase<V, R, I>* pChannel,
2171     R* pRegion,
2172     Pool<Event>::Iterator& itNoteOnEvent,
2173     Voice::type_t VoiceType,
2174     int iLayer,
2175     int iKeyGroup,
2176     bool ReleaseTriggerVoice,
2177     bool VoiceStealing,
2178     typename Pool<V>::Iterator& itNewVoice
2179     ) {
2180     int key = itNoteOnEvent->Param.Note.Key;
2181     typename MidiKeyboardManager<V>::MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];
2182     if (itNewVoice) {
2183     // launch the new voice
2184     if (itNewVoice->Trigger(pChannel, itNoteOnEvent, pChannel->Pitch, pRegion, VoiceType, iKeyGroup) < 0) {
2185     dmsg(4,("Voice not triggered\n"));
2186 schoenebeck 2879 GetVoicePool()->free(itNewVoice);
2187 iliev 2027 }
2188     else { // on success
2189     --VoiceSpawnsLeft;
2190     if (!pKey->Active) { // mark as active key
2191     pKey->Active = true;
2192     pKey->itSelf = pChannel->pActiveKeys->allocAppend();
2193     *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
2194     }
2195 persson 2115 if (itNewVoice->Type & Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
2196 iliev 2027 return 0; // success
2197     }
2198     }
2199     else if (VoiceStealing) {
2200     // try to steal one voice
2201     int result = StealVoice(pChannel, itNoteOnEvent);
2202     if (!result) { // voice stolen successfully
2203     // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
2204     RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
2205     if (itStealEvent) {
2206     *itStealEvent = *itNoteOnEvent; // copy event
2207     itStealEvent->Param.Note.Layer = iLayer;
2208     itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
2209     pKey->VoiceTheftsQueued++;
2210     }
2211     else dmsg(1,("Voice stealing queue full!\n"));
2212     }
2213     }
2214    
2215     return -1;
2216     }
2217 schoenebeck 2448
2218     /**
2219     * Checks whether scale tuning setting has been changed since last
2220     * time this method was called, if yes, it recalculates the pitch
2221     * for all active voices.
2222     */
2223     void ProcessScaleTuningChange() {
2224     const bool changed = ScaleTuningChanged.readAndReset();
2225     if (!changed) return;
2226    
2227     for (int i = 0; i < engineChannels.size(); i++) {
2228     EngineChannelBase<V, R, I>* channel =
2229     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
2230     channel->OnScaleTuningChanged();
2231     }
2232     }
2233 iliev 2027
2234 iliev 2012 private:
2235 schoenebeck 2879 Pool< Note<V> >* pNotePool;
2236     Pool<note_id_t> noteIDPool;
2237 iliev 2012 Pool<V>* pVoicePool; ///< Contains all voices that can be activated.
2238     Pool<RR*> SuspendedRegions;
2239     Mutex SuspendedRegionsMutex;
2240     Condition SuspensionChangeOngoing;
2241     RR* pPendingRegionSuspension;
2242     RR* pPendingRegionResumption;
2243     int iPendingStreamDeletions;
2244     };
2245    
2246     template <class V, class RR, class R, class D, class IM, class I>
2247     IM EngineBase<V, RR, R, D, IM, I>::instruments;
2248    
2249     } // namespace LinuxSampler
2250    
2251     #endif /* __LS_ENGINEBASE_H__ */
2252    

  ViewVC Help
Powered by ViewVC