/[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 3691 by schoenebeck, Fri Jan 3 12:35:20 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                    args->arg(1)->asNumber()->evalCastInt(VM_NO_PREFIX) :
978                    args->arg(1)->asNumber()->evalCastInt();
979            const bool isFinal =
980                (unit) ?
981                    true : // imply 'final' value if unit type is used
982                    args->arg(1)->asNumber()->isFinal();
983          if (!unit && cutoff > VM_FILTER_PAR_MAX_VALUE) {          if (!unit && cutoff > VM_FILTER_PAR_MAX_VALUE) {
984              wrnMsg("change_cutoff(): argument 2 may not be larger than " strfy(VM_FILTER_PAR_MAX_VALUE));              wrnMsg("change_cutoff(): argument 2 may not be larger than " strfy(VM_FILTER_PAR_MAX_VALUE));
985              cutoff = VM_FILTER_PAR_MAX_VALUE;              cutoff = VM_FILTER_PAR_MAX_VALUE;
# Line 741  namespace LinuxSampler { Line 993  namespace LinuxSampler {
993          const float fCutoff =          const float fCutoff =
994              (unit) ? cutoff : float(cutoff) / float(VM_FILTER_PAR_MAX_VALUE);              (unit) ? cutoff : float(cutoff) / float(VM_FILTER_PAR_MAX_VALUE);
995    
         if (unit && !isFinal) {  
             wrnMsg("change_cutoff(): you must pass argument 2 as 'final' value when using Hz as unit");  
             return successResult();  
         }  
   
996          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
997              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
998    
# Line 919  namespace LinuxSampler { Line 1166  namespace LinuxSampler {
1166          if (iArg == 0)          if (iArg == 0)
1167              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1168          else          else
1169              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
1170      }      }
1171    
1172      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 1176  namespace LinuxSampler {
1176              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1177      }      }
1178    
1179      bool InstrumentScriptVMFunction_change_attack::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_attack::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1180          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
1181      }      }
1182    
1183      bool InstrumentScriptVMFunction_change_attack::acceptsArgFinal(vmint iArg) const {      bool InstrumentScriptVMFunction_change_attack::acceptsArgFinal(vmint iArg) const {
1184          return iArg == 1;          return iArg == 1;
1185      }      }
1186    
1187        void InstrumentScriptVMFunction_change_attack::checkArgs(VMFnArgs* args,
1188                                                                 std::function<void(String)> err,
1189                                                                 std::function<void(String)> wrn)
1190        {
1191            // super class checks
1192            Super::checkArgs(args, err, wrn);
1193    
1194            // own checks ...
1195            if (args->argsCount() >= 2) {
1196                VMNumberExpr* argTime = args->arg(1)->asNumber();
1197                if (argTime->unitType() && !argTime->isFinal()) {
1198                    wrn("Argument 2 implies 'final' value when using seconds as unit for attack time.");
1199                }
1200            }
1201        }
1202    
1203      VMFnResult* InstrumentScriptVMFunction_change_attack::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_attack::exec(VMFnArgs* args) {
1204          vmint attack   = args->arg(1)->asInt()->evalInt(VM_MICRO);          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1205          bool isFinal   = args->arg(1)->asInt()->isFinal();          vmint attack =
1206          StdUnit_t unit = args->arg(1)->asInt()->unitType();              (unit) ?
1207                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
1208                    args->arg(1)->asNumber()->evalCastInt();
1209            const bool isFinal =
1210                (unit) ?
1211                    true : // imply 'final' value if unit type is used
1212                    args->arg(1)->asNumber()->isFinal();
1213          // note: intentionally not checking against a max. value here!          // note: intentionally not checking against a max. value here!
1214          // (to allow i.e. passing 2000000 for doubling the attack time)          // (to allow i.e. passing 2000000 for doubling the attack time)
1215          if (attack < 0) {          if (attack < 0) {
1216              wrnMsg("change_attack(): argument 2 may not be negative");              wrnMsg("change_attack(): argument 2 may not be negative");
1217              attack = 0;              attack = 0;
1218          }          }
1219          const float fAttack = float(attack) / float(VM_EG_PAR_MAX_VALUE);          const float fAttack =
1220                (unit) ? attack : float(attack) / float(VM_EG_PAR_MAX_VALUE);
         if (unit && !isFinal) {  
             wrnMsg("change_attack(): you must pass argument 2 as 'final' value when using seconds as unit");  
             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) ? decay : float(decay) / float(VM_EG_PAR_MAX_VALUE);
         if (unit && !isFinal) {  
             wrnMsg("change_decay(): you must pass argument 2 as 'final' value when using seconds as unit");  
             return successResult();  
         }  
1351    
1352          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
1353              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
# Line 1143  namespace LinuxSampler { Line 1426  namespace LinuxSampler {
1426          if (iArg == 0)          if (iArg == 0)
1427              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1428          else          else
1429              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
1430      }      }
1431    
1432      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 1436  namespace LinuxSampler {
1436              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1437      }      }
1438    
1439      bool InstrumentScriptVMFunction_change_release::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_release::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1440          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
1441      }      }
1442    
1443      bool InstrumentScriptVMFunction_change_release::acceptsArgFinal(vmint iArg) const {      bool InstrumentScriptVMFunction_change_release::acceptsArgFinal(vmint iArg) const {
1444          return iArg == 1;          return iArg == 1;
1445      }      }
1446    
1447        void InstrumentScriptVMFunction_change_release::checkArgs(VMFnArgs* args,
1448                                                                  std::function<void(String)> err,
1449                                                                  std::function<void(String)> wrn)
1450        {
1451            // super class checks
1452            Super::checkArgs(args, err, wrn);
1453    
1454            // own checks ...
1455            if (args->argsCount() >= 2) {
1456                VMNumberExpr* argTime = args->arg(1)->asNumber();
1457                if (argTime->unitType() && !argTime->isFinal()) {
1458                    wrn("Argument 2 implies 'final' value when using seconds as unit for release time.");
1459                }
1460            }
1461        }
1462    
1463      VMFnResult* InstrumentScriptVMFunction_change_release::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_release::exec(VMFnArgs* args) {
1464          vmint release  = args->arg(1)->asInt()->evalInt(VM_MICRO);          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1465          bool isFinal   = args->arg(1)->asInt()->isFinal();          vmint release =
1466          StdUnit_t unit = args->arg(1)->asInt()->unitType();              (unit) ?
1467                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
1468                    args->arg(1)->asNumber()->evalCastInt();
1469            const bool isFinal =
1470                (unit) ?
1471                    true : // imply 'final' value if unit type is used
1472                    args->arg(1)->asNumber()->isFinal();
1473          // note: intentionally not checking against a max. value here!          // note: intentionally not checking against a max. value here!
1474          // (to allow i.e. passing 2000000 for doubling the release time)          // (to allow i.e. passing 2000000 for doubling the release time)
1475          if (release < 0) {          if (release < 0) {
1476              wrnMsg("change_release(): argument 2 may not be negative");              wrnMsg("change_release(): argument 2 may not be negative");
1477              release = 0;              release = 0;
1478          }          }
1479          const float fRelease = float(release) / float(VM_EG_PAR_MAX_VALUE);          const float fRelease =
1480                (unit) ? release : float(release) / float(VM_EG_PAR_MAX_VALUE);
         if (unit && !isFinal) {  
             wrnMsg("change_release(): you must pass argument 2 as 'final' value when using seconds as unit");  
             return successResult();  
         }  
1481    
1482          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
1483              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
# Line 1250  namespace LinuxSampler { Line 1551  namespace LinuxSampler {
1551          if (iArg == 0)          if (iArg == 0)
1552              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
1553          else          else
1554              return type == INT_EXPR;              return type == INT_EXPR || (m_acceptReal && type == REAL_EXPR);
1555      }      }
1556    
1557      bool VMChangeSynthParamFunction::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool VMChangeSynthParamFunction::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
# Line 1260  namespace LinuxSampler { Line 1561  namespace LinuxSampler {
1561              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
1562      }      }
1563    
1564      bool VMChangeSynthParamFunction::acceptsArgUnitPrefix(vmint iArg) const {      bool VMChangeSynthParamFunction::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1565          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)
1566      }      }
1567    
1568      bool VMChangeSynthParamFunction::acceptsArgFinal(vmint iArg) const {      bool VMChangeSynthParamFunction::acceptsArgFinal(vmint iArg) const {
# Line 1289  namespace LinuxSampler { Line 1590  namespace LinuxSampler {
1590          param = value;          param = value;
1591      }      }
1592    
1593        void VMChangeSynthParamFunction::checkArgs(VMFnArgs* args,
1594                                                   std::function<void(String)> err,
1595                                                   std::function<void(String)> wrn)
1596        {
1597            // super class checks
1598            Super::checkArgs(args, err, wrn);
1599    
1600            // own checks ...
1601            if (m_unit && m_unit != VM_BEL && args->argsCount() >= 2) {
1602                VMNumberExpr* arg = args->arg(1)->asNumber();
1603                if (arg && arg->unitType() && !arg->isFinal()) {
1604                    wrn("Argument 2 implies 'final' value when unit type " +
1605                        unitTypeStr(arg->unitType()) + " is used.");
1606                }
1607            }
1608        }
1609    
1610      // Arbitrarily chosen constant value symbolizing "no limit".      // Arbitrarily chosen constant value symbolizing "no limit".
1611      #define NO_LIMIT 1315916909      #define NO_LIMIT 1315916909
1612    
# Line 1299  namespace LinuxSampler { Line 1617  namespace LinuxSampler {
1617               MetricPrefix_t T_unitPrefix0, MetricPrefix_t ... T_unitPrefixN>               MetricPrefix_t T_unitPrefix0, MetricPrefix_t ... T_unitPrefixN>
1618      VMFnResult* VMChangeSynthParamFunction::execTemplate(VMFnArgs* args, const char* functionName)      VMFnResult* VMChangeSynthParamFunction::execTemplate(VMFnArgs* args, const char* functionName)
1619      {      {
1620          const StdUnit_t unit = args->arg(1)->asInt()->unitType();          const StdUnit_t unit = args->arg(1)->asNumber()->unitType();
1621          const bool isFinal   = args->arg(1)->asInt()->isFinal();          const bool isFinal =
1622                (m_unit && m_unit != VM_BEL && unit) ?
1623                    true : // imply 'final' value if unit type is used (except of 'Bel' which may be relative)
1624                    args->arg(1)->asNumber()->isFinal();
1625          vmint value =          vmint value =
1626              (unit & m_unit) ?              (m_acceptUnitPrefix && ((m_unit && unit) || (!m_unit && args->arg(1)->asNumber()->hasUnitFactorNow())))
1627                  args->arg(1)->asInt()->evalInt(T_unitPrefix0, T_unitPrefixN ...) :                  ? args->arg(1)->asNumber()->evalCastInt(T_unitPrefix0, T_unitPrefixN ...)
1628                  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();  
         }  
1629    
1630          // check if passed value is in allowed range          // check if passed value is in allowed range
1631          if (unit && m_unit) {          if (unit && m_unit) {
# Line 1722  namespace LinuxSampler { Line 2038  namespace LinuxSampler {
2038          if (iArg == 0)          if (iArg == 0)
2039              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
2040          else          else
2041              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
2042      }      }
2043    
2044      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 2048  namespace LinuxSampler {
2048              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
2049      }      }
2050    
2051      bool InstrumentScriptVMFunction_fade_in::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_fade_in::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
2052          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
2053      }      }
2054    
2055      VMFnResult* InstrumentScriptVMFunction_fade_in::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_fade_in::exec(VMFnArgs* args) {
2056          vmint duration = args->arg(1)->asInt()->evalInt(VM_MICRO);          StdUnit_t unit = args->arg(1)->asNumber()->unitType();
2057            vmint duration =
2058                (unit) ?
2059                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
2060                    args->arg(1)->asNumber()->evalCastInt();
2061          if (duration < 0) {          if (duration < 0) {
2062              wrnMsg("fade_in(): argument 2 may not be negative");              wrnMsg("fade_in(): argument 2 may not be negative");
2063              duration = 0;              duration = 0;
# Line 1853  namespace LinuxSampler { Line 2173  namespace LinuxSampler {
2173          if (iArg == 0)          if (iArg == 0)
2174              return type == INT_EXPR || type == INT_ARR_EXPR;              return type == INT_EXPR || type == INT_ARR_EXPR;
2175          else          else
2176              return type == INT_EXPR;              return type == INT_EXPR || type == REAL_EXPR;
2177      }      }
2178    
2179      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 2183  namespace LinuxSampler {
2183              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
2184      }      }
2185    
2186      bool InstrumentScriptVMFunction_fade_out::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_fade_out::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
2187          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
2188      }      }
2189    
2190      VMFnResult* InstrumentScriptVMFunction_fade_out::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_fade_out::exec(VMFnArgs* args) {
2191          vmint duration = args->arg(1)->asInt()->evalInt(VM_MICRO);          StdUnit_t unit = args->arg(1)->asNumber()->unitType();
2192            vmint duration =
2193                (unit) ?
2194                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
2195                    args->arg(1)->asNumber()->evalCastInt();
2196          if (duration < 0) {          if (duration < 0) {
2197              wrnMsg("fade_out(): argument 2 may not be negative");              wrnMsg("fade_out(): argument 2 may not be negative");
2198              duration = 0;              duration = 0;
# Line 2209  namespace LinuxSampler { Line 2533  namespace LinuxSampler {
2533      // change_play_pos() function      // change_play_pos() function
2534    
2535      InstrumentScriptVMFunction_change_play_pos::InstrumentScriptVMFunction_change_play_pos(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_change_play_pos::InstrumentScriptVMFunction_change_play_pos(InstrumentScriptVM* parent)
2536      : m_vm(parent)          : m_vm(parent)
2537      {      {
2538      }      }
2539    
2540        bool InstrumentScriptVMFunction_change_play_pos::acceptsArgType(vmint iArg, ExprType_t type) const {
2541            if (iArg == 0)
2542                return type == INT_EXPR;
2543            else
2544                return type == INT_EXPR || type == REAL_EXPR;
2545        }
2546    
2547      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
2548          if (iArg == 1)          if (iArg == 1)
2549              return type == VM_NO_UNIT || type == VM_SECOND;              return type == VM_NO_UNIT || type == VM_SECOND;
# Line 2220  namespace LinuxSampler { Line 2551  namespace LinuxSampler {
2551              return type == VM_NO_UNIT;              return type == VM_NO_UNIT;
2552      }      }
2553    
2554      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitPrefix(vmint iArg) const {      bool InstrumentScriptVMFunction_change_play_pos::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
2555          return iArg == 1;          return iArg == 1 && type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
2556      }      }
2557    
2558      VMFnResult* InstrumentScriptVMFunction_change_play_pos::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_play_pos::exec(VMFnArgs* args) {
2559          const ScriptID id = args->arg(0)->asInt()->evalInt(VM_MICRO);          const ScriptID id = args->arg(0)->asInt()->evalInt();
2560          if (!id) {          if (!id) {
2561              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");
2562              return successResult();              return successResult();
# Line 2235  namespace LinuxSampler { Line 2566  namespace LinuxSampler {
2566              return successResult();              return successResult();
2567          }          }
2568    
2569          const vmint pos = args->arg(1)->asInt()->evalInt();          StdUnit_t unit = args->arg(1)->asNumber()->unitType();
2570            const vmint pos =
2571                (unit) ?
2572                    args->arg(1)->asNumber()->evalCastInt(VM_MICRO) :
2573                    args->arg(1)->asNumber()->evalCastInt();
2574          if (pos < 0) {          if (pos < 0) {
2575              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");
2576              return successResult();              return successResult();

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

  ViewVC Help
Powered by ViewVC