/[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 3742 by schoenebeck, Fri Feb 14 15:15:13 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 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 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 919  namespace LinuxSampler { Line 1164  namespace LinuxSampler {
1164          if (iArg == 0)          if (iArg == 0)
1165              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1166          else          else
1167              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
1168      }      }
1169    
1170      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 1174  namespace LinuxSampler {
1174              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1175      }      }
1176    
1177      bool InstrumentScriptVMFunction_change_attack::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_attack::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1178          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
1179      }      }
1180    
1181      bool InstrumentScriptVMFunction_change_attack::acceptsArgFinal(vmint iArg) const {      bool InstrumentScriptVMFunction_change_attack::acceptsArgFinal(vmint iArg) const {
1182          return iArg == 1;          return iArg == 1;
1183      }      }
1184    
1185        void InstrumentScriptVMFunction_change_attack::checkArgs(VMFnArgs* args,
1186                                                                 std::function<void(String)> err,
1187                                                                 std::function<void(String)> wrn)
1188        {
1189            // super class checks
1190            Super::checkArgs(args, err, wrn);
1191    
1192            // own checks ...
1193            if (args->argsCount() >= 2) {
1194                VMNumberExpr* argTime = args->arg(1)->asNumber();
1195                if (argTime->unitType() && !argTime->isFinal()) {
1196                    wrn("Argument 2 implies 'final' value when using seconds as unit for attack time.");
1197                }
1198            }
1199        }
1200    
1201      VMFnResult* InstrumentScriptVMFunction_change_attack::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_attack::exec(VMFnArgs* args) {
1202          vmint attack   = args->arg(1)->asInt()->evalInt(VM_MICRO);          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1203          bool isFinal   = args->arg(1)->asInt()->isFinal();          vmint attack =
1204          StdUnit_t unit = args->arg(1)->asInt()->unitType();              (unit) ?
1205                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
1206                    args->arg(1)->asNumber()->evalCastInt();
1207            const bool isFinal =
1208                (unit) ?
1209                    true : // imply 'final' value if unit type is used
1210                    args->arg(1)->asNumber()->isFinal();
1211          // note: intentionally not checking against a max. value here!          // note: intentionally not checking against a max. value here!
1212          // (to allow i.e. passing 2000000 for doubling the attack time)          // (to allow i.e. passing 2000000 for doubling the attack time)
1213          if (attack < 0) {          if (attack < 0) {
1214              wrnMsg("change_attack(): argument 2 may not be negative");              wrnMsg("change_attack(): argument 2 may not be negative");
1215              attack = 0;              attack = 0;
1216          }          }
1217          const float fAttack = float(attack) / float(VM_EG_PAR_MAX_VALUE);          const float fAttack =
1218                (unit) ?
1219          if (unit && !isFinal) {                  float(attack) / 1000000.f /* us -> s */ :
1220              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();  
         }  
1221    
1222          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
1223              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
# Line 1031  namespace LinuxSampler { Line 1296  namespace LinuxSampler {
1296          if (iArg == 0)          if (iArg == 0)
1297              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1298          else          else
1299              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
1300      }      }
1301    
1302      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 1306  namespace LinuxSampler {
1306              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1307      }      }
1308    
1309      bool InstrumentScriptVMFunction_change_decay::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_decay::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1310          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
1311      }      }
1312    
1313      bool InstrumentScriptVMFunction_change_decay::acceptsArgFinal(vmint iArg) const {      bool InstrumentScriptVMFunction_change_decay::acceptsArgFinal(vmint iArg) const {
1314          return iArg == 1;          return iArg == 1;
1315      }      }
1316    
1317        void InstrumentScriptVMFunction_change_decay::checkArgs(VMFnArgs* args,
1318                                                                std::function<void(String)> err,
1319                                                                std::function<void(String)> wrn)
1320        {
1321            // super class checks
1322            Super::checkArgs(args, err, wrn);
1323    
1324            // own checks ...
1325            if (args->argsCount() >= 2) {
1326                VMNumberExpr* argTime = args->arg(1)->asNumber();
1327                if (argTime->unitType() && !argTime->isFinal()) {
1328                    wrn("Argument 2 implies 'final' value when using seconds as unit for decay time.");
1329                }
1330            }
1331        }
1332    
1333      VMFnResult* InstrumentScriptVMFunction_change_decay::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_decay::exec(VMFnArgs* args) {
1334          vmint decay    = args->arg(1)->asInt()->evalInt(VM_MICRO);          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1335          bool isFinal   = args->arg(1)->asInt()->isFinal();          vmint decay =
1336          StdUnit_t unit = args->arg(1)->asInt()->unitType();              (unit) ?
1337                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
1338                    args->arg(1)->asNumber()->evalCastInt();
1339            const bool isFinal =
1340                (unit) ?
1341                    true : // imply 'final' value if unit type is used
1342                    args->arg(1)->asNumber()->isFinal();
1343          // note: intentionally not checking against a max. value here!          // note: intentionally not checking against a max. value here!
1344          // (to allow i.e. passing 2000000 for doubling the decay time)          // (to allow i.e. passing 2000000 for doubling the decay time)
1345          if (decay < 0) {          if (decay < 0) {
1346              wrnMsg("change_decay(): argument 2 may not be negative");              wrnMsg("change_decay(): argument 2 may not be negative");
1347              decay = 0;              decay = 0;
1348          }          }
1349          const float fDecay = float(decay) / float(VM_EG_PAR_MAX_VALUE);          const float fDecay =
1350                (unit) ?
1351          if (unit && !isFinal) {                  float(decay) / 1000000.f /* us -> s */ :
1352              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();  
         }  
1353    
1354          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
1355              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
# Line 1143  namespace LinuxSampler { Line 1428  namespace LinuxSampler {
1428          if (iArg == 0)          if (iArg == 0)
1429              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1430          else          else
1431              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
1432      }      }
1433    
1434      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 1438  namespace LinuxSampler {
1438              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1439      }      }
1440    
1441      bool InstrumentScriptVMFunction_change_release::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_release::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1442          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
1443      }      }
1444    
1445      bool InstrumentScriptVMFunction_change_release::acceptsArgFinal(vmint iArg) const {      bool InstrumentScriptVMFunction_change_release::acceptsArgFinal(vmint iArg) const {
1446          return iArg == 1;          return iArg == 1;
1447      }      }
1448    
1449        void InstrumentScriptVMFunction_change_release::checkArgs(VMFnArgs* args,
1450                                                                  std::function<void(String)> err,
1451                                                                  std::function<void(String)> wrn)
1452        {
1453            // super class checks
1454            Super::checkArgs(args, err, wrn);
1455    
1456            // own checks ...
1457            if (args->argsCount() >= 2) {
1458                VMNumberExpr* argTime = args->arg(1)->asNumber();
1459                if (argTime->unitType() && !argTime->isFinal()) {
1460                    wrn("Argument 2 implies 'final' value when using seconds as unit for release time.");
1461                }
1462            }
1463        }
1464    
1465      VMFnResult* InstrumentScriptVMFunction_change_release::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_release::exec(VMFnArgs* args) {
1466          vmint release  = args->arg(1)->asInt()->evalInt(VM_MICRO);          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1467          bool isFinal   = args->arg(1)->asInt()->isFinal();          vmint release =
1468          StdUnit_t unit = args->arg(1)->asInt()->unitType();              (unit) ?
1469                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
1470                    args->arg(1)->asNumber()->evalCastInt();
1471            const bool isFinal =
1472                (unit) ?
1473                    true : // imply 'final' value if unit type is used
1474                    args->arg(1)->asNumber()->isFinal();
1475          // note: intentionally not checking against a max. value here!          // note: intentionally not checking against a max. value here!
1476          // (to allow i.e. passing 2000000 for doubling the release time)          // (to allow i.e. passing 2000000 for doubling the release time)
1477          if (release < 0) {          if (release < 0) {
1478              wrnMsg("change_release(): argument 2 may not be negative");              wrnMsg("change_release(): argument 2 may not be negative");
1479              release = 0;              release = 0;
1480          }          }
1481          const float fRelease = float(release) / float(VM_EG_PAR_MAX_VALUE);          const float fRelease =
1482                (unit) ?
1483          if (unit && !isFinal) {                  float(release) / 1000000.f /* us -> s */ :
1484              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();  
         }  
1485    
1486          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
1487              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
# Line 1250  namespace LinuxSampler { Line 1555  namespace LinuxSampler {
1555          if (iArg == 0)          if (iArg == 0)
1556              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1557          else          else
1558              return type == INT_EXPR;              return type == INT_EXPR || (m_acceptReal && type == REAL_EXPR);
1559      }      }
1560    
1561      bool VMChangeSynthParamFunction::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool VMChangeSynthParamFunction::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
# Line 1260  namespace LinuxSampler { Line 1565  namespace LinuxSampler {
1565              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1566      }      }
1567    
1568      bool VMChangeSynthParamFunction::acceptsArgUnitPrefix(vmint iArg) const {      bool VMChangeSynthParamFunction::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1569          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)
1570      }      }
1571    
1572      bool VMChangeSynthParamFunction::acceptsArgFinal(vmint iArg) const {      bool VMChangeSynthParamFunction::acceptsArgFinal(vmint iArg) const {
# Line 1289  namespace LinuxSampler { Line 1594  namespace LinuxSampler {
1594          param = value;          param = value;
1595      }      }
1596    
1597        void VMChangeSynthParamFunction::checkArgs(VMFnArgs* args,
1598                                                   std::function<void(String)> err,
1599                                                   std::function<void(String)> wrn)
1600        {
1601            // super class checks
1602            Super::checkArgs(args, err, wrn);
1603    
1604            // own checks ...
1605            if (m_unit && m_unit != VM_BEL && args->argsCount() >= 2) {
1606                VMNumberExpr* arg = args->arg(1)->asNumber();
1607                if (arg && arg->unitType() && !arg->isFinal()) {
1608                    wrn("Argument 2 implies 'final' value when unit type " +
1609                        unitTypeStr(arg->unitType()) + " is used.");
1610                }
1611            }
1612        }
1613    
1614      // Arbitrarily chosen constant value symbolizing "no limit".      // Arbitrarily chosen constant value symbolizing "no limit".
1615      #define NO_LIMIT 1315916909      #define NO_LIMIT 1315916909
1616    
# Line 1299  namespace LinuxSampler { Line 1621  namespace LinuxSampler {
1621               MetricPrefix_t T_unitPrefix0, MetricPrefix_t ... T_unitPrefixN>               MetricPrefix_t T_unitPrefix0, MetricPrefix_t ... T_unitPrefixN>
1622      VMFnResult* VMChangeSynthParamFunction::execTemplate(VMFnArgs* args, const char* functionName)      VMFnResult* VMChangeSynthParamFunction::execTemplate(VMFnArgs* args, const char* functionName)
1623      {      {
1624          const StdUnit_t unit = args->arg(1)->asInt()->unitType();          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1625          const bool isFinal   = args->arg(1)->asInt()->isFinal();          const bool isFinal =
1626                (m_unit && m_unit != VM_BEL && unit) ?
1627                    true : // imply 'final' value if unit type is used (except of 'Bel' which may be relative)
1628                    args->arg(1)->asNumber()->isFinal();
1629          vmint value =          vmint value =
1630              (unit & m_unit) ?              (m_acceptUnitPrefix && ((m_unit && unit) || (!m_unit && args->arg(1)->asNumber()->hasUnitFactorNow())))
1631                  args->arg(1)->asInt()->evalInt(T_unitPrefix0, T_unitPrefixN ...) :                  ? args->arg(1)->asNumber()->evalCastInt(T_unitPrefix0, T_unitPrefixN ...)
1632                  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();  
         }  
1633    
1634          // check if passed value is in allowed range          // check if passed value is in allowed range
1635          if (unit && m_unit) {          if (unit && m_unit) {
# Line 1493  namespace LinuxSampler { Line 1813  namespace LinuxSampler {
1813                      &NoteBase::_Override::AmpLFODepth,                      &NoteBase::_Override::AmpLFODepth,
1814                      Event::synth_param_amp_lfo_depth,                      Event::synth_param_amp_lfo_depth,
1815                      /* if value passed without unit */                      /* if value passed without unit */
1816                      0, 1000000, true,                      0, NO_LIMIT, true,
1817                      /* not used (since this function does not accept unit) */                      /* not used (since this function does not accept unit) */
1818                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_amp_lfo_depth" );                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_amp_lfo_depth" );
1819      }      }
# Line 1506  namespace LinuxSampler { Line 1826  namespace LinuxSampler {
1826                      &NoteBase::_Override::AmpLFOFreq,                      &NoteBase::_Override::AmpLFOFreq,
1827                      Event::synth_param_amp_lfo_freq,                      Event::synth_param_amp_lfo_freq,
1828                      /* if value passed without unit */                      /* if value passed without unit */
1829                      0, 1000000, true,                      0, NO_LIMIT, true,
1830                      /* if value passed with 'Hz' unit */                      /* if value passed with 'Hz' unit */
1831                      0, 30000, VM_NO_PREFIX>( args, "change_amp_lfo_freq" );                      0, 30000, VM_NO_PREFIX>( args, "change_amp_lfo_freq" );
1832      }      }
# Line 1519  namespace LinuxSampler { Line 1839  namespace LinuxSampler {
1839                      &NoteBase::_Override::CutoffLFODepth,                      &NoteBase::_Override::CutoffLFODepth,
1840                      Event::synth_param_cutoff_lfo_depth,                      Event::synth_param_cutoff_lfo_depth,
1841                      /* if value passed without unit */                      /* if value passed without unit */
1842                      0, 1000000, true,                      0, NO_LIMIT, true,
1843                      /* not used (since this function does not accept unit) */                      /* not used (since this function does not accept unit) */
1844                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_cutoff_lfo_depth" );                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_cutoff_lfo_depth" );
1845      }      }
# Line 1532  namespace LinuxSampler { Line 1852  namespace LinuxSampler {
1852                      &NoteBase::_Override::CutoffLFOFreq,                      &NoteBase::_Override::CutoffLFOFreq,
1853                      Event::synth_param_cutoff_lfo_freq,                      Event::synth_param_cutoff_lfo_freq,
1854                      /* if value passed without unit */                      /* if value passed without unit */
1855                      0, 1000000, true,                      0, NO_LIMIT, true,
1856                      /* if value passed with 'Hz' unit */                      /* if value passed with 'Hz' unit */
1857                      0, 30000, VM_NO_PREFIX>( args, "change_cutoff_lfo_freq" );                      0, 30000, VM_NO_PREFIX>( args, "change_cutoff_lfo_freq" );
1858      }      }
# Line 1545  namespace LinuxSampler { Line 1865  namespace LinuxSampler {
1865                      &NoteBase::_Override::PitchLFODepth,                      &NoteBase::_Override::PitchLFODepth,
1866                      Event::synth_param_pitch_lfo_depth,                      Event::synth_param_pitch_lfo_depth,
1867                      /* if value passed without unit */                      /* if value passed without unit */
1868                      0, 1000000, true,                      0, NO_LIMIT, true,
1869                      /* not used (since this function does not accept unit) */                      /* not used (since this function does not accept unit) */
1870                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_pitch_lfo_depth" );                      NO_LIMIT, NO_LIMIT, VM_NO_PREFIX>( args, "change_pitch_lfo_depth" );
1871      }      }
# Line 1558  namespace LinuxSampler { Line 1878  namespace LinuxSampler {
1878                      &NoteBase::_Override::PitchLFOFreq,                      &NoteBase::_Override::PitchLFOFreq,
1879                      Event::synth_param_pitch_lfo_freq,                      Event::synth_param_pitch_lfo_freq,
1880                      /* if value passed without unit */                      /* if value passed without unit */
1881                      0, 1000000, true,                      0, NO_LIMIT, true,
1882                      /* if value passed with 'Hz' unit */                      /* if value passed with 'Hz' unit */
1883                      0, 30000, VM_NO_PREFIX>( args, "change_pitch_lfo_freq" );                      0, 30000, VM_NO_PREFIX>( args, "change_pitch_lfo_freq" );
1884      }      }
# Line 1722  namespace LinuxSampler { Line 2042  namespace LinuxSampler {
2042          if (iArg == 0)          if (iArg == 0)
2043              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
2044          else          else
2045              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
2046      }      }
2047    
2048      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 2052  namespace LinuxSampler {
2052              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
2053      }      }
2054    
2055      bool InstrumentScriptVMFunction_fade_in::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_fade_in::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
2056          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
2057      }      }
2058    
2059      VMFnResult* InstrumentScriptVMFunction_fade_in::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_fade_in::exec(VMFnArgs* args) {
2060          vmint duration = args->arg(1)->asInt()->evalInt(VM_MICRO);          StdUnit_t unit = args->arg(1)->asNumber()->unitType();
2061            vmint duration =
2062                (unit) ?
2063                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
2064                    args->arg(1)->asNumber()->evalCastInt();
2065          if (duration < 0) {          if (duration < 0) {
2066              wrnMsg("fade_in(): argument 2 may not be negative");              wrnMsg("fade_in(): argument 2 may not be negative");
2067              duration = 0;              duration = 0;
# Line 1853  namespace LinuxSampler { Line 2177  namespace LinuxSampler {
2177          if (iArg == 0)          if (iArg == 0)
2178              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
2179          else          else
2180              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
2181      }      }
2182    
2183      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 2187  namespace LinuxSampler {
2187              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
2188      }      }
2189    
2190      bool InstrumentScriptVMFunction_fade_out::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_fade_out::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
2191          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
2192      }      }
2193    
2194      VMFnResult* InstrumentScriptVMFunction_fade_out::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_fade_out::exec(VMFnArgs* args) {
2195          vmint duration = args->arg(1)->asInt()->evalInt(VM_MICRO);          StdUnit_t unit = args->arg(1)->asNumber()->unitType();
2196            vmint duration =
2197                (unit) ?
2198                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
2199                    args->arg(1)->asNumber()->evalCastInt();
2200          if (duration < 0) {          if (duration < 0) {
2201              wrnMsg("fade_out(): argument 2 may not be negative");              wrnMsg("fade_out(): argument 2 may not be negative");
2202              duration = 0;              duration = 0;
# Line 2209  namespace LinuxSampler { Line 2537  namespace LinuxSampler {
2537      // change_play_pos() function      // change_play_pos() function
2538    
2539      InstrumentScriptVMFunction_change_play_pos::InstrumentScriptVMFunction_change_play_pos(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_change_play_pos::InstrumentScriptVMFunction_change_play_pos(InstrumentScriptVM* parent)
2540      : m_vm(parent)          : m_vm(parent)
2541      {      {
2542      }      }
2543    
2544        bool InstrumentScriptVMFunction_change_play_pos::acceptsArgType(vmint iArg, ExprType_t type) const {
2545            if (iArg == 0)
2546                return type == INT_EXPR;
2547            else
2548                return type == INT_EXPR || type == REAL_EXPR;
2549        }
2550    
2551      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
2552          if (iArg == 1)          if (iArg == 1)
2553              return type == VM_NO_UNIT || type == VM_SECOND;              return type == VM_NO_UNIT || type == VM_SECOND;
# Line 2220  namespace LinuxSampler { Line 2555  namespace LinuxSampler {
2555              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
2556      }      }
2557    
2558      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
2559          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
2560      }      }
2561    
2562      VMFnResult* InstrumentScriptVMFunction_change_play_pos::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_play_pos::exec(VMFnArgs* args) {
2563          const ScriptID id = args->arg(0)->asInt()->evalInt(VM_MICRO);          const ScriptID id = args->arg(0)->asInt()->evalInt();
2564          if (!id) {          if (!id) {
2565              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");
2566              return successResult();              return successResult();
# Line 2235  namespace LinuxSampler { Line 2570  namespace LinuxSampler {
2570              return successResult();              return successResult();
2571          }          }
2572    
2573          const vmint pos = args->arg(1)->asInt()->evalInt();          StdUnit_t unit = args->arg(1)->asNumber()->unitType();
2574            const vmint pos =
2575                (unit) ?
2576                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
2577                    args->arg(1)->asNumber()->evalCastInt();
2578          if (pos < 0) {          if (pos < 0) {
2579              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");
2580              return successResult();              return successResult();

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

  ViewVC Help
Powered by ViewVC