/[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 2600 by schoenebeck, Sat Jun 7 00:16:03 2014 UTC revision 2935 by schoenebeck, Sun Jul 10 14:24:13 2016 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014 Christian Schoenebeck   * Copyright (c) 2014-2016 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"  #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 {  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.      /** @brief Real-time instrument script virtual machine.
200       *       *
201       * Extends the core ScriptVM implementation with MIDI specific built-in       * Extends the core ScriptVM implementation with MIDI specific built-in
# Line 44  namespace LinuxSampler { Line 223  namespace LinuxSampler {
223          VMIntRelPtr  m_EVENT_ID;          VMIntRelPtr  m_EVENT_ID;
224          VMInt8RelPtr m_EVENT_NOTE;          VMInt8RelPtr m_EVENT_NOTE;
225          VMInt8RelPtr m_EVENT_VELOCITY;          VMInt8RelPtr m_EVENT_VELOCITY;
226          //VMIntArray m_KEY_DOWN; //TODO: ...          VMInt8Array  m_KEY_DOWN;
227          //VMIntArray m_POLY_AT; //TODO: ...          //VMIntArray m_POLY_AT; //TODO: ...
228          //int m_POLY_AT_NUM; //TODO: ...          //int m_POLY_AT_NUM; //TODO: ...
229    
# Line 53  namespace LinuxSampler { Line 232  namespace LinuxSampler {
232          InstrumentScriptVMFunction_set_controller m_fnSetController;          InstrumentScriptVMFunction_set_controller m_fnSetController;
233          InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;          InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;
234          InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;          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;          friend class InstrumentScriptVMFunction_play_note;
247          friend class InstrumentScriptVMFunction_set_controller;          friend class InstrumentScriptVMFunction_set_controller;
248          friend class InstrumentScriptVMFunction_ignore_event;          friend class InstrumentScriptVMFunction_ignore_event;
249          friend class InstrumentScriptVMFunction_ignore_controller;          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  } // namespace LinuxSampler

Legend:
Removed from v.2600  
changed lines
  Added in v.2935

  ViewVC Help
Powered by ViewVC