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 - 2016 Christian Schoenebeck * |
* Copyright (C) 2005 - 2017 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 * |
29 |
#include "../../common/RTAVLTree.h" |
#include "../../common/RTAVLTree.h" |
30 |
#include "../../common/Pool.h" |
#include "../../common/Pool.h" |
31 |
#include "../EngineChannel.h" |
#include "../EngineChannel.h" |
32 |
|
#include "../../scriptvm/common.h" |
33 |
|
|
34 |
namespace LinuxSampler { |
namespace LinuxSampler { |
35 |
|
|
68 |
RTList<ScriptEvent>::Iterator popNextScheduledScriptEvent(RTAVLTree<ScriptEvent>& queue, Pool<ScriptEvent>& pool, sched_time_t end); |
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 |
* Returns the scheduler time for the first sample point of the next |
80 |
* audio fragment cycle. |
* audio fragment cycle. |
81 |
*/ |
*/ |
133 |
typedef pool_element_id_t note_id_t; |
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 should only be created by an |
* controller like LFO or EG. An event should only be created by an |
149 |
* EventGenerator! |
* EventGenerator! |
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 |
type_channel_pressure, ///< a.k.a. aftertouch |
166 |
type_note_pressure, ///< polyphonic key pressure (aftertouch) |
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 |
|
synth_param_attack, |
178 |
|
synth_param_decay, |
179 |
|
synth_param_release, |
180 |
|
synth_param_amp_lfo_depth, |
181 |
|
synth_param_amp_lfo_freq, |
182 |
|
synth_param_pitch_lfo_depth, |
183 |
|
synth_param_pitch_lfo_freq, |
184 |
|
}; |
185 |
union { |
union { |
186 |
/// Note-on and note-off event specifics |
/// Note-on and note-off event specifics |
187 |
struct _Note { |
struct _Note { |
190 |
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. |
191 |
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). |
192 |
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). |
193 |
note_id_t ID; ///< Unique numeric ID of the @c Note object associated with this note (on) event. |
note_id_t ID; ///< Unique numeric ID of the @c Note object associated with this note event. |
194 |
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. |
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. |
195 |
void* pRegion; ///< Engine specific pointer to instrument region |
void* pRegion; ///< Engine specific pointer to instrument region |
196 |
} Note; |
} Note; |
221 |
uint8_t Key; ///< MIDI note number where key pressure (polyphonic aftertouch) changed. |
uint8_t Key; ///< MIDI note number where key pressure (polyphonic aftertouch) changed. |
222 |
uint8_t Value; ///< New pressure value for note. |
uint8_t Value; ///< New pressure value for note. |
223 |
} NotePressure; |
} NotePressure; |
224 |
|
///< Note synthesis parameter change event's specifics (used for real-time instrument script built-in functions which may alter synthesis parameters on note level). |
225 |
|
struct _NoteSynthParam { |
226 |
|
note_id_t NoteID; ///< ID of Note whose voices shall be modified. |
227 |
|
synth_param_t Type; ///< Synthesis parameter which is to be changed. |
228 |
|
float Delta; ///< The value change that should be applied against the note's current synthesis parameter value. |
229 |
|
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). |
230 |
|
float AbsValue; ///< New current absolute value of synthesis parameter (that is after @c Delta being applied). |
231 |
|
} NoteSynthParam; |
232 |
} Param; |
} Param; |
233 |
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). |
234 |
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) |
236 |
inline void Init() { |
inline void Init() { |
237 |
Param.Note.ID = 0; |
Param.Note.ID = 0; |
238 |
Param.Note.ParentNoteID = 0; |
Param.Note.ParentNoteID = 0; |
239 |
|
Param.NoteSynthParam.NoteID = 0; |
240 |
} |
} |
241 |
inline int32_t FragmentPos() { |
inline int32_t FragmentPos() { |
242 |
if (iFragmentPos >= 0) return iFragmentPos; |
if (iFragmentPos >= 0) return iFragmentPos; |
251 |
TimeStamp = other.TimeStamp; |
TimeStamp = other.TimeStamp; |
252 |
iFragmentPos = other.iFragmentPos; |
iFragmentPos = other.iFragmentPos; |
253 |
} |
} |
254 |
|
inline sched_time_t SchedTime() { |
255 |
|
return pEventGenerator->schedTimeAtCurrentFragmentStart() + FragmentPos(); |
256 |
|
} |
257 |
protected: |
protected: |
258 |
typedef EventGenerator::time_stamp_t time_stamp_t; |
typedef EventGenerator::time_stamp_t time_stamp_t; |
259 |
Event(EventGenerator* pGenerator, EventGenerator::time_stamp_t Time); |
Event(EventGenerator* pGenerator, EventGenerator::time_stamp_t Time); |
272 |
*/ |
*/ |
273 |
class SchedulerNode : public RTAVLNode { |
class SchedulerNode : public RTAVLNode { |
274 |
public: |
public: |
275 |
|
using RTAVLNode::reset; // make reset() method public |
276 |
|
|
277 |
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. |
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. |
278 |
|
|
279 |
/// Required operator implementation for RTAVLTree class. |
/// Required operator implementation for RTAVLTree class. |
285 |
inline bool operator<(const SchedulerNode& other) const { |
inline bool operator<(const SchedulerNode& other) const { |
286 |
return this->scheduleTime < other.scheduleTime; |
return this->scheduleTime < other.scheduleTime; |
287 |
} |
} |
288 |
|
|
289 |
|
/// This is actually just for code readability. |
290 |
|
inline RTAVLTreeBase* currentSchedulerQueue() const { return rtavlTree(); } |
291 |
}; |
}; |
292 |
|
|
293 |
/** |
/** |
324 |
VMExecContext* execCtx; ///< Script's current execution state (polyphonic variables and execution stack). |
VMExecContext* execCtx; ///< Script's current execution state (polyphonic variables and execution stack). |
325 |
int currentHandler; ///< Current index in 'handlers' list above. |
int currentHandler; ///< Current index in 'handlers' list above. |
326 |
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. |
327 |
|
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()). |
328 |
|
VMEventHandlerType_t handlerType; ///< Native representation of built-in script variable $NI_CALLBACK_TYPE, reflecting the script event type of this script event. |
329 |
}; |
}; |
330 |
|
|
331 |
/** |
/** |