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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3564 - (hide annotations) (download)
Sat Aug 24 09:18:57 2019 UTC (4 years, 8 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 schoenebeck 2581 /*
2 schoenebeck 3551 * Copyright (c) 2014-2019 Christian Schoenebeck
3 schoenebeck 2581 *
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 schoenebeck 3221 #include <algorithm> // for std::sort()
14 schoenebeck 2619 #include <math.h>
15     #include <stdlib.h>
16 schoenebeck 2581 #include "tree.h"
17     #include "ScriptVM.h"
18 schoenebeck 3285 #include "../common/RTMath.h"
19 schoenebeck 2581
20     namespace LinuxSampler {
21    
22 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
23     // class VMEmptyResultFunction
24    
25 schoenebeck 2581 VMFnResult* VMEmptyResultFunction::errorResult() {
26     result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
27     return &result;
28     }
29    
30 schoenebeck 2598 VMFnResult* VMEmptyResultFunction::successResult() {
31     result.flags = STMT_SUCCESS;
32     return &result;
33 schoenebeck 2596 }
34    
35 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
36     // class VMIntResultFunction
37    
38 schoenebeck 3557 VMFnResult* VMIntResultFunction::errorResult(vmint i) {
39 schoenebeck 2598 result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
40     result.value = i;
41     return &result;
42 schoenebeck 2596 }
43    
44 schoenebeck 3557 VMFnResult* VMIntResultFunction::successResult(vmint i) {
45 schoenebeck 2581 result.flags = STMT_SUCCESS;
46 schoenebeck 2598 result.value = i;
47 schoenebeck 2581 return &result;
48     }
49    
50 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
51     // class VMStringResultFunction
52    
53 schoenebeck 2581 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 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
66     // built-in script function: message()
67    
68 schoenebeck 3557 bool CoreVMFunction_message::acceptsArgType(vmint iArg, ExprType_t type) const {
69 schoenebeck 2581 return type == INT_EXPR || type == STRING_EXPR;
70     }
71    
72     VMFnResult* CoreVMFunction_message::exec(VMFnArgs* args) {
73     if (!args->argsCount()) return errorResult();
74    
75 schoenebeck 3285 uint64_t usecs = RTMath::unsafeMicroSeconds(RTMath::real_clock);
76    
77 schoenebeck 2581 VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(args->arg(0));
78     if (strExpr) {
79 schoenebeck 3285 printf("[ScriptVM %.3f] %s\n", usecs/1000000.f, strExpr->evalStr().c_str());
80 schoenebeck 2581 return successResult();
81     }
82    
83     VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(args->arg(0));
84     if (intExpr) {
85 schoenebeck 3557 printf("[ScriptVM %.3f] %lld\n", usecs/1000000.f, (int64_t)intExpr->evalInt());
86 schoenebeck 2581 return successResult();
87     }
88    
89     return errorResult();
90     }
91    
92 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
93     // built-in script function: exit()
94    
95 schoenebeck 3557 vmint CoreVMFunction_exit::maxAllowedArgs() const {
96 schoenebeck 3551 return (vm->isExitResultEnabled()) ? 1 : 0;
97     }
98    
99 schoenebeck 3557 bool CoreVMFunction_exit::acceptsArgType(vmint iArg, ExprType_t type) const {
100 schoenebeck 3551 if (!vm->isExitResultEnabled()) return false;
101     return type == INT_EXPR || type == STRING_EXPR;
102     }
103    
104 schoenebeck 2581 VMFnResult* CoreVMFunction_exit::exec(VMFnArgs* args) {
105     this->result.flags = STMT_ABORT_SIGNALLED;
106 schoenebeck 3551 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 schoenebeck 2581 return &result;
122     }
123    
124 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
125     // built-in script function: wait()
126    
127 schoenebeck 3561 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 schoenebeck 3564 bool CoreVMFunction_wait::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
135     return iArg == 0 && type == VM_SECOND;
136 schoenebeck 3561 }
137    
138 schoenebeck 2581 VMFnResult* CoreVMFunction_wait::exec(VMFnArgs* args) {
139     ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
140     VMIntExpr* expr = dynamic_cast<VMIntExpr*>(args->arg(0));
141 schoenebeck 3564 StdUnit_t unit = expr->unitType();
142     vmint us = (unit) ? expr->evalInt(VM_MICRO) : expr->evalInt();
143 schoenebeck 2972 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 schoenebeck 2581 return &result;
154     }
155    
156 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
157     // built-in script function: abs()
158    
159 schoenebeck 3557 bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {
160 schoenebeck 2619 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 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
168     // built-in script function: random()
169    
170 schoenebeck 3557 bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {
171 schoenebeck 2619 return type == INT_EXPR;
172     }
173    
174     VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {
175 schoenebeck 3557 vmint iMin = args->arg(0)->asInt()->evalInt();
176     vmint iMax = args->arg(1)->asInt()->evalInt();
177 schoenebeck 2620 float f = float(::rand()) / float(RAND_MAX);
178 schoenebeck 2619 return successResult(
179     iMin + roundf( f * float(iMax - iMin) )
180     );
181     }
182    
183 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
184     // built-in script function: num_elements()
185    
186 schoenebeck 3557 bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {
187 schoenebeck 2619 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 schoenebeck 2945 ///////////////////////////////////////////////////////////////////////////
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 schoenebeck 3557 vmint i = in->evalInt() + 1;
203 schoenebeck 2945 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 schoenebeck 3557 vmint i = in->evalInt() - 1;
217 schoenebeck 2945 IntLiteral tmp(i);
218     out->assignExpr(&tmp);
219     return successResult(i);
220     }
221    
222 schoenebeck 2965 ///////////////////////////////////////////////////////////////////////////
223 schoenebeck 3076 // built-in script function: in_range()
224    
225     VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {
226 schoenebeck 3557 vmint i = args->arg(0)->asInt()->evalInt();
227     vmint lo = args->arg(1)->asInt()->evalInt();
228     vmint hi = args->arg(2)->asInt()->evalInt();
229 schoenebeck 3076 if (lo > hi) { // swap lo and hi
230 schoenebeck 3557 vmint tmp = lo;
231 schoenebeck 3076 lo = hi;
232     hi = tmp;
233     }
234     return successResult(i >= lo && i <= hi);
235     }
236    
237     ///////////////////////////////////////////////////////////////////////////
238 schoenebeck 2965 // built-in script function: sh_left()
239    
240     VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
241 schoenebeck 3557 vmint i = args->arg(0)->asInt()->evalInt();
242     vmint n = args->arg(1)->asInt()->evalInt();
243 schoenebeck 2965 return successResult(i << n);
244     }
245    
246     ///////////////////////////////////////////////////////////////////////////
247     // built-in script function: sh_right()
248    
249     VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
250 schoenebeck 3557 vmint i = args->arg(0)->asInt()->evalInt();
251     vmint n = args->arg(1)->asInt()->evalInt();
252 schoenebeck 2965 return successResult(i >> n);
253     }
254    
255 schoenebeck 2970 ///////////////////////////////////////////////////////////////////////////
256     // built-in script function: min()
257    
258     VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
259 schoenebeck 3557 vmint l = args->arg(0)->asInt()->evalInt();
260     vmint r = args->arg(1)->asInt()->evalInt();
261 schoenebeck 2970 return successResult(l < r ? l : r);
262     }
263    
264     ///////////////////////////////////////////////////////////////////////////
265     // built-in script function: max()
266    
267     VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
268 schoenebeck 3557 vmint l = args->arg(0)->asInt()->evalInt();
269     vmint r = args->arg(1)->asInt()->evalInt();
270 schoenebeck 2970 return successResult(l > r ? l : r);
271     }
272    
273 schoenebeck 3221 ///////////////////////////////////////////////////////////////////////////
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 schoenebeck 3557 const vmint n = l->arraySize();
284     for (vmint i = 0; i < n; ++i)
285 schoenebeck 3221 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 schoenebeck 3557 ExprType_t CoreVMFunction_search::argType(vmint iArg) const {
294 schoenebeck 3221 return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
295     }
296    
297 schoenebeck 3557 bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
298 schoenebeck 3221 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 schoenebeck 3557 const vmint needle = args->arg(1)->asInt()->evalInt();
307     const vmint n = a->arraySize();
308     for (vmint i = 0; i < n; ++i)
309 schoenebeck 3221 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 schoenebeck 3557 ExprType_t CoreVMFunction_sort::argType(vmint iArg) const {
318 schoenebeck 3221 return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
319     }
320    
321 schoenebeck 3557 bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
322 schoenebeck 3221 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 schoenebeck 3557 vmint m_index;
331 schoenebeck 3221 };
332    
333 schoenebeck 3222 static inline void swap(class ArrElemRef a, class ArrElemRef b);
334 schoenebeck 3221
335     class ArrElemRef : protected ArrElemPOD {
336     public:
337     ArrElemRef() {
338     m_array = NULL;
339     m_index = 0;
340     }
341 schoenebeck 3557 ArrElemRef(VMIntArrayExpr* a, vmint index) {
342 schoenebeck 3221 m_array = a;
343     m_index = index;
344     }
345     inline ArrElemRef& operator=(const ArrElemRef& e) {
346     setValue(e.getValue());
347     return *this;
348     }
349 schoenebeck 3557 inline ArrElemRef& operator=(vmint val) {
350 schoenebeck 3221 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 schoenebeck 3557 inline bool operator==(vmint val) const {
359 schoenebeck 3221 return getValue() == val;
360     }
361     inline bool operator!=(const ArrElemRef& e) const {
362     return !(operator==(e));
363     }
364 schoenebeck 3557 inline bool operator!=(vmint val) const {
365 schoenebeck 3221 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 schoenebeck 3557 inline bool operator<(vmint val) const {
373 schoenebeck 3221 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 schoenebeck 3557 inline bool operator>(vmint val) const {
381 schoenebeck 3221 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 schoenebeck 3557 inline bool operator<=(vmint val) const {
389 schoenebeck 3221 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 schoenebeck 3557 inline bool operator>=(vmint val) const {
397 schoenebeck 3221 return getValue() >= val;
398     }
399 schoenebeck 3557 inline operator vmint() const {
400 schoenebeck 3221 return getValue();
401     }
402     protected:
403 schoenebeck 3557 inline vmint getValue() const {
404 schoenebeck 3221 return m_array->evalIntElement(m_index);
405     }
406 schoenebeck 3557 inline void setValue(vmint value) {
407 schoenebeck 3221 m_array->assignIntElement(m_index, value);
408     }
409    
410 schoenebeck 3222 friend void swap(class ArrElemRef a, class ArrElemRef b);
411 schoenebeck 3221 };
412    
413     class ArrElemPtr : protected ArrElemPOD {
414     public:
415     ArrElemPtr() {
416     m_array = NULL;
417     m_index = 0;
418     }
419 schoenebeck 3557 ArrElemPtr(VMIntArrayExpr* a, vmint index) {
420 schoenebeck 3221 m_array = a;
421     m_index = index;
422     }
423     inline ArrElemRef operator*() {
424     return *(ArrElemRef*)this;
425     }
426     };
427    
428 schoenebeck 3222 static inline void swap(ArrElemRef a, ArrElemRef b) {
429 schoenebeck 3557 vmint valueA = a.getValue();
430     vmint valueB = b.getValue();
431 schoenebeck 3221 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 schoenebeck 3557 typedef vmint value_type;
439 schoenebeck 3221 typedef ssize_t difference_type;
440     typedef ArrElemPtr pointer;
441     typedef ArrElemRef reference;
442    
443 schoenebeck 3557 ArrExprIter(VMIntArrayExpr* a, vmint index) {
444 schoenebeck 3221 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 schoenebeck 3345 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 schoenebeck 3221 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 schoenebeck 3557 inline bool operator()(const vmint& a, const vmint& b) const {
513 schoenebeck 3221 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 schoenebeck 3557 vmint n = a->arraySize();
522 schoenebeck 3221 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 schoenebeck 2581 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC