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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2871 - (hide annotations) (download) (as text)
Sun Apr 10 18:22:23 2016 UTC (8 years ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 14147 byte(s)
* All engines: Implemented scheduler for delayed MIDI events and for
  suspended real-time instrument scripts.
* Real-Time instrument scripts: Implemented support for built-in "wait()"
  function's "duration-us" argument, thus scripts using this function are
  now correctly resumed after the requested amount of microseconds.
* Real-Time instrument scripts: Implemented support for built-in
  "play_note()" function's "duration-us" argument, thus notes triggered
  with this argument are now correctly released after the requested amount
  of microseconds.
* Real-Time instrument scripts: Fixed crash which happened when trying to
  reference an undeclared script variable.
* Real-Time instrument scripts: Script events were not cleared when
  engine channel was reset, potentially causing undefined behavior.
* All engines: Attempt to partly fix resetting engine channels vs.
  resetting engine, an overall cleanup of the Reset*(),
  ConnectAudioDevice(), DisconnectAudioDevice() API methods would still be
  desirable though, because the current situation is still inconsistent
  and error prone.
* Bumped version (2.0.0.svn2).

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 2871 * Copyright (C) 2005 - 2016 Christian Schoenebeck *
7 schoenebeck 53 * *
8     * 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 *
10     * the Free Software Foundation; either version 2 of the License, or *
11     * (at your option) any later version. *
12     * *
13     * This program is distributed in the hope that it will be useful, *
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16     * GNU General Public License for more details. *
17     * *
18     * You should have received a copy of the GNU General Public License *
19     * along with this program; if not, write to the Free Software *
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24     #ifndef __LS_EVENT_H__
25     #define __LS_EVENT_H__
26    
27     #include "../../common/global.h"
28 schoenebeck 328 #include "../../common/RTMath.h"
29 schoenebeck 2871 #include "../../common/RTAVLTree.h"
30     #include "../../common/Pool.h"
31 schoenebeck 890 #include "../EngineChannel.h"
32 schoenebeck 53
33     namespace LinuxSampler {
34    
35     // just symbol prototyping
36     class Event;
37 schoenebeck 2871 class SchedulerNode;
38     class ScriptEvent;
39     class ScheduledEvent;
40 schoenebeck 53
41     /**
42 schoenebeck 2871 * 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 schoenebeck 53 * Generates Event objects and is responsible for resolving the position
54     * in the current audio fragment each Event actually belongs to.
55     */
56     class EventGenerator {
57     public:
58     EventGenerator(uint SampleRate);
59     void UpdateFragmentTime(uint SamplesToProcess);
60     Event CreateEvent();
61 schoenebeck 906 Event CreateEvent(int32_t FragmentPos);
62 schoenebeck 2871
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 schoenebeck 53 protected:
78 schoenebeck 328 typedef RTMath::time_stamp_t time_stamp_t;
79 schoenebeck 293 inline int32_t ToFragmentPos(time_stamp_t TimeStamp) {
80     return int32_t (int32_t(TimeStamp - FragmentTime.begin) * FragmentTime.sample_ratio);
81 schoenebeck 53 }
82     friend class Event;
83     private:
84     uint uiSampleRate;
85     uint uiSamplesProcessed;
86     struct __FragmentTime__ {
87     time_stamp_t begin; ///< Real time stamp of the beginning of this audio fragment cycle.
88     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)
90     } FragmentTime;
91 schoenebeck 2871 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 schoenebeck 53 };
93    
94     /**
95     * Events are usually caused by a MIDI source or an internal modulation
96 schoenebeck 906 * controller like LFO or EG. An event should only be created by an
97     * EventGenerator!
98 schoenebeck 53 *
99 schoenebeck 2594 * @see EventGenerator, ScriptEvent
100 schoenebeck 53 */
101     class Event {
102     public:
103     Event(){}
104     enum type_t {
105     type_note_on,
106     type_note_off,
107     type_pitchbend,
108     type_control_change,
109 schoenebeck 244 type_sysex, ///< MIDI system exclusive message
110 schoenebeck 53 type_cancel_release, ///< transformed either from a note-on or sustain-pedal-down event
111 schoenebeck 2559 type_release, ///< transformed either from a note-off or sustain-pedal-up event
112     type_channel_pressure, ///< a.k.a. aftertouch
113     type_note_pressure, ///< polyphonic key pressure (aftertouch)
114 schoenebeck 53 } Type;
115     union {
116 schoenebeck 246 /// Note-on and note-off event specifics
117     struct _Note {
118 schoenebeck 2600 uint8_t Channel; ///< MIDI channel (0..15)
119 schoenebeck 246 uint8_t Key; ///< MIDI key number of note-on / note-off event.
120     uint8_t Velocity; ///< Trigger or release velocity of note-on / note-off event.
121 schoenebeck 250 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).
122     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).
123 persson 2101 void* pRegion; ///< Engine specific pointer to instrument region
124 schoenebeck 246 } Note;
125     /// Control change event specifics
126     struct _CC {
127 schoenebeck 2600 uint8_t Channel; ///< MIDI channel (0..15)
128 schoenebeck 246 uint8_t Controller; ///< MIDI controller number of control change event.
129     uint8_t Value; ///< Controller Value of control change event.
130     } CC;
131     /// Pitchbend event specifics
132     struct _Pitch {
133 schoenebeck 2600 uint8_t Channel; ///< MIDI channel (0..15)
134 schoenebeck 246 int16_t Pitch; ///< Pitch value of pitchbend event.
135     } Pitch;
136     /// MIDI system exclusive event specifics
137     struct _Sysex {
138     uint Size; ///< Data length (in bytes) of MIDI system exclusive message.
139     } Sysex;
140 schoenebeck 2559 /// Channel Pressure (aftertouch) event specifics
141     struct _ChannelPressure {
142 schoenebeck 2600 uint8_t Channel; ///< MIDI channel (0..15)
143 schoenebeck 2611 uint8_t Controller; ///< Should always be assigned to CTRL_TABLE_IDX_AFTERTOUCH.
144 schoenebeck 2559 uint8_t Value; ///< New aftertouch / pressure value for keys on that channel.
145     } ChannelPressure;
146     /// Polyphonic Note Pressure (aftertouch) event specifics
147     struct _NotePressure {
148 schoenebeck 2600 uint8_t Channel; ///< MIDI channel (0..15)
149 schoenebeck 2559 uint8_t Key; ///< MIDI note number where key pressure (polyphonic aftertouch) changed.
150     uint8_t Value; ///< New pressure value for note.
151     } NotePressure;
152 schoenebeck 246 } Param;
153 schoenebeck 2600 /// Sampler format specific informations and variables.
154     union {
155     /// Gigasampler/GigaStudio format specifics.
156     struct _Gig {
157     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.
158     uint8_t DimBits; ///< Used only in conjunction with DimMask: Dimension bits that shall be selected.
159     } Gig;
160     } Format;
161 schoenebeck 412 EngineChannel* pEngineChannel; ///< Pointer to the EngineChannel where this event occured on, NULL means Engine global event (e.g. SysEx message).
162 schoenebeck 1751 MidiInputPort* pMidiInputPort; ///< Pointer to the MIDI input port on which this event occured (NOTE: currently only for global events, that is SysEx messages)
163 schoenebeck 53
164 schoenebeck 293 inline int32_t FragmentPos() {
165     if (iFragmentPos >= 0) return iFragmentPos;
166     iFragmentPos = pEventGenerator->ToFragmentPos(TimeStamp);
167     if (iFragmentPos < 0) iFragmentPos = 0; // if event arrived shortly before the beginning of current fragment
168     return iFragmentPos;
169 schoenebeck 53 }
170 schoenebeck 293 inline void ResetFragmentPos() {
171     iFragmentPos = -1;
172     }
173 schoenebeck 53 protected:
174     typedef EventGenerator::time_stamp_t time_stamp_t;
175     Event(EventGenerator* pGenerator, EventGenerator::time_stamp_t Time);
176 schoenebeck 906 Event(EventGenerator* pGenerator, int32_t FragmentPos);
177 schoenebeck 53 friend class EventGenerator;
178     private:
179     EventGenerator* pEventGenerator; ///< Creator of the event.
180     time_stamp_t TimeStamp; ///< Time stamp of the event's occurence.
181 schoenebeck 293 int32_t iFragmentPos; ///< Position in the current fragment this event refers to.
182 schoenebeck 53 };
183    
184 schoenebeck 2871 /**
185     * Used to sort timing relevant objects (i.e. events) into timing/scheduler
186     * queue. This class is just intended as base class and should be derived
187     * for its actual purpose (for the precise data type being scheduled).
188     */
189     class SchedulerNode : public RTAVLNode {
190     public:
191     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.
192    
193     /// Required operator implementation for RTAVLTree class.
194     inline bool operator==(const SchedulerNode& other) const {
195     return this->scheduleTime == other.scheduleTime;
196     }
197    
198     /// Required operator implementation for RTAVLTree class.
199     inline bool operator<(const SchedulerNode& other) const {
200     return this->scheduleTime < other.scheduleTime;
201     }
202     };
203    
204     /**
205     * Used to sort delayed MIDI events into a timing/scheduler queue. This
206     * object just contains the timing informations, the actual MIDI event is
207     * pointed by member variable @c itEvent.
208     */
209     class ScheduledEvent : public SchedulerNode {
210     public:
211     Pool<Event>::Iterator itEvent; ///< Points to the actual Event object being scheduled.
212     };
213    
214 schoenebeck 2594 class VMEventHandler;
215     class VMExecContext;
216    
217     /** @brief Real-time instrument script event.
218     *
219     * Encapsulates one execution instance of a real-time instrument script for
220     * exactly one script event handler (script event callback).
221 schoenebeck 2871 *
222     * This class derives from SchedulerNode for being able to be sorted efficiently
223     * by the script scheduler if the script was either a) calling the wait()
224     * script function or b) the script was auto suspended by the ScriptVM
225     * because the script was executing for too long. In both cases the
226     * scheduler has to sort the ScriptEvents in its execution queue according
227     * to the precise time the respective script execution instance needs to be
228     * resumed.
229 schoenebeck 2594 */
230 schoenebeck 2871 class ScriptEvent : public SchedulerNode {
231 schoenebeck 2594 public:
232     Event cause; ///< Original external event that triggered this script event (i.e. MIDI note on event, MIDI CC event, etc.).
233 schoenebeck 2871 int id; ///< Unique ID of the external event that triggered this script event.
234 schoenebeck 2594 VMEventHandler** handlers; ///< The script's event handlers (callbacks) to be processed (NULL terminated list).
235     VMExecContext* execCtx; ///< Script's current execution state (polyphonic variables and execution stack).
236     int currentHandler; ///< Current index in 'handlers' list above.
237     int executionSlices; ///< Amount of times this script event has been executed by the ScriptVM runner class.
238     };
239    
240 schoenebeck 2871 /**
241     * Insert given @a node into the supplied timing @a queue with a scheduled
242     * timing position given by @a fragmentPosBase and @a microseconds, where
243     * @a microseconds reflects the amount microseconds in future from "now"
244     * where the node shall be scheduled, and @a fragmentPos identifies the
245     * sample point within the current audio fragment cycle which shall be
246     * interpreted by this method to be "now".
247     *
248     * The meaning of @a fragmentPosBase becomes more important the larger
249     * the audio fragment size, and vice versa it bcomes less important the
250     * smaller the audio fragment size.
251     *
252     * @param queue - destination scheduler queue
253     * @param node - node (i.e. event) to be inserted into the queue
254     * @param fragmentPosBase - sample point in current audio fragment to be "now"
255     * @param microseconds - timing of node from "now" (in microseconds)
256     */
257     template<typename T>
258     void EventGenerator::scheduleAheadMicroSec(RTAVLTree<T>& queue, T& node, int32_t fragmentPosBase, uint64_t microseconds) {
259     node.scheduleTime = uiTotalSamplesProcessed + fragmentPosBase + float(uiSampleRate) * (float(microseconds) / 1000000.f);
260     queue.insert(node);
261     }
262    
263 schoenebeck 53 } // namespace LinuxSampler
264    
265     #endif // __LS_EVENT_H__

  ViewVC Help
Powered by ViewVC