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

Contents of /linuxsampler/trunk/src/engines/common/InstrumentScriptVM.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3360 - (show annotations) (download) (as text)
Fri Oct 27 21:19:18 2017 UTC (13 months, 1 week ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 18651 byte(s)
* NKSP: Added built-in script function "change_cutoff_attack()".
* NKSP: Added built-in script function "change_cutoff_decay()".
* NKSP: Added built-in script function "change_cutoff_sustain()".
* NKSP: Added built-in script function "change_cutoff_release()".
* NKSP: Added built-in script function "change_cutoff_lfo_depth()".
* NKSP: Added built-in script function "change_cutoff_lfo_freq()".
* Bumped version (2.0.0.svn77).

1 /*
2 * Copyright (c) 2014-2017 Christian Schoenebeck
3 *
4 * http://www.linuxsampler.org
5 *
6 * This file is part of LinuxSampler and released under the same terms.
7 * See README file for details.
8 */
9
10 #ifndef LS_INSTRUMENT_SCRIPT_VM_H
11 #define LS_INSTRUMENT_SCRIPT_VM_H
12
13 #include "../../common/global.h"
14 #include "../../common/ConstCapacityArray.h"
15 #include "../../scriptvm/ScriptVM.h"
16 #include "Event.h"
17 #include "../../common/Pool.h"
18 #include "InstrumentScriptVMFunctions.h"
19 #include "InstrumentScriptVMDynVars.h"
20
21 /**
22 * Amount of bits on the left hand side of all pool_element_id_t numbers (i.e.
23 * event_id_t, note_id_t) being reserved for script VM implementation internal
24 * purposes.
25 *
26 * Right now there is only one bit reserved, which allows the VM (and its
27 * built-in functions) to distinguish user supplied @c Event IDs (event_id_t)
28 * from @c Note IDs (note_id_t).
29 */
30 #define INSTR_SCRIPT_EVENT_ID_RESERVED_BITS 1
31
32 /**
33 * Used by InstrScriptIDType_T to initialize its constants at compile time.
34 *
35 * This macro is already ready to initialize additional members for
36 * InstrScriptIDType_T (that is more than the currently two enum constants).
37 * Just keep in mind that you also have to increase
38 * INSTR_SCRIPT_EVENT_ID_RESERVED_BITS when you add more!
39 *
40 * @param x - sequential consecutive number (starting with zero)
41 */
42 #define INSTR_SCRIPT_ID_TYPE_FLAG(x) \
43 (x << (sizeof(pool_element_id_t) * 8 - INSTR_SCRIPT_EVENT_ID_RESERVED_BITS))
44
45 /**
46 * These flags are used to distinguish the individual ID Types in script scope
47 * from each other. They are added as most left bit(s) to each ID in script
48 * scope.
49 */
50 enum InstrScriptIDType_T {
51 /**
52 * Used to mark IDs (in script scope) to actually be a MIDI event ID.
53 */
54 INSTR_SCRIPT_EVENT_ID_FLAG = INSTR_SCRIPT_ID_TYPE_FLAG(0),
55
56 /**
57 * Used to mark IDs (in script scope) to actually be a note ID.
58 */
59 INSTR_SCRIPT_NOTE_ID_FLAG = INSTR_SCRIPT_ID_TYPE_FLAG(1),
60 };
61
62 #define INSTR_SCRIPT_EVENT_GROUPS 28
63
64 #define EVENT_STATUS_INACTIVE 0
65 #define EVENT_STATUS_NOTE_QUEUE 1
66
67 enum {
68 EVENT_PAR_NOTE = 1,
69 EVENT_PAR_VELOCITY,
70 EVENT_PAR_VOLUME,
71 EVENT_PAR_TUNE,
72 EVENT_PAR_0 = 1024,
73 EVENT_PAR_1,
74 EVENT_PAR_2,
75 EVENT_PAR_3,
76 };
77
78 enum {
79 CALLBACK_STATUS_TERMINATED = 0,
80 CALLBACK_STATUS_QUEUE = 1,
81 CALLBACK_STATUS_RUNNING = (1 << 1)
82 };
83
84 namespace LinuxSampler {
85
86 class AbstractEngineChannel;
87 struct InstrumentScript;
88
89 /** @brief Convert IDs between script scope and engine internal scope.
90 *
91 * This class is used to translate unique IDs of events between script
92 * scope and sampler engine internal scope, that is:
93 * @code
94 * int (script scope) -> event_id_t (engine internal scope)
95 * int (script scope) -> note_id_t (engine internal scope)
96 * @endcode
97 * and vice versa:
98 * @code
99 * event_id_t (engine internal scope) -> int (script scope)
100 * note_id_t (engine internal scope) -> int (script scope)
101 * @endcode
102 * This is required because engine internally i.e. notes and regular events
103 * are using their own, separate ID generating pool, and their ID number
104 * set may thus overlap and historically there were built-in script
105 * functions in KSP which allow to pass both regular MIDI event IDs, as well
106 * as Note IDs. So we must be able to distinguish between them in our
107 * built-in script function implementations.
108 *
109 * @see INSTR_SCRIPT_EVENT_ID_RESERVED_BITS
110 */
111 class ScriptID {
112 public:
113 enum type_t {
114 EVENT, ///< ID is actually an event ID
115 NOTE, ///< ID is actually a note ID
116 };
117
118 /**
119 * Construct a ScriptID object with an ID from script scope.
120 */
121 ScriptID(uint id) : m_id(id) {}
122
123 /**
124 * Returns a ScriptID object constructed with an event ID from engine
125 * internal scope.
126 */
127 inline static ScriptID fromEventID(event_id_t id) {
128 return ScriptID(INSTR_SCRIPT_EVENT_ID_FLAG | id);
129 }
130
131 /**
132 * Returns a ScriptID object constructed with a note ID from engine
133 * internal scope.
134 */
135 inline static ScriptID fromNoteID(note_id_t id) {
136 return ScriptID(INSTR_SCRIPT_NOTE_ID_FLAG | id);
137 }
138
139 /**
140 * Whether the ID reflected by this ScriptID object is actually a note
141 * ID or rather an event ID.
142 */
143 inline type_t type() const {
144 return (m_id & INSTR_SCRIPT_NOTE_ID_FLAG) ? NOTE : EVENT;
145 }
146
147 inline bool isNoteID() const {
148 return type() == NOTE;
149 }
150
151 inline bool isEventID() const {
152 return type() == EVENT;
153 }
154
155 /**
156 * Returns event ID (for engine internal scope) of the ID reflected by
157 * this ScriptID object, it returns 0 (being an invalid ID) if the ID
158 * reflected by this ScriptID object is not an event ID.
159 */
160 inline event_id_t eventID() const {
161 switch (type()) {
162 case EVENT: return m_id;
163 default: return 0; // not an event id, return invalid ID
164 }
165 }
166
167 /**
168 * Returns note ID (for engine internal scope) of the ID reflected by
169 * this ScriptID object, it returns 0 (being an invalid ID) if the ID
170 * reflected by this ScriptID object is not a note ID.
171 */
172 inline note_id_t noteID() const {
173 switch (type()) {
174 case NOTE: return ~INSTR_SCRIPT_NOTE_ID_FLAG & m_id;
175 default: return 0; // not a note id, return invalid ID
176 }
177 }
178
179 /**
180 * Integer cast operator, which returns an ID number of this ScripID
181 * object intended for script scope.
182 */
183 inline operator uint() const {
184 return m_id;
185 }
186
187 private:
188 uint m_id;
189 };
190
191 /** @brief List of Event IDs.
192 *
193 * Used for built-in script functions:
194 * by_marks(), set_event_mark(), delete_event_mark()
195 */
196 class EventGroup : protected ConstCapacityArray<int> {
197 public:
198 EventGroup() : ConstCapacityArray<int>(CONFIG_MAX_EVENTS_PER_FRAGMENT), m_script(NULL) {}
199 void insert(int eventID);
200 void erase(int eventID);
201 void setScript(InstrumentScript* pScript) { m_script = pScript; }
202 inline int size() const { return ConstCapacityArray<int>::size(); }
203 inline void clear() { ConstCapacityArray<int>::clear(); }
204 inline int& operator[](uint index) { return ConstCapacityArray<int>::operator[](index); }
205 inline const int& operator[](uint index) const { return ConstCapacityArray<int>::operator[](index); }
206 protected:
207 InstrumentScript* m_script;
208 };
209
210 /** @brief Real-time instrument script VM representation.
211 *
212 * Holds the VM representation of all event handlers of the currently loaded
213 * script, ready to be executed by the sampler engine.
214 *
215 * Even thought scripts (or to be more specific their event handler objects)
216 * are shared between sampler engine channels, the InstrumentScript struct
217 * instances though are not shared. Each sampler engine channel has its own
218 * instance of a InstrumentScript struct. That's important, because this
219 * struct also holds engine channel local informations, for example the
220 * events that occured on the respective engine channel.
221 */
222 struct InstrumentScript {
223 VMParserContext* parserContext; ///< VM represenation of the currently loaded script or NULL if not script was loaded. Note that it is also not NULL if parser errors occurred!
224 bool bHasValidScript; ///< True in case there is a valid script currently loaded, false if script processing shall be skipped.
225 VMEventHandler* handlerInit; ///< VM representation of script's initilization callback or NULL if current script did not define such an init handler.
226 VMEventHandler* handlerNote; ///< VM representation of script's MIDI note on callback or NULL if current script did not define such an event handler.
227 VMEventHandler* handlerRelease; ///< VM representation of script's MIDI note off callback or NULL if current script did not define such an event handler.
228 VMEventHandler* handlerController; ///< VM representation of script's MIDI controller callback or NULL if current script did not define such an event handler.
229 Pool<ScriptEvent>* pEvents; ///< Pool of all available script execution instances. ScriptEvents available to be allocated from the Pool are currently unused / not executiong, whereas the ScriptEvents allocated on the list are currently suspended / have not finished execution yet (@see pKeyEvents).
230 RTList<ScriptEvent>* pKeyEvents[128]; ///< Stores previously finished executed "note on" script events for the respective active note/key as long as the key/note is active. This is however only done if there is a "note" script event handler and a "release" script event handler defined in the script and both handlers use (reference) polyphonic variables. If that is not the case, then this list is not used at all. So the purpose of pKeyEvents is only to implement preserving/passing polyphonic variable data from "on note .. end on" script block to the respective "on release .. end on" script block.
231 RTAVLTree<ScriptEvent> suspendedEvents; ///< Contains pointers to all suspended events, sorted by time when those script events are to be resumed next.
232 AbstractEngineChannel* pEngineChannel;
233 String code; ///< Source code of the instrument script. Used in case the sampler engine is changed, in that case a new ScriptVM object is created for the engine and VMParserContext object for this script needs to be recreated as well. Thus the script is then parsed again by passing the source code to recreate the parser context.
234 EventGroup eventGroups[INSTR_SCRIPT_EVENT_GROUPS]; ///< Used for built-in script functions: by_event_marks(), set_event_mark(), delete_event_mark().
235
236 InstrumentScript(AbstractEngineChannel* pEngineChannel);
237 ~InstrumentScript();
238
239 void load(const String& text);
240 void unload();
241 void resetAll();
242 void resetEvents();
243 };
244
245 /** @brief Real-time instrument script virtual machine.
246 *
247 * Extends the core ScriptVM implementation with MIDI specific built-in
248 * script functions and MIDI specific built-in script variables required
249 * for MIDI processing by instrument script for all sampler engine
250 * implementations (sampler formats) of this sampler.
251 *
252 * Note that this class is currently re-entrant safe, but @b not thread
253 * safe! See also comments of base class ScriptVM regarding this issue.
254 */
255 class InstrumentScriptVM : public ScriptVM {
256 public:
257 InstrumentScriptVM();
258 VMExecStatus_t exec(VMParserContext* parserCtx, ScriptEvent* event);
259 VMFunction* functionByName(const String& name) OVERRIDE;
260 std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;
261 std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;
262 std::map<String,int> builtInConstIntVariables() OVERRIDE;
263 std::map<String,VMDynVar*> builtInDynamicVariables() OVERRIDE;
264 protected:
265 ScriptEvent* m_event; ///< The event currently executed by exec().
266
267 // built-in script variables
268 VMInt8Array m_CC;
269 VMInt8RelPtr m_CC_NUM;
270 VMIntRelPtr m_EVENT_ID;
271 VMInt8RelPtr m_EVENT_NOTE;
272 VMInt8RelPtr m_EVENT_VELOCITY;
273 VMInt8Array m_KEY_DOWN;
274 //VMIntArray m_POLY_AT; //TODO: ...
275 //int m_POLY_AT_NUM; //TODO: ...
276 VMIntRelPtr m_NI_CALLBACK_TYPE;
277 VMIntRelPtr m_NKSP_IGNORE_WAIT;
278 VMIntRelPtr m_NKSP_CALLBACK_PARENT_ID;
279
280 // built-in script functions
281 InstrumentScriptVMFunction_play_note m_fnPlayNote;
282 InstrumentScriptVMFunction_set_controller m_fnSetController;
283 InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;
284 InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;
285 InstrumentScriptVMFunction_note_off m_fnNoteOff;
286 InstrumentScriptVMFunction_set_event_mark m_fnSetEventMark;
287 InstrumentScriptVMFunction_delete_event_mark m_fnDeleteEventMark;
288 InstrumentScriptVMFunction_by_marks m_fnByMarks;
289 InstrumentScriptVMFunction_change_vol m_fnChangeVol;
290 InstrumentScriptVMFunction_change_vol_time m_fnChangeVolTime;
291 InstrumentScriptVMFunction_change_tune m_fnChangeTune;
292 InstrumentScriptVMFunction_change_tune_time m_fnChangeTuneTime;
293 InstrumentScriptVMFunction_change_pan m_fnChangePan;
294 InstrumentScriptVMFunction_change_pan_time m_fnChangePanTime;
295 InstrumentScriptVMFunction_change_pan_curve m_fnChangePanCurve;
296 InstrumentScriptVMFunction_change_cutoff m_fnChangeCutoff;
297 InstrumentScriptVMFunction_change_reso m_fnChangeReso;
298 InstrumentScriptVMFunction_change_attack m_fnChangeAttack;
299 InstrumentScriptVMFunction_change_decay m_fnChangeDecay;
300 InstrumentScriptVMFunction_change_sustain m_fnChangeSustain;
301 InstrumentScriptVMFunction_change_release m_fnChangeRelease;
302 InstrumentScriptVMFunction_change_cutoff_attack m_fnChangeCutoffAttack;
303 InstrumentScriptVMFunction_change_cutoff_decay m_fnChangeCutoffDecay;
304 InstrumentScriptVMFunction_change_cutoff_sustain m_fnChangeCutoffSustain;
305 InstrumentScriptVMFunction_change_cutoff_release m_fnChangeCutoffRelease;
306 InstrumentScriptVMFunction_change_amp_lfo_depth m_fnChangeAmpLFODepth;
307 InstrumentScriptVMFunction_change_amp_lfo_freq m_fnChangeAmpLFOFreq;
308 InstrumentScriptVMFunction_change_cutoff_lfo_depth m_fnChangeCutoffLFODepth;
309 InstrumentScriptVMFunction_change_cutoff_lfo_freq m_fnChangeCutoffLFOFreq;
310 InstrumentScriptVMFunction_change_pitch_lfo_depth m_fnChangePitchLFODepth;
311 InstrumentScriptVMFunction_change_pitch_lfo_freq m_fnChangePitchLFOFreq;
312 InstrumentScriptVMFunction_change_note m_fnChangeNote;
313 InstrumentScriptVMFunction_change_velo m_fnChangeVelo;
314 InstrumentScriptVMFunction_fork m_fnFork;
315 InstrumentScriptVMFunction_event_status m_fnEventStatus;
316 InstrumentScriptVMFunction_wait m_fnWait2;
317 InstrumentScriptVMFunction_stop_wait m_fnStopWait;
318 InstrumentScriptVMFunction_abort m_fnAbort;
319 InstrumentScriptVMFunction_fade_in m_fnFadeIn;
320 InstrumentScriptVMFunction_fade_out m_fnFadeOut;
321 InstrumentScriptVMFunction_change_vol_curve m_fnChangeVolCurve;
322 InstrumentScriptVMFunction_change_tune_curve m_fnChangeTuneCurve;
323 InstrumentScriptVMFunction_get_event_par m_fnGetEventPar;
324 InstrumentScriptVMFunction_set_event_par m_fnSetEventPar;
325 InstrumentScriptVMFunction_change_play_pos m_fnChangePlayPos;
326 InstrumentScriptVMFunction_callback_status m_fnCallbackStatus;
327 InstrumentScriptVMDynVar_ENGINE_UPTIME m_varEngineUptime;
328 InstrumentScriptVMDynVar_NI_CALLBACK_ID m_varCallbackID;
329 InstrumentScriptVMDynVar_ALL_EVENTS m_varAllEvents;
330 InstrumentScriptVMDynVar_NKSP_CALLBACK_CHILD_ID m_varCallbackChildID;
331
332 friend class InstrumentScriptVMFunction_play_note;
333 friend class InstrumentScriptVMFunction_set_controller;
334 friend class InstrumentScriptVMFunction_ignore_event;
335 friend class InstrumentScriptVMFunction_ignore_controller;
336 friend class InstrumentScriptVMFunction_note_off;
337 friend class InstrumentScriptVMFunction_set_event_mark;
338 friend class InstrumentScriptVMFunction_delete_event_mark;
339 friend class InstrumentScriptVMFunction_by_marks;
340 friend class InstrumentScriptVMFunction_change_vol;
341 friend class InstrumentScriptVMFunction_change_vol_time;
342 friend class InstrumentScriptVMFunction_change_tune;
343 friend class InstrumentScriptVMFunction_change_tune_time;
344 friend class InstrumentScriptVMFunction_change_pan;
345 friend class InstrumentScriptVMFunction_change_pan_time;
346 friend class InstrumentScriptVMFunction_change_pan_curve;
347 friend class InstrumentScriptVMFunction_change_cutoff;
348 friend class InstrumentScriptVMFunction_change_reso;
349 friend class InstrumentScriptVMFunction_change_attack;
350 friend class InstrumentScriptVMFunction_change_decay;
351 friend class InstrumentScriptVMFunction_change_release;
352 friend class InstrumentScriptVMFunction_change_sustain;
353 friend class InstrumentScriptVMFunction_change_cutoff_attack;
354 friend class InstrumentScriptVMFunction_change_cutoff_decay;
355 friend class InstrumentScriptVMFunction_change_cutoff_release;
356 friend class InstrumentScriptVMFunction_change_cutoff_sustain;
357 friend class VMChangeSynthParamFunction;
358 friend class InstrumentScriptVMFunction_change_amp_lfo_depth;
359 friend class InstrumentScriptVMFunction_change_amp_lfo_freq;
360 friend class InstrumentScriptVMFunction_change_cutoff_lfo_depth;
361 friend class InstrumentScriptVMFunction_change_cutoff_lfo_freq;
362 friend class InstrumentScriptVMFunction_change_pitch_lfo_depth;
363 friend class InstrumentScriptVMFunction_change_pitch_lfo_freq;
364 friend class VMChangeFadeCurveFunction;
365 friend class InstrumentScriptVMFunction_fade_in;
366 friend class InstrumentScriptVMFunction_fade_out;
367 friend class InstrumentScriptVMFunction_get_event_par;
368 friend class InstrumentScriptVMFunction_set_event_par;
369 friend class InstrumentScriptVMFunction_change_note;
370 friend class InstrumentScriptVMFunction_change_velo;
371 friend class InstrumentScriptVMFunction_change_play_pos;
372 friend class InstrumentScriptVMFunction_event_status;
373 friend class InstrumentScriptVMFunction_wait;
374 friend class InstrumentScriptVMFunction_stop_wait;
375 friend class InstrumentScriptVMFunction_abort;
376 friend class InstrumentScriptVMFunction_fork;
377 friend class InstrumentScriptVMFunction_callback_status;
378 friend class InstrumentScriptVMDynVar_ENGINE_UPTIME;
379 friend class InstrumentScriptVMDynVar_NI_CALLBACK_ID;
380 friend class InstrumentScriptVMDynVar_ALL_EVENTS;
381 friend class InstrumentScriptVMDynVar_NKSP_CALLBACK_CHILD_ID;
382 };
383
384 } // namespace LinuxSampler
385
386 #endif // LS_INSTRUMENT_SCRIPT_VM_H

  ViewVC Help
Powered by ViewVC