/[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 3293 - (hide annotations) (download) (as text)
Tue Jun 27 22:19:19 2017 UTC (6 years, 9 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 126456 byte(s)
* NKSP: Added built-in script function "fork()".
* NKSP: Added built-in array variable %NKSP_CALLBACK_CHILD_ID[].
* NKSP: Added built-in variable $NKSP_CALLBACK_PARENT_ID.
* NKSP: Fixed potential crash when accessing dynamic built-in
  array variables.
* Bumped version (2.0.0.svn65).

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

  ViewVC Help
Powered by ViewVC