/[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 3118 by schoenebeck, Fri Apr 21 13:33:03 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  namespace LinuxSampler {  namespace LinuxSampler {
68    
69      class AbstractEngineChannel;      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.      /** @brief Real-time instrument script VM representation.
194       *       *
195       * Holds the VM representation of all event handlers of the currently loaded       * Holds the VM representation of all event handlers of the currently loaded
196       * script, ready to be executed by the sampler engine.       * 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 {      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!          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 209  namespace LinuxSampler {
209          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.
210          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.
211          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.
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.          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;          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.          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) {          InstrumentScript(AbstractEngineChannel* pEngineChannel);
220              parserContext = NULL;          ~InstrumentScript();
             bHasValidScript = false;  
             handlerInit = NULL;  
             handlerNote = NULL;  
             handlerRelease = NULL;  
             handlerController = NULL;  
             pEvents = NULL;  
             this->pEngineChannel = pEngineChannel;  
         }  
   
         ~InstrumentScript() {  
             resetAll();  
         }  
221    
222          void load(const String& text);          void load(const String& text);
223          void unload();          void unload();
224          void resetAll();          void resetAll();
225            void resetEvents();
226      };      };
227    
228      /** @brief Real-time instrument script virtual machine.      /** @brief Real-time instrument script virtual machine.
# Line 74  namespace LinuxSampler { Line 243  namespace LinuxSampler {
243          std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;          std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;
244          std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;          std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;
245          std::map<String,int> builtInConstIntVariables() OVERRIDE;          std::map<String,int> builtInConstIntVariables() OVERRIDE;
246            std::map<String,VMDynVar*> builtInDynamicVariables() OVERRIDE;
247      protected:      protected:
248          ScriptEvent* m_event; ///< The event currently executed by exec().          ScriptEvent* m_event; ///< The event currently executed by exec().
249    
250          // buil-in script variables          // built-in script variables
251          VMInt8Array m_CC;          VMInt8Array m_CC;
252          VMInt8RelPtr m_CC_NUM;          VMInt8RelPtr m_CC_NUM;
253          VMIntRelPtr  m_EVENT_ID;          VMIntRelPtr  m_EVENT_ID;
# Line 86  namespace LinuxSampler { Line 256  namespace LinuxSampler {
256          VMInt8Array  m_KEY_DOWN;          VMInt8Array  m_KEY_DOWN;
257          //VMIntArray m_POLY_AT; //TODO: ...          //VMIntArray m_POLY_AT; //TODO: ...
258          //int m_POLY_AT_NUM; //TODO: ...          //int m_POLY_AT_NUM; //TODO: ...
259            VMIntRelPtr  m_NI_CALLBACK_TYPE;
260            VMIntRelPtr  m_NKSP_IGNORE_WAIT;
261    
262          // buil-in script functions          // built-in script functions
263          InstrumentScriptVMFunction_play_note m_fnPlayNote;          InstrumentScriptVMFunction_play_note m_fnPlayNote;
264          InstrumentScriptVMFunction_set_controller m_fnSetController;          InstrumentScriptVMFunction_set_controller m_fnSetController;
265          InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;          InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;
266          InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;          InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;
267          InstrumentScriptVMFunction_note_off m_fnNoteOff;          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_change_amp_lfo_depth m_fnChangeAmpLFODepth;
280            InstrumentScriptVMFunction_change_amp_lfo_freq m_fnChangeAmpLFOFreq;
281            InstrumentScriptVMFunction_change_pitch_lfo_depth m_fnChangePitchLFODepth;
282            InstrumentScriptVMFunction_change_pitch_lfo_freq m_fnChangePitchLFOFreq;
283            InstrumentScriptVMFunction_event_status m_fnEventStatus;
284            InstrumentScriptVMFunction_wait m_fnWait2;
285            InstrumentScriptVMFunction_stop_wait m_fnStopWait;
286            InstrumentScriptVMDynVar_ENGINE_UPTIME m_varEngineUptime;
287            InstrumentScriptVMDynVar_NI_CALLBACK_ID m_varCallbackID;
288            InstrumentScriptVMDynVar_ALL_EVENTS m_varAllEvents;
289    
290          friend class InstrumentScriptVMFunction_play_note;          friend class InstrumentScriptVMFunction_play_note;
291          friend class InstrumentScriptVMFunction_set_controller;          friend class InstrumentScriptVMFunction_set_controller;
292          friend class InstrumentScriptVMFunction_ignore_event;          friend class InstrumentScriptVMFunction_ignore_event;
293          friend class InstrumentScriptVMFunction_ignore_controller;          friend class InstrumentScriptVMFunction_ignore_controller;
294          friend class InstrumentScriptVMFunction_note_off;          friend class InstrumentScriptVMFunction_note_off;
295            friend class InstrumentScriptVMFunction_set_event_mark;
296            friend class InstrumentScriptVMFunction_delete_event_mark;
297            friend class InstrumentScriptVMFunction_by_marks;
298            friend class InstrumentScriptVMFunction_change_vol;
299            friend class InstrumentScriptVMFunction_change_tune;
300            friend class InstrumentScriptVMFunction_change_pan;
301            friend class InstrumentScriptVMFunction_change_cutoff;
302            friend class InstrumentScriptVMFunction_change_reso;
303            friend class InstrumentScriptVMFunction_change_attack;
304            friend class InstrumentScriptVMFunction_change_decay;
305            friend class InstrumentScriptVMFunction_change_release;
306            friend class VMChangeSynthParamFunction;
307            friend class InstrumentScriptVMFunction_change_amp_lfo_depth;
308            friend class InstrumentScriptVMFunction_change_amp_lfo_freq;
309            friend class InstrumentScriptVMFunction_change_pitch_lfo_depth;
310            friend class InstrumentScriptVMFunction_change_pitch_lfo_freq;
311            friend class InstrumentScriptVMFunction_event_status;
312            friend class InstrumentScriptVMFunction_wait;
313            friend class InstrumentScriptVMFunction_stop_wait;
314            friend class InstrumentScriptVMDynVar_ENGINE_UPTIME;
315            friend class InstrumentScriptVMDynVar_NI_CALLBACK_ID;
316            friend class InstrumentScriptVMDynVar_ALL_EVENTS;
317      };      };
318    
319  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC