/[svn]/linuxsampler/trunk/src/engines/common/InstrumentScriptVMFunctions.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/common/InstrumentScriptVMFunctions.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2871 - (hide annotations) (download)
Sun Apr 10 18:22:23 2016 UTC (17 months, 2 weeks ago) by schoenebeck
File size: 11189 byte(s)
* All engines: Implemented scheduler for delayed MIDI events and for
  suspended real-time instrument scripts.
* Real-Time instrument scripts: Implemented support for built-in "wait()"
  function's "duration-us" argument, thus scripts using this function are
  now correctly resumed after the requested amount of microseconds.
* Real-Time instrument scripts: Implemented support for built-in
  "play_note()" function's "duration-us" argument, thus notes triggered
  with this argument are now correctly released after the requested amount
  of microseconds.
* Real-Time instrument scripts: Fixed crash which happened when trying to
  reference an undeclared script variable.
* Real-Time instrument scripts: Script events were not cleared when
  engine channel was reset, potentially causing undefined behavior.
* All engines: Attempt to partly fix resetting engine channels vs.
  resetting engine, an overall cleanup of the Reset*(),
  ConnectAudioDevice(), DisconnectAudioDevice() API methods would still be
  desirable though, because the current situation is still inconsistent
  and error prone.
* Bumped version (2.0.0.svn2).

1 schoenebeck 2596 /*
2 schoenebeck 2871 * Copyright (c) 2014-2016 Christian Schoenebeck
3 schoenebeck 2596 *
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     #include "InstrumentScriptVMFunctions.h"
11     #include "InstrumentScriptVM.h"
12     #include "../AbstractEngineChannel.h"
13    
14     namespace LinuxSampler {
15    
16     InstrumentScriptVMFunction_play_note::InstrumentScriptVMFunction_play_note(InstrumentScriptVM* parent)
17     : m_vm(parent)
18     {
19     }
20    
21     VMFnResult* InstrumentScriptVMFunction_play_note::exec(VMFnArgs* args) {
22     int note = args->arg(0)->asInt()->evalInt();
23     int velocity = (args->argsCount() >= 2) ? args->arg(1)->asInt()->evalInt() : 127;
24     int sampleoffset = (args->argsCount() >= 3) ? args->arg(2)->asInt()->evalInt() : 0;
25     int duration = (args->argsCount() >= 4) ? args->arg(3)->asInt()->evalInt() : 0; //TODO: once -1 is implemented, it might be a better default value instead of 0
26    
27     if (note < 0 || note > 127) {
28     errMsg("play_note(): argument 1 is an invalid note number");
29 schoenebeck 2598 return errorResult(-1);
30 schoenebeck 2596 }
31    
32     if (velocity < 0 || velocity > 127) {
33     errMsg("play_note(): argument 2 is an invalid velocity value");
34 schoenebeck 2598 return errorResult(-1);
35 schoenebeck 2596 }
36    
37     if (sampleoffset < 0) {
38     errMsg("play_note(): argument 3 may not be a negative sample offset");
39 schoenebeck 2598 return errorResult(-1);
40 schoenebeck 2596 } else if (sampleoffset != 0) {
41     wrnMsg("play_note(): argument 3 does not support a sample offset other than 0 yet");
42     }
43    
44     if (duration < -1) {
45     errMsg("play_note(): argument 4 must be a duration value of at least -1 or higher");
46 schoenebeck 2598 return errorResult(-1);
47 schoenebeck 2596 } else if (duration == -1) {
48     wrnMsg("play_note(): argument 4 does not support special value -1 as duration yet");
49     }
50    
51     AbstractEngineChannel* pEngineChannel =
52     static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
53    
54     Event e = m_vm->m_event->cause;
55     e.Type = Event::type_note_on;
56     e.Param.Note.Key = note;
57     e.Param.Note.Velocity = velocity;
58 schoenebeck 2871 memset(&e.Format, 0, sizeof(e.Format)); // init format specific stuff with zero
59 schoenebeck 2596
60 schoenebeck 2871 int id = pEngineChannel->ScheduleEventMicroSec(&e, 0);
61 schoenebeck 2596
62 schoenebeck 2871 // if a duration is supplied, then schedule a subsequent note-ff event
63     if (duration > 0) {
64     e.Type = Event::type_note_off;
65     e.Param.Note.Velocity = 127;
66     pEngineChannel->ScheduleEventMicroSec(&e, duration);
67     }
68    
69 schoenebeck 2598 return successResult(id);
70     }
71    
72 schoenebeck 2600 InstrumentScriptVMFunction_set_controller::InstrumentScriptVMFunction_set_controller(InstrumentScriptVM* parent)
73     : m_vm(parent)
74     {
75     }
76    
77     VMFnResult* InstrumentScriptVMFunction_set_controller::exec(VMFnArgs* args) {
78     int controller = args->arg(0)->asInt()->evalInt();
79     int value = args->arg(1)->asInt()->evalInt();
80    
81     AbstractEngineChannel* pEngineChannel =
82     static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
83    
84     Event e = m_vm->m_event->cause;
85 persson 2606 memset(&e.Format, 0, sizeof(e.Format)); // init format speific stuff with zero
86 schoenebeck 2600 if (controller == CTRL_TABLE_IDX_AFTERTOUCH) {
87     e.Type = Event::type_channel_pressure;
88     e.Param.ChannelPressure.Value = value & 127;
89     } else if (controller == CTRL_TABLE_IDX_PITCHBEND) {
90     e.Type = Event::type_pitchbend;
91     e.Param.Pitch.Pitch = value;
92     } else if (controller >= 0 && controller <= 127) {
93     e.Type = Event::type_control_change;
94     e.Param.CC.Controller = controller;
95     e.Param.CC.Value = value;
96     } else {
97     errMsg("set_controller(): argument 1 is an invalid controller");
98     return errorResult();
99     }
100    
101 schoenebeck 2871 int id = pEngineChannel->ScheduleEventMicroSec(&e, 0);
102 schoenebeck 2600
103     return successResult(id);
104     }
105    
106 schoenebeck 2598 InstrumentScriptVMFunction_ignore_event::InstrumentScriptVMFunction_ignore_event(InstrumentScriptVM* parent)
107     : m_vm(parent)
108     {
109     }
110    
111 schoenebeck 2630 bool InstrumentScriptVMFunction_ignore_event::acceptsArgType(int iArg, ExprType_t type) const {
112     return type == INT_EXPR || type == INT_ARR_EXPR;
113     }
114    
115 schoenebeck 2598 VMFnResult* InstrumentScriptVMFunction_ignore_event::exec(VMFnArgs* args) {
116     AbstractEngineChannel* pEngineChannel =
117 schoenebeck 2630 static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
118 schoenebeck 2598
119 schoenebeck 2630 if (args->arg(0)->exprType() == INT_EXPR) {
120     int id = args->arg(0)->asInt()->evalInt();
121     if (id < 0) {
122     wrnMsg("ignore_event(): argument may not be a negative event ID");
123     return successResult();
124     }
125     pEngineChannel->IgnoreEvent(id);
126     } else if (args->arg(0)->exprType() == INT_ARR_EXPR) {
127     VMIntArrayExpr* ids = args->arg(0)->asIntArray();
128     for (int i = 0; i < ids->arraySize(); ++i) {
129     int id = ids->evalIntElement(i);
130     pEngineChannel->IgnoreEvent(id);
131     }
132     }
133 schoenebeck 2598
134 schoenebeck 2596 return successResult();
135     }
136    
137 schoenebeck 2598 InstrumentScriptVMFunction_ignore_controller::InstrumentScriptVMFunction_ignore_controller(InstrumentScriptVM* parent)
138     : m_vm(parent)
139     {
140     }
141    
142     VMFnResult* InstrumentScriptVMFunction_ignore_controller::exec(VMFnArgs* args) {
143     int id = (args->argsCount() >= 1) ? args->arg(0)->asInt()->evalInt() : m_vm->m_event->id;
144     if (id < 0) {
145     wrnMsg("ignore_controller(): argument may not be a negative event ID");
146     return successResult();
147     }
148    
149     AbstractEngineChannel* pEngineChannel =
150     static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
151    
152     pEngineChannel->IgnoreEvent(id);
153    
154     return successResult();
155     }
156    
157 schoenebeck 2629 InstrumentScriptVMFunction_note_off::InstrumentScriptVMFunction_note_off(InstrumentScriptVM* parent)
158     : m_vm(parent)
159     {
160     }
161    
162 schoenebeck 2630 bool InstrumentScriptVMFunction_note_off::acceptsArgType(int iArg, ExprType_t type) const {
163     return type == INT_EXPR || type == INT_ARR_EXPR;
164     }
165    
166 schoenebeck 2629 VMFnResult* InstrumentScriptVMFunction_note_off::exec(VMFnArgs* args) {
167 schoenebeck 2630 AbstractEngineChannel* pEngineChannel =
168     static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
169    
170 schoenebeck 2629 int velocity = (args->argsCount() >= 2) ? args->arg(1)->asInt()->evalInt() : 127;
171 schoenebeck 2630 if (velocity < 0 || velocity > 127) {
172     errMsg("note_off(): argument 2 is an invalid velocity value");
173     return errorResult();
174     }
175 schoenebeck 2629
176 schoenebeck 2630 if (args->arg(0)->exprType() == INT_EXPR) {
177     int id = args->arg(0)->asInt()->evalInt();
178     if (id < 0) {
179     wrnMsg("note_off(): argument 1 may not be a negative event ID");
180     return successResult();
181     }
182    
183     RTList<Event>::Iterator itEvent = pEngineChannel->pEngine->EventByID(id);
184     if (!itEvent) return successResult();
185    
186     Event e = *itEvent;
187     e.Type = Event::type_note_off;
188     e.Param.Note.Velocity = velocity;
189     memset(&e.Format, 0, sizeof(e.Format)); // init format speific stuff with zero
190    
191 schoenebeck 2871 int releaseEventID = pEngineChannel->ScheduleEventMicroSec(&e, 0);
192 schoenebeck 2630 } else if (args->arg(0)->exprType() == INT_ARR_EXPR) {
193     VMIntArrayExpr* ids = args->arg(0)->asIntArray();
194     for (int i = 0; i < ids->arraySize(); ++i) {
195     int id = ids->evalIntElement(i);
196    
197     RTList<Event>::Iterator itEvent = pEngineChannel->pEngine->EventByID(id);
198     if (!itEvent) continue;
199    
200     Event e = *itEvent;
201     e.Type = Event::type_note_off;
202     e.Param.Note.Velocity = velocity;
203     memset(&e.Format, 0, sizeof(e.Format)); // init format speific stuff with zero
204    
205 schoenebeck 2871 int releaseEventID = pEngineChannel->ScheduleEventMicroSec(&e, 0);
206 schoenebeck 2630 }
207 schoenebeck 2629 }
208    
209 schoenebeck 2630 return successResult();
210     }
211    
212     InstrumentScriptVMFunction_set_event_mark::InstrumentScriptVMFunction_set_event_mark(InstrumentScriptVM* parent)
213     : m_vm(parent)
214     {
215     }
216    
217     VMFnResult* InstrumentScriptVMFunction_set_event_mark::exec(VMFnArgs* args) {
218     int eventID = args->arg(0)->asInt()->evalInt();
219     int groupID = args->arg(1)->asInt()->evalInt();
220    
221     if (groupID < 0 || groupID >= INSTR_SCRIPT_EVENT_GROUPS) {
222     errMsg("set_event_mark(): argument 2 is an invalid group id");
223 schoenebeck 2629 return errorResult();
224     }
225    
226     AbstractEngineChannel* pEngineChannel =
227     static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
228    
229 schoenebeck 2630 RTList<Event>::Iterator itEvent = pEngineChannel->pEngine->EventByID(eventID);
230 schoenebeck 2629 if (!itEvent) return successResult();
231    
232 schoenebeck 2630 pEngineChannel->pScript->eventGroups[groupID].insert(eventID);
233 schoenebeck 2629
234 schoenebeck 2630 return successResult();
235     }
236 schoenebeck 2629
237 schoenebeck 2630 InstrumentScriptVMFunction_delete_event_mark::InstrumentScriptVMFunction_delete_event_mark(InstrumentScriptVM* parent)
238     : m_vm(parent)
239     {
240     }
241    
242     VMFnResult* InstrumentScriptVMFunction_delete_event_mark::exec(VMFnArgs* args) {
243     int eventID = args->arg(0)->asInt()->evalInt();
244     int groupID = args->arg(1)->asInt()->evalInt();
245    
246     if (groupID < 0 || groupID >= INSTR_SCRIPT_EVENT_GROUPS) {
247     errMsg("delete_event_mark(): argument 2 is an invalid group id");
248     return errorResult();
249     }
250    
251     AbstractEngineChannel* pEngineChannel =
252     static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
253    
254     pEngineChannel->pScript->eventGroups[groupID].erase(eventID);
255    
256 schoenebeck 2629 return successResult();
257     }
258    
259 schoenebeck 2630 InstrumentScriptVMFunction_by_marks::InstrumentScriptVMFunction_by_marks(InstrumentScriptVM* parent)
260     : m_vm(parent)
261     {
262     }
263    
264     int InstrumentScriptVMFunction_by_marks::Result::arraySize() const {
265     return eventGroup->size();
266     }
267    
268     int InstrumentScriptVMFunction_by_marks::Result::evalIntElement(uint i) {
269     return (*eventGroup)[i];
270     }
271    
272     VMFnResult* InstrumentScriptVMFunction_by_marks::errorResult() {
273     m_result.eventGroup = NULL;
274     m_result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
275     return &m_result;
276     }
277    
278     VMFnResult* InstrumentScriptVMFunction_by_marks::successResult(EventGroup* eventGroup) {
279     m_result.eventGroup = eventGroup;
280     m_result.flags = STMT_SUCCESS;
281     return &m_result;
282     }
283    
284     VMFnResult* InstrumentScriptVMFunction_by_marks::exec(VMFnArgs* args) {
285     int groupID = args->arg(0)->asInt()->evalInt();
286    
287     if (groupID < 0 || groupID >= INSTR_SCRIPT_EVENT_GROUPS) {
288     errMsg("by_marks(): argument is an invalid group id");
289     return errorResult();
290     }
291    
292     AbstractEngineChannel* pEngineChannel =
293     static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
294    
295     return successResult( &pEngineChannel->pScript->eventGroups[groupID] );
296     }
297    
298 schoenebeck 2596 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC