/[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 2935 - (show annotations) (download) (as text)
Sun Jul 10 14:24:13 2016 UTC (7 years, 8 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 12162 byte(s)
* NKSP: Added & implemented built-in script function "change_cutoff()".
* NKSP: Added & implemented built-in script function "change_reso()".
* NKSP: Added & implemented built-in script function "event_status()".
* NKSP: Added built-in script constants "$EVENT_STATUS_INACTIVE" and
  "$EVENT_STATUS_NOTE_QUEUE" both for being used as flags for
  built-in "event_status()" script function.
* NKSP language: Added support for bitwise operators ".or.", ".and."
  and ".not.".
* NKSP language scanner: Fixed IDs matching to require at least one
  character (i.e. when matching function names or variable names).
* NKSP language scanner: disabled unusued rules.
* Bumped version (2.0.0.svn12).

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
20 /**
21 * Amount of bits on the left hand side of all pool_element_id_t numbers (i.e.
22 * event_id_t, note_id_t) being reserved for script VM implementation internal
23 * purposes.
24 *
25 * Right now there is only one bit reserved, which allows the VM (and its
26 * built-in functions) to distinguish user supplied @c Event IDs (event_id_t)
27 * from @c Note IDs (note_id_t).
28 */
29 #define INSTR_SCRIPT_EVENT_ID_RESERVED_BITS 1
30
31 /**
32 * Used to mark IDs (in script scope) to actually be a note ID.
33 */
34 #define INSTR_SCRIPT_NOTE_ID_FLAG (1 << (sizeof(pool_element_id_t) * 8 - 1))
35
36 #define INSTR_SCRIPT_EVENT_GROUPS 28
37
38 #define EVENT_STATUS_INACTIVE 0
39 #define EVENT_STATUS_NOTE_QUEUE 1
40
41 namespace LinuxSampler {
42
43 class AbstractEngineChannel;
44 class InstrumentScript;
45
46 /** @brief Convert IDs between script scope and engine internal scope.
47 *
48 * This class is used to translate unique IDs of events between script
49 * scope and sampler engine internal scope, that is:
50 * @code
51 * int (script scope) -> event_id_t (engine internal scope)
52 * int (script scope) -> note_id_t (engine internal scope)
53 * @endcode
54 * and vice versa:
55 * @code
56 * event_id_t (engine internal scope) -> int (script scope)
57 * note_id_t (engine internal scope) -> int (script scope)
58 * @endcode
59 * This is required because engine internally notes and regular events are
60 * using their own, separate ID generating pool, and their ID number set
61 * may thus overlap.
62 *
63 * @see INSTR_SCRIPT_EVENT_ID_RESERVED_BITS
64 */
65 class ScriptID {
66 public:
67 enum type_t {
68 EVENT, ///< ID is actually an event ID
69 NOTE, ///< ID is actually a note ID
70 };
71
72 /**
73 * Construct a ScriptID object with an ID from script scope.
74 */
75 ScriptID(uint id) : m_id(id) {}
76
77 /**
78 * Returns a ScriptID object constructed with an event ID from engine
79 * internal scope.
80 */
81 inline static ScriptID fromEventID(event_id_t id) {
82 return ScriptID(id);
83 }
84
85 /**
86 * Returns a ScriptID object constructed with a note ID from engine
87 * internal scope.
88 */
89 inline static ScriptID fromNoteID(note_id_t id) {
90 return ScriptID(INSTR_SCRIPT_NOTE_ID_FLAG | id);
91 }
92
93 /**
94 * Whether the ID reflected by this ScriptID object is actually a note
95 * ID or rather an event ID.
96 */
97 inline type_t type() const {
98 return (m_id & INSTR_SCRIPT_NOTE_ID_FLAG) ? NOTE : EVENT;
99 }
100
101 inline bool isNoteID() const {
102 return type() == NOTE;
103 }
104
105 inline bool isEventID() const {
106 return type() == EVENT;
107 }
108
109 /**
110 * Returns event ID (for engine internal scope) of the ID reflected by
111 * this ScriptID object, it returns 0 (being an invalid ID) if the ID
112 * reflected by this ScriptID object is not an event ID.
113 */
114 inline event_id_t eventID() const {
115 switch (type()) {
116 case EVENT: return m_id;
117 default: return 0; // not an event id, return invalid ID
118 }
119 }
120
121 /**
122 * Returns note ID (for engine internal scope) of the ID reflected by
123 * this ScriptID object, it returns 0 (being an invalid ID) if the ID
124 * reflected by this ScriptID object is not a note ID.
125 */
126 inline note_id_t noteID() const {
127 switch (type()) {
128 case NOTE: return ~INSTR_SCRIPT_NOTE_ID_FLAG & m_id;
129 default: return 0; // not a note id, return invalid ID
130 }
131 }
132
133 /**
134 * Integer cast operator, which returns an ID number of this ScripID
135 * object intended for script scope.
136 */
137 inline operator uint() const {
138 return m_id;
139 }
140
141 private:
142 uint m_id;
143 };
144
145 /** @brief List of Event IDs.
146 *
147 * Used for built-in script functions:
148 * by_marks(), set_event_mark(), delete_event_mark()
149 */
150 class EventGroup : protected ConstCapacityArray<int> {
151 public:
152 EventGroup() : ConstCapacityArray<int>(CONFIG_MAX_EVENTS_PER_FRAGMENT), m_script(NULL) {}
153 void insert(int eventID);
154 void erase(int eventID);
155 void setScript(InstrumentScript* pScript) { m_script = pScript; }
156 inline int size() const { return ConstCapacityArray<int>::size(); }
157 inline void clear() { ConstCapacityArray<int>::clear(); }
158 inline int& operator[](uint index) { return ConstCapacityArray<int>::operator[](index); }
159 inline const int& operator[](uint index) const { return ConstCapacityArray<int>::operator[](index); }
160 protected:
161 InstrumentScript* m_script;
162 };
163
164 /** @brief Real-time instrument script VM representation.
165 *
166 * Holds the VM representation of all event handlers of the currently loaded
167 * script, ready to be executed by the sampler engine.
168 *
169 * Even thought scripts (or to be more specific their event handler objects)
170 * are shared between sampler engine channels, the InstrumentScript struct
171 * instances though are not shared. Each sampler engine channel has its own
172 * instance of a InstrumentScript struct. That's important, because this
173 * struct also holds engine channel local informations, for example the
174 * events that occured on the respective engine channel.
175 */
176 struct InstrumentScript {
177 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!
178 bool bHasValidScript; ///< True in case there is a valid script currently loaded, false if script processing shall be skipped.
179 VMEventHandler* handlerInit; ///< VM representation of script's initilization callback or NULL if current script did not define such an init handler.
180 VMEventHandler* handlerNote; ///< VM representation of script's MIDI note on callback or NULL if current script did not define such an event handler.
181 VMEventHandler* handlerRelease; ///< VM representation of script's MIDI note off callback or NULL if current script did not define such an event handler.
182 VMEventHandler* handlerController; ///< VM representation of script's MIDI controller callback or NULL if current script did not define such an event handler.
183 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).
184 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.
185 RTAVLTree<ScriptEvent> suspendedEvents; ///< Contains pointers to all suspended events, sorted by time when those script events are to be resumed next.
186 AbstractEngineChannel* pEngineChannel;
187 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.
188 EventGroup eventGroups[INSTR_SCRIPT_EVENT_GROUPS]; ///< Used for built-in script functions: by_event_marks(), set_event_mark(), delete_event_mark().
189
190 InstrumentScript(AbstractEngineChannel* pEngineChannel);
191 ~InstrumentScript();
192
193 void load(const String& text);
194 void unload();
195 void resetAll();
196 void resetEvents();
197 };
198
199 /** @brief Real-time instrument script virtual machine.
200 *
201 * Extends the core ScriptVM implementation with MIDI specific built-in
202 * script functions and MIDI specific built-in script variables required
203 * for MIDI processing by instrument script for all sampler engine
204 * implementations (sampler formats) of this sampler.
205 *
206 * Note that this class is currently re-entrant safe, but @b not thread
207 * safe! See also comments of base class ScriptVM regarding this issue.
208 */
209 class InstrumentScriptVM : public ScriptVM {
210 public:
211 InstrumentScriptVM();
212 VMExecStatus_t exec(VMParserContext* parserCtx, ScriptEvent* event);
213 VMFunction* functionByName(const String& name) OVERRIDE;
214 std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;
215 std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;
216 std::map<String,int> builtInConstIntVariables() OVERRIDE;
217 protected:
218 ScriptEvent* m_event; ///< The event currently executed by exec().
219
220 // buil-in script variables
221 VMInt8Array m_CC;
222 VMInt8RelPtr m_CC_NUM;
223 VMIntRelPtr m_EVENT_ID;
224 VMInt8RelPtr m_EVENT_NOTE;
225 VMInt8RelPtr m_EVENT_VELOCITY;
226 VMInt8Array m_KEY_DOWN;
227 //VMIntArray m_POLY_AT; //TODO: ...
228 //int m_POLY_AT_NUM; //TODO: ...
229
230 // buil-in script functions
231 InstrumentScriptVMFunction_play_note m_fnPlayNote;
232 InstrumentScriptVMFunction_set_controller m_fnSetController;
233 InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;
234 InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;
235 InstrumentScriptVMFunction_note_off m_fnNoteOff;
236 InstrumentScriptVMFunction_set_event_mark m_fnSetEventMark;
237 InstrumentScriptVMFunction_delete_event_mark m_fnDeleteEventMark;
238 InstrumentScriptVMFunction_by_marks m_fnByMarks;
239 InstrumentScriptVMFunction_change_vol m_fnChangeVol;
240 InstrumentScriptVMFunction_change_tune m_fnChangeTune;
241 InstrumentScriptVMFunction_change_pan m_fnChangePan;
242 InstrumentScriptVMFunction_change_cutoff m_fnChangeCutoff;
243 InstrumentScriptVMFunction_change_reso m_fnChangeReso;
244 InstrumentScriptVMFunction_event_status m_fnEventStatus;
245
246 friend class InstrumentScriptVMFunction_play_note;
247 friend class InstrumentScriptVMFunction_set_controller;
248 friend class InstrumentScriptVMFunction_ignore_event;
249 friend class InstrumentScriptVMFunction_ignore_controller;
250 friend class InstrumentScriptVMFunction_note_off;
251 friend class InstrumentScriptVMFunction_set_event_mark;
252 friend class InstrumentScriptVMFunction_delete_event_mark;
253 friend class InstrumentScriptVMFunction_by_marks;
254 friend class InstrumentScriptVMFunction_change_vol;
255 friend class InstrumentScriptVMFunction_change_tune;
256 friend class InstrumentScriptVMFunction_change_pan;
257 friend class InstrumentScriptVMFunction_change_cutoff;
258 friend class InstrumentScriptVMFunction_change_reso;
259 friend class InstrumentScriptVMFunction_event_status;
260 };
261
262 } // namespace LinuxSampler
263
264 #endif // LS_INSTRUMENT_SCRIPT_VM_H

  ViewVC Help
Powered by ViewVC