/[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 2972 - (hide annotations) (download) (as text)
Fri Jul 22 14:37:34 2016 UTC (7 years, 8 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 120139 byte(s)
* NKSP Fix: "init" event handler was not always executed when a script
  was loaded.
* NKSP built-in wait() script function: abort script execution if
  a negative or zero wait time was passed as argument (since this is
  a common indication of a bug either of the script or even of the
  engine, which could lead to RT instability or even worse).
* Bumped version (2.0.0.svn24).

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 schoenebeck 2962 // remember the engine's time when this note was triggered exactly
693     itNewNote->triggerSchedTime = pNoteOnEvent->SchedTime();
694    
695 schoenebeck 2879 // usually the new note (and its subsequent voices) will be
696     // allocated on the key provided by the event's note number,
697     // however if this new note is requested not to be a regular
698     // note, but rather a child note, then this new note will be
699     // allocated on the parent note's key instead in order to
700     // release the child note simultaniously with its parent note
701     itNewNote->hostKey = pNoteOnEvent->Param.Note.Key;
702    
703     // in case this new note was requested to be a child note,
704     // then retrieve its parent note and link them with each other
705     const note_id_t parentNoteID = pNoteOnEvent->Param.Note.ParentNoteID;
706     if (parentNoteID) {
707     NoteIterator itParentNote = pNotePool->fromID(parentNoteID);
708     if (itParentNote) {
709     RTList<note_id_t>::Iterator itChildNoteID = itParentNote->pChildNotes->allocAppend();
710     if (itChildNoteID) {
711     // link parent and child note with each other
712     *itChildNoteID = newNoteID;
713     itNewNote->parentNoteID = parentNoteID;
714     itNewNote->hostKey = itParentNote->hostKey;
715     } else {
716     dmsg(1,("Engine: Could not assign new note as child note; Note ID pool empty!\n"));
717     pNotePool->free(itNewNote);
718     return 0; // error
719     }
720     } else {
721     // the parent note was apparently released already, so
722     // free the new note again and inform caller that it
723     // should drop the event
724     dmsg(3,("Engine: Could not assign new note as child note; Parent note is gone!\n"));
725     pNotePool->free(itNewNote);
726     return 0; // error
727     }
728     }
729    
730     dmsg(2,("Launched new note on host key %d\n", itNewNote->hostKey));
731    
732     // copy event which caused this note
733     itNewNote->cause = *pNoteOnEvent;
734     itNewNote->eventID = pEventPool->getID(pNoteOnEvent);
735    
736     // move new note to its host key
737     MidiKey* pKey = &pChannel->pMIDIKeyInfo[itNewNote->hostKey];
738     itNewNote.moveToEndOf(pKey->pActiveNotes);
739    
740     // assign unique note ID of this new note to the original note on event
741     pNoteOnEvent->Param.Note.ID = newNoteID;
742    
743     return newNoteID; // success
744     }
745    
746     /**
747 iliev 2012 * Dispatch and handle all events in this audio fragment for the given
748     * engine channel.
749     *
750     * @param pEngineChannel - engine channel on which events should be
751     * processed
752     * @param Samples - amount of sample points to be processed in
753     * this audio fragment cycle
754     */
755     void ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
756     // get all events from the engine channels's input event queue which belong to the current fragment
757     // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
758     AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
759     pChannel->ImportEvents(Samples);
760    
761 schoenebeck 2594 // if a valid real-time instrument script is loaded, pre-process
762     // the event list by running the script now, since the script
763     // might filter events or add new ones for this cycle
764 schoenebeck 2659 if (pChannel->pScript) {
765 schoenebeck 2871 const sched_time_t fragmentEndTime = pEventGenerator->schedTimeAtCurrentFragmentEnd();
766 schoenebeck 2594
767 schoenebeck 2871 // resume suspended script executions been scheduled for
768     // this audio fragment cycle (which were suspended in a
769     // previous audio fragment cycle)
770     ProcessSuspendedScriptEvents(pChannel, fragmentEndTime);
771    
772 schoenebeck 2594 // spawn new script executions for the new MIDI events of
773     // this audio fragment cycle
774 schoenebeck 2871 //
775     // 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
776 schoenebeck 2594 for (RTList<Event>::Iterator itEvent = pChannel->pEvents->first(),
777 schoenebeck 2884 end = pChannel->pEvents->end(); itEvent != end; )
778 schoenebeck 2594 {
779 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).
780     RTList<Event>::Iterator itNext = itEvent;
781     ++itNext;
782    
783 schoenebeck 2594 switch (itEvent->Type) {
784     case Event::type_note_on:
785 schoenebeck 2611 if (pChannel->pScript->handlerNote)
786     ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerNote);
787 schoenebeck 2594 break;
788     case Event::type_note_off:
789 schoenebeck 2611 if (pChannel->pScript->handlerRelease)
790     ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerRelease);
791 schoenebeck 2594 break;
792     case Event::type_control_change:
793     case Event::type_channel_pressure:
794     case Event::type_pitchbend:
795 schoenebeck 2611 if (pChannel->pScript->handlerController)
796     ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerController);
797 schoenebeck 2594 break;
798     case Event::type_note_pressure:
799     //TODO: ...
800     break;
801     }
802 schoenebeck 2884
803     // see HACK comment above
804     itEvent = itNext;
805 schoenebeck 2594 }
806 schoenebeck 2871
807     // this has to be run again, since the newly spawned scripts
808     // above may have cause suspended scripts that must be
809     // resumed within this same audio fragment cycle
810     //
811     // FIXME: see FIXME comment above
812     ProcessSuspendedScriptEvents(pChannel, fragmentEndTime);
813 schoenebeck 2594 }
814    
815 schoenebeck 2871 // if there are any delayed events scheduled for the current
816     // audio fragment cycle, then move and sort them into the main
817     // event list
818     if (!pChannel->delayedEvents.queue.isEmpty()) {
819     dmsg(5,("Engine: There are delayed MIDI events (total queue size: %d) ...\n", pChannel->delayedEvents.queue.size()));
820     const sched_time_t fragmentEndTime = pEventGenerator->schedTimeAtCurrentFragmentEnd();
821     RTList<Event>::Iterator itEvent = pChannel->pEvents->first();
822     while (true) {
823     RTList<ScheduledEvent>::Iterator itDelayedEventNode =
824     pEventGenerator->popNextScheduledEvent(
825     pChannel->delayedEvents.queue,
826     pChannel->delayedEvents.schedulerNodes,
827     fragmentEndTime
828     );
829     if (!itDelayedEventNode) break;
830     // get the actual delayed event object and free the used scheduler node
831     RTList<Event>::Iterator itDelayedEvent = itDelayedEventNode->itEvent;
832     pChannel->delayedEvents.schedulerNodes.free(itDelayedEventNode);
833     if (!itDelayedEvent) { // should never happen, but just to be sure ...
834     dmsg(1,("Engine: Oops, invalid delayed event!\n"));
835     continue;
836     }
837     // skip all events on main event list which have a time
838     // before (or equal to) the delayed event to be inserted
839     for (; itEvent && itEvent->FragmentPos() <= itDelayedEvent->FragmentPos();
840     ++itEvent);
841     // now move delayed event from delayedEvents.pList to
842     // the current position on the main event list
843     itEvent = itDelayedEvent.moveBefore(itEvent);
844     dmsg(5,("Engine: Inserted event of type %d into main event list (queue size: %d).\n", itEvent->Type, pChannel->delayedEvents.queue.size()));
845     }
846     dmsg(5,("Engine: End of delayed events (total queue size: %d).\n", pChannel->delayedEvents.queue.size()));
847     }
848    
849 schoenebeck 2594 // now process all events regularly
850 iliev 2012 {
851     RTList<Event>::Iterator itEvent = pChannel->pEvents->first();
852     RTList<Event>::Iterator end = pChannel->pEvents->end();
853     for (; itEvent != end; ++itEvent) {
854     switch (itEvent->Type) {
855     case Event::type_note_on:
856     dmsg(5,("Engine: Note on received\n"));
857     ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
858     break;
859 schoenebeck 2938 case Event::type_play_note:
860     dmsg(5,("Engine: Play Note received\n"));
861     ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
862     break;
863 iliev 2012 case Event::type_note_off:
864     dmsg(5,("Engine: Note off received\n"));
865     ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
866     break;
867 schoenebeck 2938 case Event::type_stop_note:
868     dmsg(5,("Engine: Stop Note received\n"));
869     ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
870     break;
871 iliev 2012 case Event::type_control_change:
872     dmsg(5,("Engine: MIDI CC received\n"));
873     ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
874     break;
875 schoenebeck 2559 case Event::type_channel_pressure:
876     dmsg(5,("Engine: MIDI Chan. Pressure received\n"));
877     ProcessChannelPressure((EngineChannel*)itEvent->pEngineChannel, itEvent);
878     break;
879     case Event::type_note_pressure:
880     dmsg(5,("Engine: MIDI Note Pressure received\n"));
881     ProcessPolyphonicKeyPressure((EngineChannel*)itEvent->pEngineChannel, itEvent);
882     break;
883 iliev 2012 case Event::type_pitchbend:
884     dmsg(5,("Engine: Pitchbend received\n"));
885     ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);
886     break;
887 schoenebeck 2931 case Event::type_note_synth_param:
888     dmsg(5,("Engine: Note Synth Param received\n"));
889     ProcessNoteSynthParam(itEvent->pEngineChannel, itEvent);
890     break;
891 iliev 2012 }
892     }
893     }
894    
895     // reset voice stealing for the next engine channel (or next audio fragment)
896     itLastStolenVoice = VoiceIterator();
897     itLastStolenVoiceGlobally = VoiceIterator();
898 schoenebeck 2879 itLastStolenNote = NoteIterator();
899     itLastStolenNoteGlobally = NoteIterator();
900 iliev 2012 iuiLastStolenKey = RTList<uint>::Iterator();
901     iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
902     pLastStolenChannel = NULL;
903     }
904    
905 schoenebeck 2871 /**
906     * Run all suspended script execution instances which are scheduled
907     * to be resumed for the current audio fragment cycle.
908     *
909     * @param pChannel - engine channel on which suspended events occurred
910     */
911     void ProcessSuspendedScriptEvents(AbstractEngineChannel* pChannel, const sched_time_t fragmentEndTime) {
912     while (true) {
913     RTList<ScriptEvent>::Iterator itEvent =
914     pEventGenerator->popNextScheduledScriptEvent(
915     pChannel->pScript->suspendedEvents,
916     *pChannel->pScript->pEvents, fragmentEndTime
917     );
918     if (!itEvent) break;
919     ResumeScriptEvent(pChannel, itEvent);
920     }
921     }
922    
923 schoenebeck 2594 /** @brief Call instrument script's event handler for this event.
924     *
925     * Causes a new execution instance of the currently loaded real-time
926     * instrument script's event handler (callback) to be spawned for
927     * the given MIDI event.
928     *
929 schoenebeck 2871 * @param pChannel - engine channel on which the MIDI event occurred
930 schoenebeck 2594 * @param itEvent - MIDI event that causes this new script execution
931     * @param pEventHandler - script's event handler to be executed
932     */
933     void ProcessEventByScript(AbstractEngineChannel* pChannel, RTList<Event>::Iterator& itEvent, VMEventHandler* pEventHandler) {
934 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
935     // check if polyphonic data is passed from "note" to "release"
936     // script event handlers
937     if (pEventHandler == pChannel->pScript->handlerRelease &&
938     pChannel->pScript->handlerNote &&
939     pChannel->pScript->handlerNote->isPolyphonic() &&
940     pChannel->pScript->handlerRelease->isPolyphonic() &&
941     !pChannel->pScript->pKeyEvents[key]->isEmpty())
942     {
943     // polyphonic variable data is used/passed from "note" to
944     // "release" script callback, so we have to recycle the
945     // original "note on" script event(s)
946     RTList<ScriptEvent>::Iterator it = pChannel->pScript->pKeyEvents[key]->first();
947     RTList<ScriptEvent>::Iterator end = pChannel->pScript->pKeyEvents[key]->end();
948     for (; it != end; ++it) {
949     ProcessScriptEvent(
950     pChannel, itEvent, pEventHandler, it
951     );
952     }
953     } else {
954     // no polyphonic data is used/passed from "note" to
955     // "release" script callback, so just use a new fresh
956     // script event object
957     RTList<ScriptEvent>::Iterator itScriptEvent =
958     pChannel->pScript->pEvents->allocAppend();
959     ProcessScriptEvent(
960     pChannel, itEvent, pEventHandler, itScriptEvent
961     );
962     }
963     }
964 schoenebeck 2594
965 schoenebeck 2871 /** @brief Spawn new execution instance of an instrument script handler.
966     *
967     * Will be called to initiate a new execution of a real-time
968     * instrument script event right from the start of the script's
969     * respective handler. If script execution did not complete after
970     * calling this method, the respective script exeuction is then
971     * suspended and a call to ResumeScriptEvent() will be used next
972     * time to continue its execution.
973     *
974     * @param pChannel - engine channel this script is running for
975     * @param itEvent - event which caused execution of this script
976     * event handler
977     * @param pEventHandler - VM representation of event handler to be
978     * executed
979     * @param itScriptEvent - script event that shall be processed
980     */
981 schoenebeck 2645 void ProcessScriptEvent(AbstractEngineChannel* pChannel, RTList<Event>::Iterator& itEvent, VMEventHandler* pEventHandler, RTList<ScriptEvent>::Iterator& itScriptEvent) {
982     if (!itScriptEvent) return; // not a valid script event (i.e. because no free script event was left in the script event pool)
983 schoenebeck 2594
984     // fill the list of script handlers to be executed by this event
985     int i = 0;
986     itScriptEvent->handlers[i++] = pEventHandler; // actual event handler (i.e. note, controller)
987     itScriptEvent->handlers[i] = NULL; // NULL termination of list
988    
989     // initialize/reset other members
990     itScriptEvent->cause = *itEvent;
991     itScriptEvent->currentHandler = 0;
992     itScriptEvent->executionSlices = 0;
993 schoenebeck 2948 itScriptEvent->ignoreAllWaitCalls = false;
994     itScriptEvent->handlerType = pEventHandler->eventHandlerType();
995 schoenebeck 2879 // this is the native representation of the $EVENT_ID script variable
996     itScriptEvent->id =
997     (itEvent->Type == Event::type_note_on)
998     ? ScriptID::fromNoteID( itEvent->Param.Note.ID )
999     : ScriptID::fromEventID( pEventPool->getID(itEvent) );
1000 schoenebeck 2594
1001     // run script handler(s)
1002     VMExecStatus_t res = pScriptVM->exec(
1003 schoenebeck 2611 pChannel->pScript->parserContext, &*itScriptEvent
1004 schoenebeck 2594 );
1005    
1006 schoenebeck 2871 // was the script suspended?
1007     if (res & VM_EXEC_SUSPENDED) { // script was suspended ...
1008     // in case the script was suspended, keep it on the allocated
1009     // ScriptEvent list to be resume at the scheduled time in future,
1010     // additionally insert it into a sorted time queue
1011     pEventGenerator->scheduleAheadMicroSec(
1012     pChannel->pScript->suspendedEvents, // scheduler queue
1013     *itScriptEvent, // script event
1014     itScriptEvent->cause.FragmentPos(), // current time of script event (basis for its next execution)
1015     itScriptEvent->execCtx->suspensionTimeMicroseconds() // how long shall it be suspended
1016     );
1017     } else { // script execution has finished without 'suspended' status ...
1018 schoenebeck 2645 // if "polyphonic" variable data is passed from script's
1019     // "note" event handler to its "release" event handler, then
1020     // the script event must be kept and recycled for the later
1021     // occuring "release" script event ...
1022     if (pEventHandler == pChannel->pScript->handlerNote &&
1023     pChannel->pScript->handlerRelease &&
1024     pChannel->pScript->handlerNote->isPolyphonic() &&
1025     pChannel->pScript->handlerRelease->isPolyphonic())
1026     {
1027     const int key = itEvent->Param.Note.Key;
1028     itScriptEvent.moveToEndOf(pChannel->pScript->pKeyEvents[key & 127]);
1029     } else {
1030     // ... otherwise if no polyphonic data is passed and
1031     // script's execution has finished without suspension
1032     // status, then free the script event for a new future
1033     // script event to be triggered from start
1034     pChannel->pScript->pEvents->free(itScriptEvent);
1035     }
1036     }
1037 schoenebeck 2594 }
1038    
1039     /** @brief Resume execution of instrument script.
1040     *
1041     * Will be called to resume execution of a real-time instrument
1042 schoenebeck 2879 * script event which has been suspended previously.
1043 schoenebeck 2594 *
1044     * Script execution might be suspended for various reasons. Usually
1045     * a script will be suspended if the script called the built-in
1046     * "wait()" function, but it might also be suspended automatically
1047     * if the script took too much execution time in an audio fragment
1048     * cycle. So in the latter case automatic suspension is performed in
1049     * order to avoid harm for the sampler's overall real-time
1050     * requirements.
1051     *
1052     * @param pChannel - engine channel this script is running for
1053     * @param itScriptEvent - script execution that shall be resumed
1054     */
1055     void ResumeScriptEvent(AbstractEngineChannel* pChannel, RTList<ScriptEvent>::Iterator& itScriptEvent) {
1056 schoenebeck 2645 VMEventHandler* handler = itScriptEvent->handlers[itScriptEvent->currentHandler];
1057    
1058 schoenebeck 2594 // run script
1059     VMExecStatus_t res = pScriptVM->exec(
1060 schoenebeck 2611 pChannel->pScript->parserContext, &*itScriptEvent
1061 schoenebeck 2594 );
1062 schoenebeck 2645
1063 schoenebeck 2871 // was the script suspended?
1064     if (res & VM_EXEC_SUSPENDED) {
1065     // in case the script was suspended, keep it on the allocated
1066     // ScriptEvent list to be resume at the scheduled time in future,
1067     // additionally insert it into a sorted time queue
1068     pEventGenerator->scheduleAheadMicroSec(
1069     pChannel->pScript->suspendedEvents, // scheduler queue
1070     *itScriptEvent, // script event
1071     itScriptEvent->cause.FragmentPos(), // current time of script event (basis for its next execution)
1072     itScriptEvent->execCtx->suspensionTimeMicroseconds() // how long shall it be suspended
1073     );
1074     } else { // script execution has finished without 'suspended' status ...
1075 schoenebeck 2645 // if "polyphonic" variable data is passed from script's
1076     // "note" event handler to its "release" event handler, then
1077     // the script event must be kept and recycled for the later
1078     // occuring "release" script event ...
1079     if (handler && handler == pChannel->pScript->handlerNote &&
1080     pChannel->pScript->handlerRelease &&
1081     pChannel->pScript->handlerNote->isPolyphonic() &&
1082     pChannel->pScript->handlerRelease->isPolyphonic())
1083     {
1084     const int key = itScriptEvent->cause.Param.Note.Key;
1085     itScriptEvent.moveToEndOf(pChannel->pScript->pKeyEvents[key & 127]);
1086     } else {
1087     // ... otherwise if no polyphonic data is passed and
1088     // script's execution has finished without suspension
1089     // status, then free the script event for a new future
1090     // script event to be triggered from start
1091     pChannel->pScript->pEvents->free(itScriptEvent);
1092     }
1093     }
1094 schoenebeck 2594 }
1095    
1096 iliev 2012 /**
1097     * Will be called by LaunchVoice() method in case there are no free
1098     * voices left. This method will select and kill one old voice for
1099     * voice stealing and postpone the note-on event until the selected
1100     * voice actually died.
1101     *
1102 schoenebeck 2871 * @param pEngineChannel - engine channel on which this event occurred on
1103 iliev 2012 * @param itNoteOnEvent - key, velocity and time stamp of the event
1104     * @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
1105     */
1106 schoenebeck 2879 int StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1107 iliev 2012 if (VoiceSpawnsLeft <= 0) {
1108     dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
1109     return -1;
1110     }
1111    
1112     EngineChannelBase<V, R, I>* pEngineChn = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1113    
1114 schoenebeck 2879 if (pEventPool->poolIsEmpty()) {
1115     dmsg(1,("Event pool emtpy!\n"));
1116     return -1;
1117     }
1118 iliev 2012
1119 schoenebeck 2879 if (!pEngineChn->StealVoice(itNoteOnEvent, &itLastStolenVoice, &itLastStolenNote, &iuiLastStolenKey)) {
1120     --VoiceSpawnsLeft;
1121     return 0;
1122     }
1123 iliev 2012
1124 schoenebeck 2879 // if we couldn't steal a voice from the same engine channel then
1125     // steal oldest voice on the oldest key from any other engine channel
1126     // (the smaller engine channel number, the higher priority)
1127     EngineChannelBase<V, R, I>* pSelectedChannel;
1128     int iChannelIndex;
1129     VoiceIterator itSelectedVoice;
1130 iliev 2012
1131 schoenebeck 2879 // select engine channel
1132     if (pLastStolenChannel) {
1133     pSelectedChannel = pLastStolenChannel;
1134     iChannelIndex = pSelectedChannel->iEngineIndexSelf;
1135     } else { // pick the engine channel followed by this engine channel
1136     iChannelIndex = (pEngineChn->iEngineIndexSelf + 1) % engineChannels.size();
1137     pSelectedChannel = static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannelIndex]);
1138     }
1139 iliev 2012
1140 schoenebeck 2879 // if we already stole in this fragment, try to proceed on same note
1141     if (this->itLastStolenVoiceGlobally) {
1142     itSelectedVoice = this->itLastStolenVoiceGlobally;
1143     do {
1144     ++itSelectedVoice;
1145     } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1146     }
1147     // did we find a 'stealable' voice?
1148     if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1149     // remember which voice we stole, so we can simply proceed on next voice stealing
1150     this->itLastStolenVoiceGlobally = itSelectedVoice;
1151     // done
1152     goto stealable_voice_found;
1153     }
1154    
1155     // get (next) oldest note
1156     if (this->itLastStolenNoteGlobally) {
1157     for (NoteIterator itNote = ++this->itLastStolenNoteGlobally;
1158     itNote; ++itNote)
1159     {
1160     for (itSelectedVoice = itNote->pActiveVoices->first(); itSelectedVoice; ++itSelectedVoice) {
1161     // proceed iterating if voice was created in this audio fragment cycle
1162     if (itSelectedVoice->IsStealable()) {
1163     // remember which voice of which note we stole, so we can simply proceed on next voice stealing
1164     this->itLastStolenNoteGlobally = itNote;
1165     this->itLastStolenVoiceGlobally = itSelectedVoice;
1166     goto stealable_voice_found; // selection succeeded
1167     }
1168     }
1169 iliev 2012 }
1170 schoenebeck 2879 }
1171 iliev 2012
1172 schoenebeck 2879 #if CONFIG_DEVMODE
1173     EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1174     #endif // CONFIG_DEVMODE
1175 iliev 2012
1176 schoenebeck 2879 while (true) { // iterate through engine channels
1177     // get (next) oldest key
1178     RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
1179     this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
1180     while (iuiSelectedKey) {
1181     MidiKey* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1182    
1183     for (NoteIterator itNote = pSelectedKey->pActiveNotes->first(),
1184     itNotesEnd = pSelectedKey->pActiveNotes->end();
1185     itNote != itNotesEnd; ++itNote)
1186     {
1187     itSelectedVoice = itNote->pActiveVoices->first();
1188 iliev 2012 // proceed iterating if voice was created in this fragment cycle
1189     while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1190     // found a "stealable" voice ?
1191     if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1192 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
1193 iliev 2012 this->iuiLastStolenKeyGlobally = iuiSelectedKey;
1194 schoenebeck 2879 this->itLastStolenNoteGlobally = itNote;
1195 iliev 2012 this->itLastStolenVoiceGlobally = itSelectedVoice;
1196     this->pLastStolenChannel = pSelectedChannel;
1197     goto stealable_voice_found; // selection succeeded
1198     }
1199     }
1200 schoenebeck 2879 ++iuiSelectedKey; // get next key on current engine channel
1201 iliev 2012 }
1202 schoenebeck 2879 // get next engine channel
1203     iChannelIndex = (iChannelIndex + 1) % engineChannels.size();
1204     pSelectedChannel = static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannelIndex]);
1205 iliev 2012
1206     #if CONFIG_DEVMODE
1207 schoenebeck 2879 if (pSelectedChannel == pBegin) {
1208     dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1209     dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1210     dmsg(1,("Exiting.\n"));
1211     exit(-1);
1212 iliev 2012 }
1213     #endif // CONFIG_DEVMODE
1214 schoenebeck 2879 }
1215 iliev 2012
1216 schoenebeck 2879 // jump point if a 'stealable' voice was found
1217     stealable_voice_found:
1218 iliev 2012
1219 schoenebeck 2879 #if CONFIG_DEVMODE
1220     if (!itSelectedVoice->IsActive()) {
1221     dmsg(1,("EngineBase: ERROR, tried to steal a voice which was not active !!!\n"));
1222 iliev 2012 return -1;
1223     }
1224 schoenebeck 2879 #endif // CONFIG_DEVMODE
1225    
1226     // now kill the selected voice
1227     itSelectedVoice->Kill(itNoteOnEvent);
1228    
1229     --VoiceSpawnsLeft;
1230    
1231     return 0; // success
1232 iliev 2012 }
1233    
1234     void HandleInstrumentChanges() {
1235     bool instrumentChanged = false;
1236     for (int i = 0; i < engineChannels.size(); i++) {
1237     EngineChannelBase<V, R, I>* pEngineChannel =
1238     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
1239    
1240     // as we're going to (carefully) write some status to the
1241     // synchronized struct, we cast away the const
1242     InstrumentChangeCmd<R, I>& cmd =
1243     const_cast<InstrumentChangeCmd<R, I>&>(pEngineChannel->InstrumentChangeCommandReader.Lock());
1244    
1245     pEngineChannel->pRegionsInUse = cmd.pRegionsInUse;
1246     pEngineChannel->pRegionsInUse->clear();
1247    
1248     if (cmd.bChangeInstrument) {
1249     // change instrument
1250     dmsg(5,("Engine: instrument change command received\n"));
1251     cmd.bChangeInstrument = false;
1252     pEngineChannel->pInstrument = cmd.pInstrument;
1253 schoenebeck 2659 pEngineChannel->pScript =
1254     cmd.pScript->bHasValidScript ? cmd.pScript : NULL;
1255 iliev 2012 instrumentChanged = true;
1256    
1257     pEngineChannel->MarkAllActiveVoicesAsOrphans();
1258 schoenebeck 2611
1259     // the script's "init" event handler is only executed
1260     // once (when the script is loaded or reloaded)
1261     if (pEngineChannel->pScript && pEngineChannel->pScript->handlerInit) {
1262 schoenebeck 2972 dmsg(5,("Engine: exec handlerInit %p\n", pEngineChannel->pScript->handlerInit));
1263 schoenebeck 2611 RTList<ScriptEvent>::Iterator itScriptEvent =
1264     pEngineChannel->pScript->pEvents->allocAppend();
1265    
1266 schoenebeck 2614 itScriptEvent->cause.pEngineChannel = pEngineChannel;
1267 schoenebeck 2618 itScriptEvent->handlers[0] = pEngineChannel->pScript->handlerInit;
1268     itScriptEvent->handlers[1] = NULL;
1269 schoenebeck 2972 itScriptEvent->currentHandler = 0;
1270     itScriptEvent->executionSlices = 0;
1271     itScriptEvent->ignoreAllWaitCalls = false;
1272     itScriptEvent->handlerType = VM_EVENT_HANDLER_INIT;
1273 schoenebeck 2614
1274 schoenebeck 2611 VMExecStatus_t res = pScriptVM->exec(
1275     pEngineChannel->pScript->parserContext, &*itScriptEvent
1276     );
1277    
1278     pEngineChannel->pScript->pEvents->free(itScriptEvent);
1279     }
1280 iliev 2012 }
1281     }
1282    
1283     if (instrumentChanged) {
1284     //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
1285     ResetSuspendedRegions();
1286     }
1287     }
1288    
1289     /**
1290     * Render all 'normal' voices (that is voices which were not stolen in
1291     * this fragment) on the given engine channel.
1292     *
1293     * @param pEngineChannel - engine channel on which audio should be
1294     * rendered
1295     * @param Samples - amount of sample points to be rendered in
1296     * this audio fragment cycle
1297     */
1298     void RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
1299     #if !CONFIG_PROCESS_MUTED_CHANNELS
1300     if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1301     #endif
1302    
1303     EngineChannelBase<V, R, I>* pChannel =
1304     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1305     pChannel->RenderActiveVoices(Samples);
1306    
1307     ActiveVoiceCountTemp += pEngineChannel->GetVoiceCount();
1308     }
1309    
1310     /**
1311     * Render all stolen voices (only voices which were stolen in this
1312     * fragment) on the given engine channel. Stolen voices are rendered
1313     * after all normal voices have been rendered; this is needed to render
1314     * audio of those voices which were selected for voice stealing until
1315     * the point were the stealing (that is the take over of the voice)
1316     * actually happened.
1317     *
1318     * @param pEngineChannel - engine channel on which audio should be
1319     * rendered
1320     * @param Samples - amount of sample points to be rendered in
1321     * this audio fragment cycle
1322     */
1323     void RenderStolenVoices(uint Samples) {
1324     RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
1325     RTList<Event>::Iterator end = pVoiceStealingQueue->end();
1326     for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
1327     EngineChannelBase<V, R, I>* pEngineChannel =
1328     static_cast<EngineChannelBase<V, R, I>*>(itVoiceStealEvent->pEngineChannel);;
1329     if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
1330 schoenebeck 2879
1331 iliev 2012 PoolVoiceIterator itNewVoice =
1332     LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
1333     if (itNewVoice) {
1334 schoenebeck 2879 // usually there should already be a new Note object
1335     NoteIterator itNote = GetNotePool()->fromID(itVoiceStealEvent->Param.Note.ID);
1336     if (!itNote) { // should not happen, but just to be sure ...
1337     const note_id_t noteID = LaunchNewNote(pEngineChannel, &*itVoiceStealEvent);
1338     if (!noteID) {
1339     dmsg(1,("Engine: Voice stealing failed; No Note object and Note pool empty!\n"));
1340     continue;
1341     }
1342     itNote = GetNotePool()->fromID(noteID);
1343     }
1344     // move voice from whereever it was, to the new note's list of active voices
1345     itNewVoice = itNewVoice.moveToEndOf(itNote->pActiveVoices);
1346     // render audio of this new voice for the first time
1347 iliev 2012 itNewVoice->Render(Samples);
1348     if (itNewVoice->IsActive()) { // still active
1349     *(pEngineChannel->pRegionsInUse->allocAppend()) = itNewVoice->GetRegion();
1350     ActiveVoiceCountTemp++;
1351     pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);
1352    
1353     if (itNewVoice->PlaybackState == Voice::playback_state_disk) {
1354     if (itNewVoice->DiskStreamRef.State != Stream::state_unused) {
1355     pEngineChannel->SetDiskStreamCount(pEngineChannel->GetDiskStreamCount() + 1);
1356     }
1357     }
1358     } else { // voice reached end, is now inactive
1359     pEngineChannel->FreeVoice(itNewVoice); // remove voice from the list of active voices
1360     }
1361     }
1362     else dmsg(1,("EngineBase: ERROR, voice stealing didn't work out!\n"));
1363    
1364     // we need to clear the key's event list explicitly here in case key was never active
1365     MidiKey* pKey = &pEngineChannel->pMIDIKeyInfo[itVoiceStealEvent->Param.Note.Key];
1366     pKey->VoiceTheftsQueued--;
1367     if (!pKey->Active && !pKey->VoiceTheftsQueued) pKey->pEvents->clear();
1368     }
1369     }
1370    
1371     /**
1372     * Free all keys which have turned inactive in this audio fragment, from
1373     * the list of active keys and clear all event lists on that engine
1374     * channel.
1375     *
1376     * @param pEngineChannel - engine channel to cleanup
1377     */
1378     void PostProcess(EngineChannel* pEngineChannel) {
1379     EngineChannelBase<V, R, I>* pChannel =
1380     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1381     pChannel->FreeAllInactiveKyes();
1382    
1383     // empty the engine channel's own event lists
1384 schoenebeck 2871 // (only events of the current audio fragment cycle)
1385     pChannel->ClearEventListsOfCurrentFragment();
1386 iliev 2012 }
1387    
1388 schoenebeck 2121 /**
1389     * Process MIDI control change events with hard coded behavior,
1390     * that is controllers whose behavior is defined independently
1391     * of the actual sampler engine type and instrument.
1392     *
1393     * @param pEngineChannel - engine channel on which the MIDI CC event was received
1394     * @param itControlChangeEvent - the actual MIDI CC event
1395     */
1396 iliev 2012 void ProcessHardcodedControllers (
1397     EngineChannel* pEngineChannel,
1398     Pool<Event>::Iterator& itControlChangeEvent
1399     ) {
1400     EngineChannelBase<V, R, I>* pChannel =
1401     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1402    
1403     switch (itControlChangeEvent->Param.CC.Controller) {
1404     case 5: { // portamento time
1405     pChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
1406     break;
1407     }
1408 schoenebeck 2121 case 6: { // data entry (currently only used for RPN and NRPN controllers)
1409     //dmsg(1,("DATA ENTRY %d\n", itControlChangeEvent->Param.CC.Value));
1410     if (pChannel->GetMidiRpnController() >= 0) { // RPN controller number was sent previously ...
1411     dmsg(4,("Guess it's an RPN ...\n"));
1412     if (pChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
1413     int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
1414     // limit to +- two octaves for now
1415     transpose = RTMath::Min(transpose, 24);
1416     transpose = RTMath::Max(transpose, -24);
1417     pChannel->GlobalTranspose = transpose;
1418     // workaround, so we won't have hanging notes
1419     pChannel->ReleaseAllVoices(itControlChangeEvent);
1420     }
1421     // to prevent other MIDI CC #6 messages to be misenterpreted as RPN controller data
1422     pChannel->ResetMidiRpnController();
1423     } else if (pChannel->GetMidiNrpnController() >= 0) { // NRPN controller number was sent previously ...
1424     dmsg(4,("Guess it's an NRPN ...\n"));
1425     const int NrpnCtrlMSB = pChannel->GetMidiNrpnController() >> 8;
1426     const int NrpnCtrlLSB = pChannel->GetMidiNrpnController() & 0xff;
1427     dmsg(4,("NRPN MSB=%d LSB=%d Data=%d\n", NrpnCtrlMSB, NrpnCtrlLSB, itControlChangeEvent->Param.CC.Value));
1428     switch (NrpnCtrlMSB) {
1429     case 0x1a: { // volume level of note (Roland GS NRPN)
1430     const uint note = NrpnCtrlLSB;
1431     const uint vol = itControlChangeEvent->Param.CC.Value;
1432     dmsg(4,("Note Volume NRPN received (note=%d,vol=%d).\n", note, vol));
1433     if (note < 128 && vol < 128)
1434     pChannel->pMIDIKeyInfo[note].Volume = VolumeCurve[vol];
1435     break;
1436     }
1437     case 0x1c: { // panpot of note (Roland GS NRPN)
1438     const uint note = NrpnCtrlLSB;
1439     const uint pan = itControlChangeEvent->Param.CC.Value;
1440     dmsg(4,("Note Pan NRPN received (note=%d,pan=%d).\n", note, pan));
1441     if (note < 128 && pan < 128) {
1442     pChannel->pMIDIKeyInfo[note].PanLeft = PanCurve[128 - pan];
1443     pChannel->pMIDIKeyInfo[note].PanRight = PanCurve[pan];
1444     }
1445     break;
1446     }
1447     case 0x1d: { // reverb send of note (Roland GS NRPN)
1448     const uint note = NrpnCtrlLSB;
1449     const float reverb = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
1450 persson 2837 dmsg(4,("Note Reverb Send NRPN received (note=%d,send=%f).\n", note, reverb));
1451 schoenebeck 2121 if (note < 128)
1452     pChannel->pMIDIKeyInfo[note].ReverbSend = reverb;
1453     break;
1454     }
1455     case 0x1e: { // chorus send of note (Roland GS NRPN)
1456     const uint note = NrpnCtrlLSB;
1457     const float chorus = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
1458 persson 2837 dmsg(4,("Note Chorus Send NRPN received (note=%d,send=%f).\n", note, chorus));
1459 schoenebeck 2121 if (note < 128)
1460     pChannel->pMIDIKeyInfo[note].ChorusSend = chorus;
1461     break;
1462     }
1463     }
1464     // to prevent other MIDI CC #6 messages to be misenterpreted as NRPN controller data
1465     pChannel->ResetMidiNrpnController();
1466 iliev 2012 }
1467     break;
1468     }
1469     case 7: { // volume
1470     //TODO: not sample accurate yet
1471     pChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1472     pChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1473     break;
1474     }
1475     case 10: { // panpot
1476     //TODO: not sample accurate yet
1477     pChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;
1478     break;
1479     }
1480     case 64: { // sustain
1481     if (itControlChangeEvent->Param.CC.Value >= 64 && !pChannel->SustainPedal) {
1482     dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1483     pChannel->SustainPedal = true;
1484     pChannel->listeners.PreProcessSustainPedalDown();
1485    
1486     #if !CONFIG_PROCESS_MUTED_CHANNELS
1487     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1488     pChannel->listeners.PostProcessSustainPedalDown();
1489     return;
1490     }
1491     #endif
1492    
1493     pChannel->ProcessSustainPedalDown(itControlChangeEvent);
1494     pChannel->listeners.PostProcessSustainPedalDown();
1495     }
1496     if (itControlChangeEvent->Param.CC.Value < 64 && pChannel->SustainPedal) {
1497     dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1498     pChannel->SustainPedal = false;
1499     pChannel->listeners.PreProcessSustainPedalUp();
1500    
1501     #if !CONFIG_PROCESS_MUTED_CHANNELS
1502     if (pChannel->GetMute()) { // skip if sampler channel is muted
1503     pChannel->listeners.PostProcessSustainPedalUp();
1504     return;
1505     }
1506     #endif
1507    
1508     pChannel->ProcessSustainPedalUp(itControlChangeEvent);
1509     pChannel->listeners.PostProcessSustainPedalUp();
1510     }
1511     break;
1512     }
1513     case 65: { // portamento on / off
1514     const bool bPortamento = itControlChangeEvent->Param.CC.Value >= 64;
1515     if (bPortamento != pChannel->PortamentoMode)
1516     KillAllVoices(pChannel, itControlChangeEvent);
1517     pChannel->PortamentoMode = bPortamento;
1518     break;
1519     }
1520     case 66: { // sostenuto
1521     if (itControlChangeEvent->Param.CC.Value >= 64 && !pChannel->SostenutoPedal) {
1522     dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1523     pChannel->SostenutoPedal = true;
1524     pChannel->listeners.PreProcessSostenutoPedalDown();
1525    
1526     #if !CONFIG_PROCESS_MUTED_CHANNELS
1527     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1528     pChannel->listeners.PostProcessSostenutoPedalDown();
1529     return;
1530     }
1531     #endif
1532    
1533     pChannel->ProcessSostenutoPedalDown();
1534     pChannel->listeners.PostProcessSostenutoPedalDown();
1535     }
1536     if (itControlChangeEvent->Param.CC.Value < 64 && pChannel->SostenutoPedal) {
1537     dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1538     pChannel->SostenutoPedal = false;
1539     pChannel->listeners.PreProcessSostenutoPedalUp();
1540    
1541     #if !CONFIG_PROCESS_MUTED_CHANNELS
1542     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1543     pChannel->listeners.PostProcessSostenutoPedalUp();
1544     return;
1545     }
1546     #endif
1547    
1548     pChannel->ProcessSostenutoPedalUp(itControlChangeEvent);
1549     pChannel->listeners.PostProcessSostenutoPedalUp();
1550     }
1551     break;
1552     }
1553 schoenebeck 2121 case 98: { // NRPN controller LSB
1554     dmsg(4,("NRPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1555     pEngineChannel->SetMidiNrpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1556     break;
1557     }
1558     case 99: { // NRPN controller MSB
1559     dmsg(4,("NRPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1560     pEngineChannel->SetMidiNrpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1561     break;
1562     }
1563 iliev 2012 case 100: { // RPN controller LSB
1564 schoenebeck 2121 dmsg(4,("RPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1565 iliev 2012 pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1566     break;
1567     }
1568     case 101: { // RPN controller MSB
1569 schoenebeck 2121 dmsg(4,("RPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1570 iliev 2012 pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1571     break;
1572     }
1573    
1574    
1575     // Channel Mode Messages
1576    
1577     case 120: { // all sound off
1578     KillAllVoices(pEngineChannel, itControlChangeEvent);
1579     break;
1580     }
1581     case 121: { // reset all controllers
1582     pChannel->ResetControllers();
1583     break;
1584     }
1585     case 123: { // all notes off
1586     #if CONFIG_PROCESS_ALL_NOTES_OFF
1587     pChannel->ReleaseAllVoices(itControlChangeEvent);
1588     #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1589     break;
1590     }
1591     case 126: { // mono mode on
1592     if (!pChannel->SoloMode)
1593     KillAllVoices(pEngineChannel, itControlChangeEvent);
1594     pChannel->SoloMode = true;
1595     break;
1596     }
1597     case 127: { // poly mode on
1598     if (pChannel->SoloMode)
1599     KillAllVoices(pEngineChannel, itControlChangeEvent);
1600     pChannel->SoloMode = false;
1601     break;
1602     }
1603     }
1604     }
1605    
1606     virtual D* CreateDiskThread() = 0;
1607    
1608     /**
1609     * Assigns and triggers a new voice for the respective MIDI key.
1610     *
1611 schoenebeck 2871 * @param pEngineChannel - engine channel on which this event occurred on
1612 iliev 2012 * @param itNoteOnEvent - key, velocity and time stamp of the event
1613     */
1614     virtual void ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1615     EngineChannelBase<V, R, I>* pChannel =
1616     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1617    
1618 schoenebeck 2879 const int key = itNoteOnEvent->Param.Note.Key;
1619     const int vel = itNoteOnEvent->Param.Note.Velocity;
1620     if (key < 0 || key > 127) return; // ignore event, key outside allowed key range
1621 iliev 2012
1622     MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];
1623    
1624 schoenebeck 2938 // There are real MIDI note-on events (Event::type_note_on) and
1625     // programmatically spawned notes (Event::type_play_note). We have
1626     // to distinguish between them, since certain processing below
1627     // must only be done on real MIDI note-on events (i.e. for
1628     // correctly updating which MIDI keys are currently pressed down).
1629     const bool isRealMIDINoteOnEvent = itNoteOnEvent->Type == Event::type_note_on;
1630    
1631     if (isRealMIDINoteOnEvent)
1632     pChannel->listeners.PreProcessNoteOn(key, vel);
1633    
1634 iliev 2012 #if !CONFIG_PROCESS_MUTED_CHANNELS
1635     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1636 schoenebeck 2938 if (isRealMIDINoteOnEvent)
1637     pChannel->listeners.PostProcessNoteOn(key, vel);
1638 iliev 2012 return;
1639     }
1640     #endif
1641    
1642     if (!pChannel->pInstrument) {
1643 schoenebeck 2938 if (isRealMIDINoteOnEvent)
1644     pChannel->listeners.PostProcessNoteOn(key, vel);
1645 iliev 2012 return; // ignore if no instrument loaded
1646     }
1647    
1648     // move note on event to the key's own event list
1649     RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
1650    
1651     // if Solo Mode then kill all already active voices
1652 schoenebeck 2938 if (pChannel->SoloMode && isRealMIDINoteOnEvent) {
1653 iliev 2012 Pool<uint>::Iterator itYoungestKey = pChannel->pActiveKeys->last();
1654     if (itYoungestKey) {
1655     const int iYoungestKey = *itYoungestKey;
1656     const MidiKey* pOtherKey = &pChannel->pMIDIKeyInfo[iYoungestKey];
1657     if (pOtherKey->Active) {
1658     // get final portamento position of currently active voice
1659     if (pChannel->PortamentoMode) {
1660 schoenebeck 2879 NoteIterator itNote = pOtherKey->pActiveNotes->last();
1661     if (itNote) {
1662     VoiceIterator itVoice = itNote->pActiveVoices->last();
1663     if (itVoice) itVoice->UpdatePortamentoPos(itNoteOnEventOnKeyList);
1664     }
1665 iliev 2012 }
1666     // kill all voices on the (other) key
1667 schoenebeck 2879 for (NoteIterator itNote = pOtherKey->pActiveNotes->first(); itNote; ++itNote) {
1668     VoiceIterator itVoiceToBeKilled = itNote->pActiveVoices->first();
1669     VoiceIterator end = itNote->pActiveVoices->end();
1670     for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1671     if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1672     itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
1673     }
1674 iliev 2012 }
1675     }
1676     }
1677     // set this key as 'currently active solo key'
1678     pChannel->SoloKey = key;
1679     }
1680    
1681 schoenebeck 2938 if (isRealMIDINoteOnEvent) {
1682     pChannel->ProcessKeySwitchChange(key);
1683 iliev 2012
1684 schoenebeck 2938 pKey->KeyPressed = true; // the MIDI key was now pressed down
1685     pChannel->KeyDown[key] = true; // just used as built-in %KEY_DOWN script variable
1686     pKey->Velocity = itNoteOnEventOnKeyList->Param.Note.Velocity;
1687     pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
1688     }
1689 iliev 2012
1690     // cancel release process of voices on this key if needed
1691 schoenebeck 2938 if (pKey->Active && !pChannel->SustainPedal && isRealMIDINoteOnEvent) {
1692 iliev 2012 RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
1693     if (itCancelReleaseEvent) {
1694     *itCancelReleaseEvent = *itNoteOnEventOnKeyList; // copy event
1695 schoenebeck 2938 itCancelReleaseEvent->Type = Event::type_cancel_release_key; // transform event type
1696 iliev 2012 }
1697     else dmsg(1,("Event pool emtpy!\n"));
1698     }
1699    
1700     TriggerNewVoices(pEngineChannel, itNoteOnEventOnKeyList);
1701    
1702     // if neither a voice was spawned or postponed then remove note on event from key again
1703     if (!pKey->Active && !pKey->VoiceTheftsQueued)
1704     pKey->pEvents->free(itNoteOnEventOnKeyList);
1705    
1706 schoenebeck 2938 if (isRealMIDINoteOnEvent && (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f))
1707     pChannel->PortamentoPos = (float) key;
1708    
1709     //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?
1710 persson 2043 if (pKey->pRoundRobinIndex) {
1711     (*pKey->pRoundRobinIndex)++; // counter specific for the key or region
1712     pChannel->RoundRobinIndex++; // common counter for the channel
1713     }
1714 schoenebeck 2938
1715     if (isRealMIDINoteOnEvent)
1716     pChannel->listeners.PostProcessNoteOn(key, vel);
1717 iliev 2012 }
1718    
1719     /**
1720     * Allocate and trigger new voice(s) for the key.
1721     */
1722     virtual void TriggerNewVoices (
1723     EngineChannel* pEngineChannel,
1724     RTList<Event>::Iterator& itNoteOnEvent,
1725     bool HandleKeyGroupConflicts = true
1726     ) = 0;
1727    
1728     /**
1729     * Allocate and trigger release voice(s) for the key.
1730     */
1731     virtual void TriggerReleaseVoices (
1732     EngineChannel* pEngineChannel,
1733     RTList<Event>::Iterator& itNoteOffEvent
1734     ) = 0;
1735    
1736     /**
1737     * Releases the voices on the given key if sustain pedal is not pressed.
1738     * If sustain is pressed, the release of the note will be postponed until
1739     * sustain pedal will be released or voice turned inactive by itself (e.g.
1740     * due to completion of sample playback).
1741     *
1742 schoenebeck 2871 * @param pEngineChannel - engine channel on which this event occurred on
1743 iliev 2012 * @param itNoteOffEvent - key, velocity and time stamp of the event
1744     */
1745     virtual void ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
1746     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1747    
1748 schoenebeck 2879 const int iKey = itNoteOffEvent->Param.Note.Key;
1749     const int vel = itNoteOffEvent->Param.Note.Velocity;
1750     if (iKey < 0 || iKey > 127) return; // ignore event, key outside allowed key range
1751 iliev 2012
1752     MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];
1753    
1754 schoenebeck 2938 // There are real MIDI note-off events (Event::type_note_off) and
1755     // programmatically spawned notes (Event::type_stop_note). We have
1756     // to distinguish between them, since certain processing below
1757     // must only be done on real MIDI note-off events (i.e. for
1758     // correctly updating which MIDI keys are currently pressed down),
1759     // plus a stop-note event just releases voices of one particular
1760     // note, whereas a note-off event releases all voices on a
1761     // particular MIDI key instead.
1762     const bool isRealMIDINoteOffEvent = itNoteOffEvent->Type == Event::type_note_off;
1763 iliev 2012
1764 schoenebeck 2938 if (isRealMIDINoteOffEvent)
1765     pChannel->listeners.PreProcessNoteOff(iKey, vel);
1766    
1767 iliev 2012 #if !CONFIG_PROCESS_MUTED_CHANNELS
1768     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1769 schoenebeck 2938 if (isRealMIDINoteOffEvent)
1770     pChannel->listeners.PostProcessNoteOff(iKey, vel);
1771 iliev 2012 return;
1772     }
1773     #endif
1774    
1775 schoenebeck 2938 if (isRealMIDINoteOffEvent) {
1776     pKey->KeyPressed = false; // the MIDI key was now released
1777     pChannel->KeyDown[iKey] = false; // just used as built-in %KEY_DOWN script variable
1778     }
1779 iliev 2012
1780     // move event to the key's own event list
1781     RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
1782    
1783 schoenebeck 2938 if (isRealMIDINoteOffEvent) {
1784     bool bShouldRelease = pKey->Active && pChannel->ShouldReleaseVoice(itNoteOffEventOnKeyList->Param.Note.Key);
1785 iliev 2012
1786 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)
1787     if (pChannel->SoloMode && pChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
1788     bool bOtherKeysPressed = false;
1789     if (iKey == pChannel->SoloKey) {
1790     pChannel->SoloKey = -1;
1791     // if there's still a key pressed down, respawn a voice (group) on the highest key
1792     for (int i = 127; i > 0; i--) {
1793     MidiKey* pOtherKey = &pChannel->pMIDIKeyInfo[i];
1794     if (pOtherKey->KeyPressed) {
1795     bOtherKeysPressed = true;
1796     // make the other key the new 'currently active solo key'
1797     pChannel->SoloKey = i;
1798     // get final portamento position of currently active voice
1799     if (pChannel->PortamentoMode) {
1800     NoteIterator itNote = pKey->pActiveNotes->first();
1801     VoiceIterator itVoice = itNote->pActiveVoices->first();
1802     if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);
1803 schoenebeck 2879 }
1804 schoenebeck 2938 // create a pseudo note on event
1805     RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
1806     if (itPseudoNoteOnEvent) {
1807     // copy event
1808     *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
1809     // transform event to a note on event
1810     itPseudoNoteOnEvent->Type = Event::type_note_on; //FIXME: should probably use Event::type_play_note instead (to avoid i.e. hanging notes)
1811     itPseudoNoteOnEvent->Param.Note.Key = i;
1812     itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
1813     // assign a new note to this note-on event
1814     if (LaunchNewNote(pChannel, &*itPseudoNoteOnEvent)) {
1815     // allocate and trigger new voice(s) for the other key
1816     TriggerNewVoices(pChannel, itPseudoNoteOnEvent, false);
1817     }
1818     // if neither a voice was spawned or postponed then remove note on event from key again
1819     if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
1820     pOtherKey->pEvents->free(itPseudoNoteOnEvent);
1821 iliev 2012
1822 schoenebeck 2938 } else dmsg(1,("Could not respawn voice, no free event left\n"));
1823     break; // done
1824     }
1825 iliev 2012 }
1826     }
1827 schoenebeck 2938 if (bOtherKeysPressed) {
1828     if (pKey->Active) { // kill all voices on this key
1829     bShouldRelease = false; // no need to release, as we kill it here
1830     for (NoteIterator itNote = pKey->pActiveNotes->first(); itNote; ++itNote) {
1831     VoiceIterator itVoiceToBeKilled = itNote->pActiveVoices->first();
1832     VoiceIterator end = itNote->pActiveVoices->end();
1833     for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1834     if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1835     itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1836     }
1837 schoenebeck 2879 }
1838 iliev 2012 }
1839 schoenebeck 2938 } else pChannel->PortamentoPos = -1.0f;
1840     }
1841 iliev 2012
1842 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
1843     if (bShouldRelease) {
1844     itNoteOffEventOnKeyList->Type = Event::type_release_key; // transform event type
1845     // spawn release triggered voice(s) if needed
1846     ProcessReleaseTrigger(pChannel, itNoteOffEventOnKeyList, pKey);
1847     }
1848     } else if (itNoteOffEventOnKeyList->Type == Event::type_stop_note) {
1849     // This programmatically caused event is caused by a call to
1850     // the built-in instrument script function note_off(). In
1851     // contrast to a real MIDI note-off event the stop-note
1852     // event just intends to release voices of one particular note.
1853     NoteBase* pNote = pChannel->pEngine->NoteByID( itNoteOffEventOnKeyList->Param.Note.ID );
1854     if (pNote) { // the requested note is still alive ...
1855     itNoteOffEventOnKeyList->Type = Event::type_release_note; // transform event type
1856     } else { // note is dead and gone ..
1857     pKey->pEvents->free(itNoteOffEventOnKeyList); // remove stop-note event from key again
1858     return; // prevent event to be removed a 2nd time below
1859     }
1860 iliev 2012 }
1861    
1862     // if neither a voice was spawned or postponed on this key then remove note off event from key again
1863     if (!pKey->Active && !pKey->VoiceTheftsQueued)
1864     pKey->pEvents->free(itNoteOffEventOnKeyList);
1865    
1866 schoenebeck 2938 if (isRealMIDINoteOffEvent)
1867     pChannel->listeners.PostProcessNoteOff(iKey, vel);
1868 iliev 2012 }
1869    
1870     /**
1871 schoenebeck 2927 * Called on sustain pedal up events to check and if required,
1872     * launch release trigger voices on the respective active key.
1873     *
1874     * @param pEngineChannel - engine channel on which this event occurred on
1875     * @param itEvent - release trigger event (contains note number)
1876     */
1877     virtual void ProcessReleaseTrigger(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) OVERRIDE {
1878     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1879    
1880     const int iKey = itEvent->Param.Note.Key;
1881     if (iKey < 0 || iKey > 127) return; // ignore event, key outside allowed key range
1882    
1883     MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];
1884    
1885     ProcessReleaseTrigger(pChannel, itEvent, pKey);
1886     }
1887    
1888     /**
1889     * Called on note-off and sustain pedal up events to check and if
1890     * required, launch release trigger voices on the respective active
1891     * key.
1892     *
1893     * @param pEngineChannel - engine channel on which this event occurred on
1894     * @param itEvent - note off event / release trigger event
1895     * @param pKey - key on which the release trigger voices shall be spawned
1896     */
1897     inline void ProcessReleaseTrigger(EngineChannelBase<V, R, I>* pChannel, RTList<Event>::Iterator& itEvent, MidiKey* pKey) {
1898     // spawn release triggered voice(s) if needed
1899     if (pKey->ReleaseTrigger && pChannel->pInstrument) {
1900     // assign a new note to this release event
1901     if (LaunchNewNote(pChannel, &*itEvent)) {
1902     // allocate and trigger new release voice(s)
1903     TriggerReleaseVoices(pChannel, itEvent);
1904     }
1905     pKey->ReleaseTrigger = false;
1906     }
1907     }
1908    
1909     /**
1910 schoenebeck 2931 * Called on note synthesis parameter change events. These are
1911     * internal events caused by calling built-in real-time instrument
1912     * script functions like change_vol(), change_pitch(), etc.
1913     *
1914     * This method performs two tasks:
1915     *
1916     * - It converts the event's relative values changes (Deltas) to
1917     * the respective final new synthesis parameter value (AbsValue),
1918     * for that particular moment of the event that is.
1919     *
1920     * - It moves the individual events to the Note's own event list
1921     * (or actually to the event list of the MIDI key), so that
1922     * voices can process those events sample accurately.
1923     *
1924     * @param pEngineChannel - engine channel on which this event occurred on
1925     * @param itEvent - note synthesis parameter change event
1926     */
1927 persson 2952 virtual void ProcessNoteSynthParam(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) {
1928 schoenebeck 2931 EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1929    
1930     NoteBase* pNote = pChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID );
1931     if (!pNote || pNote->hostKey < 0 || pNote->hostKey >= 128) return;
1932    
1933     const bool& relative = itEvent->Param.NoteSynthParam.Relative;
1934    
1935     switch (itEvent->Param.NoteSynthParam.Type) {
1936     case Event::synth_param_volume:
1937     if (relative)
1938     pNote->Override.Volume *= itEvent->Param.NoteSynthParam.Delta;
1939     else
1940     pNote->Override.Volume = itEvent->Param.NoteSynthParam.Delta;
1941     itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Volume;
1942     break;
1943     case Event::synth_param_pitch:
1944     if (relative)
1945     pNote->Override.Pitch *= itEvent->Param.NoteSynthParam.Delta;
1946     else
1947     pNote->Override.Pitch = itEvent->Param.NoteSynthParam.Delta;
1948     itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Pitch;
1949     break;
1950     case Event::synth_param_pan:
1951     if (relative) {
1952     pNote->Override.Pan = RTMath::RelativeSummedAvg(pNote->Override.Pan, itEvent->Param.NoteSynthParam.Delta, ++pNote->Override.PanSources);
1953     } else {
1954     pNote->Override.Pan = itEvent->Param.NoteSynthParam.Delta;
1955     pNote->Override.PanSources = 1; // only relevant on subsequent change_pan() instrument script calls on same note with 'relative' argument being set
1956     }
1957     itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Pan;
1958     break;
1959 schoenebeck 2935 case Event::synth_param_cutoff:
1960     pNote->Override.Cutoff = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1961     break;
1962     case Event::synth_param_resonance:
1963     pNote->Override.Resonance = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1964     break;
1965 schoenebeck 2953 case Event::synth_param_attack:
1966     pNote->Override.Attack = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1967     break;
1968     case Event::synth_param_decay:
1969     pNote->Override.Decay = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1970     break;
1971     case Event::synth_param_release:
1972     pNote->Override.Release = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1973     break;
1974 schoenebeck 2931 }
1975    
1976     // move note parameter event to its MIDI key
1977     MidiKey* pKey = &pChannel->pMIDIKeyInfo[pNote->hostKey];
1978     itEvent.moveToEndOf(pKey->pEvents);
1979     }
1980    
1981     /**
1982 iliev 2012 * Reset all voices and disk thread and clear input event queue and all
1983     * control and status variables. This method is protected by a mutex.
1984     */
1985     virtual void ResetInternal() {
1986 persson 2427 LockGuard lock(ResetInternalMutex);
1987 iliev 2012
1988     // make sure that the engine does not get any sysex messages
1989     // while it's reseting
1990     bool sysexDisabled = MidiInputPort::RemoveSysexListener(this);
1991     SetVoiceCount(0);
1992     ActiveVoiceCountMax = 0;
1993    
1994     // reset voice stealing parameters
1995     pVoiceStealingQueue->clear();
1996     itLastStolenVoice = VoiceIterator();
1997     itLastStolenVoiceGlobally = VoiceIterator();
1998 schoenebeck 2879 itLastStolenNote = NoteIterator();
1999     itLastStolenNoteGlobally = NoteIterator();
2000 iliev 2012 iuiLastStolenKey = RTList<uint>::Iterator();
2001     iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
2002     pLastStolenChannel = NULL;
2003    
2004 schoenebeck 2879 // reset all notes
2005     pNotePool->clear();
2006     for (NoteIterator itNote = pNotePool->allocAppend(); itNote;
2007     itNote = pNotePool->allocAppend())
2008     {
2009     itNote->reset();
2010     }
2011     pNotePool->clear();
2012    
2013 iliev 2012 // reset all voices
2014 schoenebeck 2879 pVoicePool->clear();
2015 iliev 2012 for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
2016     iterVoice->Reset();
2017     }
2018     pVoicePool->clear();
2019    
2020 schoenebeck 2871 // reset all engine channels
2021     for (int i = 0; i < engineChannels.size(); i++) {
2022     AbstractEngineChannel* pEngineChannel =
2023     static_cast<AbstractEngineChannel*>(engineChannels[i]);
2024     pEngineChannel->ResetInternal(false/*don't reset engine*/);
2025     }
2026    
2027 iliev 2012 // reset disk thread
2028     if (pDiskThread) pDiskThread->Reset();
2029    
2030     // delete all input events
2031     pEventQueue->init();
2032     pSysexBuffer->init();
2033     if (sysexDisabled) MidiInputPort::AddSysexListener(this);
2034     }
2035    
2036     /**
2037     * Kills all voices on an engine channel as soon as possible. Voices
2038     * won't get into release state, their volume level will be ramped down
2039     * as fast as possible.
2040     *
2041     * @param pEngineChannel - engine channel on which all voices should be killed
2042     * @param itKillEvent - event which caused this killing of all voices
2043     */
2044     virtual void KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
2045     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
2046     int count = pChannel->KillAllVoices(itKillEvent);
2047     VoiceSpawnsLeft -= count; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
2048     }
2049    
2050     /**
2051     * Allocates and triggers a new voice. This method will usually be
2052     * called by the ProcessNoteOn() method and by the voices itself
2053     * (e.g. to spawn further voices on the same key for layered sounds).
2054     *
2055 schoenebeck 2871 * @param pEngineChannel - engine channel on which this event occurred on
2056 iliev 2012 * @param itNoteOnEvent - key, velocity and time stamp of the event
2057     * @param iLayer - layer index for the new voice (optional - only
2058     * in case of layered sounds of course)
2059     * @param ReleaseTriggerVoice - if new voice is a release triggered voice
2060     * (optional, default = false)
2061     * @param VoiceStealing - if voice stealing should be performed
2062     * when there is no free voice
2063     * (optional, default = true)
2064     * @param HandleKeyGroupConflicts - if voices should be killed due to a
2065     * key group conflict
2066     * @returns pointer to new voice or NULL if there was no free voice or
2067     * if the voice wasn't triggered (for example when no region is
2068     * defined for the given key).
2069     */
2070     virtual PoolVoiceIterator LaunchVoice (
2071     EngineChannel* pEngineChannel,
2072     Pool<Event>::Iterator& itNoteOnEvent,
2073     int iLayer,
2074     bool ReleaseTriggerVoice,
2075     bool VoiceStealing,
2076     bool HandleKeyGroupConflicts
2077     ) = 0;
2078    
2079 iliev 2015 virtual int GetMinFadeOutSamples() { return MinFadeOutSamples; }
2080    
2081 iliev 2027 int InitNewVoice (
2082     EngineChannelBase<V, R, I>* pChannel,
2083     R* pRegion,
2084     Pool<Event>::Iterator& itNoteOnEvent,
2085     Voice::type_t VoiceType,
2086     int iLayer,
2087     int iKeyGroup,
2088     bool ReleaseTriggerVoice,
2089     bool VoiceStealing,
2090     typename Pool<V>::Iterator& itNewVoice
2091     ) {
2092     int key = itNoteOnEvent->Param.Note.Key;
2093     typename MidiKeyboardManager<V>::MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];
2094     if (itNewVoice) {
2095     // launch the new voice
2096     if (itNewVoice->Trigger(pChannel, itNoteOnEvent, pChannel->Pitch, pRegion, VoiceType, iKeyGroup) < 0) {
2097     dmsg(4,("Voice not triggered\n"));
2098 schoenebeck 2879 GetVoicePool()->free(itNewVoice);
2099 iliev 2027 }
2100     else { // on success
2101     --VoiceSpawnsLeft;
2102     if (!pKey->Active) { // mark as active key
2103     pKey->Active = true;
2104     pKey->itSelf = pChannel->pActiveKeys->allocAppend();
2105     *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
2106     }
2107 persson 2115 if (itNewVoice->Type & Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
2108 iliev 2027 return 0; // success
2109     }
2110     }
2111     else if (VoiceStealing) {
2112     // try to steal one voice
2113     int result = StealVoice(pChannel, itNoteOnEvent);
2114     if (!result) { // voice stolen successfully
2115     // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
2116     RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
2117     if (itStealEvent) {
2118     *itStealEvent = *itNoteOnEvent; // copy event
2119     itStealEvent->Param.Note.Layer = iLayer;
2120     itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
2121     pKey->VoiceTheftsQueued++;
2122     }
2123     else dmsg(1,("Voice stealing queue full!\n"));
2124     }
2125     }
2126    
2127     return -1;
2128     }
2129 schoenebeck 2448
2130     /**
2131     * Checks whether scale tuning setting has been changed since last
2132     * time this method was called, if yes, it recalculates the pitch
2133     * for all active voices.
2134     */
2135     void ProcessScaleTuningChange() {
2136     const bool changed = ScaleTuningChanged.readAndReset();
2137     if (!changed) return;
2138    
2139     for (int i = 0; i < engineChannels.size(); i++) {
2140     EngineChannelBase<V, R, I>* channel =
2141     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
2142     channel->OnScaleTuningChanged();
2143     }
2144     }
2145 iliev 2027
2146 iliev 2012 private:
2147 schoenebeck 2879 Pool< Note<V> >* pNotePool;
2148     Pool<note_id_t> noteIDPool;
2149 iliev 2012 Pool<V>* pVoicePool; ///< Contains all voices that can be activated.
2150     Pool<RR*> SuspendedRegions;
2151     Mutex SuspendedRegionsMutex;
2152     Condition SuspensionChangeOngoing;
2153     RR* pPendingRegionSuspension;
2154     RR* pPendingRegionResumption;
2155     int iPendingStreamDeletions;
2156     };
2157    
2158     template <class V, class RR, class R, class D, class IM, class I>
2159     IM EngineBase<V, RR, R, D, IM, I>::instruments;
2160    
2161     } // namespace LinuxSampler
2162    
2163     #endif /* __LS_ENGINEBASE_H__ */
2164    

  ViewVC Help
Powered by ViewVC