/[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 890 by schoenebeck, Sat Jul 1 13:43:04 2006 UTC revision 2948 by schoenebeck, Fri Jul 15 15:29:04 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, 2006 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    #include "../../scriptvm/common.h"
33    
34  namespace LinuxSampler {  namespace LinuxSampler {
35    
36      // just symbol prototyping      // just symbol prototyping
37      class Event;      class Event;
38        class SchedulerNode;
39        class ScriptEvent;
40        class ScheduledEvent;
41    
42        /**
43         * Data type used to schedule events sample point accurately both within, as
44         * well as beyond the scope of the current audio fragment cycle. The timing
45         * reflected by this data type is consecutively running for a very long
46         * time. Even with a sample rate of 96 kHz a scheduler time of this data
47         * type will not wrap before 6 million years. So in practice such time
48         * stamps are unique and will not repeat (unless the EventGenerator is
49         * reset).
50         */
51        typedef uint64_t sched_time_t;
52    
53      /**      /**
54       * Generates Event objects and is responsible for resolving the position       * Generates Event objects and is responsible for resolving the position
# Line 42  namespace LinuxSampler { Line 59  namespace LinuxSampler {
59              EventGenerator(uint SampleRate);              EventGenerator(uint SampleRate);
60              void UpdateFragmentTime(uint SamplesToProcess);              void UpdateFragmentTime(uint SamplesToProcess);
61              Event CreateEvent();              Event CreateEvent();
62                Event CreateEvent(int32_t FragmentPos);
63    
64                template<typename T>
65                void scheduleAheadMicroSec(RTAVLTree<T>& queue, T& node, int32_t fragmentPosBase, uint64_t microseconds);
66    
67                RTList<ScheduledEvent>::Iterator popNextScheduledEvent(RTAVLTree<ScheduledEvent>& queue, Pool<ScheduledEvent>& pool, sched_time_t end);
68                RTList<ScriptEvent>::Iterator popNextScheduledScriptEvent(RTAVLTree<ScriptEvent>& queue, Pool<ScriptEvent>& pool, sched_time_t end);
69    
70                /**
71                 * Returns the scheduler time for the first sample point of the
72                 * current audio fragment cycle.
73                 */
74                sched_time_t schedTimeAtCurrentFragmentStart() const {
75                    return uiTotalSamplesProcessed;
76                }
77    
78                /**
79                 * Returns the scheduler time for the first sample point of the next
80                 * audio fragment cycle.
81                 */
82                sched_time_t schedTimeAtCurrentFragmentEnd() const {
83                    return uiTotalSamplesProcessed + uiSamplesProcessed;
84                }
85    
86          protected:          protected:
87              typedef RTMath::time_stamp_t time_stamp_t;              typedef RTMath::time_stamp_t time_stamp_t;
88              inline int32_t ToFragmentPos(time_stamp_t TimeStamp) {              inline int32_t ToFragmentPos(time_stamp_t TimeStamp) {
# Line 56  namespace LinuxSampler { Line 97  namespace LinuxSampler {
97                  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.
98                  float        sample_ratio; ///< (Samples per cycle) / (Real time duration of cycle)                  float        sample_ratio; ///< (Samples per cycle) / (Real time duration of cycle)
99              } FragmentTime;              } FragmentTime;
100                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).
101      };      };
102    
103      /**      /**
104         * Unique numeric ID of an event which can be used to retrieve access to
105         * the actual @c Event object. Once the event associated with a certain ID
106         * was released (back to its event pool), this numeric ID becomes invalid
107         * and Pool< Event >::fromID() will detect this circumstance and will
108         * return an invalid Iterator, and thus will prevent you from misusing an
109         * event which no longer "exists".
110         *
111         * Note that an @c Event object usually just "exists" for exactly on audio
112         * fragment cycle: that is it exists right from the beginning of the audio
113         * fragment cycle where it was caused (i.e. where its MIDI data was
114         * received by the respective engine channel) and will disappear
115         * automatically at the end of that audio fragment cycle.
116         */
117        typedef pool_element_id_t event_id_t;
118    
119        /**
120         * Unique numeric ID of a note which can be used to retrieve access to the
121         * actual @c Note object. Once the note associated with a certain ID was
122         * released (back to its note pool), this numeric ID becomes invalid and
123         * Pool< Note >::fromID() will detect this circumstance and will return
124         * an invalid Iterator, and thus will prevent you from misusing a note
125         * which no longer is "alive".
126         *
127         * A @c Note object exists right when the respective MIDI note-on event
128         * was received by the respective engine channel, and remains existent
129         * until the caused note and all its voices were finally freed (which might
130         * even be long time after the respective note-off event was received,
131         * depending on the duration of the voice's release stages etc.).
132         */
133        typedef pool_element_id_t note_id_t;
134    
135        /**
136         * Unique numeric ID of a script callback ID instance which can be used to
137         * retrieve access to the actual @c ScriptEvent object. Once the script
138         * callback instance associated with a certain ID stopped its execution
139         * (that is completely stopped, not just suspended) then this numeric ID
140         * becomes invalid and Pool< ScriptEvent >::fromID() will detect this
141         * circumstance and will return an invalid Iterator, and thus will prevent
142         * you from misusing a script callback instance which no longer "exists".
143         */
144        typedef pool_element_id_t script_callback_id_t;
145    
146        /**
147       * Events are usually caused by a MIDI source or an internal modulation       * Events are usually caused by a MIDI source or an internal modulation
148       * controller like LFO or EG. An event can only be created by an       * controller like LFO or EG. An event should only be created by an
149       * EventGenerator.       * EventGenerator!
150       *       *
151       * @see EventGenerator       * @see EventGenerator, ScriptEvent
152       */       */
153      class Event {      class Event {
154          public:          public:
155              Event(){}              Event(){}
156              enum type_t {              enum type_t {
157                  type_note_on,                  type_note_on, ///< (real) MIDI note-on event
158                  type_note_off,                  type_note_off, ///< (real) MIDI note-off event
159                  type_pitchbend,                  type_pitchbend, ///< MIDI pitch bend wheel change event
160                  type_control_change,                  type_control_change, ///< MIDI CC event
161                  type_sysex,           ///< MIDI system exclusive message                  type_sysex,           ///< MIDI system exclusive message
162                  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
163                  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
164                    type_release_note,    ///< transformed from a type_stop_note event
165                    type_channel_pressure, ///< a.k.a. aftertouch
166                    type_note_pressure, ///< polyphonic key pressure (aftertouch)
167                    type_play_note, ///< caused by a call to built-in instrument script function play_note()
168                    type_stop_note, ///< caused by a call to built-in instrument script function note_off()
169                    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.)
170              } Type;              } Type;
171                enum synth_param_t {
172                    synth_param_volume,
173                    synth_param_pitch,
174                    synth_param_pan,
175                    synth_param_cutoff,
176                    synth_param_resonance,
177                };
178              union {              union {
179                  /// Note-on and note-off event specifics                  /// Note-on and note-off event specifics
180                  struct _Note {                  struct _Note {
181                        uint8_t Channel;     ///< MIDI channel (0..15)
182                      uint8_t Key;         ///< MIDI key number of note-on / note-off event.                      uint8_t Key;         ///< MIDI key number of note-on / note-off event.
183                      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.
184                      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).
185                      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).
186                        note_id_t ID;        ///< Unique numeric ID of the @c Note object associated with this note event.
187                        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.
188                        void*   pRegion;     ///< Engine specific pointer to instrument region
189                  } Note;                  } Note;
190                  /// Control change event specifics                  /// Control change event specifics
191                  struct _CC {                  struct _CC {
192                        uint8_t Channel;     ///< MIDI channel (0..15)
193                      uint8_t Controller;  ///< MIDI controller number of control change event.                      uint8_t Controller;  ///< MIDI controller number of control change event.
194                      uint8_t Value;       ///< Controller Value of control change event.                      uint8_t Value;       ///< Controller Value of control change event.
195                  } CC;                  } CC;
196                  /// Pitchbend event specifics                  /// Pitchbend event specifics
197                  struct _Pitch {                  struct _Pitch {
198                        uint8_t Channel;     ///< MIDI channel (0..15)
199                      int16_t Pitch;       ///< Pitch value of pitchbend event.                      int16_t Pitch;       ///< Pitch value of pitchbend event.
200                  } Pitch;                  } Pitch;
201                  /// MIDI system exclusive event specifics                  /// MIDI system exclusive event specifics
202                  struct _Sysex {                  struct _Sysex {
203                      uint Size;           ///< Data length (in bytes) of MIDI system exclusive message.                      uint Size;           ///< Data length (in bytes) of MIDI system exclusive message.
204                  } Sysex;                  } Sysex;
205                    /// Channel Pressure (aftertouch) event specifics
206                    struct _ChannelPressure {
207                        uint8_t Channel; ///< MIDI channel (0..15)
208                        uint8_t Controller; ///< Should always be assigned to CTRL_TABLE_IDX_AFTERTOUCH.
209                        uint8_t Value;   ///< New aftertouch / pressure value for keys on that channel.
210                    } ChannelPressure;
211                    /// Polyphonic Note Pressure (aftertouch) event specifics
212                    struct _NotePressure {
213                        uint8_t Channel; ///< MIDI channel (0..15)
214                        uint8_t Key;     ///< MIDI note number where key pressure (polyphonic aftertouch) changed.
215                        uint8_t Value;   ///< New pressure value for note.
216                    } NotePressure;
217                    ///< Note synthesis parameter change event's specifics (used for real-time instrument script built-in functions which may alter synthesis parameters on note level).
218                    struct _NoteSynthParam {
219                        note_id_t     NoteID;   ///< ID of Note whose voices shall be modified.
220                        synth_param_t Type;     ///< Synthesis parameter which is to be changed.
221                        float         Delta;    ///< The value change that should be applied against the note's current synthesis parameter value.
222                        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).
223                        float         AbsValue; ///< New current absolute value of synthesis parameter (that is after @c Delta being applied).
224                    } NoteSynthParam;
225              } Param;              } Param;
226              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).
227                MidiInputPort* pMidiInputPort; ///< Pointer to the MIDI input port on which this event occured (NOTE: currently only for global events, that is SysEx messages)
228    
229                inline void Init() {
230                    Param.Note.ID = 0;
231                    Param.Note.ParentNoteID = 0;
232                    Param.NoteSynthParam.NoteID = 0;
233                }
234              inline int32_t FragmentPos() {              inline int32_t FragmentPos() {
235                  if (iFragmentPos >= 0) return iFragmentPos;                  if (iFragmentPos >= 0) return iFragmentPos;
236                  iFragmentPos = pEventGenerator->ToFragmentPos(TimeStamp);                  iFragmentPos = pEventGenerator->ToFragmentPos(TimeStamp);
# Line 110  namespace LinuxSampler { Line 240  namespace LinuxSampler {
240              inline void ResetFragmentPos() {              inline void ResetFragmentPos() {
241                  iFragmentPos = -1;                  iFragmentPos = -1;
242              }              }
243                inline void CopyTimeFrom(const Event& other) {
244                    TimeStamp = other.TimeStamp;
245                    iFragmentPos = other.iFragmentPos;
246                }
247                inline sched_time_t SchedTime() {
248                    return pEventGenerator->schedTimeAtCurrentFragmentStart() + FragmentPos();
249                }
250          protected:          protected:
251              typedef EventGenerator::time_stamp_t time_stamp_t;              typedef EventGenerator::time_stamp_t time_stamp_t;
252              Event(EventGenerator* pGenerator, EventGenerator::time_stamp_t Time);              Event(EventGenerator* pGenerator, EventGenerator::time_stamp_t Time);
253                Event(EventGenerator* pGenerator, int32_t FragmentPos);
254              friend class EventGenerator;              friend class EventGenerator;
255          private:          private:
256              EventGenerator* pEventGenerator; ///< Creator of the event.              EventGenerator* pEventGenerator; ///< Creator of the event.
# Line 120  namespace LinuxSampler { Line 258  namespace LinuxSampler {
258              int32_t         iFragmentPos;    ///< Position in the current fragment this event refers to.              int32_t         iFragmentPos;    ///< Position in the current fragment this event refers to.
259      };      };
260    
261        /**
262         * Used to sort timing relevant objects (i.e. events) into timing/scheduler
263         * queue. This class is just intended as base class and should be derived
264         * for its actual purpose (for the precise data type being scheduled).
265         */
266        class SchedulerNode : public RTAVLNode {
267        public:
268            using RTAVLNode::reset; // make reset() method public
269    
270            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.
271    
272            /// Required operator implementation for RTAVLTree class.
273            inline bool operator==(const SchedulerNode& other) const {
274                return this->scheduleTime == other.scheduleTime;
275            }
276    
277            /// Required operator implementation for RTAVLTree class.
278            inline bool operator<(const SchedulerNode& other) const {
279                return this->scheduleTime < other.scheduleTime;
280            }
281    
282            /// This is actually just for code readability.
283            inline RTAVLTreeBase* currentSchedulerQueue() const { return rtavlTree(); }
284        };
285    
286        /**
287         * Used to sort delayed MIDI events into a timing/scheduler queue. This
288         * object just contains the timing informations, the actual MIDI event is
289         * pointed by member variable @c itEvent.
290         */
291        class ScheduledEvent : public SchedulerNode {
292        public:
293            Pool<Event>::Iterator itEvent; ///< Points to the actual Event object being scheduled.
294        };
295    
296        class VMEventHandler;
297        class VMExecContext;
298    
299        /** @brief Real-time instrument script event.
300         *
301         * Encapsulates one execution instance of a real-time instrument script for
302         * exactly one script event handler (script event callback).
303         *
304         * This class derives from SchedulerNode for being able to be sorted efficiently
305         * by the script scheduler if the script was either a) calling the wait()
306         * script function or b) the script was auto suspended by the ScriptVM
307         * because the script was executing for too long. In both cases the
308         * scheduler has to sort the ScriptEvents in its execution queue according
309         * to the precise time the respective script execution instance needs to be
310         * resumed.
311         */
312        class ScriptEvent : public SchedulerNode {
313        public:
314            Event cause; ///< Copy of original external @c Event that triggered this script event (i.e. MIDI note on event, MIDI CC event, etc.).
315            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.
316            VMEventHandler** handlers; ///< The script's event handlers (callbacks) to be processed (NULL terminated list).
317            VMExecContext* execCtx; ///< Script's current execution state (polyphonic variables and execution stack).
318            int currentHandler; ///< Current index in 'handlers' list above.
319            int executionSlices; ///< Amount of times this script event has been executed by the ScriptVM runner class.
320            bool ignoreAllWaitCalls; ///< If true: calling any built-in wait*() script function should be ignored (this variable may be set with the 2nd argument of built-in script function stop_wait()).
321            VMEventHandlerType_t handlerType; ///< Native representation of built-in script variable $NI_CALLBACK_TYPE, reflecting the script event type of this script event.
322        };
323    
324        /**
325         * Insert given @a node into the supplied timing @a queue with a scheduled
326         * timing position given by @a fragmentPosBase and @a microseconds, where
327         * @a microseconds reflects the amount of microseconds in future from "now"
328         * where the node shall be scheduled, and @a fragmentPos identifies the
329         * sample point within the current audio fragment cycle which shall be
330         * interpreted by this method to be "now".
331         *
332         * The meaning of @a fragmentPosBase becomes more important the larger
333         * the audio fragment size, and vice versa it bcomes less important the
334         * smaller the audio fragment size.
335         *
336         * @param queue - destination scheduler queue
337         * @param node - node (i.e. event) to be inserted into the queue
338         * @param fragmentPosBase - sample point in current audio fragment to be "now"
339         * @param microseconds - timing of node from "now" (in microseconds)
340         */
341        template<typename T>
342        void EventGenerator::scheduleAheadMicroSec(RTAVLTree<T>& queue, T& node, int32_t fragmentPosBase, uint64_t microseconds) {
343            node.scheduleTime = uiTotalSamplesProcessed + fragmentPosBase + float(uiSampleRate) * (float(microseconds) / 1000000.f);
344            queue.insert(node);
345        }
346    
347  } // namespace LinuxSampler  } // namespace LinuxSampler
348    
349  #endif // __LS_EVENT_H__  #endif // __LS_EVENT_H__

Legend:
Removed from v.890  
changed lines
  Added in v.2948

  ViewVC Help
Powered by ViewVC