/[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 2629 by schoenebeck, Thu Jun 12 18:25:11 2014 UTC revision 3296 by schoenebeck, Wed Jun 28 09:45:56 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"  #include "../../common/Pool.h"
18  #include "InstrumentScriptVMFunctions.h"  #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 {  namespace LinuxSampler {
85    
86      class AbstractEngineChannel;      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.      /** @brief Real-time instrument script VM representation.
211       *       *
212       * Holds the VM representation of all event handlers of the currently loaded       * Holds the VM representation of all event handlers of the currently loaded
213       * script, ready to be executed by the sampler engine.       * 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 {      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!          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!
# Line 32  namespace LinuxSampler { Line 226  namespace LinuxSampler {
226          VMEventHandler*       handlerNote; ///< VM representation of script's MIDI note on callback or NULL if current script did not define such an event handler.          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.          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.          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.          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;          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.          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) {          InstrumentScript(AbstractEngineChannel* pEngineChannel);
237              parserContext = NULL;          ~InstrumentScript();
             bHasValidScript = false;  
             handlerInit = NULL;  
             handlerNote = NULL;  
             handlerRelease = NULL;  
             handlerController = NULL;  
             pEvents = NULL;  
             this->pEngineChannel = pEngineChannel;  
         }  
   
         ~InstrumentScript() {  
             resetAll();  
         }  
238    
239          void load(const String& text);          void load(const String& text);
240          void unload();          void unload();
241          void resetAll();          void resetAll();
242            void resetEvents();
243      };      };
244    
245      /** @brief Real-time instrument script virtual machine.      /** @brief Real-time instrument script virtual machine.
# Line 74  namespace LinuxSampler { Line 260  namespace LinuxSampler {
260          std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;          std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;
261          std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;          std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;
262          std::map<String,int> builtInConstIntVariables() OVERRIDE;          std::map<String,int> builtInConstIntVariables() OVERRIDE;
263            std::map<String,VMDynVar*> builtInDynamicVariables() OVERRIDE;
264      protected:      protected:
265          ScriptEvent* m_event; ///< The event currently executed by exec().          ScriptEvent* m_event; ///< The event currently executed by exec().
266    
267          // buil-in script variables          // built-in script variables
268          VMInt8Array m_CC;          VMInt8Array m_CC;
269          VMInt8RelPtr m_CC_NUM;          VMInt8RelPtr m_CC_NUM;
270          VMIntRelPtr  m_EVENT_ID;          VMIntRelPtr  m_EVENT_ID;
# Line 86  namespace LinuxSampler { Line 273  namespace LinuxSampler {
273          VMInt8Array  m_KEY_DOWN;          VMInt8Array  m_KEY_DOWN;
274          //VMIntArray m_POLY_AT; //TODO: ...          //VMIntArray m_POLY_AT; //TODO: ...
275          //int m_POLY_AT_NUM; //TODO: ...          //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          // buil-in script functions          // built-in script functions
281          InstrumentScriptVMFunction_play_note m_fnPlayNote;          InstrumentScriptVMFunction_play_note m_fnPlayNote;
282          InstrumentScriptVMFunction_set_controller m_fnSetController;          InstrumentScriptVMFunction_set_controller m_fnSetController;
283          InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;          InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;
284          InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;          InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;
285          InstrumentScriptVMFunction_note_off m_fnNoteOff;          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_cutoff m_fnChangeCutoff;
295            InstrumentScriptVMFunction_change_reso m_fnChangeReso;
296            InstrumentScriptVMFunction_change_attack m_fnChangeAttack;
297            InstrumentScriptVMFunction_change_decay m_fnChangeDecay;
298            InstrumentScriptVMFunction_change_release m_fnChangeRelease;
299            InstrumentScriptVMFunction_change_amp_lfo_depth m_fnChangeAmpLFODepth;
300            InstrumentScriptVMFunction_change_amp_lfo_freq m_fnChangeAmpLFOFreq;
301            InstrumentScriptVMFunction_change_pitch_lfo_depth m_fnChangePitchLFODepth;
302            InstrumentScriptVMFunction_change_pitch_lfo_freq m_fnChangePitchLFOFreq;
303            InstrumentScriptVMFunction_change_note m_fnChangeNote;
304            InstrumentScriptVMFunction_change_velo m_fnChangeVelo;
305            InstrumentScriptVMFunction_fork m_fnFork;
306            InstrumentScriptVMFunction_event_status m_fnEventStatus;
307            InstrumentScriptVMFunction_wait m_fnWait2;
308            InstrumentScriptVMFunction_stop_wait m_fnStopWait;
309            InstrumentScriptVMFunction_abort m_fnAbort;
310            InstrumentScriptVMFunction_fade_in m_fnFadeIn;
311            InstrumentScriptVMFunction_fade_out m_fnFadeOut;
312            InstrumentScriptVMFunction_change_vol_curve m_fnChangeVolCurve;
313            InstrumentScriptVMFunction_change_tune_curve m_fnChangeTuneCurve;
314            InstrumentScriptVMFunction_get_event_par m_fnGetEventPar;
315            InstrumentScriptVMFunction_set_event_par m_fnSetEventPar;
316            InstrumentScriptVMFunction_change_play_pos m_fnChangePlayPos;
317            InstrumentScriptVMFunction_callback_status m_fnCallbackStatus;
318            InstrumentScriptVMDynVar_ENGINE_UPTIME m_varEngineUptime;
319            InstrumentScriptVMDynVar_NI_CALLBACK_ID m_varCallbackID;
320            InstrumentScriptVMDynVar_ALL_EVENTS m_varAllEvents;
321            InstrumentScriptVMDynVar_NKSP_CALLBACK_CHILD_ID m_varCallbackChildID;
322    
323          friend class InstrumentScriptVMFunction_play_note;          friend class InstrumentScriptVMFunction_play_note;
324          friend class InstrumentScriptVMFunction_set_controller;          friend class InstrumentScriptVMFunction_set_controller;
325          friend class InstrumentScriptVMFunction_ignore_event;          friend class InstrumentScriptVMFunction_ignore_event;
326          friend class InstrumentScriptVMFunction_ignore_controller;          friend class InstrumentScriptVMFunction_ignore_controller;
327          friend class InstrumentScriptVMFunction_note_off;          friend class InstrumentScriptVMFunction_note_off;
328            friend class InstrumentScriptVMFunction_set_event_mark;
329            friend class InstrumentScriptVMFunction_delete_event_mark;
330            friend class InstrumentScriptVMFunction_by_marks;
331            friend class InstrumentScriptVMFunction_change_vol;
332            friend class InstrumentScriptVMFunction_change_vol_time;
333            friend class InstrumentScriptVMFunction_change_tune;
334            friend class InstrumentScriptVMFunction_change_tune_time;
335            friend class InstrumentScriptVMFunction_change_pan;
336            friend class InstrumentScriptVMFunction_change_cutoff;
337            friend class InstrumentScriptVMFunction_change_reso;
338            friend class InstrumentScriptVMFunction_change_attack;
339            friend class InstrumentScriptVMFunction_change_decay;
340            friend class InstrumentScriptVMFunction_change_release;
341            friend class VMChangeSynthParamFunction;
342            friend class InstrumentScriptVMFunction_change_amp_lfo_depth;
343            friend class InstrumentScriptVMFunction_change_amp_lfo_freq;
344            friend class InstrumentScriptVMFunction_change_pitch_lfo_depth;
345            friend class InstrumentScriptVMFunction_change_pitch_lfo_freq;
346            friend class VMChangeFadeCurveFunction;
347            friend class InstrumentScriptVMFunction_fade_in;
348            friend class InstrumentScriptVMFunction_fade_out;
349            friend class InstrumentScriptVMFunction_get_event_par;
350            friend class InstrumentScriptVMFunction_set_event_par;
351            friend class InstrumentScriptVMFunction_change_note;
352            friend class InstrumentScriptVMFunction_change_velo;
353            friend class InstrumentScriptVMFunction_change_play_pos;
354            friend class InstrumentScriptVMFunction_event_status;
355            friend class InstrumentScriptVMFunction_wait;
356            friend class InstrumentScriptVMFunction_stop_wait;
357            friend class InstrumentScriptVMFunction_abort;
358            friend class InstrumentScriptVMFunction_fork;
359            friend class InstrumentScriptVMFunction_callback_status;
360            friend class InstrumentScriptVMDynVar_ENGINE_UPTIME;
361            friend class InstrumentScriptVMDynVar_NI_CALLBACK_ID;
362            friend class InstrumentScriptVMDynVar_ALL_EVENTS;
363            friend class InstrumentScriptVMDynVar_NKSP_CALLBACK_CHILD_ID;
364      };      };
365    
366  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2629  
changed lines
  Added in v.3296

  ViewVC Help
Powered by ViewVC