/[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 2434 - (hide annotations) (download) (as text)
Thu Mar 7 19:23:24 2013 UTC (11 years ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 79654 byte(s)
* Started to spread new C++ keyword "override" over the code base
  (keyword introduced with C++11 standard).

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 persson 2427 * Copyright (C) 2009-2013 Christian Schoenebeck and Grigor Iliev *
8 iliev 2012 * *
9     * This program is free software; you can redistribute it and/or modify *
10     * it under the terms of the GNU General Public License as published by *
11     * the Free Software Foundation; either version 2 of the License, or *
12     * (at your option) any later version. *
13     * *
14     * This program is distributed in the hope that it will be useful, *
15     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17     * GNU General Public License for more details. *
18     * *
19     * You should have received a copy of the GNU General Public License *
20     * along with this program; if not, write to the Free Software *
21     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
22     * MA 02111-1307 USA *
23     ***************************************************************************/
24    
25     #ifndef __LS_ENGINEBASE_H__
26     #define __LS_ENGINEBASE_H__
27    
28     #include "AbstractEngine.h"
29     #include "EngineChannelBase.h"
30     #include "common/DiskThreadBase.h"
31     #include "common/MidiKeyboardManager.h"
32     #include "InstrumentManager.h"
33     #include "../common/global_private.h"
34    
35    
36     namespace LinuxSampler {
37    
38     class AbstractEngineChannel;
39    
40     template <
41     class V /* Voice */,
42     class RR /* Root Region */,
43     class R /* Region */,
44     class D /* Disk Thread */,
45     class IM /* Instrument Manager */,
46     class I /* Instrument */
47     >
48     class EngineBase: public AbstractEngine, public RegionPools<R>, public VoicePool<V> {
49    
50     public:
51     typedef typename RTList<V>::Iterator VoiceIterator;
52     typedef typename Pool<V>::Iterator PoolVoiceIterator;
53     typedef typename RTList<RR*>::Iterator RootRegionIterator;
54     typedef typename MidiKeyboardManager<V>::MidiKey MidiKey;
55    
56     EngineBase() : SuspendedRegions(128) {
57     pDiskThread = NULL;
58     pVoicePool = new Pool<V>(GLOBAL_MAX_VOICES);
59     pRegionPool[0] = new Pool<R*>(GLOBAL_MAX_VOICES);
60     pRegionPool[1] = new Pool<R*>(GLOBAL_MAX_VOICES);
61     pVoiceStealingQueue = new RTList<Event>(pEventPool);
62     iMaxDiskStreams = GLOBAL_MAX_STREAMS;
63    
64     for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
65     iterVoice->SetEngine(this);
66     }
67     pVoicePool->clear();
68    
69     ResetInternal();
70     ResetScaleTuning();
71     ResetSuspendedRegions();
72     }
73    
74     virtual ~EngineBase() {
75     if (pDiskThread) {
76     dmsg(1,("Stopping disk thread..."));
77     pDiskThread->StopThread();
78     delete pDiskThread;
79     dmsg(1,("OK\n"));
80     }
81    
82     if (pVoicePool) {
83     pVoicePool->clear();
84     delete pVoicePool;
85     }
86    
87     if (pVoiceStealingQueue) delete pVoiceStealingQueue;
88    
89     if (pRegionPool[0]) delete pRegionPool[0];
90     if (pRegionPool[1]) delete pRegionPool[1];
91     ResetSuspendedRegions();
92     }
93    
94     // implementation of abstract methods derived from class 'LinuxSampler::Engine'
95    
96     /**
97     * Let this engine proceed to render the given amount of sample points.
98     * The engine will iterate through all engine channels and render audio
99     * for each engine channel independently. The calculated audio data of
100     * all voices of each engine channel will be placed into the audio sum
101     * buffers of the respective audio output device, connected to the
102     * respective engine channel.
103     *
104     * @param Samples - number of sample points to be rendered
105     * @returns 0 on success
106     */
107 schoenebeck 2434 virtual int RenderAudio(uint Samples) OVERRIDE {
108 iliev 2012 dmsg(8,("RenderAudio(Samples=%d)\n", Samples));
109    
110     // return if engine disabled
111     if (EngineDisabled.Pop()) {
112     dmsg(5,("EngineBase: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
113     EngineDisabled.RttDone();
114     return 0;
115     }
116    
117     // process requests for suspending / resuming regions (i.e. to avoid
118     // crashes while these regions are modified by an instrument editor)
119     ProcessSuspensionsChanges();
120    
121     // update time of start and end of this audio fragment (as events' time stamps relate to this)
122     pEventGenerator->UpdateFragmentTime(Samples);
123    
124     // We only allow the given maximum number of voices to be spawned
125     // in each audio fragment. All subsequent request for spawning new
126     // voices in the same audio fragment will be ignored.
127     VoiceSpawnsLeft = MaxVoices();
128    
129     // get all events from the engine's global input event queue which belong to the current fragment
130     // (these are usually just SysEx messages)
131     ImportEvents(Samples);
132    
133     // process engine global events (these are currently only MIDI System Exclusive messages)
134     {
135     RTList<Event>::Iterator itEvent = pGlobalEvents->first();
136     RTList<Event>::Iterator end = pGlobalEvents->end();
137     for (; itEvent != end; ++itEvent) {
138     switch (itEvent->Type) {
139     case Event::type_sysex:
140     dmsg(5,("Engine: Sysex received\n"));
141     ProcessSysex(itEvent);
142     break;
143     }
144     }
145     }
146    
147     // reset internal voice counter (just for statistic of active voices)
148     ActiveVoiceCountTemp = 0;
149    
150     HandleInstrumentChanges();
151    
152     // handle events on all engine channels
153     for (int i = 0; i < engineChannels.size(); i++) {
154     ProcessEvents(engineChannels[i], Samples);
155     }
156    
157     // render all 'normal', active voices on all engine channels
158     for (int i = 0; i < engineChannels.size(); i++) {
159     RenderActiveVoices(engineChannels[i], Samples);
160     }
161    
162     // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
163     RenderStolenVoices(Samples);
164    
165     // handle audio routing for engine channels with FX sends
166     for (int i = 0; i < engineChannels.size(); i++) {
167     AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(engineChannels[i]);
168     if (pChannel->fxSends.empty()) continue; // ignore if no FX sends
169     RouteAudio(engineChannels[i], Samples);
170     }
171    
172     // handle cleanup on all engine channels for the next audio fragment
173     for (int i = 0; i < engineChannels.size(); i++) {
174     PostProcess(engineChannels[i]);
175     }
176    
177    
178     // empty the engine's event list for the next audio fragment
179     ClearEventLists();
180    
181     // reset voice stealing for the next audio fragment
182     pVoiceStealingQueue->clear();
183    
184     // just some statistics about this engine instance
185     SetVoiceCount(ActiveVoiceCountTemp);
186     if (VoiceCount() > ActiveVoiceCountMax) ActiveVoiceCountMax = VoiceCount();
187    
188     // in case regions were previously suspended and we killed voices
189     // with disk streams due to that, check if those streams have finally
190     // been deleted by the disk thread
191     if (iPendingStreamDeletions) ProcessPendingStreamDeletions();
192    
193 persson 2162 // Release the instrument change command. (This has to
194     // be done after all voices have been rendered and not
195     // in HandleInstrumentChanges, as the RegionsInUse
196     // list has been built up by the voice renderers.)
197     for (int i = 0; i < engineChannels.size(); i++) {
198     EngineChannelBase<V, R, I>* channel =
199     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
200     channel->InstrumentChangeCommandReader.Unlock();
201     }
202 iliev 2012 FrameTime += Samples;
203    
204     EngineDisabled.RttDone();
205     return 0;
206     }
207    
208 schoenebeck 2434 virtual int MaxVoices() OVERRIDE { return pVoicePool->poolSize(); }
209 iliev 2012
210 schoenebeck 2434 virtual void SetMaxVoices(int iVoices) throw (Exception) OVERRIDE {
211 iliev 2012 if (iVoices < 1)
212     throw Exception("Maximum voices for an engine cannot be set lower than 1");
213    
214     SuspendAll();
215    
216     // NOTE: we need to clear pRegionsInUse before deleting pDimRegionPool,
217     // otherwise memory corruption will occur if there are active voices (see bug #118)
218     for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
219     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannel]);
220     pChannel->ClearRegionsInUse();
221     }
222    
223     if (pRegionPool[0]) delete pRegionPool[0];
224     if (pRegionPool[1]) delete pRegionPool[1];
225    
226     pRegionPool[0] = new Pool<R*>(iVoices);
227     pRegionPool[1] = new Pool<R*>(iVoices);
228    
229     for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
230     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannel]);
231     pChannel->ResetRegionsInUse(pRegionPool);
232     }
233    
234     try {
235     pVoicePool->resizePool(iVoices);
236     } catch (...) {
237     throw Exception("FATAL: Could not resize voice pool!");
238     }
239    
240     for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
241     iterVoice->SetEngine(this);
242     iterVoice->pDiskThread = this->pDiskThread;
243     }
244     pVoicePool->clear();
245    
246 iliev 2244 PostSetMaxVoices(iVoices);
247 iliev 2012 ResumeAll();
248     }
249 iliev 2244
250     /** Called after the new max number of voices is set and before resuming the engine. */
251     virtual void PostSetMaxVoices(int iVoices) { }
252 iliev 2012
253 schoenebeck 2434 virtual uint DiskStreamCount() OVERRIDE { return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0; }
254     virtual uint DiskStreamCountMax() OVERRIDE { return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0; }
255     virtual int MaxDiskStreams() OVERRIDE { return iMaxDiskStreams; }
256 iliev 2012
257 schoenebeck 2434 virtual void SetMaxDiskStreams(int iStreams) throw (Exception) OVERRIDE {
258 iliev 2012 if (iStreams < 0)
259     throw Exception("Maximum disk streams for an engine cannot be set lower than 0");
260    
261     SuspendAll();
262    
263     iMaxDiskStreams = iStreams;
264    
265     // reconnect to audio output device, because that will automatically
266     // recreate the disk thread with the required amount of streams
267     if (pAudioOutputDevice) Connect(pAudioOutputDevice);
268    
269     ResumeAll();
270     }
271    
272 schoenebeck 2434 virtual String DiskStreamBufferFillBytes() OVERRIDE { return (pDiskThread) ? pDiskThread->GetBufferFillBytes() : ""; }
273     virtual String DiskStreamBufferFillPercentage() OVERRIDE { return (pDiskThread) ? pDiskThread->GetBufferFillPercentage() : ""; }
274     virtual InstrumentManager* GetInstrumentManager() OVERRIDE { return &instruments; }
275 iliev 2012
276     /**
277     * Connect this engine instance with the given audio output device.
278     * This method will be called when an Engine instance is created.
279     * All of the engine's data structures which are dependant to the used
280     * audio output device / driver will be (re)allocated and / or
281     * adjusted appropriately.
282     *
283     * @param pAudioOut - audio output device to connect to
284     */
285 schoenebeck 2434 virtual void Connect(AudioOutputDevice* pAudioOut) OVERRIDE {
286 iliev 2012 // caution: don't ignore if connecting to the same device here,
287     // because otherwise SetMaxDiskStreams() implementation won't work anymore!
288    
289     pAudioOutputDevice = pAudioOut;
290    
291     ResetInternal();
292    
293     // inform audio driver for the need of two channels
294     try {
295     pAudioOutputDevice->AcquireChannels(2); // default stereo
296     }
297     catch (AudioOutputException e) {
298     String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
299     throw Exception(msg);
300     }
301    
302     this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
303     this->SampleRate = pAudioOutputDevice->SampleRate();
304    
305     MinFadeOutSamples = int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;
306     if (MaxSamplesPerCycle < MinFadeOutSamples) {
307     std::cerr << "EngineBase: WARNING, CONFIG_EG_MIN_RELEASE_TIME "
308     << "too big for current audio fragment size & sampling rate! "
309     << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;
310     // force volume ramp downs at the beginning of each fragment
311     MinFadeOutSamples = MaxSamplesPerCycle;
312     // lower minimum release time
313     const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
314     for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
315 persson 2327 iterVoice->CalculateFadeOutCoeff(minReleaseTime, SampleRate);
316 iliev 2012 }
317     pVoicePool->clear();
318     }
319    
320     // (re)create disk thread
321     if (this->pDiskThread) {
322     dmsg(1,("Stopping disk thread..."));
323     this->pDiskThread->StopThread();
324     delete this->pDiskThread;
325     dmsg(1,("OK\n"));
326     }
327     this->pDiskThread = CreateDiskThread();
328    
329     if (!pDiskThread) {
330     dmsg(0,("EngineBase new diskthread = NULL\n"));
331     exit(EXIT_FAILURE);
332     }
333    
334     for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
335     iterVoice->pDiskThread = this->pDiskThread;
336     dmsg(3,("d"));
337     }
338     pVoicePool->clear();
339    
340     // (re)create event generator
341     if (pEventGenerator) delete pEventGenerator;
342     pEventGenerator = new EventGenerator(pAudioOut->SampleRate());
343    
344     dmsg(1,("Starting disk thread..."));
345     pDiskThread->StartThread();
346     dmsg(1,("OK\n"));
347    
348 iliev 2298 bool printEqInfo = true;
349 iliev 2012 for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
350     if (!iterVoice->pDiskThread) {
351     dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
352     exit(EXIT_FAILURE);
353     }
354 iliev 2298
355     iterVoice->CreateEq();
356    
357     if(printEqInfo) {
358     iterVoice->PrintEqInfo();
359     printEqInfo = false;
360     }
361 iliev 2012 }
362     pVoicePool->clear();
363 schoenebeck 2121
364     // (re)create dedicated voice audio buffers
365     //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
366     if (pDedicatedVoiceChannelLeft) delete pDedicatedVoiceChannelLeft;
367     if (pDedicatedVoiceChannelRight) delete pDedicatedVoiceChannelRight;
368     pDedicatedVoiceChannelLeft = new AudioChannel(0, MaxSamplesPerCycle);
369     pDedicatedVoiceChannelRight = new AudioChannel(1, MaxSamplesPerCycle);
370 iliev 2012 }
371 schoenebeck 2410
372     // Implementattion for abstract method derived from Engine.
373 schoenebeck 2434 virtual void ReconnectAudioOutputDevice() OVERRIDE {
374 schoenebeck 2410 SuspendAll();
375     if (pAudioOutputDevice) Connect(pAudioOutputDevice);
376     ResumeAll();
377     }
378 iliev 2012
379     /**
380     * Similar to @c Disable() but this method additionally kills all voices
381     * and disk streams and blocks until all voices and disk streams are actually
382     * killed / deleted.
383     *
384     * @e Note: only the original calling thread is able to re-enable the
385     * engine afterwards by calling @c ResumeAll() later on!
386     */
387     virtual void SuspendAll() {
388     dmsg(2,("Engine: Suspending all ...\n"));
389     // stop the engine, so we can safely modify the engine's
390     // data structures from this foreign thread
391     DisableAndLock();
392     // we could also use the respective class member variable here,
393     // but this is probably safer and cleaner
394     int iPendingStreamDeletions = 0;
395     // kill all voices on all engine channels the *die hard* way
396     for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
397     EngineChannelBase<V, R, I>* pEngineChannel =
398     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannel]);
399    
400     iPendingStreamDeletions += pEngineChannel->KillAllVoicesImmediately();
401     }
402     // wait until all streams were actually deleted by the disk thread
403     while (iPendingStreamDeletions) {
404     while (
405     iPendingStreamDeletions &&
406     pDiskThread->AskForDeletedStream() != Stream::INVALID_HANDLE
407     ) iPendingStreamDeletions--;
408     if (!iPendingStreamDeletions) break;
409     usleep(10000); // sleep for 10ms
410     }
411     dmsg(2,("EngineBase: Everything suspended.\n"));
412     }
413    
414     /**
415     * At the moment same as calling @c Enable() directly, but this might
416     * change in future, so better call this method as counterpart to
417     * @c SuspendAll() instead of @c Enable() !
418     */
419     virtual void ResumeAll() { Enable(); }
420    
421     /**
422     * Order the engine to stop rendering audio for the given region.
423     * Additionally this method will block until all voices and their disk
424     * streams associated with that region are actually killed / deleted, so
425     * one can i.e. safely modify the region with an instrument editor after
426     * returning from this method.
427     *
428     * @param pRegion - region the engine shall stop using
429     */
430     virtual void Suspend(RR* pRegion) {
431     dmsg(2,("EngineBase: Suspending Region %x ...\n",pRegion));
432 persson 2427 {
433     LockGuard lock(SuspendedRegionsMutex);
434     SuspensionChangeOngoing.Set(true);
435     pPendingRegionSuspension = pRegion;
436     SuspensionChangeOngoing.WaitAndUnlockIf(true);
437     }
438 iliev 2012 dmsg(2,("EngineBase: Region %x suspended.",pRegion));
439     }
440    
441     /**
442     * Orders the engine to resume playing back the given region, previously
443     * suspended with @c Suspend() .
444     *
445     * @param pRegion - region the engine shall be allowed to use again
446     */
447     virtual void Resume(RR* pRegion) {
448     dmsg(2,("EngineBase: Resuming Region %x ...\n",pRegion));
449 persson 2427 {
450     LockGuard lock(SuspendedRegionsMutex);
451     SuspensionChangeOngoing.Set(true);
452     pPendingRegionResumption = pRegion;
453     SuspensionChangeOngoing.WaitAndUnlockIf(true);
454     }
455 iliev 2012 dmsg(2,("EngineBase: Region %x resumed.\n",pRegion));
456     }
457    
458     virtual void ResetSuspendedRegions() {
459     SuspendedRegions.clear();
460     iPendingStreamDeletions = 0;
461     pPendingRegionSuspension = pPendingRegionResumption = NULL;
462     SuspensionChangeOngoing.Set(false);
463     }
464    
465     /**
466     * Called by the engine's (audio) thread once per cycle to process requests
467     * from the outer world to suspend or resume a given @c gig::Region .
468     */
469     virtual void ProcessSuspensionsChanges() {
470     // process request for suspending one region
471     if (pPendingRegionSuspension) {
472     // kill all voices on all engine channels that use this region
473     for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
474     EngineChannelBase<V, R, I>* pEngineChannel =
475     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannel]);
476     SuspensionVoiceHandler handler(pPendingRegionSuspension);
477     pEngineChannel->ProcessActiveVoices(&handler);
478     iPendingStreamDeletions += handler.PendingStreamDeletions;
479     }
480     // make sure the region is not yet on the list
481     bool bAlreadySuspended = false;
482     RootRegionIterator iter = SuspendedRegions.first();
483     RootRegionIterator end = SuspendedRegions.end();
484     for (; iter != end; ++iter) { // iterate through all suspended regions
485     if (*iter == pPendingRegionSuspension) { // found
486     bAlreadySuspended = true;
487     dmsg(1,("EngineBase: attempt to suspend an already suspended region !!!\n"));
488     break;
489     }
490     }
491     if (!bAlreadySuspended) {
492     // put the region on the list of suspended regions
493     RootRegionIterator iter = SuspendedRegions.allocAppend();
494     if (iter) {
495     *iter = pPendingRegionSuspension;
496     } else std::cerr << "EngineBase: Could not suspend Region, list is full. This is a bug!!!\n" << std::flush;
497     }
498     // free request slot for next caller (and to make sure that
499     // we're not going to process the same request in the next cycle)
500     pPendingRegionSuspension = NULL;
501     // if no disk stream deletions are pending, awaken other side, as
502     // we're done in this case
503     if (!iPendingStreamDeletions) SuspensionChangeOngoing.Set(false);
504     }
505    
506     // process request for resuming one region
507     if (pPendingRegionResumption) {
508     // remove region from the list of suspended regions
509     RootRegionIterator iter = SuspendedRegions.first();
510     RootRegionIterator end = SuspendedRegions.end();
511     for (; iter != end; ++iter) { // iterate through all suspended regions
512     if (*iter == pPendingRegionResumption) { // found
513     SuspendedRegions.free(iter);
514     break; // done
515     }
516     }
517     // free request slot for next caller
518     pPendingRegionResumption = NULL;
519     // awake other side as we're done
520     SuspensionChangeOngoing.Set(false);
521     }
522     }
523    
524     /**
525     * Called by the engine's (audio) thread once per cycle to check if
526     * streams of voices that were killed due to suspension request have
527     * finally really been deleted by the disk thread.
528     */
529     virtual void ProcessPendingStreamDeletions() {
530     if (!iPendingStreamDeletions) return;
531     //TODO: or shall we better store a list with stream handles instead of a scalar amount of streams to be deleted? might be safer
532     while (
533     iPendingStreamDeletions &&
534     pDiskThread->AskForDeletedStream() != Stream::INVALID_HANDLE
535     ) iPendingStreamDeletions--;
536     // just for safety ...
537     while (pDiskThread->AskForDeletedStream() != Stream::INVALID_HANDLE);
538     // now that all disk streams are deleted, awake other side as
539     // we're finally done with suspending the requested region
540     if (!iPendingStreamDeletions) SuspensionChangeOngoing.Set(false);
541     }
542    
543     /**
544     * Returns @c true if the given region is currently set to be suspended
545     * from being used, @c false otherwise.
546     */
547     virtual bool RegionSuspended(RR* pRegion) {
548     if (SuspendedRegions.isEmpty()) return false;
549     //TODO: or shall we use a sorted container instead of the RTList? might be faster ... or trivial ;-)
550     RootRegionIterator iter = SuspendedRegions.first();
551     RootRegionIterator end = SuspendedRegions.end();
552     for (; iter != end; ++iter) // iterate through all suspended regions
553     if (*iter == pRegion) return true;
554     return false;
555     }
556    
557     // implementation of abstract method derived from class 'LinuxSampler::RegionPools'
558     virtual Pool<R*>* GetRegionPool(int index) {
559     if (index < 0 || index > 1) throw Exception("Index out of bounds");
560     return pRegionPool[index];
561     }
562    
563     // implementation of abstract method derived from class 'LinuxSampler::VoicePool'
564     virtual Pool<V>* GetVoicePool() { return pVoicePool; }
565    
566     D* GetDiskThread() { return pDiskThread; }
567    
568     //friend class EngineChannelBase<V, R, I>;
569    
570 persson 2127 static IM instruments;
571    
572 iliev 2012 protected:
573     class SuspensionVoiceHandler : public MidiKeyboardManager<V>::VoiceHandler {
574     public:
575     int PendingStreamDeletions;
576     RR* pPendingRegionSuspension;
577 schoenebeck 2434
578 iliev 2012 SuspensionVoiceHandler(RR* pPendingRegionSuspension) {
579     PendingStreamDeletions = 0;
580     this->pPendingRegionSuspension = pPendingRegionSuspension;
581     }
582    
583 schoenebeck 2434 virtual bool Process(MidiKey* pMidiKey) OVERRIDE {
584 iliev 2012 VoiceIterator itVoice = pMidiKey->pActiveVoices->first();
585     // if current key is not associated with this region, skip this key
586     if (itVoice->GetRegion()->GetParent() != pPendingRegionSuspension) return false;
587    
588     return true;
589     }
590    
591 schoenebeck 2434 virtual void Process(VoiceIterator& itVoice) OVERRIDE {
592 iliev 2012 // request a notification from disk thread side for stream deletion
593     const Stream::Handle hStream = itVoice->KillImmediately(true);
594     if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream
595     PendingStreamDeletions++;
596     }
597     //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
598     }
599     };
600    
601     Pool<R*>* pRegionPool[2]; ///< Double buffered pool, used by the engine channels to keep track of regions in use.
602     int MinFadeOutSamples; ///< The number of samples needed to make an instant fade out (e.g. for voice stealing) without leading to clicks.
603     D* pDiskThread;
604    
605     int ActiveVoiceCountTemp; ///< number of currently active voices (for internal usage, will be used for incrementation)
606     VoiceIterator itLastStolenVoice; ///< Only for voice stealing: points to the last voice which was theft in current audio fragment, NULL otherwise.
607     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.
608     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.
609     VoiceIterator itLastStolenVoiceGlobally; ///< Same as itLastStolenVoice, but engine globally
610     RTList<uint>::Iterator iuiLastStolenKeyGlobally; ///< Same as iuiLastStolenKey, but engine globally
611     RTList<Event>* pVoiceStealingQueue; ///< All voice-launching events which had to be postponed due to free voice shortage.
612     Mutex ResetInternalMutex; ///< Mutex to protect the ResetInternal function for concurrent usage (e.g. by the lscp and instrument loader threads).
613     int iMaxDiskStreams;
614    
615     /**
616     * Dispatch and handle all events in this audio fragment for the given
617     * engine channel.
618     *
619     * @param pEngineChannel - engine channel on which events should be
620     * processed
621     * @param Samples - amount of sample points to be processed in
622     * this audio fragment cycle
623     */
624     void ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
625     // get all events from the engine channels's input event queue which belong to the current fragment
626     // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
627     AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
628     pChannel->ImportEvents(Samples);
629    
630     // process events
631     {
632     RTList<Event>::Iterator itEvent = pChannel->pEvents->first();
633     RTList<Event>::Iterator end = pChannel->pEvents->end();
634     for (; itEvent != end; ++itEvent) {
635     switch (itEvent->Type) {
636     case Event::type_note_on:
637     dmsg(5,("Engine: Note on received\n"));
638     ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
639     break;
640     case Event::type_note_off:
641     dmsg(5,("Engine: Note off received\n"));
642     ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
643     break;
644     case Event::type_control_change:
645     dmsg(5,("Engine: MIDI CC received\n"));
646     ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
647     break;
648     case Event::type_pitchbend:
649     dmsg(5,("Engine: Pitchbend received\n"));
650     ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);
651     break;
652     }
653     }
654     }
655    
656     // reset voice stealing for the next engine channel (or next audio fragment)
657     itLastStolenVoice = VoiceIterator();
658     itLastStolenVoiceGlobally = VoiceIterator();
659     iuiLastStolenKey = RTList<uint>::Iterator();
660     iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
661     pLastStolenChannel = NULL;
662     }
663    
664     /**
665     * Will be called by LaunchVoice() method in case there are no free
666     * voices left. This method will select and kill one old voice for
667     * voice stealing and postpone the note-on event until the selected
668     * voice actually died.
669     *
670     * @param pEngineChannel - engine channel on which this event occured on
671     * @param itNoteOnEvent - key, velocity and time stamp of the event
672     * @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
673     */
674     int StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
675     if (VoiceSpawnsLeft <= 0) {
676     dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
677     return -1;
678     }
679    
680     EngineChannelBase<V, R, I>* pEngineChn = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
681    
682     if (!pEventPool->poolIsEmpty()) {
683    
684     if(!pEngineChn->StealVoice(itNoteOnEvent, &itLastStolenVoice, &iuiLastStolenKey)) {
685     --VoiceSpawnsLeft;
686     return 0;
687     }
688    
689     // if we couldn't steal a voice from the same engine channel then
690     // steal oldest voice on the oldest key from any other engine channel
691     // (the smaller engine channel number, the higher priority)
692     EngineChannelBase<V, R, I>* pSelectedChannel;
693     int iChannelIndex;
694     VoiceIterator itSelectedVoice;
695    
696     // select engine channel
697     if (pLastStolenChannel) {
698     pSelectedChannel = pLastStolenChannel;
699     iChannelIndex = pSelectedChannel->iEngineIndexSelf;
700     } else { // pick the engine channel followed by this engine channel
701     iChannelIndex = (pEngineChn->iEngineIndexSelf + 1) % engineChannels.size();
702     pSelectedChannel = static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannelIndex]);
703     }
704    
705     // if we already stole in this fragment, try to proceed on same key
706     if (this->itLastStolenVoiceGlobally) {
707     itSelectedVoice = this->itLastStolenVoiceGlobally;
708     do {
709     ++itSelectedVoice;
710     } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
711     }
712    
713     #if CONFIG_DEVMODE
714     EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
715     #endif // CONFIG_DEVMODE
716    
717     // did we find a 'stealable' voice?
718     if (itSelectedVoice && itSelectedVoice->IsStealable()) {
719     // remember which voice we stole, so we can simply proceed on next voice stealing
720     this->itLastStolenVoiceGlobally = itSelectedVoice;
721     } else while (true) { // iterate through engine channels
722     // get (next) oldest key
723     RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
724     this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
725     while (iuiSelectedKey) {
726     MidiKey* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
727     itSelectedVoice = pSelectedKey->pActiveVoices->first();
728     // proceed iterating if voice was created in this fragment cycle
729     while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
730     // found a "stealable" voice ?
731     if (itSelectedVoice && itSelectedVoice->IsStealable()) {
732     // remember which voice on which key on which engine channel we stole, so we can simply proceed on next voice stealing
733     this->iuiLastStolenKeyGlobally = iuiSelectedKey;
734     this->itLastStolenVoiceGlobally = itSelectedVoice;
735     this->pLastStolenChannel = pSelectedChannel;
736     goto stealable_voice_found; // selection succeeded
737     }
738     ++iuiSelectedKey; // get next key on current engine channel
739     }
740     // get next engine channel
741     iChannelIndex = (iChannelIndex + 1) % engineChannels.size();
742     pSelectedChannel = static_cast<EngineChannelBase<V, R, I>*>(engineChannels[iChannelIndex]);
743    
744     #if CONFIG_DEVMODE
745     if (pSelectedChannel == pBegin) {
746     dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
747     dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
748     dmsg(1,("Exiting.\n"));
749     exit(-1);
750     }
751     #endif // CONFIG_DEVMODE
752     }
753    
754     // jump point if a 'stealable' voice was found
755     stealable_voice_found:
756    
757     #if CONFIG_DEVMODE
758     if (!itSelectedVoice->IsActive()) {
759     dmsg(1,("EngineBase: ERROR, tried to steal a voice which was not active !!!\n"));
760     return -1;
761     }
762     #endif // CONFIG_DEVMODE
763    
764     // now kill the selected voice
765     itSelectedVoice->Kill(itNoteOnEvent);
766    
767     --VoiceSpawnsLeft;
768    
769     return 0; // success
770     }
771     else {
772     dmsg(1,("Event pool emtpy!\n"));
773     return -1;
774     }
775     }
776    
777     void HandleInstrumentChanges() {
778     bool instrumentChanged = false;
779     for (int i = 0; i < engineChannels.size(); i++) {
780     EngineChannelBase<V, R, I>* pEngineChannel =
781     static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
782    
783     // as we're going to (carefully) write some status to the
784     // synchronized struct, we cast away the const
785     InstrumentChangeCmd<R, I>& cmd =
786     const_cast<InstrumentChangeCmd<R, I>&>(pEngineChannel->InstrumentChangeCommandReader.Lock());
787    
788     pEngineChannel->pRegionsInUse = cmd.pRegionsInUse;
789     pEngineChannel->pRegionsInUse->clear();
790    
791     if (cmd.bChangeInstrument) {
792     // change instrument
793     dmsg(5,("Engine: instrument change command received\n"));
794     cmd.bChangeInstrument = false;
795     pEngineChannel->pInstrument = cmd.pInstrument;
796     instrumentChanged = true;
797    
798     pEngineChannel->MarkAllActiveVoicesAsOrphans();
799     }
800     }
801    
802     if (instrumentChanged) {
803     //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
804     ResetSuspendedRegions();
805     }
806     }
807    
808     /**
809     * Render all 'normal' voices (that is voices which were not stolen in
810     * this fragment) on the given engine channel.
811     *
812     * @param pEngineChannel - engine channel on which audio should be
813     * rendered
814     * @param Samples - amount of sample points to be rendered in
815     * this audio fragment cycle
816     */
817     void RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
818     #if !CONFIG_PROCESS_MUTED_CHANNELS
819     if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
820     #endif
821    
822     EngineChannelBase<V, R, I>* pChannel =
823     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
824     pChannel->RenderActiveVoices(Samples);
825    
826     ActiveVoiceCountTemp += pEngineChannel->GetVoiceCount();
827     }
828    
829     /**
830     * Render all stolen voices (only voices which were stolen in this
831     * fragment) on the given engine channel. Stolen voices are rendered
832     * after all normal voices have been rendered; this is needed to render
833     * audio of those voices which were selected for voice stealing until
834     * the point were the stealing (that is the take over of the voice)
835     * actually happened.
836     *
837     * @param pEngineChannel - engine channel on which audio should be
838     * rendered
839     * @param Samples - amount of sample points to be rendered in
840     * this audio fragment cycle
841     */
842     void RenderStolenVoices(uint Samples) {
843     RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
844     RTList<Event>::Iterator end = pVoiceStealingQueue->end();
845     for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
846     EngineChannelBase<V, R, I>* pEngineChannel =
847     static_cast<EngineChannelBase<V, R, I>*>(itVoiceStealEvent->pEngineChannel);;
848     if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
849     PoolVoiceIterator itNewVoice =
850     LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
851     if (itNewVoice) {
852     itNewVoice->Render(Samples);
853     if (itNewVoice->IsActive()) { // still active
854     *(pEngineChannel->pRegionsInUse->allocAppend()) = itNewVoice->GetRegion();
855     ActiveVoiceCountTemp++;
856     pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);
857    
858     if (itNewVoice->PlaybackState == Voice::playback_state_disk) {
859     if (itNewVoice->DiskStreamRef.State != Stream::state_unused) {
860     pEngineChannel->SetDiskStreamCount(pEngineChannel->GetDiskStreamCount() + 1);
861     }
862     }
863     } else { // voice reached end, is now inactive
864     pEngineChannel->FreeVoice(itNewVoice); // remove voice from the list of active voices
865     }
866     }
867     else dmsg(1,("EngineBase: ERROR, voice stealing didn't work out!\n"));
868    
869     // we need to clear the key's event list explicitly here in case key was never active
870     MidiKey* pKey = &pEngineChannel->pMIDIKeyInfo[itVoiceStealEvent->Param.Note.Key];
871     pKey->VoiceTheftsQueued--;
872     if (!pKey->Active && !pKey->VoiceTheftsQueued) pKey->pEvents->clear();
873     }
874     }
875    
876     /**
877     * Free all keys which have turned inactive in this audio fragment, from
878     * the list of active keys and clear all event lists on that engine
879     * channel.
880     *
881     * @param pEngineChannel - engine channel to cleanup
882     */
883     void PostProcess(EngineChannel* pEngineChannel) {
884     EngineChannelBase<V, R, I>* pChannel =
885     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
886     pChannel->FreeAllInactiveKyes();
887    
888     // empty the engine channel's own event lists
889     pChannel->ClearEventLists();
890     }
891    
892 schoenebeck 2121 /**
893     * Process MIDI control change events with hard coded behavior,
894     * that is controllers whose behavior is defined independently
895     * of the actual sampler engine type and instrument.
896     *
897     * @param pEngineChannel - engine channel on which the MIDI CC event was received
898     * @param itControlChangeEvent - the actual MIDI CC event
899     */
900 iliev 2012 void ProcessHardcodedControllers (
901     EngineChannel* pEngineChannel,
902     Pool<Event>::Iterator& itControlChangeEvent
903     ) {
904     EngineChannelBase<V, R, I>* pChannel =
905     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
906    
907     switch (itControlChangeEvent->Param.CC.Controller) {
908     case 5: { // portamento time
909     pChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
910     break;
911     }
912 schoenebeck 2121 case 6: { // data entry (currently only used for RPN and NRPN controllers)
913     //dmsg(1,("DATA ENTRY %d\n", itControlChangeEvent->Param.CC.Value));
914     if (pChannel->GetMidiRpnController() >= 0) { // RPN controller number was sent previously ...
915     dmsg(4,("Guess it's an RPN ...\n"));
916     if (pChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
917     int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
918     // limit to +- two octaves for now
919     transpose = RTMath::Min(transpose, 24);
920     transpose = RTMath::Max(transpose, -24);
921     pChannel->GlobalTranspose = transpose;
922     // workaround, so we won't have hanging notes
923     pChannel->ReleaseAllVoices(itControlChangeEvent);
924     }
925     // to prevent other MIDI CC #6 messages to be misenterpreted as RPN controller data
926     pChannel->ResetMidiRpnController();
927     } else if (pChannel->GetMidiNrpnController() >= 0) { // NRPN controller number was sent previously ...
928     dmsg(4,("Guess it's an NRPN ...\n"));
929     const int NrpnCtrlMSB = pChannel->GetMidiNrpnController() >> 8;
930     const int NrpnCtrlLSB = pChannel->GetMidiNrpnController() & 0xff;
931     dmsg(4,("NRPN MSB=%d LSB=%d Data=%d\n", NrpnCtrlMSB, NrpnCtrlLSB, itControlChangeEvent->Param.CC.Value));
932     switch (NrpnCtrlMSB) {
933     case 0x1a: { // volume level of note (Roland GS NRPN)
934     const uint note = NrpnCtrlLSB;
935     const uint vol = itControlChangeEvent->Param.CC.Value;
936     dmsg(4,("Note Volume NRPN received (note=%d,vol=%d).\n", note, vol));
937     if (note < 128 && vol < 128)
938     pChannel->pMIDIKeyInfo[note].Volume = VolumeCurve[vol];
939     break;
940     }
941     case 0x1c: { // panpot of note (Roland GS NRPN)
942     const uint note = NrpnCtrlLSB;
943     const uint pan = itControlChangeEvent->Param.CC.Value;
944     dmsg(4,("Note Pan NRPN received (note=%d,pan=%d).\n", note, pan));
945     if (note < 128 && pan < 128) {
946     pChannel->pMIDIKeyInfo[note].PanLeft = PanCurve[128 - pan];
947     pChannel->pMIDIKeyInfo[note].PanRight = PanCurve[pan];
948     }
949     break;
950     }
951     case 0x1d: { // reverb send of note (Roland GS NRPN)
952     const uint note = NrpnCtrlLSB;
953     const float reverb = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
954     dmsg(4,("Note Reverb Send NRPN received (note=%d,send=%d).\n", note, reverb));
955     if (note < 128)
956     pChannel->pMIDIKeyInfo[note].ReverbSend = reverb;
957     break;
958     }
959     case 0x1e: { // chorus send of note (Roland GS NRPN)
960     const uint note = NrpnCtrlLSB;
961     const float chorus = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
962     dmsg(4,("Note Chorus Send NRPN received (note=%d,send=%d).\n", note, chorus));
963     if (note < 128)
964     pChannel->pMIDIKeyInfo[note].ChorusSend = chorus;
965     break;
966     }
967     }
968     // to prevent other MIDI CC #6 messages to be misenterpreted as NRPN controller data
969     pChannel->ResetMidiNrpnController();
970 iliev 2012 }
971     break;
972     }
973     case 7: { // volume
974     //TODO: not sample accurate yet
975     pChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
976     pChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
977     break;
978     }
979     case 10: { // panpot
980     //TODO: not sample accurate yet
981     pChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;
982     break;
983     }
984     case 64: { // sustain
985     if (itControlChangeEvent->Param.CC.Value >= 64 && !pChannel->SustainPedal) {
986     dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
987     pChannel->SustainPedal = true;
988     pChannel->listeners.PreProcessSustainPedalDown();
989    
990     #if !CONFIG_PROCESS_MUTED_CHANNELS
991     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
992     pChannel->listeners.PostProcessSustainPedalDown();
993     return;
994     }
995     #endif
996    
997     pChannel->ProcessSustainPedalDown(itControlChangeEvent);
998     pChannel->listeners.PostProcessSustainPedalDown();
999     }
1000     if (itControlChangeEvent->Param.CC.Value < 64 && pChannel->SustainPedal) {
1001     dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1002     pChannel->SustainPedal = false;
1003     pChannel->listeners.PreProcessSustainPedalUp();
1004    
1005     #if !CONFIG_PROCESS_MUTED_CHANNELS
1006     if (pChannel->GetMute()) { // skip if sampler channel is muted
1007     pChannel->listeners.PostProcessSustainPedalUp();
1008     return;
1009     }
1010     #endif
1011    
1012     pChannel->ProcessSustainPedalUp(itControlChangeEvent);
1013     pChannel->listeners.PostProcessSustainPedalUp();
1014     }
1015     break;
1016     }
1017     case 65: { // portamento on / off
1018     const bool bPortamento = itControlChangeEvent->Param.CC.Value >= 64;
1019     if (bPortamento != pChannel->PortamentoMode)
1020     KillAllVoices(pChannel, itControlChangeEvent);
1021     pChannel->PortamentoMode = bPortamento;
1022     break;
1023     }
1024     case 66: { // sostenuto
1025     if (itControlChangeEvent->Param.CC.Value >= 64 && !pChannel->SostenutoPedal) {
1026     dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1027     pChannel->SostenutoPedal = true;
1028     pChannel->listeners.PreProcessSostenutoPedalDown();
1029    
1030     #if !CONFIG_PROCESS_MUTED_CHANNELS
1031     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1032     pChannel->listeners.PostProcessSostenutoPedalDown();
1033     return;
1034     }
1035     #endif
1036    
1037     pChannel->ProcessSostenutoPedalDown();
1038     pChannel->listeners.PostProcessSostenutoPedalDown();
1039     }
1040     if (itControlChangeEvent->Param.CC.Value < 64 && pChannel->SostenutoPedal) {
1041     dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1042     pChannel->SostenutoPedal = false;
1043     pChannel->listeners.PreProcessSostenutoPedalUp();
1044    
1045     #if !CONFIG_PROCESS_MUTED_CHANNELS
1046     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1047     pChannel->listeners.PostProcessSostenutoPedalUp();
1048     return;
1049     }
1050     #endif
1051    
1052     pChannel->ProcessSostenutoPedalUp(itControlChangeEvent);
1053     pChannel->listeners.PostProcessSostenutoPedalUp();
1054     }
1055     break;
1056     }
1057 schoenebeck 2121 case 98: { // NRPN controller LSB
1058     dmsg(4,("NRPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1059     pEngineChannel->SetMidiNrpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1060     break;
1061     }
1062     case 99: { // NRPN controller MSB
1063     dmsg(4,("NRPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1064     pEngineChannel->SetMidiNrpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1065     break;
1066     }
1067 iliev 2012 case 100: { // RPN controller LSB
1068 schoenebeck 2121 dmsg(4,("RPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1069 iliev 2012 pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1070     break;
1071     }
1072     case 101: { // RPN controller MSB
1073 schoenebeck 2121 dmsg(4,("RPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1074 iliev 2012 pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1075     break;
1076     }
1077    
1078    
1079     // Channel Mode Messages
1080    
1081     case 120: { // all sound off
1082     KillAllVoices(pEngineChannel, itControlChangeEvent);
1083     break;
1084     }
1085     case 121: { // reset all controllers
1086     pChannel->ResetControllers();
1087     break;
1088     }
1089     case 123: { // all notes off
1090     #if CONFIG_PROCESS_ALL_NOTES_OFF
1091     pChannel->ReleaseAllVoices(itControlChangeEvent);
1092     #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1093     break;
1094     }
1095     case 126: { // mono mode on
1096     if (!pChannel->SoloMode)
1097     KillAllVoices(pEngineChannel, itControlChangeEvent);
1098     pChannel->SoloMode = true;
1099     break;
1100     }
1101     case 127: { // poly mode on
1102     if (pChannel->SoloMode)
1103     KillAllVoices(pEngineChannel, itControlChangeEvent);
1104     pChannel->SoloMode = false;
1105     break;
1106     }
1107     }
1108     }
1109    
1110     virtual D* CreateDiskThread() = 0;
1111    
1112     /**
1113     * Assigns and triggers a new voice for the respective MIDI key.
1114     *
1115     * @param pEngineChannel - engine channel on which this event occured on
1116     * @param itNoteOnEvent - key, velocity and time stamp of the event
1117     */
1118     virtual void ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1119     EngineChannelBase<V, R, I>* pChannel =
1120     static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1121    
1122     //HACK: we should better add the transpose value only to the most mandatory places (like for retrieving the region and calculating the tuning), because otherwise voices will unintendedly survive when changing transpose while playing
1123     int k = itNoteOnEvent->Param.Note.Key + pChannel->GlobalTranspose;
1124     if (k < 0 || k > 127) return; //ignore keys outside the key range
1125    
1126     itNoteOnEvent->Param.Note.Key += pChannel->GlobalTranspose;
1127     int vel = itNoteOnEvent->Param.Note.Velocity;
1128    
1129     const int key = itNoteOnEvent->Param.Note.Key;
1130     MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];
1131    
1132     pChannel->listeners.PreProcessNoteOn(key, vel);
1133     #if !CONFIG_PROCESS_MUTED_CHANNELS
1134     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1135     pChannel->listeners.PostProcessNoteOn(key, vel);
1136     return;
1137     }
1138     #endif
1139    
1140     if (!pChannel->pInstrument) {
1141     pChannel->listeners.PostProcessNoteOn(key, vel);
1142     return; // ignore if no instrument loaded
1143     }
1144    
1145     // move note on event to the key's own event list
1146     RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
1147    
1148     // if Solo Mode then kill all already active voices
1149     if (pChannel->SoloMode) {
1150     Pool<uint>::Iterator itYoungestKey = pChannel->pActiveKeys->last();
1151     if (itYoungestKey) {
1152     const int iYoungestKey = *itYoungestKey;
1153     const MidiKey* pOtherKey = &pChannel->pMIDIKeyInfo[iYoungestKey];
1154     if (pOtherKey->Active) {
1155     // get final portamento position of currently active voice
1156     if (pChannel->PortamentoMode) {
1157     VoiceIterator itVoice = pOtherKey->pActiveVoices->last();
1158     if (itVoice) itVoice->UpdatePortamentoPos(itNoteOnEventOnKeyList);
1159     }
1160     // kill all voices on the (other) key
1161     VoiceIterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
1162     VoiceIterator end = pOtherKey->pActiveVoices->end();
1163     for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1164 persson 2115 if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1165 iliev 2012 itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
1166     }
1167     }
1168     }
1169     // set this key as 'currently active solo key'
1170     pChannel->SoloKey = key;
1171     }
1172    
1173     pChannel->ProcessKeySwitchChange(key);
1174    
1175     pKey->KeyPressed = true; // the MIDI key was now pressed down
1176     pKey->Velocity = itNoteOnEventOnKeyList->Param.Note.Velocity;
1177     pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
1178    
1179     // cancel release process of voices on this key if needed
1180     if (pKey->Active && !pChannel->SustainPedal) {
1181     RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
1182     if (itCancelReleaseEvent) {
1183     *itCancelReleaseEvent = *itNoteOnEventOnKeyList; // copy event
1184     itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
1185     }
1186     else dmsg(1,("Event pool emtpy!\n"));
1187     }
1188    
1189     TriggerNewVoices(pEngineChannel, itNoteOnEventOnKeyList);
1190    
1191     // if neither a voice was spawned or postponed then remove note on event from key again
1192     if (!pKey->Active && !pKey->VoiceTheftsQueued)
1193     pKey->pEvents->free(itNoteOnEventOnKeyList);
1194    
1195     if (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f) pChannel->PortamentoPos = (float) key;
1196 persson 2043 if (pKey->pRoundRobinIndex) {
1197     (*pKey->pRoundRobinIndex)++; // counter specific for the key or region
1198     pChannel->RoundRobinIndex++; // common counter for the channel
1199     }
1200 iliev 2012 pChannel->listeners.PostProcessNoteOn(key, vel);
1201     }
1202    
1203     /**
1204     * Allocate and trigger new voice(s) for the key.
1205     */
1206     virtual void TriggerNewVoices (
1207     EngineChannel* pEngineChannel,
1208     RTList<Event>::Iterator& itNoteOnEvent,
1209     bool HandleKeyGroupConflicts = true
1210     ) = 0;
1211    
1212     /**
1213     * Allocate and trigger release voice(s) for the key.
1214     */
1215     virtual void TriggerReleaseVoices (
1216     EngineChannel* pEngineChannel,
1217     RTList<Event>::Iterator& itNoteOffEvent
1218     ) = 0;
1219    
1220     /**
1221     * Releases the voices on the given key if sustain pedal is not pressed.
1222     * If sustain is pressed, the release of the note will be postponed until
1223     * sustain pedal will be released or voice turned inactive by itself (e.g.
1224     * due to completion of sample playback).
1225     *
1226     * @param pEngineChannel - engine channel on which this event occured on
1227     * @param itNoteOffEvent - key, velocity and time stamp of the event
1228     */
1229     virtual void ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
1230     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1231    
1232     int k = itNoteOffEvent->Param.Note.Key + pChannel->GlobalTranspose;
1233     if (k < 0 || k > 127) return; //ignore keys outside the key range
1234    
1235     //HACK: we should better add the transpose value only to the most mandatory places (like for retrieving the region and calculating the tuning), because otherwise voices will unintendedly survive when changing transpose while playing
1236     itNoteOffEvent->Param.Note.Key += pChannel->GlobalTranspose;
1237     int vel = itNoteOffEvent->Param.Note.Velocity;
1238    
1239     const int iKey = itNoteOffEvent->Param.Note.Key;
1240     MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];
1241    
1242     pChannel->listeners.PreProcessNoteOff(iKey, vel);
1243    
1244     #if !CONFIG_PROCESS_MUTED_CHANNELS
1245     if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1246     pChannel->listeners.PostProcessNoteOff(iKey, vel);
1247     return;
1248     }
1249     #endif
1250    
1251     pKey->KeyPressed = false; // the MIDI key was now released
1252    
1253     // move event to the key's own event list
1254     RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
1255    
1256     bool bShouldRelease = pKey->Active && pChannel->ShouldReleaseVoice(itNoteOffEventOnKeyList->Param.Note.Key);
1257    
1258     // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
1259     if (pChannel->SoloMode && pChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
1260     bool bOtherKeysPressed = false;
1261     if (iKey == pChannel->SoloKey) {
1262     pChannel->SoloKey = -1;
1263     // if there's still a key pressed down, respawn a voice (group) on the highest key
1264     for (int i = 127; i > 0; i--) {
1265     MidiKey* pOtherKey = &pChannel->pMIDIKeyInfo[i];
1266     if (pOtherKey->KeyPressed) {
1267     bOtherKeysPressed = true;
1268     // make the other key the new 'currently active solo key'
1269     pChannel->SoloKey = i;
1270     // get final portamento position of currently active voice
1271     if (pChannel->PortamentoMode) {
1272     VoiceIterator itVoice = pKey->pActiveVoices->first();
1273     if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);
1274     }
1275     // create a pseudo note on event
1276     RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
1277     if (itPseudoNoteOnEvent) {
1278     // copy event
1279     *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
1280     // transform event to a note on event
1281     itPseudoNoteOnEvent->Type = Event::type_note_on;
1282     itPseudoNoteOnEvent->Param.Note.Key = i;
1283     itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
1284     // allocate and trigger new voice(s) for the other key
1285     TriggerNewVoices(pChannel, itPseudoNoteOnEvent, false);
1286     // if neither a voice was spawned or postponed then remove note on event from key again
1287     if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
1288     pOtherKey->pEvents->free(itPseudoNoteOnEvent);
1289    
1290     } else dmsg(1,("Could not respawn voice, no free event left\n"));
1291     break; // done
1292     }
1293     }
1294     }
1295     if (bOtherKeysPressed) {
1296     if (pKey->Active) { // kill all voices on this key
1297     bShouldRelease = false; // no need to release, as we kill it here
1298     VoiceIterator itVoiceToBeKilled = pKey->pActiveVoices->first();
1299     VoiceIterator end = pKey->pActiveVoices->end();
1300     for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1301 persson 2115 if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1302 iliev 2012 itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1303     }
1304     }
1305     } else pChannel->PortamentoPos = -1.0f;
1306     }
1307    
1308     // if no solo mode (the usual case) or if solo mode and no other key pressed, then release voices on this key if needed
1309     if (bShouldRelease) {
1310     itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type
1311    
1312     // spawn release triggered voice(s) if needed
1313     if (pKey->ReleaseTrigger && pChannel->pInstrument) {
1314     TriggerReleaseVoices(pChannel, itNoteOffEventOnKeyList);
1315     pKey->ReleaseTrigger = false;
1316     }
1317     }
1318    
1319     // if neither a voice was spawned or postponed on this key then remove note off event from key again
1320     if (!pKey->Active && !pKey->VoiceTheftsQueued)
1321     pKey->pEvents->free(itNoteOffEventOnKeyList);
1322    
1323     pChannel->listeners.PostProcessNoteOff(iKey, vel);
1324     }
1325    
1326     /**
1327     * Reset all voices and disk thread and clear input event queue and all
1328     * control and status variables. This method is protected by a mutex.
1329     */
1330     virtual void ResetInternal() {
1331 persson 2427 LockGuard lock(ResetInternalMutex);
1332 iliev 2012
1333     // make sure that the engine does not get any sysex messages
1334     // while it's reseting
1335     bool sysexDisabled = MidiInputPort::RemoveSysexListener(this);
1336     SetVoiceCount(0);
1337     ActiveVoiceCountMax = 0;
1338    
1339     // reset voice stealing parameters
1340     pVoiceStealingQueue->clear();
1341     itLastStolenVoice = VoiceIterator();
1342     itLastStolenVoiceGlobally = VoiceIterator();
1343     iuiLastStolenKey = RTList<uint>::Iterator();
1344     iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
1345     pLastStolenChannel = NULL;
1346    
1347     // reset all voices
1348     for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
1349     iterVoice->Reset();
1350     }
1351     pVoicePool->clear();
1352    
1353     // reset disk thread
1354     if (pDiskThread) pDiskThread->Reset();
1355    
1356     // delete all input events
1357     pEventQueue->init();
1358     pSysexBuffer->init();
1359     if (sysexDisabled) MidiInputPort::AddSysexListener(this);
1360     }
1361    
1362     /**
1363     * Kills all voices on an engine channel as soon as possible. Voices
1364     * won't get into release state, their volume level will be ramped down
1365     * as fast as possible.
1366     *
1367     * @param pEngineChannel - engine channel on which all voices should be killed
1368     * @param itKillEvent - event which caused this killing of all voices
1369     */
1370     virtual void KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
1371     EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1372     int count = pChannel->KillAllVoices(itKillEvent);
1373     VoiceSpawnsLeft -= count; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
1374     }
1375    
1376     /**
1377     * Allocates and triggers a new voice. This method will usually be
1378     * called by the ProcessNoteOn() method and by the voices itself
1379     * (e.g. to spawn further voices on the same key for layered sounds).
1380     *
1381     * @param pEngineChannel - engine channel on which this event occured on
1382     * @param itNoteOnEvent - key, velocity and time stamp of the event
1383     * @param iLayer - layer index for the new voice (optional - only
1384     * in case of layered sounds of course)
1385     * @param ReleaseTriggerVoice - if new voice is a release triggered voice
1386     * (optional, default = false)
1387     * @param VoiceStealing - if voice stealing should be performed
1388     * when there is no free voice
1389     * (optional, default = true)
1390     * @param HandleKeyGroupConflicts - if voices should be killed due to a
1391     * key group conflict
1392     * @returns pointer to new voice or NULL if there was no free voice or
1393     * if the voice wasn't triggered (for example when no region is
1394     * defined for the given key).
1395     */
1396     virtual PoolVoiceIterator LaunchVoice (
1397     EngineChannel* pEngineChannel,
1398     Pool<Event>::Iterator& itNoteOnEvent,
1399     int iLayer,
1400     bool ReleaseTriggerVoice,
1401     bool VoiceStealing,
1402     bool HandleKeyGroupConflicts
1403     ) = 0;
1404    
1405 iliev 2015 virtual int GetMinFadeOutSamples() { return MinFadeOutSamples; }
1406    
1407 iliev 2027 int InitNewVoice (
1408     EngineChannelBase<V, R, I>* pChannel,
1409     R* pRegion,
1410     Pool<Event>::Iterator& itNoteOnEvent,
1411     Voice::type_t VoiceType,
1412     int iLayer,
1413     int iKeyGroup,
1414     bool ReleaseTriggerVoice,
1415     bool VoiceStealing,
1416     typename Pool<V>::Iterator& itNewVoice
1417     ) {
1418     int key = itNoteOnEvent->Param.Note.Key;
1419     typename MidiKeyboardManager<V>::MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];
1420     if (itNewVoice) {
1421     // launch the new voice
1422     if (itNewVoice->Trigger(pChannel, itNoteOnEvent, pChannel->Pitch, pRegion, VoiceType, iKeyGroup) < 0) {
1423     dmsg(4,("Voice not triggered\n"));
1424     pKey->pActiveVoices->free(itNewVoice);
1425     }
1426     else { // on success
1427     --VoiceSpawnsLeft;
1428     if (!pKey->Active) { // mark as active key
1429     pKey->Active = true;
1430     pKey->itSelf = pChannel->pActiveKeys->allocAppend();
1431     *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
1432     }
1433 persson 2115 if (itNewVoice->Type & Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
1434 iliev 2027 return 0; // success
1435     }
1436     }
1437     else if (VoiceStealing) {
1438     // try to steal one voice
1439     int result = StealVoice(pChannel, itNoteOnEvent);
1440     if (!result) { // voice stolen successfully
1441     // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
1442     RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
1443     if (itStealEvent) {
1444     *itStealEvent = *itNoteOnEvent; // copy event
1445     itStealEvent->Param.Note.Layer = iLayer;
1446     itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
1447     pKey->VoiceTheftsQueued++;
1448     }
1449     else dmsg(1,("Voice stealing queue full!\n"));
1450     }
1451     }
1452    
1453     return -1;
1454     }
1455    
1456 iliev 2012 private:
1457     Pool<V>* pVoicePool; ///< Contains all voices that can be activated.
1458     Pool<RR*> SuspendedRegions;
1459     Mutex SuspendedRegionsMutex;
1460     Condition SuspensionChangeOngoing;
1461     RR* pPendingRegionSuspension;
1462     RR* pPendingRegionResumption;
1463     int iPendingStreamDeletions;
1464     };
1465    
1466     template <class V, class RR, class R, class D, class IM, class I>
1467     IM EngineBase<V, RR, R, D, IM, I>::instruments;
1468    
1469     } // namespace LinuxSampler
1470    
1471     #endif /* __LS_ENGINEBASE_H__ */
1472    

  ViewVC Help
Powered by ViewVC