/[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 2948 - (hide annotations) (download) (as text)
Fri Jul 15 15:29:04 2016 UTC (7 years, 8 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 118974 byte(s)
* NKSP: Implemented built-in script function "stop_wait()".
* NKSP: Implemented built-in script variable "$NI_CALLBACK_ID".
* NKSP: Implemented built-in script variable "$NI_CALLBACK_TYPE".
* NKSP: Implemented built-in script variable "$NKSP_IGNORE_WAIT".
* NKSP: Added support for read-only built-in variables
  (respectively handled by the script parser).
* NKSP: Added built-in script constant "$NI_CB_TYPE_INIT".
* NKSP: Added built-in script constant "$NI_CB_TYPE_NOTE".
* NKSP: Added built-in script constant "$NI_CB_TYPE_RELEASE".
* NKSP: Added built-in script constant "$NI_CB_TYPE_CONTROLLER".
* Bumped version (2.0.0.svn17).

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

  ViewVC Help
Powered by ViewVC