--- linuxsampler/trunk/src/engines/common/InstrumentScriptVMFunctions.cpp 2017/06/05 18:40:18 3277 +++ linuxsampler/trunk/src/engines/common/InstrumentScriptVMFunctions.cpp 2017/11/28 15:54:49 3381 @@ -838,10 +838,9 @@ VMFnResult* InstrumentScriptVMFunction_change_attack::exec(VMFnArgs* args) { int attack = args->arg(1)->asInt()->evalInt(); - if (attack > VM_EG_PAR_MAX_VALUE) { - wrnMsg("change_attack(): argument 2 may not be larger than 1000000"); - attack = VM_EG_PAR_MAX_VALUE; - } else if (attack < 0) { + // note: intentionally not checking against a max. value here! + // (to allow i.e. passing 2000000 for doubling the attack time) + if (attack < 0) { wrnMsg("change_attack(): argument 2 may not be negative"); attack = 0; } @@ -925,10 +924,9 @@ VMFnResult* InstrumentScriptVMFunction_change_decay::exec(VMFnArgs* args) { int decay = args->arg(1)->asInt()->evalInt(); - if (decay > VM_EG_PAR_MAX_VALUE) { - wrnMsg("change_decay(): argument 2 may not be larger than 1000000"); - decay = VM_EG_PAR_MAX_VALUE; - } else if (decay < 0) { + // note: intentionally not checking against a max. value here! + // (to allow i.e. passing 2000000 for doubling the decay time) + if (decay < 0) { wrnMsg("change_decay(): argument 2 may not be negative"); decay = 0; } @@ -1012,10 +1010,9 @@ VMFnResult* InstrumentScriptVMFunction_change_release::exec(VMFnArgs* args) { int release = args->arg(1)->asInt()->evalInt(); - if (release > VM_EG_PAR_MAX_VALUE) { - wrnMsg("change_release(): argument 2 may not be larger than 1000000"); - release = VM_EG_PAR_MAX_VALUE; - } else if (release < 0) { + // note: intentionally not checking against a max. value here! + // (to allow i.e. passing 2000000 for doubling the release time) + if (release < 0) { wrnMsg("change_release(): argument 2 may not be negative"); release = 0; } @@ -1177,6 +1174,51 @@ return successResult(); } + // change_sustain() function + + VMFnResult* InstrumentScriptVMFunction_change_sustain::exec(VMFnArgs* args) { + return VMChangeSynthParamFunction::execTemplate< + &NoteBase::_Override::Sustain, + Event::synth_param_sustain, + false, NO_LIMIT, 0>( args, "change_sustain" ); + } + + // change_cutoff_attack() function + + VMFnResult* InstrumentScriptVMFunction_change_cutoff_attack::exec(VMFnArgs* args) { + return VMChangeSynthParamFunction::execTemplate< + &NoteBase::_Override::CutoffAttack, + Event::synth_param_cutoff_attack, + false, NO_LIMIT, 0>( args, "change_cutoff_attack" ); + } + + // change_cutoff_decay() function + + VMFnResult* InstrumentScriptVMFunction_change_cutoff_decay::exec(VMFnArgs* args) { + return VMChangeSynthParamFunction::execTemplate< + &NoteBase::_Override::CutoffDecay, + Event::synth_param_cutoff_decay, + false, NO_LIMIT, 0>( args, "change_cutoff_decay" ); + } + + // change_cutoff_sustain() function + + VMFnResult* InstrumentScriptVMFunction_change_cutoff_sustain::exec(VMFnArgs* args) { + return VMChangeSynthParamFunction::execTemplate< + &NoteBase::_Override::CutoffSustain, + Event::synth_param_cutoff_sustain, + false, NO_LIMIT, 0>( args, "change_cutoff_sustain" ); + } + + // change_cutoff_release() function + + VMFnResult* InstrumentScriptVMFunction_change_cutoff_release::exec(VMFnArgs* args) { + return VMChangeSynthParamFunction::execTemplate< + &NoteBase::_Override::CutoffRelease, + Event::synth_param_cutoff_release, + false, NO_LIMIT, 0>( args, "change_cutoff_release" ); + } + // change_amp_lfo_depth() function VMFnResult* InstrumentScriptVMFunction_change_amp_lfo_depth::exec(VMFnArgs* args) { @@ -1195,6 +1237,24 @@ true, 1000000, 0>( args, "change_amp_lfo_freq" ); } + // change_cutoff_lfo_depth() function + + VMFnResult* InstrumentScriptVMFunction_change_cutoff_lfo_depth::exec(VMFnArgs* args) { + return VMChangeSynthParamFunction::execTemplate< + &NoteBase::_Override::CutoffLFODepth, + Event::synth_param_cutoff_lfo_depth, + true, 1000000, 0>( args, "change_cutoff_lfo_depth" ); + } + + // change_cutoff_lfo_freq() function + + VMFnResult* InstrumentScriptVMFunction_change_cutoff_lfo_freq::exec(VMFnArgs* args) { + return VMChangeSynthParamFunction::execTemplate< + &NoteBase::_Override::CutoffLFOFreq, + Event::synth_param_cutoff_lfo_freq, + true, 1000000, 0>( args, "change_cutoff_lfo_freq" ); + } + // change_pitch_lfo_depth() function VMFnResult* InstrumentScriptVMFunction_change_pitch_lfo_depth::exec(VMFnArgs* args) { @@ -1231,6 +1291,15 @@ false, NO_LIMIT, 0>( args, "change_tune_time" ); } + // change_pan_time() function + + VMFnResult* InstrumentScriptVMFunction_change_pan_time::exec(VMFnArgs* args) { + return VMChangeSynthParamFunction::execTemplate< + &NoteBase::_Override::PanTime, + Event::synth_param_pan_time, + false, NO_LIMIT, 0>( args, "change_pan_time" ); + } + // template for change_*_curve() functions bool VMChangeFadeCurveFunction::acceptsArgType(int iArg, ExprType_t type) const { @@ -1332,6 +1401,14 @@ Event::synth_param_pitch_curve>( args, "change_tune_curve" ); } + // change_pan_curve() function + + VMFnResult* InstrumentScriptVMFunction_change_pan_curve::exec(VMFnArgs* args) { + return VMChangeFadeCurveFunction::execTemplate< + &NoteBase::_Override::PanCurve, + Event::synth_param_pan_curve>( args, "change_pan_curve" ); + } + // fade_in() function InstrumentScriptVMFunction_fade_in::InstrumentScriptVMFunction_fade_in(InstrumentScriptVM* parent) @@ -1865,6 +1942,33 @@ return successResult(pNote ? EVENT_STATUS_NOTE_QUEUE : EVENT_STATUS_INACTIVE); } + // callback_status() function + + InstrumentScriptVMFunction_callback_status::InstrumentScriptVMFunction_callback_status(InstrumentScriptVM* parent) + : m_vm(parent) + { + } + + VMFnResult* InstrumentScriptVMFunction_callback_status::exec(VMFnArgs* args) { + const script_callback_id_t id = args->arg(0)->asInt()->evalInt(); + if (!id) { + wrnMsg("callback_status(): callback ID for argument 1 may not be zero"); + return successResult(); + } + + AbstractEngineChannel* pEngineChannel = + static_cast(m_vm->m_event->cause.pEngineChannel); + + RTList::Iterator itCallback = pEngineChannel->ScriptCallbackByID(id); + if (!itCallback) + return successResult(CALLBACK_STATUS_TERMINATED); + + return successResult( + (m_vm->m_event->execCtx == itCallback->execCtx) ? + CALLBACK_STATUS_RUNNING : CALLBACK_STATUS_QUEUE + ); + } + // wait() function (overrides core wait() implementation) InstrumentScriptVMFunction_wait::InstrumentScriptVMFunction_wait(InstrumentScriptVM* parent) @@ -1914,7 +2018,7 @@ // abort() function InstrumentScriptVMFunction_abort::InstrumentScriptVMFunction_abort(InstrumentScriptVM* parent) - : m_vm(parent) + : m_vm(parent) { } @@ -1936,4 +2040,58 @@ return successResult(); } + // fork() function + + InstrumentScriptVMFunction_fork::InstrumentScriptVMFunction_fork(InstrumentScriptVM* parent) + : m_vm(parent) + { + } + + VMFnResult* InstrumentScriptVMFunction_fork::exec(VMFnArgs* args) { + // check if this is actually the parent going to fork, or rather one of + // the children which is already forked + if (m_vm->m_event->forkIndex != 0) { // this is the entry point for a child ... + int forkResult = m_vm->m_event->forkIndex; + // reset so that this child may i.e. also call fork() later on + m_vm->m_event->forkIndex = 0; + return successResult(forkResult); + } + + // if we are here, then this is the parent, so we must fork this parent + + const int n = + (args->argsCount() >= 1) ? args->arg(0)->asInt()->evalInt() : 1; + const bool bAutoAbort = + (args->argsCount() >= 2) ? args->arg(1)->asInt()->evalInt() : true; + + if (m_vm->m_event->countChildHandlers() + n > MAX_FORK_PER_SCRIPT_HANDLER) { + wrnMsg("fork(): requested amount would exceed allowed limit per event handler"); + return successResult(-1); + } + + AbstractEngineChannel* pEngineChannel = + static_cast(m_vm->m_event->cause.pEngineChannel); + + if (!pEngineChannel->hasFreeScriptCallbacks(n)) { + wrnMsg("fork(): global limit of event handlers exceeded"); + return successResult(-1); + } + + for (int iChild = 0; iChild < n; ++iChild) { + RTList::Iterator itChild = + pEngineChannel->forkScriptCallback(m_vm->m_event, bAutoAbort); + if (!itChild) { // should never happen, otherwise its a bug ... + errMsg("fork(): internal error while allocating child"); + return errorResult(-1); // terminate script + } + // since both parent, as well all child script execution instances + // all land in this exect() method, the following is (more or less) + // the only feature that lets us distinguish the parent and + // respective children from each other in this exect() method + itChild->forkIndex = iChild + 1; + } + + return successResult(0); + } + } // namespace LinuxSampler