/[svn]/linuxsampler/trunk/src/scriptvm/CoreVMFunctions.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/scriptvm/CoreVMFunctions.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3564 - (show annotations) (download)
Sat Aug 24 09:18:57 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 16446 byte(s)
NKSP: Bug fixes regarding new measurement units feature:

* Fix: Engine internal Fade of script synthesis parameters volume, pitch
  and pan were not rendered at all.

* Fix: Backward compatibility of built-in function arguments without a
  metric unit prefix was broken (resulted in incorrect value
  transformation).

* Fix: built-in script function change_play_pos() resolved wrong arguments.

* Bumped version (2.1.1.svn5).

1 /*
2 * Copyright (c) 2014-2019 Christian Schoenebeck
3 *
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 "CoreVMFunctions.h"
11
12 #include <iostream>
13 #include <algorithm> // for std::sort()
14 #include <math.h>
15 #include <stdlib.h>
16 #include "tree.h"
17 #include "ScriptVM.h"
18 #include "../common/RTMath.h"
19
20 namespace LinuxSampler {
21
22 ///////////////////////////////////////////////////////////////////////////
23 // class VMEmptyResultFunction
24
25 VMFnResult* VMEmptyResultFunction::errorResult() {
26 result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
27 return &result;
28 }
29
30 VMFnResult* VMEmptyResultFunction::successResult() {
31 result.flags = STMT_SUCCESS;
32 return &result;
33 }
34
35 ///////////////////////////////////////////////////////////////////////////
36 // class VMIntResultFunction
37
38 VMFnResult* VMIntResultFunction::errorResult(vmint i) {
39 result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
40 result.value = i;
41 return &result;
42 }
43
44 VMFnResult* VMIntResultFunction::successResult(vmint i) {
45 result.flags = STMT_SUCCESS;
46 result.value = i;
47 return &result;
48 }
49
50 ///////////////////////////////////////////////////////////////////////////
51 // class VMStringResultFunction
52
53 VMFnResult* VMStringResultFunction::errorResult(const String& s) {
54 result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
55 result.value = s;
56 return &result;
57 }
58
59 VMFnResult* VMStringResultFunction::successResult(const String& s) {
60 result.flags = STMT_SUCCESS;
61 result.value = s;
62 return &result;
63 }
64
65 ///////////////////////////////////////////////////////////////////////////
66 // built-in script function: message()
67
68 bool CoreVMFunction_message::acceptsArgType(vmint iArg, ExprType_t type) const {
69 return type == INT_EXPR || type == STRING_EXPR;
70 }
71
72 VMFnResult* CoreVMFunction_message::exec(VMFnArgs* args) {
73 if (!args->argsCount()) return errorResult();
74
75 uint64_t usecs = RTMath::unsafeMicroSeconds(RTMath::real_clock);
76
77 VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(args->arg(0));
78 if (strExpr) {
79 printf("[ScriptVM %.3f] %s\n", usecs/1000000.f, strExpr->evalStr().c_str());
80 return successResult();
81 }
82
83 VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(args->arg(0));
84 if (intExpr) {
85 printf("[ScriptVM %.3f] %lld\n", usecs/1000000.f, (int64_t)intExpr->evalInt());
86 return successResult();
87 }
88
89 return errorResult();
90 }
91
92 ///////////////////////////////////////////////////////////////////////////
93 // built-in script function: exit()
94
95 vmint CoreVMFunction_exit::maxAllowedArgs() const {
96 return (vm->isExitResultEnabled()) ? 1 : 0;
97 }
98
99 bool CoreVMFunction_exit::acceptsArgType(vmint iArg, ExprType_t type) const {
100 if (!vm->isExitResultEnabled()) return false;
101 return type == INT_EXPR || type == STRING_EXPR;
102 }
103
104 VMFnResult* CoreVMFunction_exit::exec(VMFnArgs* args) {
105 this->result.flags = STMT_ABORT_SIGNALLED;
106 if (vm->isExitResultEnabled() && args->argsCount()) {
107 ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
108 switch (args->arg(0)->exprType()) {
109 case INT_EXPR:
110 ctx->exitRes.intLiteral.value = args->arg(0)->asInt()->evalInt();
111 ctx->exitRes.value = &ctx->exitRes.intLiteral;
112 break;
113 case STRING_EXPR:
114 ctx->exitRes.stringLiteral.value = args->arg(0)->asString()->evalStr();
115 ctx->exitRes.value = &ctx->exitRes.stringLiteral;
116 break;
117 default:
118 ; // noop - just to shut up the compiler
119 }
120 }
121 return &result;
122 }
123
124 ///////////////////////////////////////////////////////////////////////////
125 // built-in script function: wait()
126
127 bool CoreVMFunction_wait::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
128 if (iArg == 0)
129 return type == VM_NO_UNIT || type == VM_SECOND;
130 else
131 return type == VM_NO_UNIT;
132 }
133
134 bool CoreVMFunction_wait::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
135 return iArg == 0 && type == VM_SECOND;
136 }
137
138 VMFnResult* CoreVMFunction_wait::exec(VMFnArgs* args) {
139 ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
140 VMIntExpr* expr = dynamic_cast<VMIntExpr*>(args->arg(0));
141 StdUnit_t unit = expr->unitType();
142 vmint us = (unit) ? expr->evalInt(VM_MICRO) : expr->evalInt();
143 if (us < 0) {
144 wrnMsg("wait(): argument may not be negative! Aborting script!");
145 this->result.flags = STMT_ABORT_SIGNALLED;
146 } else if (us == 0) {
147 wrnMsg("wait(): argument may not be zero! Aborting script!");
148 this->result.flags = STMT_ABORT_SIGNALLED;
149 } else {
150 ctx->suspendMicroseconds = us;
151 this->result.flags = STMT_SUSPEND_SIGNALLED;
152 }
153 return &result;
154 }
155
156 ///////////////////////////////////////////////////////////////////////////
157 // built-in script function: abs()
158
159 bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {
160 return type == INT_EXPR;
161 }
162
163 VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {
164 return successResult( ::abs(args->arg(0)->asInt()->evalInt()) );
165 }
166
167 ///////////////////////////////////////////////////////////////////////////
168 // built-in script function: random()
169
170 bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {
171 return type == INT_EXPR;
172 }
173
174 VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {
175 vmint iMin = args->arg(0)->asInt()->evalInt();
176 vmint iMax = args->arg(1)->asInt()->evalInt();
177 float f = float(::rand()) / float(RAND_MAX);
178 return successResult(
179 iMin + roundf( f * float(iMax - iMin) )
180 );
181 }
182
183 ///////////////////////////////////////////////////////////////////////////
184 // built-in script function: num_elements()
185
186 bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {
187 return type == INT_ARR_EXPR;
188 }
189
190 VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {
191 return successResult( args->arg(0)->asIntArray()->arraySize() );
192 }
193
194 ///////////////////////////////////////////////////////////////////////////
195 // built-in script function: inc()
196
197 VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {
198 VMExpr* arg = args->arg(0);
199 VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
200 VMVariable* out = dynamic_cast<VMVariable*>(arg);
201 if (!in || !out) successResult(0);
202 vmint i = in->evalInt() + 1;
203 IntLiteral tmp(i);
204 out->assignExpr(&tmp);
205 return successResult(i);
206 }
207
208 ///////////////////////////////////////////////////////////////////////////
209 // built-in script function: dec()
210
211 VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {
212 VMExpr* arg = args->arg(0);
213 VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
214 VMVariable* out = dynamic_cast<VMVariable*>(arg);
215 if (!in || !out) successResult(0);
216 vmint i = in->evalInt() - 1;
217 IntLiteral tmp(i);
218 out->assignExpr(&tmp);
219 return successResult(i);
220 }
221
222 ///////////////////////////////////////////////////////////////////////////
223 // built-in script function: in_range()
224
225 VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {
226 vmint i = args->arg(0)->asInt()->evalInt();
227 vmint lo = args->arg(1)->asInt()->evalInt();
228 vmint hi = args->arg(2)->asInt()->evalInt();
229 if (lo > hi) { // swap lo and hi
230 vmint tmp = lo;
231 lo = hi;
232 hi = tmp;
233 }
234 return successResult(i >= lo && i <= hi);
235 }
236
237 ///////////////////////////////////////////////////////////////////////////
238 // built-in script function: sh_left()
239
240 VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
241 vmint i = args->arg(0)->asInt()->evalInt();
242 vmint n = args->arg(1)->asInt()->evalInt();
243 return successResult(i << n);
244 }
245
246 ///////////////////////////////////////////////////////////////////////////
247 // built-in script function: sh_right()
248
249 VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
250 vmint i = args->arg(0)->asInt()->evalInt();
251 vmint n = args->arg(1)->asInt()->evalInt();
252 return successResult(i >> n);
253 }
254
255 ///////////////////////////////////////////////////////////////////////////
256 // built-in script function: min()
257
258 VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
259 vmint l = args->arg(0)->asInt()->evalInt();
260 vmint r = args->arg(1)->asInt()->evalInt();
261 return successResult(l < r ? l : r);
262 }
263
264 ///////////////////////////////////////////////////////////////////////////
265 // built-in script function: max()
266
267 VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
268 vmint l = args->arg(0)->asInt()->evalInt();
269 vmint r = args->arg(1)->asInt()->evalInt();
270 return successResult(l > r ? l : r);
271 }
272
273 ///////////////////////////////////////////////////////////////////////////
274 // built-in script function: array_equal()
275
276 VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {
277 VMIntArrayExpr* l = args->arg(0)->asIntArray();
278 VMIntArrayExpr* r = args->arg(1)->asIntArray();
279 if (l->arraySize() != r->arraySize()) {
280 wrnMsg("array_equal(): the two arrays differ in size");
281 return successResult(0); // false
282 }
283 const vmint n = l->arraySize();
284 for (vmint i = 0; i < n; ++i)
285 if (l->evalIntElement(i) != r->evalIntElement(i))
286 return successResult(0); // false
287 return successResult(1); // true
288 }
289
290 ///////////////////////////////////////////////////////////////////////////
291 // built-in script function: search()
292
293 ExprType_t CoreVMFunction_search::argType(vmint iArg) const {
294 return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
295 }
296
297 bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
298 if (iArg == 0)
299 return type == INT_ARR_EXPR;
300 else
301 return type == INT_EXPR;
302 }
303
304 VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {
305 VMIntArrayExpr* a = args->arg(0)->asIntArray();
306 const vmint needle = args->arg(1)->asInt()->evalInt();
307 const vmint n = a->arraySize();
308 for (vmint i = 0; i < n; ++i)
309 if (a->evalIntElement(i) == needle)
310 return successResult(i);
311 return successResult(-1); // not found
312 }
313
314 ///////////////////////////////////////////////////////////////////////////
315 // built-in script function: sort()
316
317 ExprType_t CoreVMFunction_sort::argType(vmint iArg) const {
318 return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
319 }
320
321 bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
322 if (iArg == 0)
323 return type == INT_ARR_EXPR;
324 else
325 return type == INT_EXPR;
326 }
327
328 struct ArrElemPOD {
329 VMIntArrayExpr* m_array;
330 vmint m_index;
331 };
332
333 static inline void swap(class ArrElemRef a, class ArrElemRef b);
334
335 class ArrElemRef : protected ArrElemPOD {
336 public:
337 ArrElemRef() {
338 m_array = NULL;
339 m_index = 0;
340 }
341 ArrElemRef(VMIntArrayExpr* a, vmint index) {
342 m_array = a;
343 m_index = index;
344 }
345 inline ArrElemRef& operator=(const ArrElemRef& e) {
346 setValue(e.getValue());
347 return *this;
348 }
349 inline ArrElemRef& operator=(vmint val) {
350 setValue(val);
351 return *this;
352 }
353 inline bool operator==(const ArrElemRef& e) const {
354 if (m_index == e.m_index)
355 return true;
356 return getValue() == e.getValue();
357 }
358 inline bool operator==(vmint val) const {
359 return getValue() == val;
360 }
361 inline bool operator!=(const ArrElemRef& e) const {
362 return !(operator==(e));
363 }
364 inline bool operator!=(vmint val) const {
365 return !(operator==(val));
366 }
367 inline bool operator<(const ArrElemRef& e) const {
368 if (m_index == e.m_index)
369 return false;
370 return getValue() < e.getValue();
371 }
372 inline bool operator<(vmint val) const {
373 return getValue() < val;
374 }
375 inline bool operator>(const ArrElemRef& e) const {
376 if (m_index == e.m_index)
377 return false;
378 return getValue() > e.getValue();
379 }
380 inline bool operator>(vmint val) const {
381 return getValue() > val;
382 }
383 inline bool operator<=(const ArrElemRef& e) const {
384 if (m_index == e.m_index)
385 return true;
386 return getValue() <= e.getValue();
387 }
388 inline bool operator<=(vmint val) const {
389 return getValue() <= val;
390 }
391 inline bool operator>=(const ArrElemRef& e) const {
392 if (m_index == e.m_index)
393 return true;
394 return getValue() >= e.getValue();
395 }
396 inline bool operator>=(vmint val) const {
397 return getValue() >= val;
398 }
399 inline operator vmint() const {
400 return getValue();
401 }
402 protected:
403 inline vmint getValue() const {
404 return m_array->evalIntElement(m_index);
405 }
406 inline void setValue(vmint value) {
407 m_array->assignIntElement(m_index, value);
408 }
409
410 friend void swap(class ArrElemRef a, class ArrElemRef b);
411 };
412
413 class ArrElemPtr : protected ArrElemPOD {
414 public:
415 ArrElemPtr() {
416 m_array = NULL;
417 m_index = 0;
418 }
419 ArrElemPtr(VMIntArrayExpr* a, vmint index) {
420 m_array = a;
421 m_index = index;
422 }
423 inline ArrElemRef operator*() {
424 return *(ArrElemRef*)this;
425 }
426 };
427
428 static inline void swap(ArrElemRef a, ArrElemRef b) {
429 vmint valueA = a.getValue();
430 vmint valueB = b.getValue();
431 a.setValue(valueB);
432 b.setValue(valueA);
433 }
434
435 class ArrExprIter : public ArrElemPOD {
436 public:
437 typedef std::random_access_iterator_tag iterator_category;
438 typedef vmint value_type;
439 typedef ssize_t difference_type;
440 typedef ArrElemPtr pointer;
441 typedef ArrElemRef reference;
442
443 ArrExprIter(VMIntArrayExpr* a, vmint index) {
444 m_array = a;
445 m_index = index;
446 }
447 inline ArrElemRef operator*() {
448 return *(ArrElemRef*)this;
449 }
450 inline ArrExprIter& operator++() { // prefix increment
451 ++m_index;
452 return *this;
453 }
454 inline ArrExprIter& operator--() { // prefix decrement
455 --m_index;
456 return *this;
457 }
458 inline ArrExprIter operator++(int) { // postfix increment
459 ArrExprIter it = *this;
460 ++m_index;
461 return it;
462 }
463 inline ArrExprIter operator--(int) { // postfix decrement
464 ArrExprIter it = *this;
465 --m_index;
466 return it;
467 }
468 inline ArrExprIter& operator+=(difference_type d) {
469 m_index += d;
470 return *this;
471 }
472 inline ArrExprIter& operator-=(difference_type d) {
473 m_index -= d;
474 return *this;
475 }
476 inline bool operator==(const ArrExprIter& other) const {
477 return m_index == other.m_index;
478 }
479 inline bool operator!=(const ArrExprIter& other) const {
480 return m_index != other.m_index;
481 }
482 inline bool operator<(const ArrExprIter& other) const {
483 return m_index < other.m_index;
484 }
485 inline bool operator>(const ArrExprIter& other) const {
486 return m_index > other.m_index;
487 }
488 inline bool operator<=(const ArrExprIter& other) const {
489 return m_index <= other.m_index;
490 }
491 inline bool operator>=(const ArrExprIter& other) const {
492 return m_index >= other.m_index;
493 }
494 inline difference_type operator+(const ArrExprIter& other) const {
495 return m_index + other.m_index;
496 }
497 inline difference_type operator-(const ArrExprIter& other) const {
498 return m_index - other.m_index;
499 }
500 inline ArrExprIter operator-(difference_type d) const {
501 return ArrExprIter(m_array, m_index - d);
502 }
503 inline ArrExprIter operator+(difference_type d) const {
504 return ArrExprIter(m_array, m_index + d);
505 }
506 inline ArrExprIter operator*(difference_type factor) const {
507 return ArrExprIter(m_array, m_index * factor);
508 }
509 };
510
511 struct DescArrExprSorter {
512 inline bool operator()(const vmint& a, const vmint& b) const {
513 return a > b;
514 }
515 };
516
517 VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {
518 VMIntArrayExpr* a = args->arg(0)->asIntArray();
519 bool bAscending =
520 (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();
521 vmint n = a->arraySize();
522 ArrExprIter itBegin(a, 0);
523 ArrExprIter itEnd(a, n);
524 if (bAscending) {
525 std::sort(itBegin, itEnd);
526 } else {
527 DescArrExprSorter sorter;
528 std::sort(itBegin, itEnd, sorter);
529 }
530 return successResult();
531 }
532
533 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC