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

Diff of /linuxsampler/trunk/src/engines/common/Event.h

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

revision 2611 by schoenebeck, Mon Jun 9 19:20:37 2014 UTC revision 2938 by schoenebeck, Mon Jul 11 17:10:40 2016 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
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 - 2014 Christian Schoenebeck                       *   *   Copyright (C) 2005 - 2016 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   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 26  Line 26 
26    
27  #include "../../common/global.h"  #include "../../common/global.h"
28  #include "../../common/RTMath.h"  #include "../../common/RTMath.h"
29    #include "../../common/RTAVLTree.h"
30    #include "../../common/Pool.h"
31  #include "../EngineChannel.h"  #include "../EngineChannel.h"
32    
33  namespace LinuxSampler {  namespace LinuxSampler {
34    
35      // just symbol prototyping      // just symbol prototyping
36      class Event;      class Event;
37        class SchedulerNode;
38        class ScriptEvent;
39        class ScheduledEvent;
40    
41        /**
42         * Data type used to schedule events sample point accurately both within, as
43         * well as beyond the scope of the current audio fragment cycle. The timing
44         * reflected by this data type is consecutively running for a very long
45         * time. Even with a sample rate of 96 kHz a scheduler time of this data
46         * type will not wrap before 6 million years. So in practice such time
47         * stamps are unique and will not repeat (unless the EventGenerator is
48         * reset).
49         */
50        typedef uint64_t sched_time_t;
51    
52      /**      /**
53       * Generates Event objects and is responsible for resolving the position       * Generates Event objects and is responsible for resolving the position
# Line 43  namespace LinuxSampler { Line 59  namespace LinuxSampler {
59              void UpdateFragmentTime(uint SamplesToProcess);              void UpdateFragmentTime(uint SamplesToProcess);
60              Event CreateEvent();              Event CreateEvent();
61              Event CreateEvent(int32_t FragmentPos);              Event CreateEvent(int32_t FragmentPos);
62    
63                template<typename T>
64                void scheduleAheadMicroSec(RTAVLTree<T>& queue, T& node, int32_t fragmentPosBase, uint64_t microseconds);
65    
66                RTList<ScheduledEvent>::Iterator popNextScheduledEvent(RTAVLTree<ScheduledEvent>& queue, Pool<ScheduledEvent>& pool, sched_time_t end);
67                RTList<ScriptEvent>::Iterator popNextScheduledScriptEvent(RTAVLTree<ScriptEvent>& queue, Pool<ScriptEvent>& pool, sched_time_t end);
68    
69                /**
70                 * Returns the scheduler time for the first sample point of the next
71                 * audio fragment cycle.
72                 */
73                sched_time_t schedTimeAtCurrentFragmentEnd() const {
74                    return uiTotalSamplesProcessed + uiSamplesProcessed;
75                }
76    
77          protected:          protected:
78              typedef RTMath::time_stamp_t time_stamp_t;              typedef RTMath::time_stamp_t time_stamp_t;
79              inline int32_t ToFragmentPos(time_stamp_t TimeStamp) {              inline int32_t ToFragmentPos(time_stamp_t TimeStamp) {
# Line 57  namespace LinuxSampler { Line 88  namespace LinuxSampler {
88                  time_stamp_t end;          ///< Real time stamp of the end of this audio fragment cycle.                  time_stamp_t end;          ///< Real time stamp of the end of this audio fragment cycle.
89                  float        sample_ratio; ///< (Samples per cycle) / (Real time duration of cycle)                  float        sample_ratio; ///< (Samples per cycle) / (Real time duration of cycle)
90              } FragmentTime;              } FragmentTime;
91                sched_time_t uiTotalSamplesProcessed; ///< Total amount of sample points that have been processed since this EventGenerator object has been created. This is used to schedule instrument script events long time ahead in future (that is beyond the scope of the current audio fragment).
92      };      };
93    
94      /**      /**
95         * Unique numeric ID of an event which can be used to retrieve access to
96         * the actual @c Event object. Once the event associated with a certain ID
97         * was released (back to its event pool), this numeric ID becomes invalid
98         * and Pool< Event >::fromID() will detect this circumstance and will
99         * return an invalid Iterator, and thus will prevent you from misusing an
100         * event which no longer "exists".
101         *
102         * Note that an @c Event object usually just "exists" for exactly on audio
103         * fragment cycle: that is it exists right from the beginning of the audio
104         * fragment cycle where it was caused (i.e. where its MIDI data was
105         * received by the respective engine channel) and will disappear
106         * automatically at the end of that audio fragment cycle.
107         */
108        typedef pool_element_id_t event_id_t;
109    
110        /**
111         * Unique numeric ID of a note which can be used to retrieve access to the
112         * actual @c Note object. Once the note associated with a certain ID was
113         * released (back to its note pool), this numeric ID becomes invalid and
114         * Pool< Note >::fromID() will detect this circumstance and will return
115         * an invalid Iterator, and thus will prevent you from misusing a note
116         * which no longer is "alive".
117         *
118         * A @c Note object exists right when the respective MIDI note-on event
119         * was received by the respective engine channel, and remains existent
120         * until the caused note and all its voices were finally freed (which might
121         * even be long time after the respective note-off event was received,
122         * depending on the duration of the voice's release stages etc.).
123         */
124        typedef pool_element_id_t note_id_t;
125    
126        /**
127       * Events are usually caused by a MIDI source or an internal modulation       * Events are usually caused by a MIDI source or an internal modulation
128       * controller like LFO or EG. An event should only be created by an       * controller like LFO or EG. An event should only be created by an
129       * EventGenerator!       * EventGenerator!
# Line 70  namespace LinuxSampler { Line 134  namespace LinuxSampler {
134          public:          public:
135              Event(){}              Event(){}
136              enum type_t {              enum type_t {
137                  type_note_on,                  type_note_on, ///< (real) MIDI note-on event
138                  type_note_off,                  type_note_off, ///< (real) MIDI note-off event
139                  type_pitchbend,                  type_pitchbend, ///< MIDI pitch bend wheel change event
140                  type_control_change,                  type_control_change, ///< MIDI CC event
141                  type_sysex,           ///< MIDI system exclusive message                  type_sysex,           ///< MIDI system exclusive message
142                  type_cancel_release,  ///< transformed either from a note-on or sustain-pedal-down event                  type_cancel_release_key, ///< transformed either from a (real) MIDI note-on or sustain-pedal-down event
143                  type_release,         ///< transformed either from a note-off or sustain-pedal-up event                  type_release_key,     ///< transformed either from a (real) MIDI note-off or sustain-pedal-up event
144                    type_release_note,    ///< transformed from a type_stop_note event
145                  type_channel_pressure, ///< a.k.a. aftertouch                  type_channel_pressure, ///< a.k.a. aftertouch
146                  type_note_pressure, ///< polyphonic key pressure (aftertouch)                  type_note_pressure, ///< polyphonic key pressure (aftertouch)
147                    type_play_note, ///< caused by a call to built-in instrument script function play_note()
148                    type_stop_note, ///< caused by a call to built-in instrument script function note_off()
149                    type_note_synth_param, ///< change a note's synthesis parameters (upon real-time instrument script function calls, i.e. change_vol(), change_tune(), change_pan(), etc.)
150              } Type;              } Type;
151                enum synth_param_t {
152                    synth_param_volume,
153                    synth_param_pitch,
154                    synth_param_pan,
155                    synth_param_cutoff,
156                    synth_param_resonance,
157                };
158              union {              union {
159                  /// Note-on and note-off event specifics                  /// Note-on and note-off event specifics
160                  struct _Note {                  struct _Note {
# Line 88  namespace LinuxSampler { Line 163  namespace LinuxSampler {
163                      uint8_t Velocity;    ///< Trigger or release velocity of note-on / note-off event.                      uint8_t Velocity;    ///< Trigger or release velocity of note-on / note-off event.
164                      int8_t  Layer;       ///< Layer index (usually only used if a note-on event has to be postponed, e.g. due to shortage of free voices).                      int8_t  Layer;       ///< Layer index (usually only used if a note-on event has to be postponed, e.g. due to shortage of free voices).
165                      int8_t  ReleaseTrigger; ///< If new voice should be a release triggered voice (actually boolean field and usually only used if a note-on event has to be postponed, e.g. due to shortage of free voices).                      int8_t  ReleaseTrigger; ///< If new voice should be a release triggered voice (actually boolean field and usually only used if a note-on event has to be postponed, e.g. due to shortage of free voices).
166                        note_id_t ID;        ///< Unique numeric ID of the @c Note object associated with this note event.
167                        note_id_t ParentNoteID; ///< If not zero: Unique numeric ID of the parent @c Note object that shall become parent of resulting new Note object of this Event. So this is used to associate a new note with a previous note, i.e. to release the new note once the parent note was released.
168                      void*   pRegion;     ///< Engine specific pointer to instrument region                      void*   pRegion;     ///< Engine specific pointer to instrument region
169                  } Note;                  } Note;
170                  /// Control change event specifics                  /// Control change event specifics
# Line 117  namespace LinuxSampler { Line 194  namespace LinuxSampler {
194                      uint8_t Key;     ///< MIDI note number where key pressure (polyphonic aftertouch) changed.                      uint8_t Key;     ///< MIDI note number where key pressure (polyphonic aftertouch) changed.
195                      uint8_t Value;   ///< New pressure value for note.                      uint8_t Value;   ///< New pressure value for note.
196                  } NotePressure;                  } NotePressure;
197                    ///< Note synthesis parameter change event's specifics (used for real-time instrument script built-in functions which may alter synthesis parameters on note level).
198                    struct _NoteSynthParam {
199                        note_id_t     NoteID;   ///< ID of Note whose voices shall be modified.
200                        synth_param_t Type;     ///< Synthesis parameter which is to be changed.
201                        float         Delta;    ///< The value change that should be applied against the note's current synthesis parameter value.
202                        bool          Relative; ///< Whether @c Delta should be applied relatively against the note's current synthesis parameter value (false means the paramter's current value is simply replaced by Delta).
203                        float         AbsValue; ///< New current absolute value of synthesis parameter (that is after @c Delta being applied).
204                    } NoteSynthParam;
205              } Param;              } Param;
             /// Sampler format specific informations and variables.  
             union {  
                 /// Gigasampler/GigaStudio format specifics.  
                 struct _Gig {  
                     uint8_t DimMask; ///< May be used to override the Dimension zone to be selected for a new voice: each 1 bit means that respective bit shall be overridden by taking the respective bit from DimBits instead.  
                     uint8_t DimBits; ///< Used only in conjunction with DimMask: Dimension bits that shall be selected.  
                 } Gig;  
             } Format;  
206              EngineChannel* pEngineChannel; ///< Pointer to the EngineChannel where this event occured on, NULL means Engine global event (e.g. SysEx message).              EngineChannel* pEngineChannel; ///< Pointer to the EngineChannel where this event occured on, NULL means Engine global event (e.g. SysEx message).
207              MidiInputPort* pMidiInputPort; ///< Pointer to the MIDI input port on which this event occured (NOTE: currently only for global events, that is SysEx messages)              MidiInputPort* pMidiInputPort; ///< Pointer to the MIDI input port on which this event occured (NOTE: currently only for global events, that is SysEx messages)
208    
209                inline void Init() {
210                    Param.Note.ID = 0;
211                    Param.Note.ParentNoteID = 0;
212                    Param.NoteSynthParam.NoteID = 0;
213                }
214              inline int32_t FragmentPos() {              inline int32_t FragmentPos() {
215                  if (iFragmentPos >= 0) return iFragmentPos;                  if (iFragmentPos >= 0) return iFragmentPos;
216                  iFragmentPos = pEventGenerator->ToFragmentPos(TimeStamp);                  iFragmentPos = pEventGenerator->ToFragmentPos(TimeStamp);
# Line 138  namespace LinuxSampler { Line 220  namespace LinuxSampler {
220              inline void ResetFragmentPos() {              inline void ResetFragmentPos() {
221                  iFragmentPos = -1;                  iFragmentPos = -1;
222              }              }
223                inline void CopyTimeFrom(const Event& other) {
224                    TimeStamp = other.TimeStamp;
225                    iFragmentPos = other.iFragmentPos;
226                }
227          protected:          protected:
228              typedef EventGenerator::time_stamp_t time_stamp_t;              typedef EventGenerator::time_stamp_t time_stamp_t;
229              Event(EventGenerator* pGenerator, EventGenerator::time_stamp_t Time);              Event(EventGenerator* pGenerator, EventGenerator::time_stamp_t Time);
# Line 149  namespace LinuxSampler { Line 235  namespace LinuxSampler {
235              int32_t         iFragmentPos;    ///< Position in the current fragment this event refers to.              int32_t         iFragmentPos;    ///< Position in the current fragment this event refers to.
236      };      };
237    
238        /**
239         * Used to sort timing relevant objects (i.e. events) into timing/scheduler
240         * queue. This class is just intended as base class and should be derived
241         * for its actual purpose (for the precise data type being scheduled).
242         */
243        class SchedulerNode : public RTAVLNode {
244        public:
245            sched_time_t scheduleTime; ///< Time ahead in future (in sample points) when this object shall be processed. This value is compared with EventGenerator's uiTotalSamplesProcessed member variable.
246    
247            /// Required operator implementation for RTAVLTree class.
248            inline bool operator==(const SchedulerNode& other) const {
249                return this->scheduleTime == other.scheduleTime;
250            }
251    
252            /// Required operator implementation for RTAVLTree class.
253            inline bool operator<(const SchedulerNode& other) const {
254                return this->scheduleTime < other.scheduleTime;
255            }
256        };
257    
258        /**
259         * Used to sort delayed MIDI events into a timing/scheduler queue. This
260         * object just contains the timing informations, the actual MIDI event is
261         * pointed by member variable @c itEvent.
262         */
263        class ScheduledEvent : public SchedulerNode {
264        public:
265            Pool<Event>::Iterator itEvent; ///< Points to the actual Event object being scheduled.
266        };
267    
268      class VMEventHandler;      class VMEventHandler;
269      class VMExecContext;      class VMExecContext;
270    
# Line 156  namespace LinuxSampler { Line 272  namespace LinuxSampler {
272       *       *
273       * Encapsulates one execution instance of a real-time instrument script for       * Encapsulates one execution instance of a real-time instrument script for
274       * exactly one script event handler (script event callback).       * exactly one script event handler (script event callback).
275         *
276         * This class derives from SchedulerNode for being able to be sorted efficiently
277         * by the script scheduler if the script was either a) calling the wait()
278         * script function or b) the script was auto suspended by the ScriptVM
279         * because the script was executing for too long. In both cases the
280         * scheduler has to sort the ScriptEvents in its execution queue according
281         * to the precise time the respective script execution instance needs to be
282         * resumed.
283       */       */
284      class ScriptEvent {      class ScriptEvent : public SchedulerNode {
285      public:      public:
286          Event cause; ///< Original external event that triggered this script event (i.e. MIDI note on event, MIDI CC event, etc.).          Event cause; ///< Copy of original external @c Event that triggered this script event (i.e. MIDI note on event, MIDI CC event, etc.).
287          int id; ///< Unique ID of the external event that triggered this cript event.          pool_element_id_t id; ///< Native representation of built-in script variable $EVENT_ID. For scripts' "note" event handler this will reflect the unique ID of the @c Note object, for all other event handlers the unique ID of the original external @c Event object that triggered this script event.
288          VMEventHandler** handlers; ///< The script's event handlers (callbacks) to be processed (NULL terminated list).          VMEventHandler** handlers; ///< The script's event handlers (callbacks) to be processed (NULL terminated list).
289          VMExecContext* execCtx; ///< Script's current execution state (polyphonic variables and execution stack).          VMExecContext* execCtx; ///< Script's current execution state (polyphonic variables and execution stack).
290          int currentHandler; ///< Current index in 'handlers' list above.          int currentHandler; ///< Current index in 'handlers' list above.
291          int executionSlices; ///< Amount of times this script event has been executed by the ScriptVM runner class.          int executionSlices; ///< Amount of times this script event has been executed by the ScriptVM runner class.
292      };      };
293    
294        /**
295         * Insert given @a node into the supplied timing @a queue with a scheduled
296         * timing position given by @a fragmentPosBase and @a microseconds, where
297         * @a microseconds reflects the amount of microseconds in future from "now"
298         * where the node shall be scheduled, and @a fragmentPos identifies the
299         * sample point within the current audio fragment cycle which shall be
300         * interpreted by this method to be "now".
301         *
302         * The meaning of @a fragmentPosBase becomes more important the larger
303         * the audio fragment size, and vice versa it bcomes less important the
304         * smaller the audio fragment size.
305         *
306         * @param queue - destination scheduler queue
307         * @param node - node (i.e. event) to be inserted into the queue
308         * @param fragmentPosBase - sample point in current audio fragment to be "now"
309         * @param microseconds - timing of node from "now" (in microseconds)
310         */
311        template<typename T>
312        void EventGenerator::scheduleAheadMicroSec(RTAVLTree<T>& queue, T& node, int32_t fragmentPosBase, uint64_t microseconds) {
313            node.scheduleTime = uiTotalSamplesProcessed + fragmentPosBase + float(uiSampleRate) * (float(microseconds) / 1000000.f);
314            queue.insert(node);
315        }
316    
317  } // namespace LinuxSampler  } // namespace LinuxSampler
318    
319  #endif // __LS_EVENT_H__  #endif // __LS_EVENT_H__

Legend:
Removed from v.2611  
changed lines
  Added in v.2938

  ViewVC Help
Powered by ViewVC