/[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 3034 - (show annotations) (download) (as text)
Mon Oct 31 00:05:00 2016 UTC (7 years, 4 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 14387 byte(s)
* Fixed a bunch of minor issues (mostly compiler warnings).
* Bumped version (2.0.0.svn31).

1 /*
2 * Copyright (c) 2014-2016 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 namespace LinuxSampler {
68
69 class AbstractEngineChannel;
70 struct InstrumentScript;
71
72 /** @brief Convert IDs between script scope and engine internal scope.
73 *
74 * This class is used to translate unique IDs of events between script
75 * scope and sampler engine internal scope, that is:
76 * @code
77 * int (script scope) -> event_id_t (engine internal scope)
78 * int (script scope) -> note_id_t (engine internal scope)
79 * @endcode
80 * and vice versa:
81 * @code
82 * event_id_t (engine internal scope) -> int (script scope)
83 * note_id_t (engine internal scope) -> int (script scope)
84 * @endcode
85 * This is required because engine internally i.e. notes and regular events
86 * are using their own, separate ID generating pool, and their ID number
87 * set may thus overlap and historically there were built-in script
88 * functions in KSP which allow to pass both regular MIDI event IDs, as well
89 * as Note IDs. So we must be able to distinguish between them in our
90 * built-in script function implementations.
91 *
92 * @see INSTR_SCRIPT_EVENT_ID_RESERVED_BITS
93 */
94 class ScriptID {
95 public:
96 enum type_t {
97 EVENT, ///< ID is actually an event ID
98 NOTE, ///< ID is actually a note ID
99 };
100
101 /**
102 * Construct a ScriptID object with an ID from script scope.
103 */
104 ScriptID(uint id) : m_id(id) {}
105
106 /**
107 * Returns a ScriptID object constructed with an event ID from engine
108 * internal scope.
109 */
110 inline static ScriptID fromEventID(event_id_t id) {
111 return ScriptID(INSTR_SCRIPT_EVENT_ID_FLAG | id);
112 }
113
114 /**
115 * Returns a ScriptID object constructed with a note ID from engine
116 * internal scope.
117 */
118 inline static ScriptID fromNoteID(note_id_t id) {
119 return ScriptID(INSTR_SCRIPT_NOTE_ID_FLAG | id);
120 }
121
122 /**
123 * Whether the ID reflected by this ScriptID object is actually a note
124 * ID or rather an event ID.
125 */
126 inline type_t type() const {
127 return (m_id & INSTR_SCRIPT_NOTE_ID_FLAG) ? NOTE : EVENT;
128 }
129
130 inline bool isNoteID() const {
131 return type() == NOTE;
132 }
133
134 inline bool isEventID() const {
135 return type() == EVENT;
136 }
137
138 /**
139 * Returns event ID (for engine internal scope) of the ID reflected by
140 * this ScriptID object, it returns 0 (being an invalid ID) if the ID
141 * reflected by this ScriptID object is not an event ID.
142 */
143 inline event_id_t eventID() const {
144 switch (type()) {
145 case EVENT: return m_id;
146 default: return 0; // not an event id, return invalid ID
147 }
148 }
149
150 /**
151 * Returns note ID (for engine internal scope) of the ID reflected by
152 * this ScriptID object, it returns 0 (being an invalid ID) if the ID
153 * reflected by this ScriptID object is not a note ID.
154 */
155 inline note_id_t noteID() const {
156 switch (type()) {
157 case NOTE: return ~INSTR_SCRIPT_NOTE_ID_FLAG & m_id;
158 default: return 0; // not a note id, return invalid ID
159 }
160 }
161
162 /**
163 * Integer cast operator, which returns an ID number of this ScripID
164 * object intended for script scope.
165 */
166 inline operator uint() const {
167 return m_id;
168 }
169
170 private:
171 uint m_id;
172 };
173
174 /** @brief List of Event IDs.
175 *
176 * Used for built-in script functions:
177 * by_marks(), set_event_mark(), delete_event_mark()
178 */
179 class EventGroup : protected ConstCapacityArray<int> {
180 public:
181 EventGroup() : ConstCapacityArray<int>(CONFIG_MAX_EVENTS_PER_FRAGMENT), m_script(NULL) {}
182 void insert(int eventID);
183 void erase(int eventID);
184 void setScript(InstrumentScript* pScript) { m_script = pScript; }
185 inline int size() const { return ConstCapacityArray<int>::size(); }
186 inline void clear() { ConstCapacityArray<int>::clear(); }
187 inline int& operator[](uint index) { return ConstCapacityArray<int>::operator[](index); }
188 inline const int& operator[](uint index) const { return ConstCapacityArray<int>::operator[](index); }
189 protected:
190 InstrumentScript* m_script;
191 };
192
193 /** @brief Real-time instrument script VM representation.
194 *
195 * Holds the VM representation of all event handlers of the currently loaded
196 * script, ready to be executed by the sampler engine.
197 *
198 * Even thought scripts (or to be more specific their event handler objects)
199 * are shared between sampler engine channels, the InstrumentScript struct
200 * instances though are not shared. Each sampler engine channel has its own
201 * instance of a InstrumentScript struct. That's important, because this
202 * struct also holds engine channel local informations, for example the
203 * events that occured on the respective engine channel.
204 */
205 struct InstrumentScript {
206 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!
207 bool bHasValidScript; ///< True in case there is a valid script currently loaded, false if script processing shall be skipped.
208 VMEventHandler* handlerInit; ///< VM representation of script's initilization callback or NULL if current script did not define such an init handler.
209 VMEventHandler* handlerNote; ///< VM representation of script's MIDI note on callback or NULL if current script did not define such an event handler.
210 VMEventHandler* handlerRelease; ///< VM representation of script's MIDI note off callback or NULL if current script did not define such an event handler.
211 VMEventHandler* handlerController; ///< VM representation of script's MIDI controller callback or NULL if current script did not define such an event handler.
212 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).
213 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.
214 RTAVLTree<ScriptEvent> suspendedEvents; ///< Contains pointers to all suspended events, sorted by time when those script events are to be resumed next.
215 AbstractEngineChannel* pEngineChannel;
216 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.
217 EventGroup eventGroups[INSTR_SCRIPT_EVENT_GROUPS]; ///< Used for built-in script functions: by_event_marks(), set_event_mark(), delete_event_mark().
218
219 InstrumentScript(AbstractEngineChannel* pEngineChannel);
220 ~InstrumentScript();
221
222 void load(const String& text);
223 void unload();
224 void resetAll();
225 void resetEvents();
226 };
227
228 /** @brief Real-time instrument script virtual machine.
229 *
230 * Extends the core ScriptVM implementation with MIDI specific built-in
231 * script functions and MIDI specific built-in script variables required
232 * for MIDI processing by instrument script for all sampler engine
233 * implementations (sampler formats) of this sampler.
234 *
235 * Note that this class is currently re-entrant safe, but @b not thread
236 * safe! See also comments of base class ScriptVM regarding this issue.
237 */
238 class InstrumentScriptVM : public ScriptVM {
239 public:
240 InstrumentScriptVM();
241 VMExecStatus_t exec(VMParserContext* parserCtx, ScriptEvent* event);
242 VMFunction* functionByName(const String& name) OVERRIDE;
243 std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;
244 std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;
245 std::map<String,int> builtInConstIntVariables() OVERRIDE;
246 std::map<String,VMDynVar*> builtInDynamicVariables() OVERRIDE;
247 protected:
248 ScriptEvent* m_event; ///< The event currently executed by exec().
249
250 // buil-in script variables
251 VMInt8Array m_CC;
252 VMInt8RelPtr m_CC_NUM;
253 VMIntRelPtr m_EVENT_ID;
254 VMInt8RelPtr m_EVENT_NOTE;
255 VMInt8RelPtr m_EVENT_VELOCITY;
256 VMInt8Array m_KEY_DOWN;
257 //VMIntArray m_POLY_AT; //TODO: ...
258 //int m_POLY_AT_NUM; //TODO: ...
259 VMIntRelPtr m_NI_CALLBACK_TYPE;
260 VMIntRelPtr m_NKSP_IGNORE_WAIT;
261
262 // buil-in script functions
263 InstrumentScriptVMFunction_play_note m_fnPlayNote;
264 InstrumentScriptVMFunction_set_controller m_fnSetController;
265 InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;
266 InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;
267 InstrumentScriptVMFunction_note_off m_fnNoteOff;
268 InstrumentScriptVMFunction_set_event_mark m_fnSetEventMark;
269 InstrumentScriptVMFunction_delete_event_mark m_fnDeleteEventMark;
270 InstrumentScriptVMFunction_by_marks m_fnByMarks;
271 InstrumentScriptVMFunction_change_vol m_fnChangeVol;
272 InstrumentScriptVMFunction_change_tune m_fnChangeTune;
273 InstrumentScriptVMFunction_change_pan m_fnChangePan;
274 InstrumentScriptVMFunction_change_cutoff m_fnChangeCutoff;
275 InstrumentScriptVMFunction_change_reso m_fnChangeReso;
276 InstrumentScriptVMFunction_change_attack m_fnChangeAttack;
277 InstrumentScriptVMFunction_change_decay m_fnChangeDecay;
278 InstrumentScriptVMFunction_change_release m_fnChangeRelease;
279 InstrumentScriptVMFunction_event_status m_fnEventStatus;
280 InstrumentScriptVMFunction_wait m_fnWait2;
281 InstrumentScriptVMFunction_stop_wait m_fnStopWait;
282 InstrumentScriptVMDynVar_ENGINE_UPTIME m_varEngineUptime;
283 InstrumentScriptVMDynVar_NI_CALLBACK_ID m_varCallbackID;
284
285 friend class InstrumentScriptVMFunction_play_note;
286 friend class InstrumentScriptVMFunction_set_controller;
287 friend class InstrumentScriptVMFunction_ignore_event;
288 friend class InstrumentScriptVMFunction_ignore_controller;
289 friend class InstrumentScriptVMFunction_note_off;
290 friend class InstrumentScriptVMFunction_set_event_mark;
291 friend class InstrumentScriptVMFunction_delete_event_mark;
292 friend class InstrumentScriptVMFunction_by_marks;
293 friend class InstrumentScriptVMFunction_change_vol;
294 friend class InstrumentScriptVMFunction_change_tune;
295 friend class InstrumentScriptVMFunction_change_pan;
296 friend class InstrumentScriptVMFunction_change_cutoff;
297 friend class InstrumentScriptVMFunction_change_reso;
298 friend class InstrumentScriptVMFunction_change_attack;
299 friend class InstrumentScriptVMFunction_change_decay;
300 friend class InstrumentScriptVMFunction_change_release;
301 friend class InstrumentScriptVMFunction_event_status;
302 friend class InstrumentScriptVMFunction_wait;
303 friend class InstrumentScriptVMFunction_stop_wait;
304 friend class InstrumentScriptVMDynVar_ENGINE_UPTIME;
305 friend class InstrumentScriptVMDynVar_NI_CALLBACK_ID;
306 };
307
308 } // namespace LinuxSampler
309
310 #endif // LS_INSTRUMENT_SCRIPT_VM_H

  ViewVC Help
Powered by ViewVC