/[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 3561 - (hide annotations) (download) (as text)
Fri Aug 23 11:44:00 2019 UTC (4 years, 7 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 24741 byte(s)
NKSP: Added standard units support for numbers and final "!" operator:

* NKSP strictness: Variable names, function names and preprocessor condition
  names must start with a regular character (a-z or A-Z); starting them with
  a digit or underscore is no longer allowed.

* NKSP parser fix: equal comparison operator "=" and not equal comparison
  operator "#" must only accept integer operands.

* NKSP language: Implemented support for standard units like Hertz, seconds,
  Bel including support for metric unit prefixes; so one can now e.g.
  conveniently use numbers in scripts like "5us" meaning "5 microseconds",
  or e.g. "12kHz" meaning "12 kilo Hertz", or e.g. "-14mdB" meaning
  "minus 14 Millidecibel", or e.g. "28c" meaning "28 cents" (for tuning).

* NKSP language: Introduced "final" operator "!" which is specifically
  intended for synthesis parameter values to denote that the synthesis
  parameter value is intended to be the "final" value for that synthesis
  parameter that should explicitly be used by the engine and thus causing
  the sampler engine to ignore all other modulation sources for the same
  synthesis parameter (like e.g. LFO, EG); by simply prefixing a value,
  variable or formula with this new "!" operator the expression is marked as
  being "final".

* Bumped version (2.1.1.svn4).

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 3561 * Copyright (C) 2005 - 2019 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 2948 #include "../../scriptvm/common.h"
33 schoenebeck 53
34     namespace LinuxSampler {
35    
36     // just symbol prototyping
37     class Event;
38 schoenebeck 2871 class SchedulerNode;
39     class ScriptEvent;
40     class ScheduledEvent;
41 schoenebeck 53
42     /**
43 schoenebeck 2871 * 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 schoenebeck 53 * Generates Event objects and is responsible for resolving the position
55     * in the current audio fragment each Event actually belongs to.
56     */
57     class EventGenerator {
58     public:
59     EventGenerator(uint SampleRate);
60     void UpdateFragmentTime(uint SamplesToProcess);
61 schoenebeck 3283 void SetSampleRate(uint SampleRate);
62 schoenebeck 53 Event CreateEvent();
63 schoenebeck 906 Event CreateEvent(int32_t FragmentPos);
64 schoenebeck 2871
65     template<typename T>
66     void scheduleAheadMicroSec(RTAVLTree<T>& queue, T& node, int32_t fragmentPosBase, uint64_t microseconds);
67    
68     RTList<ScheduledEvent>::Iterator popNextScheduledEvent(RTAVLTree<ScheduledEvent>& queue, Pool<ScheduledEvent>& pool, sched_time_t end);
69     RTList<ScriptEvent>::Iterator popNextScheduledScriptEvent(RTAVLTree<ScriptEvent>& queue, Pool<ScriptEvent>& pool, sched_time_t end);
70    
71     /**
72 schoenebeck 2948 * Returns the scheduler time for the first sample point of the
73     * current audio fragment cycle.
74     */
75     sched_time_t schedTimeAtCurrentFragmentStart() const {
76     return uiTotalSamplesProcessed;
77     }
78    
79     /**
80 schoenebeck 2871 * Returns the scheduler time for the first sample point of the next
81     * audio fragment cycle.
82     */
83     sched_time_t schedTimeAtCurrentFragmentEnd() const {
84     return uiTotalSamplesProcessed + uiSamplesProcessed;
85     }
86    
87 schoenebeck 53 protected:
88 schoenebeck 328 typedef RTMath::time_stamp_t time_stamp_t;
89 schoenebeck 293 inline int32_t ToFragmentPos(time_stamp_t TimeStamp) {
90     return int32_t (int32_t(TimeStamp - FragmentTime.begin) * FragmentTime.sample_ratio);
91 schoenebeck 53 }
92     friend class Event;
93     private:
94     uint uiSampleRate;
95     uint uiSamplesProcessed;
96     struct __FragmentTime__ {
97     time_stamp_t begin; ///< Real time stamp of the beginning of this audio fragment cycle.
98     time_stamp_t end; ///< Real time stamp of the end of this audio fragment cycle.
99     float sample_ratio; ///< (Samples per cycle) / (Real time duration of cycle)
100     } FragmentTime;
101 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).
102 schoenebeck 53 };
103    
104     /**
105 schoenebeck 2879 * Unique numeric ID of an event which can be used to retrieve access to
106     * the actual @c Event object. Once the event associated with a certain ID
107     * was released (back to its event pool), this numeric ID becomes invalid
108     * and Pool< Event >::fromID() will detect this circumstance and will
109     * return an invalid Iterator, and thus will prevent you from misusing an
110     * event which no longer "exists".
111     *
112     * Note that an @c Event object usually just "exists" for exactly on audio
113     * fragment cycle: that is it exists right from the beginning of the audio
114     * fragment cycle where it was caused (i.e. where its MIDI data was
115     * received by the respective engine channel) and will disappear
116     * automatically at the end of that audio fragment cycle.
117     */
118     typedef pool_element_id_t event_id_t;
119    
120     /**
121     * Unique numeric ID of a note which can be used to retrieve access to the
122     * actual @c Note object. Once the note associated with a certain ID was
123     * released (back to its note pool), this numeric ID becomes invalid and
124     * Pool< Note >::fromID() will detect this circumstance and will return
125     * an invalid Iterator, and thus will prevent you from misusing a note
126     * which no longer is "alive".
127     *
128     * A @c Note object exists right when the respective MIDI note-on event
129     * was received by the respective engine channel, and remains existent
130     * until the caused note and all its voices were finally freed (which might
131     * even be long time after the respective note-off event was received,
132     * depending on the duration of the voice's release stages etc.).
133     */
134     typedef pool_element_id_t note_id_t;
135    
136     /**
137 schoenebeck 2948 * Unique numeric ID of a script callback ID instance which can be used to
138     * retrieve access to the actual @c ScriptEvent object. Once the script
139     * callback instance associated with a certain ID stopped its execution
140     * (that is completely stopped, not just suspended) then this numeric ID
141     * becomes invalid and Pool< ScriptEvent >::fromID() will detect this
142     * circumstance and will return an invalid Iterator, and thus will prevent
143     * you from misusing a script callback instance which no longer "exists".
144     */
145     typedef pool_element_id_t script_callback_id_t;
146    
147     /**
148 schoenebeck 53 * Events are usually caused by a MIDI source or an internal modulation
149 schoenebeck 906 * controller like LFO or EG. An event should only be created by an
150     * EventGenerator!
151 schoenebeck 53 *
152 schoenebeck 2594 * @see EventGenerator, ScriptEvent
153 schoenebeck 53 */
154     class Event {
155     public:
156     Event(){}
157     enum type_t {
158 schoenebeck 2938 type_note_on, ///< (real) MIDI note-on event
159     type_note_off, ///< (real) MIDI note-off event
160     type_pitchbend, ///< MIDI pitch bend wheel change event
161     type_control_change, ///< MIDI CC event
162 schoenebeck 244 type_sysex, ///< MIDI system exclusive message
163 schoenebeck 2938 type_cancel_release_key, ///< transformed either from a (real) MIDI note-on or sustain-pedal-down event
164     type_release_key, ///< transformed either from a (real) MIDI note-off or sustain-pedal-up event
165     type_release_note, ///< transformed from a type_stop_note event
166 schoenebeck 2559 type_channel_pressure, ///< a.k.a. aftertouch
167     type_note_pressure, ///< polyphonic key pressure (aftertouch)
168 schoenebeck 2938 type_play_note, ///< caused by a call to built-in instrument script function play_note()
169     type_stop_note, ///< caused by a call to built-in instrument script function note_off()
170 schoenebeck 3188 type_kill_note, ///< caused by a call to built-in instrument script function fade_out()
171 schoenebeck 2938 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.)
172 schoenebeck 53 } Type;
173 schoenebeck 2931 enum synth_param_t {
174     synth_param_volume,
175 schoenebeck 3188 synth_param_volume_time,
176 schoenebeck 3246 synth_param_volume_curve,
177 schoenebeck 2931 synth_param_pitch,
178 schoenebeck 3188 synth_param_pitch_time,
179 schoenebeck 3246 synth_param_pitch_curve,
180 schoenebeck 2931 synth_param_pan,
181 schoenebeck 3335 synth_param_pan_time,
182     synth_param_pan_curve,
183 schoenebeck 2935 synth_param_cutoff,
184     synth_param_resonance,
185 schoenebeck 2953 synth_param_attack,
186     synth_param_decay,
187 schoenebeck 3316 synth_param_sustain,
188 schoenebeck 2953 synth_param_release,
189 schoenebeck 3360 synth_param_cutoff_attack,
190     synth_param_cutoff_decay,
191     synth_param_cutoff_sustain,
192     synth_param_cutoff_release,
193 schoenebeck 3118 synth_param_amp_lfo_depth,
194     synth_param_amp_lfo_freq,
195 schoenebeck 3360 synth_param_cutoff_lfo_depth,
196     synth_param_cutoff_lfo_freq,
197 schoenebeck 3118 synth_param_pitch_lfo_depth,
198     synth_param_pitch_lfo_freq,
199 schoenebeck 2931 };
200 schoenebeck 3561 enum class ValueScope : unsigned char {
201     /**
202     * The new synthesis parameter value should be applied
203     * relatively to itself (as normalized value range), and then
204     * applied relatively against other sources (i.e. LFOs, EGs)
205     * for the same synthesis parameter.
206     */
207     SELF_RELATIVE,
208     /**
209     * The new synthesis paramater value of itself should be
210     * replaced, and then applied relatively to other sources
211     * (i.e. LFOs, EGs) for the same synthesis parameter.
212     */
213     RELATIVE,
214     /**
215     * The new synthesis parameter value should be applied
216     * relatively to itself (as normalized value range), and then
217     * applied directly (as normalized value range) as final value
218     * of this synthesis chain, thus all other sources (i.e. LFOs,
219     * EGs) should entirely be ignored.
220     */
221     FINAL_SELF_RELATIVE,
222     /**
223     * The new synthesis parameter value of itself should be
224     * replaced, and then applied directly (as normalized value
225     * range) as final value of this synthesis chain, thus all other
226     * sources (i.e. LFOs, EGs) should entirely be ignored.
227     */
228     FINAL_NORM,
229     /**
230     * Same as @c FINAL_NORM, but this one is already in the native
231     * unit (i.e. seconds, Hz) of this synthesis parameter.
232     */
233     FINAL_NATIVE,
234     };
235 schoenebeck 53 union {
236 schoenebeck 246 /// Note-on and note-off event specifics
237     struct _Note {
238 schoenebeck 2600 uint8_t Channel; ///< MIDI channel (0..15)
239 schoenebeck 246 uint8_t Key; ///< MIDI key number of note-on / note-off event.
240     uint8_t Velocity; ///< Trigger or release velocity of note-on / note-off event.
241 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).
242     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).
243 schoenebeck 2938 note_id_t ID; ///< Unique numeric ID of the @c Note object associated with this note event.
244 schoenebeck 2879 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.
245 persson 2101 void* pRegion; ///< Engine specific pointer to instrument region
246 schoenebeck 246 } Note;
247     /// Control change event specifics
248     struct _CC {
249 schoenebeck 2600 uint8_t Channel; ///< MIDI channel (0..15)
250 schoenebeck 246 uint8_t Controller; ///< MIDI controller number of control change event.
251     uint8_t Value; ///< Controller Value of control change event.
252     } CC;
253     /// Pitchbend event specifics
254     struct _Pitch {
255 schoenebeck 2600 uint8_t Channel; ///< MIDI channel (0..15)
256 schoenebeck 246 int16_t Pitch; ///< Pitch value of pitchbend event.
257     } Pitch;
258     /// MIDI system exclusive event specifics
259     struct _Sysex {
260     uint Size; ///< Data length (in bytes) of MIDI system exclusive message.
261     } Sysex;
262 schoenebeck 2559 /// Channel Pressure (aftertouch) event specifics
263     struct _ChannelPressure {
264 schoenebeck 2600 uint8_t Channel; ///< MIDI channel (0..15)
265 schoenebeck 2611 uint8_t Controller; ///< Should always be assigned to CTRL_TABLE_IDX_AFTERTOUCH.
266 schoenebeck 2559 uint8_t Value; ///< New aftertouch / pressure value for keys on that channel.
267     } ChannelPressure;
268     /// Polyphonic Note Pressure (aftertouch) event specifics
269     struct _NotePressure {
270 schoenebeck 2600 uint8_t Channel; ///< MIDI channel (0..15)
271 schoenebeck 2559 uint8_t Key; ///< MIDI note number where key pressure (polyphonic aftertouch) changed.
272     uint8_t Value; ///< New pressure value for note.
273     } NotePressure;
274 schoenebeck 2931 ///< Note synthesis parameter change event's specifics (used for real-time instrument script built-in functions which may alter synthesis parameters on note level).
275     struct _NoteSynthParam {
276     note_id_t NoteID; ///< ID of Note whose voices shall be modified.
277     synth_param_t Type; ///< Synthesis parameter which is to be changed.
278     float Delta; ///< The value change that should be applied against the note's current synthesis parameter value.
279     float AbsValue; ///< New current absolute value of synthesis parameter (that is after @c Delta being applied).
280 schoenebeck 3561 ValueScope Scope; ///< How @c Delta should be applied against @c AbsValue, and how @c AbsValue should then actually be applied to the synthesis chain.
281    
282     inline bool isFinal() const { return Scope >= ValueScope::FINAL_SELF_RELATIVE; }
283 schoenebeck 2931 } NoteSynthParam;
284 schoenebeck 246 } Param;
285 schoenebeck 412 EngineChannel* pEngineChannel; ///< Pointer to the EngineChannel where this event occured on, NULL means Engine global event (e.g. SysEx message).
286 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)
287 schoenebeck 53
288 schoenebeck 2879 inline void Init() {
289     Param.Note.ID = 0;
290     Param.Note.ParentNoteID = 0;
291 schoenebeck 2931 Param.NoteSynthParam.NoteID = 0;
292 schoenebeck 3561 Param.NoteSynthParam.Scope = ValueScope::RELATIVE;
293 schoenebeck 2879 }
294 schoenebeck 293 inline int32_t FragmentPos() {
295     if (iFragmentPos >= 0) return iFragmentPos;
296     iFragmentPos = pEventGenerator->ToFragmentPos(TimeStamp);
297     if (iFragmentPos < 0) iFragmentPos = 0; // if event arrived shortly before the beginning of current fragment
298     return iFragmentPos;
299 schoenebeck 53 }
300 schoenebeck 293 inline void ResetFragmentPos() {
301     iFragmentPos = -1;
302     }
303 schoenebeck 2879 inline void CopyTimeFrom(const Event& other) {
304     TimeStamp = other.TimeStamp;
305     iFragmentPos = other.iFragmentPos;
306     }
307 schoenebeck 2948 inline sched_time_t SchedTime() {
308     return pEventGenerator->schedTimeAtCurrentFragmentStart() + FragmentPos();
309     }
310 schoenebeck 3561 inline static ValueScope scopeBy_FinalRelativeUnit(bool bFinal, bool bRelative, bool bNativeUnit) {
311     if (!bFinal && bRelative)
312     return ValueScope::SELF_RELATIVE;
313     if (!bFinal)
314     return ValueScope::RELATIVE;
315     if (bRelative)
316     return ValueScope::FINAL_SELF_RELATIVE;
317     if (bNativeUnit)
318     return ValueScope::FINAL_NATIVE;
319     return ValueScope::FINAL_NORM;
320     }
321 schoenebeck 53 protected:
322     typedef EventGenerator::time_stamp_t time_stamp_t;
323     Event(EventGenerator* pGenerator, EventGenerator::time_stamp_t Time);
324 schoenebeck 906 Event(EventGenerator* pGenerator, int32_t FragmentPos);
325 schoenebeck 53 friend class EventGenerator;
326     private:
327     EventGenerator* pEventGenerator; ///< Creator of the event.
328     time_stamp_t TimeStamp; ///< Time stamp of the event's occurence.
329 schoenebeck 293 int32_t iFragmentPos; ///< Position in the current fragment this event refers to.
330 schoenebeck 53 };
331    
332 schoenebeck 2871 /**
333     * Used to sort timing relevant objects (i.e. events) into timing/scheduler
334     * queue. This class is just intended as base class and should be derived
335     * for its actual purpose (for the precise data type being scheduled).
336     */
337     class SchedulerNode : public RTAVLNode {
338     public:
339 schoenebeck 2948 using RTAVLNode::reset; // make reset() method public
340    
341 schoenebeck 2871 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.
342    
343     /// Required operator implementation for RTAVLTree class.
344     inline bool operator==(const SchedulerNode& other) const {
345     return this->scheduleTime == other.scheduleTime;
346     }
347    
348     /// Required operator implementation for RTAVLTree class.
349     inline bool operator<(const SchedulerNode& other) const {
350     return this->scheduleTime < other.scheduleTime;
351     }
352 schoenebeck 2948
353     /// This is actually just for code readability.
354     inline RTAVLTreeBase* currentSchedulerQueue() const { return rtavlTree(); }
355 schoenebeck 2871 };
356    
357     /**
358     * Used to sort delayed MIDI events into a timing/scheduler queue. This
359     * object just contains the timing informations, the actual MIDI event is
360     * pointed by member variable @c itEvent.
361     */
362     class ScheduledEvent : public SchedulerNode {
363     public:
364     Pool<Event>::Iterator itEvent; ///< Points to the actual Event object being scheduled.
365     };
366    
367 schoenebeck 2594 class VMEventHandler;
368     class VMExecContext;
369    
370 schoenebeck 3293 /**
371     * Maximum amount of child script handler instances one script handler is
372     * allowed to create by calling built-in script function fork().
373     */
374     #define MAX_FORK_PER_SCRIPT_HANDLER 8
375    
376 schoenebeck 2594 /** @brief Real-time instrument script event.
377     *
378     * Encapsulates one execution instance of a real-time instrument script for
379     * exactly one script event handler (script event callback).
380 schoenebeck 2871 *
381     * This class derives from SchedulerNode for being able to be sorted efficiently
382     * by the script scheduler if the script was either a) calling the wait()
383     * script function or b) the script was auto suspended by the ScriptVM
384     * because the script was executing for too long. In both cases the
385     * scheduler has to sort the ScriptEvents in its execution queue according
386     * to the precise time the respective script execution instance needs to be
387     * resumed.
388 schoenebeck 2594 */
389 schoenebeck 2871 class ScriptEvent : public SchedulerNode {
390 schoenebeck 2594 public:
391 schoenebeck 2879 Event cause; ///< Copy of original external @c Event that triggered this script event (i.e. MIDI note on event, MIDI CC event, etc.).
392     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.
393 schoenebeck 2594 VMEventHandler** handlers; ///< The script's event handlers (callbacks) to be processed (NULL terminated list).
394     VMExecContext* execCtx; ///< Script's current execution state (polyphonic variables and execution stack).
395     int currentHandler; ///< Current index in 'handlers' list above.
396     int executionSlices; ///< Amount of times this script event has been executed by the ScriptVM runner class.
397 schoenebeck 2948 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()).
398     VMEventHandlerType_t handlerType; ///< Native representation of built-in script variable $NI_CALLBACK_TYPE, reflecting the script event type of this script event.
399 schoenebeck 3293 script_callback_id_t parentHandlerID; ///< Only in case this script handler instance was created by calling built-in script function fork(): callback ID of the parent event handler instance which created this child. For regular event handler instances which were not created by fork(), this variable reflects 0 (which is always considered an invalid handler ID).
400     script_callback_id_t childHandlerID[MAX_FORK_PER_SCRIPT_HANDLER+1]; ///< In case built-in script function fork() was called by this script handler instance: A zero terminated ID list of all child event handler instances (note: children will not vanish from this list after they terminated).
401     bool autoAbortByParent; ///< Only if this is a child event handler created by calling fork(): if this is true then this child will automatically aborted if the parent event handler terminates.
402     int forkIndex; ///< Only for fork() calls: distinguishment feature which is 0 for parent, 1 for 1st child, 2 for 2nd child, etc.
403    
404     void forkTo(ScriptEvent* e, bool bAutoAbort) const;
405     int countChildHandlers() const;
406     void addChildHandlerID(script_callback_id_t childID);
407 schoenebeck 2594 };
408    
409 schoenebeck 2871 /**
410     * Insert given @a node into the supplied timing @a queue with a scheduled
411     * timing position given by @a fragmentPosBase and @a microseconds, where
412 schoenebeck 2879 * @a microseconds reflects the amount of microseconds in future from "now"
413 schoenebeck 2871 * where the node shall be scheduled, and @a fragmentPos identifies the
414     * sample point within the current audio fragment cycle which shall be
415     * interpreted by this method to be "now".
416     *
417     * The meaning of @a fragmentPosBase becomes more important the larger
418 schoenebeck 3293 * the audio fragment size, and vice versa it becomes less important the
419 schoenebeck 2871 * smaller the audio fragment size.
420     *
421     * @param queue - destination scheduler queue
422     * @param node - node (i.e. event) to be inserted into the queue
423     * @param fragmentPosBase - sample point in current audio fragment to be "now"
424     * @param microseconds - timing of node from "now" (in microseconds)
425     */
426     template<typename T>
427     void EventGenerator::scheduleAheadMicroSec(RTAVLTree<T>& queue, T& node, int32_t fragmentPosBase, uint64_t microseconds) {
428 schoenebeck 3205 // round up (+1) if microseconds is not zero (i.e. because 44.1 kHz and
429     // 1 us would yield in < 1 and thus would be offset == 0)
430     const sched_time_t offset =
431     (microseconds != 0LL) ?
432     1.f + (float(uiSampleRate) * (float(microseconds) / 1000000.f))
433     : 0.f;
434     node.scheduleTime = uiTotalSamplesProcessed + fragmentPosBase + offset;
435 schoenebeck 2871 queue.insert(node);
436     }
437    
438 schoenebeck 53 } // namespace LinuxSampler
439    
440     #endif // __LS_EVENT_H__

  ViewVC Help
Powered by ViewVC