/[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 2879 - (hide annotations) (download) (as text)
Tue Apr 19 14:07:53 2016 UTC (7 years, 11 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 108931 byte(s)
* All engines: Active voices are now internally grouped to "Note" objects,
  instead of being directly assigned to a keyboard key. This allows more
  fine graded processing of voices, which is i.e. required for certain
  instrument script features.
* Built-in script function "play_note()": Added support for passing
  special value -1 for "duration-us" argument, which will cause the
  triggered note to be released once the original note was released.
* Bumped version (2.0.0.svn3).

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

  ViewVC Help
Powered by ViewVC