19 |
#include <vector> |
#include <vector> |
20 |
#include <map> |
#include <map> |
21 |
#include <stddef.h> // offsetof() |
#include <stddef.h> // offsetof() |
22 |
|
#include <functional> // std::function<> |
23 |
|
|
24 |
namespace LinuxSampler { |
namespace LinuxSampler { |
25 |
|
|
138 |
}; |
}; |
139 |
|
|
140 |
/** |
/** |
141 |
|
* This constant is used for comparison with Unit::unitFactor() to check |
142 |
|
* whether a number does have any metric unit prefix at all. |
143 |
|
* |
144 |
|
* @see Unit::unitFactor() |
145 |
|
*/ |
146 |
|
static const vmfloat VM_NO_FACTOR = vmfloat(1); |
147 |
|
|
148 |
|
/** |
149 |
* All measurement unit types supported by this script engine. |
* All measurement unit types supported by this script engine. |
150 |
* |
* |
151 |
* @e Note: there is no standard unit "cents" here (for pitch/tuning), use |
* @e Note: there is no standard unit "cents" here (for pitch/tuning), use |
162 |
VM_BEL, ///< Measuring relation between two energy levels (in logarithmic scale). Since we are using it for accoustics, we are always referring to A-weighted Bels (i.e. dBA). |
VM_BEL, ///< Measuring relation between two energy levels (in logarithmic scale). Since we are using it for accoustics, we are always referring to A-weighted Bels (i.e. dBA). |
163 |
}; |
}; |
164 |
|
|
165 |
|
//TODO: see Unit::hasUnitFactorEver() |
166 |
|
enum EverTriState_t { |
167 |
|
VM_NEVER = 0, |
168 |
|
VM_MAYBE, |
169 |
|
VM_ALWAYS, |
170 |
|
}; |
171 |
|
|
172 |
// just symbol prototyping |
// just symbol prototyping |
173 |
class VMIntExpr; |
class VMIntExpr; |
174 |
class VMRealExpr; |
class VMRealExpr; |
175 |
class VMStringExpr; |
class VMStringExpr; |
176 |
class VMScalarNumberExpr; |
class VMScalarNumberExpr; |
177 |
|
class VMArrayExpr; |
178 |
class VMIntArrayExpr; |
class VMIntArrayExpr; |
179 |
class VMRealArrayExpr; |
class VMRealArrayExpr; |
180 |
class VMStringArrayExpr; |
class VMStringArrayExpr; |
181 |
class VMParserContext; |
class VMParserContext; |
182 |
|
|
183 |
/** @brief Virtual machine measuring unit. |
/** @brief Virtual machine standard measuring unit. |
184 |
* |
* |
185 |
* Abstract base class representing standard measurement units throughout |
* Abstract base class representing standard measurement units throughout |
186 |
* the script engine. These might be i.e. "dB" (deci Bel) for loudness, |
* the script engine. These might be e.g. "dB" (deci Bel) for loudness, |
187 |
* "Hz" (Hertz) for frequencies or "s" for "seconds". |
* "Hz" (Hertz) for frequencies or "s" for "seconds". These unit types can |
188 |
|
* combined with metric prefixes, for instance "kHz" (kilo Hertz), |
189 |
|
* "us" (micro second), etc. |
190 |
* |
* |
191 |
* Originally the script engine only supported abstract integer values for |
* Originally the script engine only supported abstract integer values for |
192 |
* controlling any synthesis parameter or built-in function argument or |
* controlling any synthesis parameter or built-in function argument or |
193 |
* variable. Under certain situations it makes sense though for an |
* variable. Under certain situations it makes sense though for an |
194 |
* instrument script author to provide values in real, standard measurement |
* instrument script author to provide values in real, standard measurement |
195 |
* units, for example setting the frequency of some LFO directly to "20Hz". |
* units to provide a more natural and intuitive approach for writing |
196 |
* Hence support for standard units in scripts was added as an extension to |
* instrument scripts, for example by setting the frequency of some LFO |
197 |
* the NKSP script engine. |
* directly to "20Hz" or reducing loudness by "-4.2dB". Hence support for |
198 |
|
* standard units in scripts was added as an extension to the NKSP script |
199 |
|
* engine. |
200 |
|
* |
201 |
|
* So a unit consists of 1) a sequence of metric prefixes as scale factor |
202 |
|
* (e.g. "k" for kilo) and 2) the actual unit type (e.g. "Hz" for Hertz). |
203 |
|
* The unit type is a constant feature of number literals and variables, so |
204 |
|
* once a variable was declared with a unit type (or no unit type at all) |
205 |
|
* then that unit type of that variable cannot be changed for the entire |
206 |
|
* life time of the script. This is different from the unit's metric |
207 |
|
* prefix(es) of variables which may freely be changed at runtime. |
208 |
*/ |
*/ |
209 |
class VMUnit { |
class VMUnit { |
210 |
public: |
public: |
211 |
/** |
/** |
212 |
* Returns the metric prefix of this unit. A metric prefix essentially |
* Returns the metric prefix(es) of this unit as unit factor. A metric |
213 |
* is just a mathematical scale factor that should be applied to the |
* prefix essentially is just a mathematical scale factor that should be |
214 |
* number associated with the measurement unit. Usually a unit either |
* applied to the number associated with the measurement unit. Consider |
215 |
* has exactly none or one prefix, but note that there might also be |
* a string literal in an NKSP script like '3kHz' where 'k' (kilo) is |
216 |
* units with more than one prefix, for example mdB (mili deci bel) |
* the metric prefix, which essentically is a scale factor of 1000. |
|
* is used sometimes which has two prefixes. This is an exception though |
|
|
* and more than two prefixes is currently not supported by the script |
|
|
* engine. |
|
217 |
* |
* |
218 |
* Start iterating over the prefixes of this unit by passing @c 0 as |
* Usually a unit either has exactly none or one metric prefix, but note |
219 |
* argument to this method. The prefixes are terminated with return |
* that there might also be units with more than one prefix, for example |
220 |
* value VM_NO_PREFIX being always the last element. |
* @c mdB (milli deci Bel) is used sometimes which has two prefixes. The |
221 |
|
* latter is an exception though and more than two prefixes is currently |
222 |
|
* not supported by the script engine. |
223 |
* |
* |
224 |
* @param i - index of prefix |
* The factor returned by this method is the final mathematical factor |
225 |
* @returns prefix of requested index or VM_NO_PREFIX otherwise |
* that should be multiplied against the number associated with this |
226 |
* @see unitFactor() |
* unit. This factor results from the sequence of metric prefixes of |
227 |
|
* this unit. |
228 |
|
* |
229 |
|
* @see MetricPrefix_t, hasUnitFactorNow(), hasUnitFactorEver(), |
230 |
|
* VM_NO_FACTOR |
231 |
|
* @returns current metric unit factor |
232 |
*/ |
*/ |
233 |
virtual MetricPrefix_t unitPrefix(vmuint i) const = 0; |
virtual vmfloat unitFactor() const = 0; |
234 |
|
|
235 |
|
//TODO: this still needs to be implemented in tree.h/.pp, built-in functions and as 2nd pass of parser appropriately |
236 |
|
/*virtual*/ EverTriState_t hasUnitFactorEver() const { return VM_NEVER; } |
237 |
|
|
238 |
/** |
/** |
239 |
* Conveniently returns the final mathematical factor that should be |
* Whether this unit currently does have any metric unit prefix. |
|
* multiplied against the number associated with this unit. This factor |
|
|
* results from the sequence of metric prefixes of this unit. |
|
240 |
* |
* |
241 |
* @see unitPrefix() |
* This is actually just a convenience method which returns @c true if |
242 |
|
* unitFactor() is not @c 1.0. |
243 |
|
* |
244 |
|
* @see MetricPrefix_t, unitFactor(), hasUnitFactorEver(), VM_NO_FACTOR |
245 |
|
* @returns @c true if this unit currently has any metric prefix |
246 |
*/ |
*/ |
247 |
vmfloat unitFactor() const; |
bool hasUnitFactorNow() const; |
248 |
|
|
249 |
/** |
/** |
250 |
* This is the actual fundamental measuring unit base type of this unit, |
* This is the actual fundamental measuring unit base type of this unit, |
251 |
* which might be either Hertz, second or Bel. |
* which might be either Hertz, second or Bel. |
252 |
* |
* |
253 |
* @returns standard unit type identifier or VM_NO_UNIT if no unit used |
* Note that a number without a unit type may still have metric |
254 |
|
* prefixes. |
255 |
|
* |
256 |
|
* @returns standard unit type identifier or VM_NO_UNIT if no unit type |
257 |
|
* is used for this object |
258 |
*/ |
*/ |
259 |
virtual StdUnit_t unitType() const = 0; |
virtual StdUnit_t unitType() const = 0; |
260 |
|
|
267 |
/** |
/** |
268 |
* Returns the actual mathematical factor represented by the passed |
* Returns the actual mathematical factor represented by the passed |
269 |
* two @a prefix1 and @a prefix2 arguments. |
* two @a prefix1 and @a prefix2 arguments. |
270 |
|
* |
271 |
|
* @returns scale factor of given metric unit prefixes |
272 |
*/ |
*/ |
273 |
static vmfloat unitFactor(MetricPrefix_t prefix1, MetricPrefix_t prefix2); |
static vmfloat unitFactor(MetricPrefix_t prefix1, MetricPrefix_t prefix2); |
274 |
|
|
275 |
|
/** |
276 |
|
* Returns the actual mathematical factor represented by the passed |
277 |
|
* @a prefixes array. The passed array should always be terminated by a |
278 |
|
* VM_NO_PREFIX value as last element. |
279 |
|
* |
280 |
|
* @param prefixes - sequence of metric prefixes |
281 |
|
* @param size - max. amount of elements of array @a prefixes |
282 |
|
* @returns scale factor of given metric unit prefixes |
283 |
|
*/ |
284 |
|
static vmfloat unitFactor(const MetricPrefix_t* prefixes, vmuint size = 2); |
285 |
}; |
}; |
286 |
|
|
287 |
/** @brief Virtual machine expression |
/** @brief Virtual machine expression |
421 |
virtual VMRealArrayExpr* asRealArray() const; |
virtual VMRealArrayExpr* asRealArray() const; |
422 |
|
|
423 |
/** |
/** |
424 |
|
* This is an alternative to calling either asIntArray() or |
425 |
|
* asRealArray(). This method here might be used if the fundamental |
426 |
|
* scalar data type (real or integer) of the array is not relevant, |
427 |
|
* i.e. for just getting the size of the array. Since all as*() methods |
428 |
|
* here are very strict regarding type casting, this asArray() method |
429 |
|
* sometimes can reduce code complexity. |
430 |
|
* |
431 |
|
* Likewise calling this method only returns a valid pointer if the |
432 |
|
* expression is some array type (currently either integer array or real |
433 |
|
* number array). For any other expression type this method will return |
434 |
|
* NULL instead. |
435 |
|
* |
436 |
|
* @see exprType() |
437 |
|
*/ |
438 |
|
VMArrayExpr* asArray() const; |
439 |
|
|
440 |
|
/** |
441 |
* Returns true in case this expression can be considered to be a |
* Returns true in case this expression can be considered to be a |
442 |
* constant expression. A constant expression will retain the same |
* constant expression. A constant expression will retain the same |
443 |
* value throughout the entire life time of a script and the |
* value throughout the entire life time of a script and the |
504 |
* requested synthesis parameter. |
* requested synthesis parameter. |
505 |
*/ |
*/ |
506 |
virtual bool isFinal() const = 0; |
virtual bool isFinal() const = 0; |
507 |
|
|
508 |
|
/** |
509 |
|
* Calling this method evaluates the expression and returns the value |
510 |
|
* of the expression as integer. If this scalar number expression is a |
511 |
|
* real number expression then this method automatically casts the value |
512 |
|
* from real number to integer. |
513 |
|
*/ |
514 |
|
vmint evalCastInt(); |
515 |
|
|
516 |
|
/** |
517 |
|
* Calling this method evaluates the expression and returns the value |
518 |
|
* of the expression as real number. If this scalar number expression is |
519 |
|
* an integer expression then this method automatically casts the value |
520 |
|
* from integer to real number. |
521 |
|
*/ |
522 |
|
vmfloat evalCastReal(); |
523 |
}; |
}; |
524 |
|
|
525 |
/** @brief Virtual machine integer expression |
/** @brief Virtual machine integer expression |
637 |
virtual vmint arraySize() const = 0; |
virtual vmint arraySize() const = 0; |
638 |
}; |
}; |
639 |
|
|
640 |
|
/** @brief Virtual Machine Number Array Expression |
641 |
|
* |
642 |
|
* This is the abstract base class for all expressions which either evaluate |
643 |
|
* to an integer array or real number array. |
644 |
|
*/ |
645 |
|
class VMNumberArrayExpr : virtual public VMArrayExpr { |
646 |
|
public: |
647 |
|
/** |
648 |
|
* Returns the metric unit factor of the requested array element. |
649 |
|
* |
650 |
|
* @param i - array element index (must be between 0 .. arraySize() - 1) |
651 |
|
* @see VMUnit::unitFactor() for details about metric unit factors |
652 |
|
*/ |
653 |
|
virtual vmfloat unitFactorOfElement(vmuint i) const = 0; |
654 |
|
|
655 |
|
/** |
656 |
|
* Changes the current unit factor of the array element given by element |
657 |
|
* index @a i. |
658 |
|
* |
659 |
|
* @param i - array element index (must be between 0 .. arraySize() - 1) |
660 |
|
* @param factor - new unit factor to be assigned |
661 |
|
* @see VMUnit::unitFactor() for details about metric unit factors |
662 |
|
*/ |
663 |
|
virtual void assignElementUnitFactor(vmuint i, vmfloat factor) = 0; |
664 |
|
}; |
665 |
|
|
666 |
/** @brief Virtual Machine Integer Array Expression |
/** @brief Virtual Machine Integer Array Expression |
667 |
* |
* |
668 |
* This is the abstract base class for all expressions inside scripts which |
* This is the abstract base class for all expressions inside scripts which |
670 |
* abstract methods arraySize(), evalIntElement() and assignIntElement() to |
* abstract methods arraySize(), evalIntElement() and assignIntElement() to |
671 |
* access the individual integer array values. |
* access the individual integer array values. |
672 |
*/ |
*/ |
673 |
class VMIntArrayExpr : virtual public VMArrayExpr { |
class VMIntArrayExpr : virtual public VMNumberArrayExpr { |
674 |
public: |
public: |
675 |
/** |
/** |
676 |
* Returns the (scalar) integer value of the array element given by |
* Returns the (scalar) integer value of the array element given by |
702 |
* classes implement the abstract methods arraySize(), evalRealElement() and |
* classes implement the abstract methods arraySize(), evalRealElement() and |
703 |
* assignRealElement() to access the array's individual real numbers. |
* assignRealElement() to access the array's individual real numbers. |
704 |
*/ |
*/ |
705 |
class VMRealArrayExpr : virtual public VMArrayExpr { |
class VMRealArrayExpr : virtual public VMNumberArrayExpr { |
706 |
public: |
public: |
707 |
/** |
/** |
708 |
* Returns the (scalar) real mumber (floating point value) of the array |
* Returns the (scalar) real mumber (floating point value) of the array |
821 |
virtual ExprType_t returnType(VMFnArgs* args) = 0; |
virtual ExprType_t returnType(VMFnArgs* args) = 0; |
822 |
|
|
823 |
/** |
/** |
824 |
|
* Standard measuring unit type of the function's result value |
825 |
|
* (e.g. second, Hertz). |
826 |
|
* |
827 |
|
* Some functions may have a different standard measuring unit type for |
828 |
|
* their return value depending on the arguments to be passed to this |
829 |
|
* function. That's what the @a args parameter is for, so that the |
830 |
|
* method implementation can look ahead of what kind of parameters are |
831 |
|
* going to be passed to the built-in function later on in order to |
832 |
|
* decide which return value type would be used and returned by the |
833 |
|
* function accordingly in that case. |
834 |
|
* |
835 |
|
* @param args - function arguments going to be passed for executing |
836 |
|
* this built-in function later on |
837 |
|
* @see Unit for details about standard measuring units |
838 |
|
*/ |
839 |
|
virtual StdUnit_t returnUnitType(VMFnArgs* args) = 0; |
840 |
|
|
841 |
|
/** |
842 |
|
* Whether the result value returned by this built-in function is |
843 |
|
* considered to be a 'final' value. |
844 |
|
* |
845 |
|
* Some functions may have a different 'final' feature for their return |
846 |
|
* value depending on the arguments to be passed to this function. |
847 |
|
* That's what the @a args parameter is for, so that the method |
848 |
|
* implementation can look ahead of what kind of parameters are going to |
849 |
|
* be passed to the built-in function later on in order to decide which |
850 |
|
* return value type would be used and returned by the function |
851 |
|
* accordingly in that case. |
852 |
|
* |
853 |
|
* @param args - function arguments going to be passed for executing |
854 |
|
* this built-in function later on |
855 |
|
* @see VMScalarNumberExpr::isFinal() for details about 'final' values |
856 |
|
*/ |
857 |
|
virtual bool returnsFinal(VMFnArgs* args) = 0; |
858 |
|
|
859 |
|
/** |
860 |
* Minimum amount of function arguments this function accepts. If a |
* Minimum amount of function arguments this function accepts. If a |
861 |
* script is calling this function with less arguments, the script |
* script is calling this function with less arguments, the script |
862 |
* parser will throw a parser error. |
* parser will throw a parser error. |
964 |
* @return true if a "final" value would be accepted for the respective |
* @return true if a "final" value would be accepted for the respective |
965 |
* function argument by the function |
* function argument by the function |
966 |
* |
* |
967 |
* @see VMIntExpr::isFinal() |
* @see VMScalarNumberExpr::isFinal(), returnsFinal() |
968 |
*/ |
*/ |
969 |
virtual bool acceptsArgFinal(vmint iArg) const; |
virtual bool acceptsArgFinal(vmint iArg) const; |
970 |
|
|
984 |
virtual bool modifiesArg(vmint iArg) const = 0; |
virtual bool modifiesArg(vmint iArg) const = 0; |
985 |
|
|
986 |
/** |
/** |
987 |
|
* This method is called by the parser to let the built-in function |
988 |
|
* perform its own, individual parse time checks on the arguments to be |
989 |
|
* passed to the built-in function. So this method is the place for |
990 |
|
* implementing custom checks which are very specific to the individual |
991 |
|
* built-in function's purpose and its individual requirements. |
992 |
|
* |
993 |
|
* For instance the built-in 'in_range()' function uses this method to |
994 |
|
* check whether the last 2 of their 3 arguments are of same data type |
995 |
|
* and if not it triggers a parser error. 'in_range()' also checks |
996 |
|
* whether all of its 3 arguments do have the same standard measuring |
997 |
|
* unit type and likewise raises a parser error if not. |
998 |
|
* |
999 |
|
* For less critical issues built-in functions may also raise parser |
1000 |
|
* warnings instead. |
1001 |
|
* |
1002 |
|
* It is recommended that classes implementing (that is overriding) this |
1003 |
|
* method should always call their super class's implementation of this |
1004 |
|
* method to ensure their potential parse time checks are always |
1005 |
|
* performed as well. |
1006 |
|
* |
1007 |
|
* @param args - function arguments going to be passed for executing |
1008 |
|
* this built-in function later on |
1009 |
|
* @param err - the parser's error handler to be called by this method |
1010 |
|
* implementation to trigger a parser error with the |
1011 |
|
* respective error message text |
1012 |
|
* @param wrn - the parser's warning handler to be called by this method |
1013 |
|
* implementation to trigger a parser warning with the |
1014 |
|
* respective warning message text |
1015 |
|
*/ |
1016 |
|
virtual void checkArgs(VMFnArgs* args, |
1017 |
|
std::function<void(String)> err, |
1018 |
|
std::function<void(String)> wrn); |
1019 |
|
|
1020 |
|
/** |
1021 |
* Implements the actual function execution. This exec() method is |
* Implements the actual function execution. This exec() method is |
1022 |
* called by the VM whenever this function implementation shall be |
* called by the VM whenever this function implementation shall be |
1023 |
* executed at script runtime. This method blocks until the function |
* executed at script runtime. This method blocks until the function |
1413 |
*/ |
*/ |
1414 |
class VMDynIntVar : virtual public VMDynVar, virtual public VMIntExpr { |
class VMDynIntVar : virtual public VMDynVar, virtual public VMIntExpr { |
1415 |
public: |
public: |
1416 |
MetricPrefix_t unitPrefix(vmuint i) const OVERRIDE { return VM_NO_PREFIX; } |
vmfloat unitFactor() const OVERRIDE { return VM_NO_FACTOR; } |
1417 |
StdUnit_t unitType() const OVERRIDE { return VM_NO_UNIT; } |
StdUnit_t unitType() const OVERRIDE { return VM_NO_UNIT; } |
1418 |
bool isFinal() const OVERRIDE { return false; } |
bool isFinal() const OVERRIDE { return false; } |
1419 |
}; |
}; |