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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3561 by schoenebeck, Fri Aug 23 11:44:00 2019 UTC revision 3743 by schoenebeck, Fri Feb 14 15:35:53 2020 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014-2019 Christian Schoenebeck   * Copyright (c) 2014-2020 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 13  Line 13 
13  #include "../../common/global_private.h"  #include "../../common/global_private.h"
14    
15  namespace LinuxSampler {  namespace LinuxSampler {
16        
17      // play_note() function      // play_note() function
18    
19      InstrumentScriptVMFunction_play_note::InstrumentScriptVMFunction_play_note(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_play_note::InstrumentScriptVMFunction_play_note(InstrumentScriptVM* parent)
# Line 21  namespace LinuxSampler { Line 21  namespace LinuxSampler {
21      {      {
22      }      }
23    
24        bool InstrumentScriptVMFunction_play_note::acceptsArgType(vmint iArg, ExprType_t type) const {
25            if (iArg == 2 || iArg == 3)
26                return type == INT_EXPR || type == REAL_EXPR;
27            else
28                return type == INT_EXPR;
29        }
30    
31        bool InstrumentScriptVMFunction_play_note::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
32            if (iArg == 2 || iArg == 3)
33                return type == VM_NO_UNIT || type == VM_SECOND;
34            else
35                return type == VM_NO_UNIT;
36        }
37    
38        bool InstrumentScriptVMFunction_play_note::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
39            if (iArg == 2 || iArg == 3)
40                return type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
41            else
42                return false;
43        }
44    
45        void InstrumentScriptVMFunction_play_note::checkArgs(VMFnArgs* args,
46                                                             std::function<void(String)> err,
47                                                             std::function<void(String)> wrn)
48        {
49            // super class checks
50            Super::checkArgs(args, err, wrn);
51    
52            // own checks ...
53            if (args->arg(0)->isConstExpr()) {
54                vmint note = args->arg(0)->asNumber()->evalCastInt();
55                if (note < 0 || note > 127) {
56                    err("MIDI note number value for argument 1 must be between 0..127");
57                    return;
58                }
59            }
60            if (args->argsCount() >= 2 && args->arg(1)->isConstExpr()) {
61                vmint velocity = args->arg(1)->asNumber()->evalCastInt();
62                if (velocity < 0 || velocity > 127) {
63                    err("MIDI velocity value for argument 2 must be between 0..127");
64                    return;
65                }
66            }
67            if (args->argsCount() >= 3 && args->arg(2)->isConstExpr()) {
68                VMNumberExpr* argSampleOffset = args->arg(2)->asNumber();
69                vmint sampleoffset =
70                    (argSampleOffset->unitType()) ?
71                        argSampleOffset->evalCastInt(VM_MICRO) :
72                        argSampleOffset->evalCastInt();
73                if (sampleoffset < -1) {
74                    err("Sample offset of argument 3 may not be less than -1");
75                    return;
76                }
77            }
78            if (args->argsCount() >= 4 && args->arg(3)->isConstExpr()) {
79                VMNumberExpr* argDuration = args->arg(3)->asNumber();
80                vmint duration =
81                    (argDuration->unitType()) ?
82                        argDuration->evalCastInt(VM_MICRO) :
83                        argDuration->evalCastInt();
84                if (duration < -2) {
85                    err("Argument 4 must be a duration value of at least -2 or higher");
86                    return;
87                }
88            }
89        }
90    
91      VMFnResult* InstrumentScriptVMFunction_play_note::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_play_note::exec(VMFnArgs* args) {
92          vmint note = args->arg(0)->asInt()->evalInt();          vmint note = args->arg(0)->asInt()->evalInt();
93          vmint velocity = (args->argsCount() >= 2) ? args->arg(1)->asInt()->evalInt() : 127;          vmint velocity = (args->argsCount() >= 2) ? args->arg(1)->asInt()->evalInt() : 127;
94          vmint duration = (args->argsCount() >= 4) ? args->arg(3)->asInt()->evalInt() : 0; //TODO: -1 might be a better default value instead of 0          VMNumberExpr* argDuration = (args->argsCount() >= 4) ? args->arg(3)->asNumber() : NULL;
95            vmint duration =
96                (argDuration) ?
97                    (argDuration->unitType()) ?
98                        argDuration->evalCastInt(VM_MICRO) :
99                        argDuration->evalCastInt() : 0; //TODO: -1 might be a better default value instead of 0
100    
101          if (note < 0 || note > 127) {          if (note < 0 || note > 127) {
102              errMsg("play_note(): argument 1 is an invalid note number");              errMsg("play_note(): argument 1 is an invalid note number");
# Line 69  namespace LinuxSampler { Line 141  namespace LinuxSampler {
141          // if a sample offset is supplied, assign the offset as override          // if a sample offset is supplied, assign the offset as override
142          // to the previously created Note object          // to the previously created Note object
143          if (args->argsCount() >= 3) {          if (args->argsCount() >= 3) {
144              vmint sampleoffset = args->arg(2)->asInt()->evalInt();              VMNumberExpr* argSampleOffset = args->arg(2)->asNumber();
145                vmint sampleoffset =
146                    (argSampleOffset->unitType()) ?
147                        argSampleOffset->evalCastInt(VM_MICRO) :
148                        argSampleOffset->evalCastInt();
149              if (sampleoffset >= 0) {              if (sampleoffset >= 0) {
150                  NoteBase* pNote = pEngineChannel->pEngine->NoteByID(id);                  NoteBase* pNote = pEngineChannel->pEngine->NoteByID(id);
151                  if (pNote) {                  if (pNote) {
# Line 135  namespace LinuxSampler { Line 211  namespace LinuxSampler {
211          return successResult( ScriptID::fromEventID(id) );          return successResult( ScriptID::fromEventID(id) );
212      }      }
213    
214        // set_rpn() function
215    
216        InstrumentScriptVMFunction_set_rpn::InstrumentScriptVMFunction_set_rpn(InstrumentScriptVM* parent)
217            : m_vm(parent)
218        {
219        }
220    
221        VMFnResult* InstrumentScriptVMFunction_set_rpn::exec(VMFnArgs* args) {
222            vmint parameter = args->arg(0)->asInt()->evalInt();
223            vmint value     = args->arg(1)->asInt()->evalInt();
224    
225            if (parameter < 0 || parameter > 16383) {
226                errMsg("set_rpn(): argument 1 exceeds RPN parameter number range");
227                return errorResult();
228            }
229            if (value < 0 || value > 16383) {
230                errMsg("set_rpn(): argument 2 exceeds RPN value range");
231                return errorResult();
232            }
233    
234            AbstractEngineChannel* pEngineChannel =
235                static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
236    
237            Event e = m_vm->m_event->cause; // copy to get fragment time for "now"
238            e.Init(); // clear IDs
239            e.Type = Event::type_rpn;
240            e.Param.RPN.Parameter = parameter;
241            e.Param.RPN.Value = value;
242    
243            const event_id_t id = pEngineChannel->ScheduleEventMicroSec(&e, 0);
244    
245            // even if id is null, don't return an errorResult() here, because that
246            // would abort the script, and under heavy load it may be considerable
247            // that ScheduleEventMicroSec() fails above, so simply ignore that
248            return successResult( ScriptID::fromEventID(id) );
249        }
250    
251        // set_nrpn() function
252    
253        InstrumentScriptVMFunction_set_nrpn::InstrumentScriptVMFunction_set_nrpn(InstrumentScriptVM* parent)
254            : m_vm(parent)
255        {
256        }
257    
258        VMFnResult* InstrumentScriptVMFunction_set_nrpn::exec(VMFnArgs* args) {
259            vmint parameter = args->arg(0)->asInt()->evalInt();
260            vmint value     = args->arg(1)->asInt()->evalInt();
261    
262            if (parameter < 0 || parameter > 16383) {
263                errMsg("set_nrpn(): argument 1 exceeds NRPN parameter number range");
264                return errorResult();
265            }
266            if (value < 0 || value > 16383) {
267                errMsg("set_nrpn(): argument 2 exceeds NRPN value range");
268                return errorResult();
269            }
270    
271            AbstractEngineChannel* pEngineChannel =
272                static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
273    
274            Event e = m_vm->m_event->cause; // copy to get fragment time for "now"
275            e.Init(); // clear IDs
276            e.Type = Event::type_nrpn;
277            e.Param.NRPN.Parameter = parameter;
278            e.Param.NRPN.Value = value;
279    
280            const event_id_t id = pEngineChannel->ScheduleEventMicroSec(&e, 0);
281    
282            // even if id is null, don't return an errorResult() here, because that
283            // would abort the script, and under heavy load it may be considerable
284            // that ScheduleEventMicroSec() fails above, so simply ignore that
285            return successResult( ScriptID::fromEventID(id) );
286        }
287    
288      // ignore_event() function      // ignore_event() function
289    
290      InstrumentScriptVMFunction_ignore_event::InstrumentScriptVMFunction_ignore_event(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_ignore_event::InstrumentScriptVMFunction_ignore_event(InstrumentScriptVM* parent)
# Line 202  namespace LinuxSampler { Line 352  namespace LinuxSampler {
352          return type == INT_EXPR || type == INT_ARR_EXPR;          return type == INT_EXPR || type == INT_ARR_EXPR;
353      }      }
354    
355        void InstrumentScriptVMFunction_note_off::checkArgs(VMFnArgs* args,
356                                                            std::function<void(String)> err,
357                                                            std::function<void(String)> wrn)
358        {
359            // super class checks
360            Super::checkArgs(args, err, wrn);
361    
362            // own checks ...
363            if (args->argsCount() >= 2 && args->arg(1)->isConstExpr() && args->arg(1)->exprType() == INT_EXPR) {
364                vmint velocity = args->arg(1)->asInt()->evalInt();
365                if (velocity < 0 || velocity > 127) {
366                    err("MIDI velocity value for argument 2 must be between 0..127");
367                    return;
368                }
369            }
370        }
371    
372      VMFnResult* InstrumentScriptVMFunction_note_off::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_note_off::exec(VMFnArgs* args) {
373          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
374              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
# Line 266  namespace LinuxSampler { Line 433  namespace LinuxSampler {
433      {      {
434      }      }
435    
436        void InstrumentScriptVMFunction_set_event_mark::checkArgs(VMFnArgs* args,
437                                                                  std::function<void(String)> err,
438                                                                  std::function<void(String)> wrn)
439        {
440            // super class checks
441            Super::checkArgs(args, err, wrn);
442    
443            // own checks ...
444            if (args->argsCount() >= 2 && args->arg(1)->isConstExpr()) {
445                const vmint groupID = args->arg(1)->asInt()->evalInt();
446                if (groupID < 0 || groupID >= INSTR_SCRIPT_EVENT_GROUPS) {
447                    err("Argument 2 value is an invalid group id.");
448                    return;
449                }
450            }
451        }
452    
453      VMFnResult* InstrumentScriptVMFunction_set_event_mark::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_set_event_mark::exec(VMFnArgs* args) {
454          const ScriptID id = args->arg(0)->asInt()->evalInt();          const ScriptID id = args->arg(0)->asInt()->evalInt();
455          const vmint groupID = args->arg(1)->asInt()->evalInt();          const vmint groupID = args->arg(1)->asInt()->evalInt();
# Line 304  namespace LinuxSampler { Line 488  namespace LinuxSampler {
488      {      {
489      }      }
490    
491        void InstrumentScriptVMFunction_delete_event_mark::checkArgs(VMFnArgs* args,
492                                                                     std::function<void(String)> err,
493                                                                     std::function<void(String)> wrn)
494        {
495            // super class checks
496            Super::checkArgs(args, err, wrn);
497    
498            // own checks ...
499            if (args->argsCount() >= 2 && args->arg(1)->isConstExpr()) {
500                const vmint groupID = args->arg(1)->asInt()->evalInt();
501                if (groupID < 0 || groupID >= INSTR_SCRIPT_EVENT_GROUPS) {
502                    err("Argument 2 value is an invalid group id.");
503                    return;
504                }
505            }
506        }
507    
508      VMFnResult* InstrumentScriptVMFunction_delete_event_mark::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_delete_event_mark::exec(VMFnArgs* args) {
509          const ScriptID id = args->arg(0)->asInt()->evalInt();          const ScriptID id = args->arg(0)->asInt()->evalInt();
510          const vmint groupID = args->arg(1)->asInt()->evalInt();          const vmint groupID = args->arg(1)->asInt()->evalInt();
# Line 348  namespace LinuxSampler { Line 549  namespace LinuxSampler {
549          return &m_result;          return &m_result;
550      }      }
551    
552        void InstrumentScriptVMFunction_by_marks::checkArgs(VMFnArgs* args,
553                                                            std::function<void(String)> err,
554                                                            std::function<void(String)> wrn)
555        {
556            // super class checks
557            Super::checkArgs(args, err, wrn);
558    
559            // own checks ...
560            if (args->arg(0)->isConstExpr()) {
561                const vmint groupID = args->arg(0)->asInt()->evalInt();
562                if (groupID < 0 || groupID >= INSTR_SCRIPT_EVENT_GROUPS) {
563                    err("Argument value is an invalid group id.");
564                    return;
565                }
566            }
567        }
568    
569      VMFnResult* InstrumentScriptVMFunction_by_marks::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_by_marks::exec(VMFnArgs* args) {
570          vmint groupID = args->arg(0)->asInt()->evalInt();          vmint groupID = args->arg(0)->asInt()->evalInt();
571    
# Line 372  namespace LinuxSampler { Line 590  namespace LinuxSampler {
590      bool InstrumentScriptVMFunction_change_vol::acceptsArgType(vmint iArg, ExprType_t type) const {      bool InstrumentScriptVMFunction_change_vol::acceptsArgType(vmint iArg, ExprType_t type) const {
591          if (iArg == 0)          if (iArg == 0)
592              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
593            else if (iArg == 1)
594                return type == INT_EXPR || type == REAL_EXPR;
595          else          else
596              return type == INT_EXPR;              return type == INT_EXPR;
597      }      }
# Line 383  namespace LinuxSampler { Line 603  namespace LinuxSampler {
603              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
604      }      }
605    
606      bool InstrumentScriptVMFunction_change_vol::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_vol::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
607          return iArg == 1;          return iArg == 1 && type == VM_BEL; // only allow metric prefix(es) if 'Bel' is used as unit type
608      }      }
609    
610      bool InstrumentScriptVMFunction_change_vol::acceptsArgFinal(vmint iArg) const {      bool InstrumentScriptVMFunction_change_vol::acceptsArgFinal(vmint iArg) const {
# Line 392  namespace LinuxSampler { Line 612  namespace LinuxSampler {
612      }      }
613    
614      VMFnResult* InstrumentScriptVMFunction_change_vol::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_vol::exec(VMFnArgs* args) {
615          vmint volume   = args->arg(1)->asInt()->evalInt(VM_MILLI,VM_DECI); // volume change in milli dB          StdUnit_t unit = args->arg(1)->asNumber()->unitType();
616          bool isFinal   = args->arg(1)->asInt()->isFinal();          vmint volume =
617          StdUnit_t unit = args->arg(1)->asInt()->unitType();              (unit) ?
618                    args->arg(1)->asNumber()->evalCastInt(VM_MILLI,VM_DECI) :
619                    args->arg(1)->asNumber()->evalCastInt(); // volume change in milli dB
620            bool isFinal = args->arg(1)->asNumber()->isFinal();
621          bool relative = (args->argsCount() >= 3) ? (args->arg(2)->asInt()->evalInt() & 1) : false;          bool relative = (args->argsCount() >= 3) ? (args->arg(2)->asInt()->evalInt() & 1) : false;
622          const float fVolumeLin = RTMath::DecibelToLinRatio(float(volume) / 1000.f);          const float fVolumeLin = RTMath::DecibelToLinRatio(float(volume) / 1000.f);
623    
# Line 486  namespace LinuxSampler { Line 709  namespace LinuxSampler {
709      bool InstrumentScriptVMFunction_change_tune::acceptsArgType(vmint iArg, ExprType_t type) const {      bool InstrumentScriptVMFunction_change_tune::acceptsArgType(vmint iArg, ExprType_t type) const {
710          if (iArg == 0)          if (iArg == 0)
711              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
712            else if (iArg == 1)
713                return type == INT_EXPR || type == REAL_EXPR;
714          else          else
715              return type == INT_EXPR;              return type == INT_EXPR;
716      }      }
717    
718      bool InstrumentScriptVMFunction_change_tune::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_tune::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
719          return iArg == 1;          return iArg == 1;
720      }      }
721    
# Line 499  namespace LinuxSampler { Line 724  namespace LinuxSampler {
724      }      }
725    
726      VMFnResult* InstrumentScriptVMFunction_change_tune::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_tune::exec(VMFnArgs* args) {
727          vmint tune     = args->arg(1)->asInt()->evalInt(VM_MILLI,VM_CENTI); // tuning change in milli cents          vmint tune =
728          bool isFinal   = args->arg(1)->asInt()->isFinal();              (args->arg(1)->asNumber()->hasUnitFactorNow())
729          StdUnit_t unit = args->arg(1)->asInt()->unitType();                  ? args->arg(1)->asNumber()->evalCastInt(VM_MILLI,VM_CENTI)
730                    : args->arg(1)->asNumber()->evalCastInt(); // tuning change in milli cents
731            bool isFinal = args->arg(1)->asNumber()->isFinal();
732            StdUnit_t unit = args->arg(1)->asNumber()->unitType();
733          bool relative = (args->argsCount() >= 3) ? (args->arg(2)->asInt()->evalInt() & 1) : false;          bool relative = (args->argsCount() >= 3) ? (args->arg(2)->asInt()->evalInt() & 1) : false;
734          const float fFreqRatio = RTMath::CentsToFreqRatioUnlimited(float(tune) / 1000.f);          const float fFreqRatio = RTMath::CentsToFreqRatioUnlimited(float(tune) / 1000.f);
735    
# Line 705  namespace LinuxSampler { Line 933  namespace LinuxSampler {
933      bool InstrumentScriptVMFunction_change_cutoff::acceptsArgType(vmint iArg, ExprType_t type) const {      bool InstrumentScriptVMFunction_change_cutoff::acceptsArgType(vmint iArg, ExprType_t type) const {
934          if (iArg == 0)          if (iArg == 0)
935              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
936            else if (iArg == 1)
937                return type == INT_EXPR || type == REAL_EXPR;
938          else          else
939              return type == INT_EXPR;              return type == INT_EXPR;
940      }      }
# Line 716  namespace LinuxSampler { Line 946  namespace LinuxSampler {
946              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
947      }      }
948    
949      bool InstrumentScriptVMFunction_change_cutoff::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_cutoff::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
950          return iArg == 1;          return iArg == 1 && type == VM_HERTZ; // only allow metric prefix(es) if 'Hz' is used as unit type
951      }      }
952    
953      bool InstrumentScriptVMFunction_change_cutoff::acceptsArgFinal(vmint iArg) const {      bool InstrumentScriptVMFunction_change_cutoff::acceptsArgFinal(vmint iArg) const {
954          return iArg == 1;          return iArg == 1;
955      }      }
956    
957        void InstrumentScriptVMFunction_change_cutoff::checkArgs(VMFnArgs* args,
958                                                                 std::function<void(String)> err,
959                                                                 std::function<void(String)> wrn)
960        {
961            // super class checks
962            Super::checkArgs(args, err, wrn);
963    
964            // own checks ...
965            if (args->argsCount() >= 2) {
966                VMNumberExpr* argCutoff = args->arg(1)->asNumber();
967                if (argCutoff->unitType() && !argCutoff->isFinal()) {
968                    wrn("Argument 2 implies 'final' value when using Hz as unit for cutoff frequency.");
969                }
970            }
971        }
972    
973      VMFnResult* InstrumentScriptVMFunction_change_cutoff::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_cutoff::exec(VMFnArgs* args) {
974          vmint cutoff   = args->arg(1)->asInt()->evalInt(VM_NO_PREFIX);          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
975          bool isFinal   = args->arg(1)->asInt()->isFinal();          vmint cutoff =
976          StdUnit_t unit = args->arg(1)->asInt()->unitType();              (unit) ?
977          if (!unit && cutoff > VM_FILTER_PAR_MAX_VALUE) {                  args->arg(1)->asNumber()->evalCastInt(VM_NO_PREFIX) :
978              wrnMsg("change_cutoff(): argument 2 may not be larger than " strfy(VM_FILTER_PAR_MAX_VALUE));                  args->arg(1)->asNumber()->evalCastInt();
979              cutoff = VM_FILTER_PAR_MAX_VALUE;          const bool isFinal =
980          } else if (unit && cutoff > VM_FILTER_PAR_MAX_HZ) {              (unit) ?
981                    true : // imply 'final' value if unit type is used
982                    args->arg(1)->asNumber()->isFinal();
983            // note: intentionally not checking against a max. value here if no unit!
984            // (to allow i.e. passing 2000000 for doubling cutoff frequency)
985            if (unit && cutoff > VM_FILTER_PAR_MAX_HZ) {
986              wrnMsg("change_cutoff(): argument 2 may not be larger than " strfy(VM_FILTER_PAR_MAX_HZ) " Hz");              wrnMsg("change_cutoff(): argument 2 may not be larger than " strfy(VM_FILTER_PAR_MAX_HZ) " Hz");
987              cutoff = VM_FILTER_PAR_MAX_HZ;              cutoff = VM_FILTER_PAR_MAX_HZ;
988          } else if (cutoff < 0) {          } else if (cutoff < 0) {
# Line 741  namespace LinuxSampler { Line 992  namespace LinuxSampler {
992          const float fCutoff =          const float fCutoff =
993              (unit) ? cutoff : float(cutoff) / float(VM_FILTER_PAR_MAX_VALUE);              (unit) ? cutoff : float(cutoff) / float(VM_FILTER_PAR_MAX_VALUE);
994    
         if (unit && !isFinal) {  
             wrnMsg("change_cutoff(): you must pass argument 2 as 'final' value when using Hz as unit");  
             return successResult();  
         }  
   
995          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
996              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
997    
# Line 813  namespace LinuxSampler { Line 1059  namespace LinuxSampler {
1059      }      }
1060    
1061      // change_reso() function      // change_reso() function
1062        
1063      InstrumentScriptVMFunction_change_reso::InstrumentScriptVMFunction_change_reso(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_change_reso::InstrumentScriptVMFunction_change_reso(InstrumentScriptVM* parent)
1064          : m_vm(parent)          : m_vm(parent)
1065      {      {
# Line 833  namespace LinuxSampler { Line 1079  namespace LinuxSampler {
1079      VMFnResult* InstrumentScriptVMFunction_change_reso::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_reso::exec(VMFnArgs* args) {
1080          vmint resonance = args->arg(1)->asInt()->evalInt();          vmint resonance = args->arg(1)->asInt()->evalInt();
1081          bool isFinal    = args->arg(1)->asInt()->isFinal();          bool isFinal    = args->arg(1)->asInt()->isFinal();
1082          if (resonance > VM_FILTER_PAR_MAX_VALUE) {          // note: intentionally not checking against a max. value here!
1083              wrnMsg("change_reso(): argument 2 may not be larger than 1000000");          // (to allow i.e. passing 2000000 for doubling the resonance)
1084              resonance = VM_FILTER_PAR_MAX_VALUE;          if (resonance < 0) {
         } else if (resonance < 0) {  
1085              wrnMsg("change_reso(): argument 2 may not be negative");              wrnMsg("change_reso(): argument 2 may not be negative");
1086              resonance = 0;              resonance = 0;
1087          }          }
# Line 907  namespace LinuxSampler { Line 1152  namespace LinuxSampler {
1152    
1153          return successResult();          return successResult();
1154      }      }
1155        
1156      // change_attack() function      // change_attack() function
1157        //
1158        //TODO: Derive from generalized, shared template class
1159        // VMChangeSynthParamFunction instead (like e.g. change_cutoff_attack()
1160        // implementation below already does) to ease maintenance.
1161    
1162      InstrumentScriptVMFunction_change_attack::InstrumentScriptVMFunction_change_attack(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_change_attack::InstrumentScriptVMFunction_change_attack(InstrumentScriptVM* parent)
1163          : m_vm(parent)          : m_vm(parent)
# Line 919  namespace LinuxSampler { Line 1168  namespace LinuxSampler {
1168          if (iArg == 0)          if (iArg == 0)
1169              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1170          else          else
1171              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
1172      }      }
1173    
1174      bool InstrumentScriptVMFunction_change_attack::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool InstrumentScriptVMFunction_change_attack::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
# Line 929  namespace LinuxSampler { Line 1178  namespace LinuxSampler {
1178              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1179      }      }
1180    
1181      bool InstrumentScriptVMFunction_change_attack::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_attack::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1182          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
1183      }      }
1184    
1185      bool InstrumentScriptVMFunction_change_attack::acceptsArgFinal(vmint iArg) const {      bool InstrumentScriptVMFunction_change_attack::acceptsArgFinal(vmint iArg) const {
1186          return iArg == 1;          return iArg == 1;
1187      }      }
1188    
1189        void InstrumentScriptVMFunction_change_attack::checkArgs(VMFnArgs* args,
1190                                                                 std::function<void(String)> err,
1191                                                                 std::function<void(String)> wrn)
1192        {
1193            // super class checks
1194            Super::checkArgs(args, err, wrn);
1195    
1196            // own checks ...
1197            if (args->argsCount() >= 2) {
1198                VMNumberExpr* argTime = args->arg(1)->asNumber();
1199                if (argTime->unitType() && !argTime->isFinal()) {
1200                    wrn("Argument 2 implies 'final' value when using seconds as unit for attack time.");
1201                }
1202            }
1203        }
1204    
1205      VMFnResult* InstrumentScriptVMFunction_change_attack::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_attack::exec(VMFnArgs* args) {
1206          vmint attack   = args->arg(1)->asInt()->evalInt(VM_MICRO);          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1207          bool isFinal   = args->arg(1)->asInt()->isFinal();          vmint attack =
1208          StdUnit_t unit = args->arg(1)->asInt()->unitType();              (unit) ?
1209                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
1210                    args->arg(1)->asNumber()->evalCastInt();
1211            const bool isFinal =
1212                (unit) ?
1213                    true : // imply 'final' value if unit type is used
1214                    args->arg(1)->asNumber()->isFinal();
1215          // note: intentionally not checking against a max. value here!          // note: intentionally not checking against a max. value here!
1216          // (to allow i.e. passing 2000000 for doubling the attack time)          // (to allow i.e. passing 2000000 for doubling the attack time)
1217          if (attack < 0) {          if (attack < 0) {
1218              wrnMsg("change_attack(): argument 2 may not be negative");              wrnMsg("change_attack(): argument 2 may not be negative");
1219              attack = 0;              attack = 0;
1220          }          }
1221          const float fAttack = float(attack) / float(VM_EG_PAR_MAX_VALUE);          const float fAttack =
1222                (unit) ?
1223          if (unit && !isFinal) {                  float(attack) / 1000000.f /* us -> s */ :
1224              wrnMsg("change_attack(): you must pass argument 2 as 'final' value when using seconds as unit");                  float(attack) / float(VM_EG_PAR_MAX_VALUE);
             return successResult();  
         }  
1225    
1226          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
1227              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
# Line 1021  namespace LinuxSampler { Line 1290  namespace LinuxSampler {
1290      }      }
1291    
1292      // change_decay() function      // change_decay() function
1293            //
1294        //TODO: Derive from generalized, shared template class
1295        // VMChangeSynthParamFunction instead (like e.g. change_cutoff_decay()
1296        // implementation below already does) to ease maintenance.
1297    
1298      InstrumentScriptVMFunction_change_decay::InstrumentScriptVMFunction_change_decay(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_change_decay::InstrumentScriptVMFunction_change_decay(InstrumentScriptVM* parent)
1299          : m_vm(parent)          : m_vm(parent)
1300      {      {
# Line 1031  namespace LinuxSampler { Line 1304  namespace LinuxSampler {
1304          if (iArg == 0)          if (iArg == 0)
1305              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1306          else          else
1307              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
1308      }      }
1309    
1310      bool InstrumentScriptVMFunction_change_decay::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool InstrumentScriptVMFunction_change_decay::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
# Line 1041  namespace LinuxSampler { Line 1314  namespace LinuxSampler {
1314              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1315      }      }
1316    
1317      bool InstrumentScriptVMFunction_change_decay::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_decay::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1318          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
1319      }      }
1320    
1321      bool InstrumentScriptVMFunction_change_decay::acceptsArgFinal(vmint iArg) const {      bool InstrumentScriptVMFunction_change_decay::acceptsArgFinal(vmint iArg) const {
1322          return iArg == 1;          return iArg == 1;
1323      }      }
1324    
1325        void InstrumentScriptVMFunction_change_decay::checkArgs(VMFnArgs* args,
1326                                                                std::function<void(String)> err,
1327                                                                std::function<void(String)> wrn)
1328        {
1329            // super class checks
1330            Super::checkArgs(args, err, wrn);
1331    
1332            // own checks ...
1333            if (args->argsCount() >= 2) {
1334                VMNumberExpr* argTime = args->arg(1)->asNumber();
1335                if (argTime->unitType() && !argTime->isFinal()) {
1336                    wrn("Argument 2 implies 'final' value when using seconds as unit for decay time.");
1337                }
1338            }
1339        }
1340    
1341      VMFnResult* InstrumentScriptVMFunction_change_decay::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_decay::exec(VMFnArgs* args) {
1342          vmint decay    = args->arg(1)->asInt()->evalInt(VM_MICRO);          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1343          bool isFinal   = args->arg(1)->asInt()->isFinal();          vmint decay =
1344          StdUnit_t unit = args->arg(1)->asInt()->unitType();              (unit) ?
1345                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
1346                    args->arg(1)->asNumber()->evalCastInt();
1347            const bool isFinal =
1348                (unit) ?
1349                    true : // imply 'final' value if unit type is used
1350                    args->arg(1)->asNumber()->isFinal();
1351          // note: intentionally not checking against a max. value here!          // note: intentionally not checking against a max. value here!
1352          // (to allow i.e. passing 2000000 for doubling the decay time)          // (to allow i.e. passing 2000000 for doubling the decay time)
1353          if (decay < 0) {          if (decay < 0) {
1354              wrnMsg("change_decay(): argument 2 may not be negative");              wrnMsg("change_decay(): argument 2 may not be negative");
1355              decay = 0;              decay = 0;
1356          }          }
1357          const float fDecay = float(decay) / float(VM_EG_PAR_MAX_VALUE);          const float fDecay =
1358                (unit) ?
1359          if (unit && !isFinal) {                  float(decay) / 1000000.f /* us -> s */ :
1360              wrnMsg("change_decay(): you must pass argument 2 as 'final' value when using seconds as unit");                  float(decay) / float(VM_EG_PAR_MAX_VALUE);
             return successResult();  
         }  
1361    
1362          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
1363              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
# Line 1133  namespace LinuxSampler { Line 1426  namespace LinuxSampler {
1426      }      }
1427    
1428      // change_release() function      // change_release() function
1429            //
1430        //TODO: Derive from generalized, shared template class
1431        // VMChangeSynthParamFunction instead (like e.g. change_cutoff_release()
1432        // implementation below already does) to ease maintenance.
1433    
1434      InstrumentScriptVMFunction_change_release::InstrumentScriptVMFunction_change_release(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_change_release::InstrumentScriptVMFunction_change_release(InstrumentScriptVM* parent)
1435          : m_vm(parent)          : m_vm(parent)
1436      {      {
# Line 1143  namespace LinuxSampler { Line 1440  namespace LinuxSampler {
1440          if (iArg == 0)          if (iArg == 0)
1441              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1442          else          else
1443              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
1444      }      }
1445    
1446      bool InstrumentScriptVMFunction_change_release::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool InstrumentScriptVMFunction_change_release::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
# Line 1153  namespace LinuxSampler { Line 1450  namespace LinuxSampler {
1450              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1451      }      }
1452    
1453      bool InstrumentScriptVMFunction_change_release::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_release::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1454          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
1455      }      }
1456    
1457      bool InstrumentScriptVMFunction_change_release::acceptsArgFinal(vmint iArg) const {      bool InstrumentScriptVMFunction_change_release::acceptsArgFinal(vmint iArg) const {
1458          return iArg == 1;          return iArg == 1;
1459      }      }
1460    
1461        void InstrumentScriptVMFunction_change_release::checkArgs(VMFnArgs* args,
1462                                                                  std::function<void(String)> err,
1463                                                                  std::function<void(String)> wrn)
1464        {
1465            // super class checks
1466            Super::checkArgs(args, err, wrn);
1467    
1468            // own checks ...
1469            if (args->argsCount() >= 2) {
1470                VMNumberExpr* argTime = args->arg(1)->asNumber();
1471                if (argTime->unitType() && !argTime->isFinal()) {
1472                    wrn("Argument 2 implies 'final' value when using seconds as unit for release time.");
1473                }
1474            }
1475        }
1476    
1477      VMFnResult* InstrumentScriptVMFunction_change_release::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_release::exec(VMFnArgs* args) {
1478          vmint release  = args->arg(1)->asInt()->evalInt(VM_MICRO);          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1479          bool isFinal   = args->arg(1)->asInt()->isFinal();          vmint release =
1480          StdUnit_t unit = args->arg(1)->asInt()->unitType();              (unit) ?
1481                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
1482                    args->arg(1)->asNumber()->evalCastInt();
1483            const bool isFinal =
1484                (unit) ?
1485                    true : // imply 'final' value if unit type is used
1486                    args->arg(1)->asNumber()->isFinal();
1487          // note: intentionally not checking against a max. value here!          // note: intentionally not checking against a max. value here!
1488          // (to allow i.e. passing 2000000 for doubling the release time)          // (to allow i.e. passing 2000000 for doubling the release time)
1489          if (release < 0) {          if (release < 0) {
1490              wrnMsg("change_release(): argument 2 may not be negative");              wrnMsg("change_release(): argument 2 may not be negative");
1491              release = 0;              release = 0;
1492          }          }
1493          const float fRelease = float(release) / float(VM_EG_PAR_MAX_VALUE);          const float fRelease =
1494                (unit) ?
1495          if (unit && !isFinal) {                  float(release) / 1000000.f /* us -> s */ :
1496              wrnMsg("change_release(): you must pass argument 2 as 'final' value when using seconds as unit");                  float(release) / float(VM_EG_PAR_MAX_VALUE);
             return successResult();  
         }  
1497    
1498          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
1499              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
# Line 1250  namespace LinuxSampler { Line 1567  namespace LinuxSampler {
1567          if (iArg == 0)          if (iArg == 0)
1568              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1569          else          else
1570              return type == INT_EXPR;              return type == INT_EXPR || (m_acceptReal && type == REAL_EXPR);
1571      }      }
1572    
1573      bool VMChangeSynthParamFunction::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool VMChangeSynthParamFunction::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
# Line 1260  namespace LinuxSampler { Line 1577  namespace LinuxSampler {
1577              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1578      }      }
1579    
1580      bool VMChangeSynthParamFunction::acceptsArgUnitPrefix(vmint iArg) const {      bool VMChangeSynthParamFunction::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1581          return m_unit && iArg == 1;          return m_acceptUnitPrefix && iArg == 1 && type == m_unit; // only allow metric prefix(es) if approprirate unit type is used (e.g. Hz)
1582      }      }
1583    
1584      bool VMChangeSynthParamFunction::acceptsArgFinal(vmint iArg) const {      bool VMChangeSynthParamFunction::acceptsArgFinal(vmint iArg) const {
# Line 1289  namespace LinuxSampler { Line 1606  namespace LinuxSampler {
1606          param = value;          param = value;
1607      }      }
1608    
1609        void VMChangeSynthParamFunction::checkArgs(VMFnArgs* args,
1610                                                   std::function<void(String)> err,
1611                                                   std::function<void(String)> wrn)
1612        {
1613            // super class checks
1614            Super::checkArgs(args, err, wrn);
1615    
1616            // own checks ...
1617            if (m_unit && m_unit != VM_BEL && args->argsCount() >= 2) {
1618                VMNumberExpr* arg = args->arg(1)->asNumber();
1619                if (arg && arg->unitType() && !arg->isFinal()) {
1620                    wrn("Argument 2 implies 'final' value when unit type " +
1621                        unitTypeStr(arg->unitType()) + " is used.");
1622                }
1623            }
1624        }
1625    
1626      // Arbitrarily chosen constant value symbolizing "no limit".      // Arbitrarily chosen constant value symbolizing "no limit".
1627      #define NO_LIMIT 1315916909      #define NO_LIMIT 1315916909
1628    
# Line 1299  namespace LinuxSampler { Line 1633  namespace LinuxSampler {
1633               MetricPrefix_t T_unitPrefix0, MetricPrefix_t ... T_unitPrefixN>               MetricPrefix_t T_unitPrefix0, MetricPrefix_t ... T_unitPrefixN>
1634      VMFnResult* VMChangeSynthParamFunction::execTemplate(VMFnArgs* args, const char* functionName)      VMFnResult* VMChangeSynthParamFunction::execTemplate(VMFnArgs* args, const char* functionName)
1635      {      {
1636          const StdUnit_t unit = args->arg(1)->asInt()->unitType();          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1637          const bool isFinal   = args->arg(1)->asInt()->isFinal();          const bool isFinal =
1638                (m_unit && m_unit != VM_BEL && unit) ?
1639                    true : // imply 'final' value if unit type is used (except of 'Bel' which may be relative)
1640                    args->arg(1)->asNumber()->isFinal();
1641          vmint value =          vmint value =
1642              (unit & m_unit) ?              (m_acceptUnitPrefix && ((m_unit && unit) || (!m_unit && args->arg(1)->asNumber()->hasUnitFactorNow())))
1643                  args->arg(1)->asInt()->evalInt(T_unitPrefix0, T_unitPrefixN ...) :                  ? args->arg(1)->asNumber()->evalCastInt(T_unitPrefix0, T_unitPrefixN ...)
1644                  args->arg(1)->asInt()->evalInt(VM_NO_PREFIX);                  : args->arg(1)->asNumber()->evalCastInt();
   
         if (unit && !isFinal && m_unit != VM_BEL && m_unit) {  
             wrnMsg(String(functionName) + "(): you must pass argument 2 as 'final' value when using a unit");  
             return successResult();  
         }  
1645    
1646          // check if passed value is in allowed range          // check if passed value is in allowed range
1647          if (unit && m_unit) {          if (unit && m_unit) {
# Line 1493  namespace LinuxSampler { Line 1825  namespace LinuxSampler {
1825                      &NoteBase::_Override::AmpLFODepth,                      &NoteBase::_Override::AmpLFODepth,
1826                      Event::synth_param_amp_lfo_depth,                      Event::synth_param_amp_lfo_depth,
1827                      /* if value passed without unit */                      /* if value passed without unit */
1828                      0, 1000000, true,                      0, NO_LIMIT, true,
1829                      /* not used (since this function does not accept unit) */                      /* not used (since this function does not accept unit) */
1830                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_amp_lfo_depth" );                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_amp_lfo_depth" );
1831      }      }
# Line 1506  namespace LinuxSampler { Line 1838  namespace LinuxSampler {
1838                      &NoteBase::_Override::AmpLFOFreq,                      &NoteBase::_Override::AmpLFOFreq,
1839                      Event::synth_param_amp_lfo_freq,                      Event::synth_param_amp_lfo_freq,
1840                      /* if value passed without unit */                      /* if value passed without unit */
1841                      0, 1000000, true,                      0, NO_LIMIT, true,
1842                      /* if value passed with 'Hz' unit */                      /* if value passed with 'Hz' unit */
1843                      0, 30000, VM_NO_PREFIX>( args, "change_amp_lfo_freq" );                      0, 30000, VM_NO_PREFIX>( args, "change_amp_lfo_freq" );
1844      }      }
# Line 1519  namespace LinuxSampler { Line 1851  namespace LinuxSampler {
1851                      &NoteBase::_Override::CutoffLFODepth,                      &NoteBase::_Override::CutoffLFODepth,
1852                      Event::synth_param_cutoff_lfo_depth,                      Event::synth_param_cutoff_lfo_depth,
1853                      /* if value passed without unit */                      /* if value passed without unit */
1854                      0, 1000000, true,                      0, NO_LIMIT, true,
1855                      /* not used (since this function does not accept unit) */                      /* not used (since this function does not accept unit) */
1856                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_cutoff_lfo_depth" );                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_cutoff_lfo_depth" );
1857      }      }
# Line 1532  namespace LinuxSampler { Line 1864  namespace LinuxSampler {
1864                      &NoteBase::_Override::CutoffLFOFreq,                      &NoteBase::_Override::CutoffLFOFreq,
1865                      Event::synth_param_cutoff_lfo_freq,                      Event::synth_param_cutoff_lfo_freq,
1866                      /* if value passed without unit */                      /* if value passed without unit */
1867                      0, 1000000, true,                      0, NO_LIMIT, true,
1868                      /* if value passed with 'Hz' unit */                      /* if value passed with 'Hz' unit */
1869                      0, 30000, VM_NO_PREFIX>( args, "change_cutoff_lfo_freq" );                      0, 30000, VM_NO_PREFIX>( args, "change_cutoff_lfo_freq" );
1870      }      }
# Line 1545  namespace LinuxSampler { Line 1877  namespace LinuxSampler {
1877                      &NoteBase::_Override::PitchLFODepth,                      &NoteBase::_Override::PitchLFODepth,
1878                      Event::synth_param_pitch_lfo_depth,                      Event::synth_param_pitch_lfo_depth,
1879                      /* if value passed without unit */                      /* if value passed without unit */
1880                      0, 1000000, true,                      0, NO_LIMIT, true,
1881                      /* not used (since this function does not accept unit) */                      /* not used (since this function does not accept unit) */
1882                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_pitch_lfo_depth" );                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_pitch_lfo_depth" );
1883      }      }
# Line 1558  namespace LinuxSampler { Line 1890  namespace LinuxSampler {
1890                      &NoteBase::_Override::PitchLFOFreq,                      &NoteBase::_Override::PitchLFOFreq,
1891                      Event::synth_param_pitch_lfo_freq,                      Event::synth_param_pitch_lfo_freq,
1892                      /* if value passed without unit */                      /* if value passed without unit */
1893                      0, 1000000, true,                      0, NO_LIMIT, true,
1894                      /* if value passed with 'Hz' unit */                      /* if value passed with 'Hz' unit */
1895                      0, 30000, VM_NO_PREFIX>( args, "change_pitch_lfo_freq" );                      0, 30000, VM_NO_PREFIX>( args, "change_pitch_lfo_freq" );
1896      }      }
# Line 1722  namespace LinuxSampler { Line 2054  namespace LinuxSampler {
2054          if (iArg == 0)          if (iArg == 0)
2055              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
2056          else          else
2057              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
2058      }      }
2059    
2060      bool InstrumentScriptVMFunction_fade_in::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool InstrumentScriptVMFunction_fade_in::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
# Line 1732  namespace LinuxSampler { Line 2064  namespace LinuxSampler {
2064              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
2065      }      }
2066    
2067      bool InstrumentScriptVMFunction_fade_in::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_fade_in::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
2068          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
2069      }      }
2070    
2071      VMFnResult* InstrumentScriptVMFunction_fade_in::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_fade_in::exec(VMFnArgs* args) {
2072          vmint duration = args->arg(1)->asInt()->evalInt(VM_MICRO);          StdUnit_t unit = args->arg(1)->asNumber()->unitType();
2073            vmint duration =
2074                (unit) ?
2075                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
2076                    args->arg(1)->asNumber()->evalCastInt();
2077          if (duration < 0) {          if (duration < 0) {
2078              wrnMsg("fade_in(): argument 2 may not be negative");              wrnMsg("fade_in(): argument 2 may not be negative");
2079              duration = 0;              duration = 0;
# Line 1853  namespace LinuxSampler { Line 2189  namespace LinuxSampler {
2189          if (iArg == 0)          if (iArg == 0)
2190              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
2191          else          else
2192              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
2193      }      }
2194    
2195      bool InstrumentScriptVMFunction_fade_out::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool InstrumentScriptVMFunction_fade_out::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
# Line 1863  namespace LinuxSampler { Line 2199  namespace LinuxSampler {
2199              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
2200      }      }
2201    
2202      bool InstrumentScriptVMFunction_fade_out::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_fade_out::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
2203          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
2204      }      }
2205    
2206      VMFnResult* InstrumentScriptVMFunction_fade_out::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_fade_out::exec(VMFnArgs* args) {
2207          vmint duration = args->arg(1)->asInt()->evalInt(VM_MICRO);          StdUnit_t unit = args->arg(1)->asNumber()->unitType();
2208            vmint duration =
2209                (unit) ?
2210                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
2211                    args->arg(1)->asNumber()->evalCastInt();
2212          if (duration < 0) {          if (duration < 0) {
2213              wrnMsg("fade_out(): argument 2 may not be negative");              wrnMsg("fade_out(): argument 2 may not be negative");
2214              duration = 0;              duration = 0;
# Line 1986  namespace LinuxSampler { Line 2326  namespace LinuxSampler {
2326                      e.Type = Event::type_kill_note;                      e.Type = Event::type_kill_note;
2327                      e.Param.Note.ID = id.noteID();                      e.Param.Note.ID = id.noteID();
2328                      e.Param.Note.Key = pNote->hostKey;                      e.Param.Note.Key = pNote->hostKey;
2329                        
2330                      pEngineChannel->ScheduleEventMicroSec(&e, duration + 1);                      pEngineChannel->ScheduleEventMicroSec(&e, duration + 1);
2331                  }                  }
2332              }              }
# Line 2209  namespace LinuxSampler { Line 2549  namespace LinuxSampler {
2549      // change_play_pos() function      // change_play_pos() function
2550    
2551      InstrumentScriptVMFunction_change_play_pos::InstrumentScriptVMFunction_change_play_pos(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_change_play_pos::InstrumentScriptVMFunction_change_play_pos(InstrumentScriptVM* parent)
2552      : m_vm(parent)          : m_vm(parent)
2553      {      {
2554      }      }
2555    
2556        bool InstrumentScriptVMFunction_change_play_pos::acceptsArgType(vmint iArg, ExprType_t type) const {
2557            if (iArg == 0)
2558                return type == INT_EXPR;
2559            else
2560                return type == INT_EXPR || type == REAL_EXPR;
2561        }
2562    
2563      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
2564          if (iArg == 1)          if (iArg == 1)
2565              return type == VM_NO_UNIT || type == VM_SECOND;              return type == VM_NO_UNIT || type == VM_SECOND;
# Line 2220  namespace LinuxSampler { Line 2567  namespace LinuxSampler {
2567              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
2568      }      }
2569    
2570      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
2571          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
2572      }      }
2573    
2574      VMFnResult* InstrumentScriptVMFunction_change_play_pos::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_play_pos::exec(VMFnArgs* args) {
2575          const ScriptID id = args->arg(0)->asInt()->evalInt(VM_MICRO);          const ScriptID id = args->arg(0)->asInt()->evalInt();
2576          if (!id) {          if (!id) {
2577              wrnMsg("change_play_pos(): note ID for argument 1 may not be zero");              wrnMsg("change_play_pos(): note ID for argument 1 may not be zero");
2578              return successResult();              return successResult();
# Line 2235  namespace LinuxSampler { Line 2582  namespace LinuxSampler {
2582              return successResult();              return successResult();
2583          }          }
2584    
2585          const vmint pos = args->arg(1)->asInt()->evalInt();          StdUnit_t unit = args->arg(1)->asNumber()->unitType();
2586            const vmint pos =
2587                (unit) ?
2588                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
2589                    args->arg(1)->asNumber()->evalCastInt();
2590          if (pos < 0) {          if (pos < 0) {
2591              wrnMsg("change_play_pos(): playback position of argument 2 may not be negative");              wrnMsg("change_play_pos(): playback position of argument 2 may not be negative");
2592              return successResult();              return successResult();
# Line 2309  namespace LinuxSampler { Line 2660  namespace LinuxSampler {
2660    
2661      InstrumentScriptVMFunction_wait::InstrumentScriptVMFunction_wait(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_wait::InstrumentScriptVMFunction_wait(InstrumentScriptVM* parent)
2662          : CoreVMFunction_wait(parent)          : CoreVMFunction_wait(parent)
2663      {          {
2664      }      }
2665    
2666      VMFnResult* InstrumentScriptVMFunction_wait::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_wait::exec(VMFnArgs* args) {
# Line 2325  namespace LinuxSampler { Line 2676  namespace LinuxSampler {
2676    
2677      InstrumentScriptVMFunction_stop_wait::InstrumentScriptVMFunction_stop_wait(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_stop_wait::InstrumentScriptVMFunction_stop_wait(InstrumentScriptVM* parent)
2678          : m_vm(parent)          : m_vm(parent)
2679      {          {
2680      }      }
2681    
2682      VMFnResult* InstrumentScriptVMFunction_stop_wait::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_stop_wait::exec(VMFnArgs* args) {

Legend:
Removed from v.3561  
changed lines
  Added in v.3743

  ViewVC Help
Powered by ViewVC