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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2942 - (hide annotations) (download) (as text)
Wed Jul 13 15:51:06 2016 UTC (7 years, 9 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 12399 byte(s)
* NKSP: Implemented built-in script variable "$KSP_TIMER".
* NKSP: Implemented built-in script variable "$NKSP_REAL_TIMER".
* NKSP: Implemented built-in script variable "$NKSP_PERF_TIMER".
* NKSP: Implemented built-in script variable "$ENGINE_UPTIME".
* Bumped version (2.0.0.svn14).

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

  ViewVC Help
Powered by ViewVC