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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2594 by schoenebeck, Thu Jun 5 00:16:25 2014 UTC revision 3293 by schoenebeck, Tue Jun 27 22:19:19 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014 Christian Schoenebeck   * Copyright (c) 2014-2017 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 11  Line 11 
11  #define LS_INSTRUMENT_SCRIPT_VM_H  #define LS_INSTRUMENT_SCRIPT_VM_H
12    
13  #include "../../common/global.h"  #include "../../common/global.h"
14    #include "../../common/ConstCapacityArray.h"
15  #include "../../scriptvm/ScriptVM.h"  #include "../../scriptvm/ScriptVM.h"
16  #include "Event.h"  #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  namespace LinuxSampler {  namespace LinuxSampler {
79    
80        class AbstractEngineChannel;
81        struct InstrumentScript;
82    
83        /** @brief Convert IDs between script scope and engine internal scope.
84         *
85         * This class is used to translate unique IDs of events between script
86         * scope and sampler engine internal scope, that is:
87         * @code
88         * int (script scope) -> event_id_t (engine internal scope)
89         * int (script scope) -> note_id_t (engine internal scope)
90         * @endcode
91         * and vice versa:
92         * @code
93         * event_id_t (engine internal scope) -> int (script scope)
94         * note_id_t (engine internal scope)  -> int (script scope)
95         * @endcode
96         * This is required because engine internally i.e. notes and regular events
97         * are using their own, separate ID generating pool, and their ID number
98         * set may thus overlap and historically there were built-in script
99         * functions in KSP which allow to pass both regular MIDI event IDs, as well
100         * as Note IDs. So we must be able to distinguish between them in our
101         * built-in script function implementations.
102         *
103         * @see INSTR_SCRIPT_EVENT_ID_RESERVED_BITS
104         */
105        class ScriptID {
106        public:
107            enum type_t {
108                EVENT, ///< ID is actually an event ID
109                NOTE, ///< ID is actually a note ID
110            };
111    
112            /**
113             * Construct a ScriptID object with an ID from script scope.
114             */
115            ScriptID(uint id) : m_id(id) {}
116    
117            /**
118             * Returns a ScriptID object constructed with an event ID from engine
119             * internal scope.
120             */
121            inline static ScriptID fromEventID(event_id_t id) {
122                return ScriptID(INSTR_SCRIPT_EVENT_ID_FLAG | id);
123            }
124    
125            /**
126             * Returns a ScriptID object constructed with a note ID from engine
127             * internal scope.
128             */
129            inline static ScriptID fromNoteID(note_id_t id) {
130                return ScriptID(INSTR_SCRIPT_NOTE_ID_FLAG | id);
131            }
132    
133            /**
134             * Whether the ID reflected by this ScriptID object is actually a note
135             * ID or rather an event ID.
136             */
137            inline type_t type() const {
138                return (m_id & INSTR_SCRIPT_NOTE_ID_FLAG) ? NOTE : EVENT;
139            }
140    
141            inline bool isNoteID() const {
142                return type() == NOTE;
143            }
144    
145            inline bool isEventID() const {
146                return type() == EVENT;
147            }
148    
149            /**
150             * Returns event ID (for engine internal scope) of the ID reflected by
151             * this ScriptID object, it returns 0 (being an invalid ID) if the ID
152             * reflected by this ScriptID object is not an event ID.
153             */
154            inline event_id_t eventID() const {
155                switch (type()) {
156                    case EVENT: return m_id;
157                    default:    return 0; // not an event id, return invalid ID
158                }
159            }
160    
161            /**
162             * Returns note ID (for engine internal scope) of the ID reflected by
163             * this ScriptID object, it returns 0 (being an invalid ID) if the ID
164             * reflected by this ScriptID object is not a note ID.
165             */
166            inline note_id_t noteID() const {
167                switch (type()) {
168                    case NOTE: return ~INSTR_SCRIPT_NOTE_ID_FLAG & m_id;
169                    default:   return 0; // not a note id, return invalid ID
170                }
171            }
172    
173            /**
174             * Integer cast operator, which returns an ID number of this ScripID
175             * object intended for script scope.
176             */
177            inline operator uint() const {
178                return m_id;
179            }
180    
181        private:
182            uint m_id;
183        };
184    
185        /** @brief List of Event IDs.
186         *
187         * Used for built-in script functions:
188         *     by_marks(), set_event_mark(), delete_event_mark()
189         */
190        class EventGroup : protected ConstCapacityArray<int> {
191        public:
192            EventGroup() : ConstCapacityArray<int>(CONFIG_MAX_EVENTS_PER_FRAGMENT), m_script(NULL) {}
193            void insert(int eventID);
194            void erase(int eventID);
195            void setScript(InstrumentScript* pScript) { m_script = pScript; }
196            inline int size() const { return ConstCapacityArray<int>::size(); }
197            inline void clear() { ConstCapacityArray<int>::clear(); }
198            inline int& operator[](uint index) { return ConstCapacityArray<int>::operator[](index); }
199            inline const int& operator[](uint index) const { return ConstCapacityArray<int>::operator[](index); }
200        protected:
201            InstrumentScript* m_script;
202        };
203    
204        /** @brief Real-time instrument script VM representation.
205         *
206         * Holds the VM representation of all event handlers of the currently loaded
207         * script, ready to be executed by the sampler engine.
208         *
209         * Even thought scripts (or to be more specific their event handler objects)
210         * are shared between sampler engine channels, the InstrumentScript struct
211         * instances though are not shared. Each sampler engine channel has its own
212         * instance of a InstrumentScript struct. That's important, because this
213         * struct also holds engine channel local informations, for example the
214         * events that occured on the respective engine channel.
215         */
216        struct InstrumentScript {
217            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!
218            bool                  bHasValidScript; ///< True in case there is a valid script currently loaded, false if script processing shall be skipped.
219            VMEventHandler*       handlerInit; ///< VM representation of script's initilization callback or NULL if current script did not define such an init handler.
220            VMEventHandler*       handlerNote; ///< VM representation of script's MIDI note on callback or NULL if current script did not define such an event handler.
221            VMEventHandler*       handlerRelease; ///< VM representation of script's MIDI note off callback or NULL if current script did not define such an event handler.
222            VMEventHandler*       handlerController; ///< VM representation of script's MIDI controller callback or NULL if current script did not define such an event handler.
223            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).
224            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.
225            RTAVLTree<ScriptEvent> suspendedEvents; ///< Contains pointers to all suspended events, sorted by time when those script events are to be resumed next.
226            AbstractEngineChannel* pEngineChannel;
227            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.
228            EventGroup            eventGroups[INSTR_SCRIPT_EVENT_GROUPS]; ///< Used for built-in script functions: by_event_marks(), set_event_mark(), delete_event_mark().
229    
230            InstrumentScript(AbstractEngineChannel* pEngineChannel);
231            ~InstrumentScript();
232    
233            void load(const String& text);
234            void unload();
235            void resetAll();
236            void resetEvents();
237        };
238    
239      /** @brief Real-time instrument script virtual machine.      /** @brief Real-time instrument script virtual machine.
240       *       *
241       * Extends the core ScriptVM implementation with MIDI specific built-in       * Extends the core ScriptVM implementation with MIDI specific built-in
# Line 30  namespace LinuxSampler { Line 250  namespace LinuxSampler {
250      public:      public:
251          InstrumentScriptVM();          InstrumentScriptVM();
252          VMExecStatus_t exec(VMParserContext* parserCtx, ScriptEvent* event);          VMExecStatus_t exec(VMParserContext* parserCtx, ScriptEvent* event);
253            VMFunction* functionByName(const String& name) OVERRIDE;
254          std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;          std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;
255          std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;          std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;
256          std::map<String,int> builtInConstIntVariables() OVERRIDE;          std::map<String,int> builtInConstIntVariables() OVERRIDE;
257            std::map<String,VMDynVar*> builtInDynamicVariables() OVERRIDE;
258      protected:      protected:
259          ScriptEvent* m_event; ///< The event currently executed by exec().          ScriptEvent* m_event; ///< The event currently executed by exec().
260    
261          Event* m_cause;          // built-in script variables
   
         // buil-in script variables  
262          VMInt8Array m_CC;          VMInt8Array m_CC;
263          VMInt8RelPtr m_CC_NUM;          VMInt8RelPtr m_CC_NUM;
264            VMIntRelPtr  m_EVENT_ID;
265          VMInt8RelPtr m_EVENT_NOTE;          VMInt8RelPtr m_EVENT_NOTE;
266          VMInt8RelPtr m_EVENT_VELOCITY;          VMInt8RelPtr m_EVENT_VELOCITY;
267          //VMIntArray m_KEY_DOWN; //TODO: ...          VMInt8Array  m_KEY_DOWN;
268          //VMIntArray m_POLY_AT; //TODO: ...          //VMIntArray m_POLY_AT; //TODO: ...
269          //int m_POLY_AT_NUM; //TODO: ...          //int m_POLY_AT_NUM; //TODO: ...
270            VMIntRelPtr  m_NI_CALLBACK_TYPE;
271            VMIntRelPtr  m_NKSP_IGNORE_WAIT;
272            VMIntRelPtr  m_NKSP_CALLBACK_PARENT_ID;
273    
274            // built-in script functions
275            InstrumentScriptVMFunction_play_note m_fnPlayNote;
276            InstrumentScriptVMFunction_set_controller m_fnSetController;
277            InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;
278            InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;
279            InstrumentScriptVMFunction_note_off m_fnNoteOff;
280            InstrumentScriptVMFunction_set_event_mark m_fnSetEventMark;
281            InstrumentScriptVMFunction_delete_event_mark m_fnDeleteEventMark;
282            InstrumentScriptVMFunction_by_marks m_fnByMarks;
283            InstrumentScriptVMFunction_change_vol m_fnChangeVol;
284            InstrumentScriptVMFunction_change_vol_time m_fnChangeVolTime;
285            InstrumentScriptVMFunction_change_tune m_fnChangeTune;
286            InstrumentScriptVMFunction_change_tune_time m_fnChangeTuneTime;
287            InstrumentScriptVMFunction_change_pan m_fnChangePan;
288            InstrumentScriptVMFunction_change_cutoff m_fnChangeCutoff;
289            InstrumentScriptVMFunction_change_reso m_fnChangeReso;
290            InstrumentScriptVMFunction_change_attack m_fnChangeAttack;
291            InstrumentScriptVMFunction_change_decay m_fnChangeDecay;
292            InstrumentScriptVMFunction_change_release m_fnChangeRelease;
293            InstrumentScriptVMFunction_change_amp_lfo_depth m_fnChangeAmpLFODepth;
294            InstrumentScriptVMFunction_change_amp_lfo_freq m_fnChangeAmpLFOFreq;
295            InstrumentScriptVMFunction_change_pitch_lfo_depth m_fnChangePitchLFODepth;
296            InstrumentScriptVMFunction_change_pitch_lfo_freq m_fnChangePitchLFOFreq;
297            InstrumentScriptVMFunction_change_note m_fnChangeNote;
298            InstrumentScriptVMFunction_change_velo m_fnChangeVelo;
299            InstrumentScriptVMFunction_fork m_fnFork;
300            InstrumentScriptVMFunction_event_status m_fnEventStatus;
301            InstrumentScriptVMFunction_wait m_fnWait2;
302            InstrumentScriptVMFunction_stop_wait m_fnStopWait;
303            InstrumentScriptVMFunction_abort m_fnAbort;
304            InstrumentScriptVMFunction_fade_in m_fnFadeIn;
305            InstrumentScriptVMFunction_fade_out m_fnFadeOut;
306            InstrumentScriptVMFunction_change_vol_curve m_fnChangeVolCurve;
307            InstrumentScriptVMFunction_change_tune_curve m_fnChangeTuneCurve;
308            InstrumentScriptVMFunction_get_event_par m_fnGetEventPar;
309            InstrumentScriptVMFunction_set_event_par m_fnSetEventPar;
310            InstrumentScriptVMFunction_change_play_pos m_fnChangePlayPos;
311            InstrumentScriptVMDynVar_ENGINE_UPTIME m_varEngineUptime;
312            InstrumentScriptVMDynVar_NI_CALLBACK_ID m_varCallbackID;
313            InstrumentScriptVMDynVar_ALL_EVENTS m_varAllEvents;
314            InstrumentScriptVMDynVar_NKSP_CALLBACK_CHILD_ID m_varCallbackChildID;
315    
316            friend class InstrumentScriptVMFunction_play_note;
317            friend class InstrumentScriptVMFunction_set_controller;
318            friend class InstrumentScriptVMFunction_ignore_event;
319            friend class InstrumentScriptVMFunction_ignore_controller;
320            friend class InstrumentScriptVMFunction_note_off;
321            friend class InstrumentScriptVMFunction_set_event_mark;
322            friend class InstrumentScriptVMFunction_delete_event_mark;
323            friend class InstrumentScriptVMFunction_by_marks;
324            friend class InstrumentScriptVMFunction_change_vol;
325            friend class InstrumentScriptVMFunction_change_vol_time;
326            friend class InstrumentScriptVMFunction_change_tune;
327            friend class InstrumentScriptVMFunction_change_tune_time;
328            friend class InstrumentScriptVMFunction_change_pan;
329            friend class InstrumentScriptVMFunction_change_cutoff;
330            friend class InstrumentScriptVMFunction_change_reso;
331            friend class InstrumentScriptVMFunction_change_attack;
332            friend class InstrumentScriptVMFunction_change_decay;
333            friend class InstrumentScriptVMFunction_change_release;
334            friend class VMChangeSynthParamFunction;
335            friend class InstrumentScriptVMFunction_change_amp_lfo_depth;
336            friend class InstrumentScriptVMFunction_change_amp_lfo_freq;
337            friend class InstrumentScriptVMFunction_change_pitch_lfo_depth;
338            friend class InstrumentScriptVMFunction_change_pitch_lfo_freq;
339            friend class VMChangeFadeCurveFunction;
340            friend class InstrumentScriptVMFunction_fade_in;
341            friend class InstrumentScriptVMFunction_fade_out;
342            friend class InstrumentScriptVMFunction_get_event_par;
343            friend class InstrumentScriptVMFunction_set_event_par;
344            friend class InstrumentScriptVMFunction_change_note;
345            friend class InstrumentScriptVMFunction_change_velo;
346            friend class InstrumentScriptVMFunction_change_play_pos;
347            friend class InstrumentScriptVMFunction_event_status;
348            friend class InstrumentScriptVMFunction_wait;
349            friend class InstrumentScriptVMFunction_stop_wait;
350            friend class InstrumentScriptVMFunction_abort;
351            friend class InstrumentScriptVMFunction_fork;
352            friend class InstrumentScriptVMDynVar_ENGINE_UPTIME;
353            friend class InstrumentScriptVMDynVar_NI_CALLBACK_ID;
354            friend class InstrumentScriptVMDynVar_ALL_EVENTS;
355            friend class InstrumentScriptVMDynVar_NKSP_CALLBACK_CHILD_ID;
356      };      };
357    
358  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2594  
changed lines
  Added in v.3293

  ViewVC Help
Powered by ViewVC