/[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 3561 - (show annotations) (download)
Fri Aug 23 11:44:00 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 16343 byte(s)
NKSP: Added standard units support for numbers and final "!" operator:

* NKSP strictness: Variable names, function names and preprocessor condition
  names must start with a regular character (a-z or A-Z); starting them with
  a digit or underscore is no longer allowed.

* NKSP parser fix: equal comparison operator "=" and not equal comparison
  operator "#" must only accept integer operands.

* NKSP language: Implemented support for standard units like Hertz, seconds,
  Bel including support for metric unit prefixes; so one can now e.g.
  conveniently use numbers in scripts like "5us" meaning "5 microseconds",
  or e.g. "12kHz" meaning "12 kilo Hertz", or e.g. "-14mdB" meaning
  "minus 14 Millidecibel", or e.g. "28c" meaning "28 cents" (for tuning).

* NKSP language: Introduced "final" operator "!" which is specifically
  intended for synthesis parameter values to denote that the synthesis
  parameter value is intended to be the "final" value for that synthesis
  parameter that should explicitly be used by the engine and thus causing
  the sampler engine to ignore all other modulation sources for the same
  synthesis parameter (like e.g. LFO, EG); by simply prefixing a value,
  variable or formula with this new "!" operator the expression is marked as
  being "final".

* Bumped version (2.1.1.svn4).

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) const {
135 return iArg == 0;
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 vmint us = expr->evalInt(VM_MICRO);
142 if (us < 0) {
143 wrnMsg("wait(): argument may not be negative! Aborting script!");
144 this->result.flags = STMT_ABORT_SIGNALLED;
145 } else if (us == 0) {
146 wrnMsg("wait(): argument may not be zero! Aborting script!");
147 this->result.flags = STMT_ABORT_SIGNALLED;
148 } else {
149 ctx->suspendMicroseconds = us;
150 this->result.flags = STMT_SUSPEND_SIGNALLED;
151 }
152 return &result;
153 }
154
155 ///////////////////////////////////////////////////////////////////////////
156 // built-in script function: abs()
157
158 bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {
159 return type == INT_EXPR;
160 }
161
162 VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {
163 return successResult( ::abs(args->arg(0)->asInt()->evalInt()) );
164 }
165
166 ///////////////////////////////////////////////////////////////////////////
167 // built-in script function: random()
168
169 bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {
170 return type == INT_EXPR;
171 }
172
173 VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {
174 vmint iMin = args->arg(0)->asInt()->evalInt();
175 vmint iMax = args->arg(1)->asInt()->evalInt();
176 float f = float(::rand()) / float(RAND_MAX);
177 return successResult(
178 iMin + roundf( f * float(iMax - iMin) )
179 );
180 }
181
182 ///////////////////////////////////////////////////////////////////////////
183 // built-in script function: num_elements()
184
185 bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {
186 return type == INT_ARR_EXPR;
187 }
188
189 VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {
190 return successResult( args->arg(0)->asIntArray()->arraySize() );
191 }
192
193 ///////////////////////////////////////////////////////////////////////////
194 // built-in script function: inc()
195
196 VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {
197 VMExpr* arg = args->arg(0);
198 VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
199 VMVariable* out = dynamic_cast<VMVariable*>(arg);
200 if (!in || !out) successResult(0);
201 vmint i = in->evalInt() + 1;
202 IntLiteral tmp(i);
203 out->assignExpr(&tmp);
204 return successResult(i);
205 }
206
207 ///////////////////////////////////////////////////////////////////////////
208 // built-in script function: dec()
209
210 VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {
211 VMExpr* arg = args->arg(0);
212 VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
213 VMVariable* out = dynamic_cast<VMVariable*>(arg);
214 if (!in || !out) successResult(0);
215 vmint i = in->evalInt() - 1;
216 IntLiteral tmp(i);
217 out->assignExpr(&tmp);
218 return successResult(i);
219 }
220
221 ///////////////////////////////////////////////////////////////////////////
222 // built-in script function: in_range()
223
224 VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {
225 vmint i = args->arg(0)->asInt()->evalInt();
226 vmint lo = args->arg(1)->asInt()->evalInt();
227 vmint hi = args->arg(2)->asInt()->evalInt();
228 if (lo > hi) { // swap lo and hi
229 vmint tmp = lo;
230 lo = hi;
231 hi = tmp;
232 }
233 return successResult(i >= lo && i <= hi);
234 }
235
236 ///////////////////////////////////////////////////////////////////////////
237 // built-in script function: sh_left()
238
239 VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
240 vmint i = args->arg(0)->asInt()->evalInt();
241 vmint n = args->arg(1)->asInt()->evalInt();
242 return successResult(i << n);
243 }
244
245 ///////////////////////////////////////////////////////////////////////////
246 // built-in script function: sh_right()
247
248 VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
249 vmint i = args->arg(0)->asInt()->evalInt();
250 vmint n = args->arg(1)->asInt()->evalInt();
251 return successResult(i >> n);
252 }
253
254 ///////////////////////////////////////////////////////////////////////////
255 // built-in script function: min()
256
257 VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
258 vmint l = args->arg(0)->asInt()->evalInt();
259 vmint r = args->arg(1)->asInt()->evalInt();
260 return successResult(l < r ? l : r);
261 }
262
263 ///////////////////////////////////////////////////////////////////////////
264 // built-in script function: max()
265
266 VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
267 vmint l = args->arg(0)->asInt()->evalInt();
268 vmint r = args->arg(1)->asInt()->evalInt();
269 return successResult(l > r ? l : r);
270 }
271
272 ///////////////////////////////////////////////////////////////////////////
273 // built-in script function: array_equal()
274
275 VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {
276 VMIntArrayExpr* l = args->arg(0)->asIntArray();
277 VMIntArrayExpr* r = args->arg(1)->asIntArray();
278 if (l->arraySize() != r->arraySize()) {
279 wrnMsg("array_equal(): the two arrays differ in size");
280 return successResult(0); // false
281 }
282 const vmint n = l->arraySize();
283 for (vmint i = 0; i < n; ++i)
284 if (l->evalIntElement(i) != r->evalIntElement(i))
285 return successResult(0); // false
286 return successResult(1); // true
287 }
288
289 ///////////////////////////////////////////////////////////////////////////
290 // built-in script function: search()
291
292 ExprType_t CoreVMFunction_search::argType(vmint iArg) const {
293 return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
294 }
295
296 bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
297 if (iArg == 0)
298 return type == INT_ARR_EXPR;
299 else
300 return type == INT_EXPR;
301 }
302
303 VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {
304 VMIntArrayExpr* a = args->arg(0)->asIntArray();
305 const vmint needle = args->arg(1)->asInt()->evalInt();
306 const vmint n = a->arraySize();
307 for (vmint i = 0; i < n; ++i)
308 if (a->evalIntElement(i) == needle)
309 return successResult(i);
310 return successResult(-1); // not found
311 }
312
313 ///////////////////////////////////////////////////////////////////////////
314 // built-in script function: sort()
315
316 ExprType_t CoreVMFunction_sort::argType(vmint iArg) const {
317 return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
318 }
319
320 bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
321 if (iArg == 0)
322 return type == INT_ARR_EXPR;
323 else
324 return type == INT_EXPR;
325 }
326
327 struct ArrElemPOD {
328 VMIntArrayExpr* m_array;
329 vmint m_index;
330 };
331
332 static inline void swap(class ArrElemRef a, class ArrElemRef b);
333
334 class ArrElemRef : protected ArrElemPOD {
335 public:
336 ArrElemRef() {
337 m_array = NULL;
338 m_index = 0;
339 }
340 ArrElemRef(VMIntArrayExpr* a, vmint index) {
341 m_array = a;
342 m_index = index;
343 }
344 inline ArrElemRef& operator=(const ArrElemRef& e) {
345 setValue(e.getValue());
346 return *this;
347 }
348 inline ArrElemRef& operator=(vmint val) {
349 setValue(val);
350 return *this;
351 }
352 inline bool operator==(const ArrElemRef& e) const {
353 if (m_index == e.m_index)
354 return true;
355 return getValue() == e.getValue();
356 }
357 inline bool operator==(vmint val) const {
358 return getValue() == val;
359 }
360 inline bool operator!=(const ArrElemRef& e) const {
361 return !(operator==(e));
362 }
363 inline bool operator!=(vmint val) const {
364 return !(operator==(val));
365 }
366 inline bool operator<(const ArrElemRef& e) const {
367 if (m_index == e.m_index)
368 return false;
369 return getValue() < e.getValue();
370 }
371 inline bool operator<(vmint val) const {
372 return getValue() < val;
373 }
374 inline bool operator>(const ArrElemRef& e) const {
375 if (m_index == e.m_index)
376 return false;
377 return getValue() > e.getValue();
378 }
379 inline bool operator>(vmint val) const {
380 return getValue() > val;
381 }
382 inline bool operator<=(const ArrElemRef& e) const {
383 if (m_index == e.m_index)
384 return true;
385 return getValue() <= e.getValue();
386 }
387 inline bool operator<=(vmint val) const {
388 return getValue() <= val;
389 }
390 inline bool operator>=(const ArrElemRef& e) const {
391 if (m_index == e.m_index)
392 return true;
393 return getValue() >= e.getValue();
394 }
395 inline bool operator>=(vmint val) const {
396 return getValue() >= val;
397 }
398 inline operator vmint() const {
399 return getValue();
400 }
401 protected:
402 inline vmint getValue() const {
403 return m_array->evalIntElement(m_index);
404 }
405 inline void setValue(vmint value) {
406 m_array->assignIntElement(m_index, value);
407 }
408
409 friend void swap(class ArrElemRef a, class ArrElemRef b);
410 };
411
412 class ArrElemPtr : protected ArrElemPOD {
413 public:
414 ArrElemPtr() {
415 m_array = NULL;
416 m_index = 0;
417 }
418 ArrElemPtr(VMIntArrayExpr* a, vmint index) {
419 m_array = a;
420 m_index = index;
421 }
422 inline ArrElemRef operator*() {
423 return *(ArrElemRef*)this;
424 }
425 };
426
427 static inline void swap(ArrElemRef a, ArrElemRef b) {
428 vmint valueA = a.getValue();
429 vmint valueB = b.getValue();
430 a.setValue(valueB);
431 b.setValue(valueA);
432 }
433
434 class ArrExprIter : public ArrElemPOD {
435 public:
436 typedef std::random_access_iterator_tag iterator_category;
437 typedef vmint value_type;
438 typedef ssize_t difference_type;
439 typedef ArrElemPtr pointer;
440 typedef ArrElemRef reference;
441
442 ArrExprIter(VMIntArrayExpr* a, vmint index) {
443 m_array = a;
444 m_index = index;
445 }
446 inline ArrElemRef operator*() {
447 return *(ArrElemRef*)this;
448 }
449 inline ArrExprIter& operator++() { // prefix increment
450 ++m_index;
451 return *this;
452 }
453 inline ArrExprIter& operator--() { // prefix decrement
454 --m_index;
455 return *this;
456 }
457 inline ArrExprIter operator++(int) { // postfix increment
458 ArrExprIter it = *this;
459 ++m_index;
460 return it;
461 }
462 inline ArrExprIter operator--(int) { // postfix decrement
463 ArrExprIter it = *this;
464 --m_index;
465 return it;
466 }
467 inline ArrExprIter& operator+=(difference_type d) {
468 m_index += d;
469 return *this;
470 }
471 inline ArrExprIter& operator-=(difference_type d) {
472 m_index -= d;
473 return *this;
474 }
475 inline bool operator==(const ArrExprIter& other) const {
476 return m_index == other.m_index;
477 }
478 inline bool operator!=(const ArrExprIter& other) const {
479 return m_index != other.m_index;
480 }
481 inline bool operator<(const ArrExprIter& other) const {
482 return m_index < other.m_index;
483 }
484 inline bool operator>(const ArrExprIter& other) const {
485 return m_index > other.m_index;
486 }
487 inline bool operator<=(const ArrExprIter& other) const {
488 return m_index <= other.m_index;
489 }
490 inline bool operator>=(const ArrExprIter& other) const {
491 return m_index >= other.m_index;
492 }
493 inline difference_type operator+(const ArrExprIter& other) const {
494 return m_index + other.m_index;
495 }
496 inline difference_type operator-(const ArrExprIter& other) const {
497 return m_index - other.m_index;
498 }
499 inline ArrExprIter operator-(difference_type d) const {
500 return ArrExprIter(m_array, m_index - d);
501 }
502 inline ArrExprIter operator+(difference_type d) const {
503 return ArrExprIter(m_array, m_index + d);
504 }
505 inline ArrExprIter operator*(difference_type factor) const {
506 return ArrExprIter(m_array, m_index * factor);
507 }
508 };
509
510 struct DescArrExprSorter {
511 inline bool operator()(const vmint& a, const vmint& b) const {
512 return a > b;
513 }
514 };
515
516 VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {
517 VMIntArrayExpr* a = args->arg(0)->asIntArray();
518 bool bAscending =
519 (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();
520 vmint n = a->arraySize();
521 ArrExprIter itBegin(a, 0);
522 ArrExprIter itEnd(a, n);
523 if (bAscending) {
524 std::sort(itBegin, itEnd);
525 } else {
526 DescArrExprSorter sorter;
527 std::sort(itBegin, itEnd, sorter);
528 }
529 return successResult();
530 }
531
532 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC