/[svn]/linuxsampler/trunk/src/engines/EngineChannelBase.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/EngineChannelBase.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2871 by schoenebeck, Sun Apr 10 18:22:23 2016 UTC revision 3073 by schoenebeck, Thu Jan 5 16:04:00 2017 UTC
# Line 5  Line 5 
5   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *
8   *   Copyright (C) 2012-2016 Christian Schoenebeck and Andreas Persson     *   *   Copyright (C) 2012-2017 Christian Schoenebeck and Andreas Persson     *
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   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  *   *   it under the terms of the GNU General Public License as published by  *
# Line 50  namespace LinuxSampler { Line 50  namespace LinuxSampler {
50      };      };
51    
52      template<class V>      template<class V>
53      class VoicePool {      class NotePool {
54          public:          public:
55                /**
56                 * Pool from where Voice objects are allocated from (and freed back to).
57                 */
58              virtual Pool<V>* GetVoicePool() = 0;              virtual Pool<V>* GetVoicePool() = 0;
59    
60                /**
61                 * Pool from where new Note objects are allocated from (and freed back to).
62                 */
63                virtual Pool< Note<V> >* GetNotePool() = 0;
64    
65                /**
66                 * Pool for saving already existing Note object IDs somewhere.
67                 *
68                 * @b IMPORTANT: This pool is @b NOT used for generating any IDs for
69                 * Note objects! The respective Note objective IDs are emitted by
70                 * the Note object pool (see GetNotePool() above).
71                 */
72                virtual Pool<note_id_t>* GetNoteIDPool() = 0;
73      };      };
74    
75      template <class V /* Voice */, class R /* Region */, class I /* Instrument */>      template <class V /* Voice */, class R /* Region */, class I /* Instrument */>
76      class EngineChannelBase: public AbstractEngineChannel, public MidiKeyboardManager<V>, public ResourceConsumer<I> {      class EngineChannelBase: public AbstractEngineChannel, public MidiKeyboardManager<V>, public ResourceConsumer<I> {
77          public:          public:
78                typedef typename RTList< Note<V> >::Iterator NoteIterator;
79              typedef typename RTList<R*>::Iterator RTListRegionIterator;              typedef typename RTList<R*>::Iterator RTListRegionIterator;
80              typedef typename MidiKeyboardManager<V>::MidiKey MidiKey;              typedef typename MidiKeyboardManager<V>::MidiKey MidiKey;
81    
# Line 124  namespace LinuxSampler { Line 142  namespace LinuxSampler {
142                  }                  }
143              }              }
144    
145              virtual void Connect(AudioOutputDevice* pAudioOut) {              virtual void Connect(AudioOutputDevice* pAudioOut) OVERRIDE {
146                  if (pEngine) {                  if (pEngine) {
147                      if (pEngine->pAudioOutputDevice == pAudioOut) return;                      if (pEngine->pAudioOutputDevice == pAudioOut) return;
148                      DisconnectAudioOutputDevice();                      DisconnectAudioOutputDevice();
# Line 163  namespace LinuxSampler { Line 181  namespace LinuxSampler {
181                      bStatusChanged = true;                      bStatusChanged = true;
182                  }                  }
183    
184                  VoicePool<V>* pVoicePool = dynamic_cast<VoicePool<V>*>(pEngine);                  NotePool<V>* pNotePool = dynamic_cast<NotePool<V>*>(pEngine);
185                  MidiKeyboardManager<V>::AllocateActiveVoices(pVoicePool->GetVoicePool());                  MidiKeyboardManager<V>::AllocateActiveNotesLists(
186                  MidiKeyboardManager<V>::AllocateEvents(pEngine->pEventPool);                      pNotePool->GetNotePool(),
187                        pNotePool->GetVoicePool()
188                    );
189                    MidiKeyboardManager<V>::AllocateEventsLists(pEngine->pEventPool);
190    
191                  AudioDeviceChannelLeft  = 0;                  AudioDeviceChannelLeft  = 0;
192                  AudioDeviceChannelRight = 1;                  AudioDeviceChannelRight = 1;
# Line 183  namespace LinuxSampler { Line 204  namespace LinuxSampler {
204                  MidiInputPort::AddSysexListener(pEngine);                  MidiInputPort::AddSysexListener(pEngine);
205              }              }
206    
207              virtual void DisconnectAudioOutputDevice() {              virtual void DisconnectAudioOutputDevice() OVERRIDE {
208                  if (pEngine) { // if clause to prevent disconnect loops                  if (pEngine) { // if clause to prevent disconnect loops
209    
210                      ResetInternal(false/*don't reset engine*/); // 'false' is error prone here, but the danger of recursion with 'true' would be worse, there could be a better solution though                      ResetInternal(false/*don't reset engine*/); // 'false' is error prone here, but the danger of recursion with 'true' would be worse, there could be a better solution though
# Line 206  namespace LinuxSampler { Line 227  namespace LinuxSampler {
227                          delayedEvents.pList = NULL;                          delayedEvents.pList = NULL;
228                      }                      }
229    
230                      MidiKeyboardManager<V>::DeleteActiveVoices();                      MidiKeyboardManager<V>::DeleteActiveNotesLists();
231                      MidiKeyboardManager<V>::DeleteEvents();                      MidiKeyboardManager<V>::DeleteEventsLists();
232                      DeleteGroupEventLists();                      DeleteGroupEventLists();
233    
234                      AudioOutputDevice* oldAudioDevice = pEngine->pAudioOutputDevice;                      AudioOutputDevice* oldAudioDevice = pEngine->pAudioOutputDevice;
# Line 286  namespace LinuxSampler { Line 307  namespace LinuxSampler {
307                  bStatusChanged = true; // status of engine has changed, so set notify flag                  bStatusChanged = true; // status of engine has changed, so set notify flag
308              }              }
309    
310                /**
311                 * Called on sustain pedal up events to check and if required,
312                 * launch release trigger voices on the respective active key.
313                 *
314                 * @param pEngineChannel - engine channel on which this event occurred on
315                 * @param itEvent - release trigger event (contains note number)
316                 */
317                virtual void ProcessReleaseTrigger(RTList<Event>::Iterator& itEvent) OVERRIDE {
318                    if (!pEngine) return;
319                    pEngine->ProcessReleaseTrigger(this, itEvent);
320                }
321    
322              void RenderActiveVoices(uint Samples) {              void RenderActiveVoices(uint Samples) {
323                  RenderVoicesHandler handler(this, Samples);                  RenderVoicesHandler handler(this, Samples);
324                  this->ProcessActiveVoices(&handler);                  this->ProcessActiveVoices(&handler);
# Line 294  namespace LinuxSampler { Line 327  namespace LinuxSampler {
327                  SetDiskStreamCount(handler.StreamCount);                  SetDiskStreamCount(handler.StreamCount);
328              }              }
329    
330                /**
331                 * Called by real-time instrument script functions to schedule a
332                 * new note (new note-on event and a new @c Note object linked to it)
333                 * @a delay microseconds in future.
334                 *
335                 * @b IMPORTANT: for the supplied @a delay to be scheduled
336                 * correctly, the passed @a pEvent must be assigned a valid
337                 * fragment time within the current audio fragment boundaries. That
338                 * fragment time will be used by this method as basis for
339                 * interpreting what "now" acutally is, and thus it will be used as
340                 * basis for calculating the precise scheduling time for @a delay.
341                 * The easiest way to achieve this is by copying a recent event
342                 * which happened within the current audio fragment cycle: i.e. the
343                 * original event which caused calling this method here, or by using
344                 * Event::copyTimefrom() method to only copy the time, without any
345                 * other event data.
346                 *
347                 * @param pEvent - note-on event to be scheduled in future (event
348                 *                 data will be copied)
349                 * @param delay - amount of microseconds in future (from now) when
350                 *                event shall be processed
351                 * @returns unique note ID of scheduled new note, or NULL on error
352                 */
353                note_id_t ScheduleNoteMicroSec(const Event* pEvent, int delay) OVERRIDE {
354                    // add (copied) note-on event into scheduler queue
355                    const event_id_t noteOnEventID = ScheduleEventMicroSec(pEvent, delay);
356                    if (!noteOnEventID) return 0; // error
357                    // get access to (copied) event on the scheduler queue
358                    RTList<Event>::Iterator itEvent = pEvents->fromID(noteOnEventID);
359                    // stick a new note to the (copied) event on the queue
360                    const note_id_t noteID = pEngine->LaunchNewNote(this, &*itEvent);
361                    return noteID;
362                }
363    
364                /**
365                 * Called by real-time instrument script functions to ignore the note
366                 * reflected by given note ID. The note's event will be freed immediately
367                 * to its event pool and this will prevent voices to be launched for the
368                 * note.
369                 *
370                 * NOTE: preventing a note by calling this method works only if the note
371                 * was launched within the current audio fragment cycle.
372                 *
373                 * @param id - unique ID of note to be dropped
374                 */
375                void IgnoreNote(note_id_t id) OVERRIDE {
376                    Pool< Note<V> >* pNotePool =
377                        dynamic_cast<NotePool<V>*>(pEngine)->GetNotePool();
378    
379                    NoteIterator itNote = pNotePool->fromID(id);
380                    if (!itNote) return; // note probably already released
381    
382                    // if the note already got active voices, then it is too late to drop it
383                    if (!itNote->pActiveVoices->isEmpty()) return;
384    
385                    // if the original (note-on) event is not available anymore, then it is too late to drop it
386                    RTList<Event>::Iterator itEvent = pEvents->fromID(itNote->eventID);
387                    if (!itEvent) return;
388    
389                    // drop the note
390                    pNotePool->free(itNote);
391    
392                    // drop the original event
393                    pEvents->free(itEvent);
394                }
395    
396                /**
397                 * Copies the note IDs of all currently active notes on this engine
398                 * channel to the note ID buffer @a dstBuf, and returns the amount
399                 * of note IDs that have been copied to the destination buffer.
400                 *
401                 * @param dstBuf  - destination buffer for note IDs
402                 * @param bufSize - size of destination buffer (as amount of max.
403                 *                  note IDs, not as amount of bytes)
404                 * @returns amount of note IDs that have been copied to buffer
405                 */
406                uint AllNoteIDs(note_id_t* dstBuf, uint bufSize) OVERRIDE {
407                    uint n = 0;
408    
409                    Pool< Note<V> >* pNotePool =
410                        dynamic_cast<NotePool<V>*>(pEngine)->GetNotePool();
411    
412                    RTList<uint>::Iterator iuiKey = this->pActiveKeys->first();
413                    RTList<uint>::Iterator end    = this->pActiveKeys->end();
414                    for(; iuiKey != end; ++iuiKey) {
415                        MidiKey* pKey = &this->pMIDIKeyInfo[*iuiKey];
416                        NoteIterator itNote = pKey->pActiveNotes->first();
417                        for (; itNote; ++itNote) {
418                            if (n >= bufSize) goto done;
419                            dstBuf[n++] = pNotePool->getID(itNote);
420                        }
421                    }
422                    done:
423                    return n;
424                }
425    
426              RTList<R*>* pRegionsInUse;     ///< temporary pointer into the instrument change command, used by the audio thread              RTList<R*>* pRegionsInUse;     ///< temporary pointer into the instrument change command, used by the audio thread
427              I* pInstrument;              I* pInstrument;
428    
# Line 354  namespace LinuxSampler { Line 483  namespace LinuxSampler {
483                      EngineChannelBase<V, R, I>* pChannel;                      EngineChannelBase<V, R, I>* pChannel;
484    
485                      RenderVoicesHandler(EngineChannelBase<V, R, I>* channel, uint samples) :                      RenderVoicesHandler(EngineChannelBase<V, R, I>* channel, uint samples) :
486                          pChannel(channel), Samples(samples), VoiceCount(0), StreamCount(0) { }                          Samples(samples), VoiceCount(0), StreamCount(0), pChannel(channel) { }
487    
488                      virtual void Process(RTListVoiceIterator& itVoice) {                      virtual void Process(RTListVoiceIterator& itVoice) {
489                          // now render current voice                          // now render current voice
# Line 387  namespace LinuxSampler { Line 516  namespace LinuxSampler {
516                  MidiKeyboardManager<V>::Reset();                  MidiKeyboardManager<V>::Reset();
517              }              }
518    
519              virtual void ResetControllers() {              virtual void ResetControllers() OVERRIDE {
520                  AbstractEngineChannel::ResetControllers();                  AbstractEngineChannel::ResetControllers();
521    
522                  MidiKeyboardManager<V>::SustainPedal   = false;                  MidiKeyboardManager<V>::SustainPedal   = false;

Legend:
Removed from v.2871  
changed lines
  Added in v.3073

  ViewVC Help
Powered by ViewVC