Compare commits

...

8 Commits

Author SHA1 Message Date
kevin
0e3ac61b68 notes.md : Updates 2025-03-22 17:48:04 -04:00
kevin
777c3bbd54 flow/proc_dict.cfg : Added "notify" attribute to variables that depend on being tracked via notify(). 2025-03-22 17:47:53 -04:00
kevin
edfd1bf6fd cwFlowTest.cpp : flow::test() now recognizes when exec(flowH) return kEofRC. 2025-03-22 17:46:49 -04:00
kevin
dad07db157 cwFlowPerf.cpp,cwFlowProc.cpp : Changed references from _value() to _notify(). (Hopefully no functional changes.) 2025-03-22 17:45:48 -04:00
kevin
30912ddb0c cwFlowProc.h : Replaced std_value() with std_notify(). 2025-03-22 17:44:16 -04:00
kevin
467aa9c495 cwFlowNet.cpp : Allocat modVarMapA[] to support variable notification on change.
Add calls to proc_notify() and var_schedule_notification().
2025-03-22 17:43:36 -04:00
kevin
1cb0db11b2 cwFlowType.h/cpp : Implement variable change notification.
- Added modVarMapA[] and related variables.
- Added var_schedule_notification() and proc_notify().
- Replaced class_members_str.value with .notify.
2025-03-22 17:38:30 -04:00
kevin
0a9daab833 cwFlow.h : Comments improved. No functional changes. 2025-03-22 16:15:39 -04:00
10 changed files with 465 additions and 344 deletions

View File

@ -48,9 +48,11 @@ namespace cw
const ui_net_t* ui_net( handle_t h );
// Run one cycle of the network.
// May return kEofRC if the cycle was programatically halted.
rc_t exec_cycle( handle_t h );
// Run a non-real-time program to completion.
// May return kEofRC if the cycle was programatically halted.
rc_t exec( handle_t h );
// Send any pending updates from the flow network to the UI.

View File

@ -1341,11 +1341,12 @@ namespace cw
proc->varMapIdN = max_vid + 1;
proc->varMapN = proc->varMapIdN * proc->varMapChN;
proc->varMapA = mem::allocZ<variable_t*>( proc->varMapN );
proc->modVarMapN = proc->varMapN;
proc->modVarMapA = mem::allocZ<variable_t*>( proc->modVarMapN );
proc->modVarMapN = 0;
proc->modVarMapA = nullptr;
// assign each variable to a location in the map
for(variable_t* var=proc->varL; var!=nullptr; var=var->var_link)
{
if( var->vid != kInvalidId )
{
unsigned idx = kInvalidIdx;
@ -1373,10 +1374,20 @@ namespace cw
goto errLabel;
}
}
}
if( cwIsFlag(var->varDesc->flags,kNotifyVarDescFl) )
proc->modVarMapN += 1;
}
}
// if there are variables marked for notification ...
if( proc->modVarMapN )
{
// ... then allocate space in modVarMapA[]
proc->modVarMapN *= proc->varMapChN; // (assume that all variables have multiple channels)
proc->modVarMapA = mem::allocZ<variable_t*>( proc->modVarMapN );
}
}
errLabel:
return rc;
@ -1449,7 +1460,7 @@ namespace cw
return rc;
}
rc_t _proc_call_value_func_on_all_variables( proc_t* proc )
rc_t _proc_schedule_variables_for_notification( proc_t* proc )
{
rc_t rc = kOkRC;
rc_t rc1 = kOkRC;
@ -1459,11 +1470,13 @@ namespace cw
{
variable_t* var = proc->varMapA[i];
if((rc = var_call_custom_value_func( var )) != kOkRC )
if((rc = var_schedule_notification( var )) != kOkRC )
rc1 = cwLogError(rc,"The proc inst instance '%s:%i' reported an invalid valid on variable:%s chIdx:%i.", var->proc->label, var->proc->label_sfx_id, var->label, var->chIdx );
}
rc = proc_notify(proc, kCallbackPnFl | kQuietPnFl );
return rc1;
return rcSelect(rc,rc1);
}
rc_t _proc_parse_ui_cfg(proc_t* proc, const proc_inst_parse_state_t& pstate)
@ -2099,8 +2112,8 @@ namespace cw
if((rc = _proc_set_log_flags(proc,pstate.log_labels)) != kOkRC )
goto errLabel;
// call the 'value()' function to inform the proc instance of the current value of all of it's variables.
if((rc = _proc_call_value_func_on_all_variables( proc )) != kOkRC )
// call the 'notify()' function to inform the proc instance of the current value of all of it's variables.
if((rc = _proc_schedule_variables_for_notification( proc )) != kOkRC )
goto errLabel;
// parse the proc UI cfg record
@ -2111,7 +2124,7 @@ namespace cw
// validate the proc's state.
if((rc = proc_validate(proc)) != kOkRC )
{
rc = cwLogError(rc,"proc inst instance validation failed.");
rc = cwLogError(rc,"proc inst '%s:%i' validation failed.", cwStringNullGuard(proc->label),proc->label_sfx_id );
goto errLabel;
}
@ -3636,6 +3649,10 @@ cw::rc_t cw::flow::exec_cycle( network_t& net )
for(unsigned i=0; i<net.procN; ++i)
{
// Call notify() on all variables marked for notification that have changed since the last exec_cycle()
proc_notify(net.procA[i], kCallbackPnFl | kQuietPnFl);
// execute the proc
if((rc = net.procA[i]->class_desc->members->exec(net.procA[i])) != kOkRC )
{
if( rc == kEofRC )
@ -3645,7 +3662,7 @@ cw::rc_t cw::flow::exec_cycle( network_t& net )
rc = cwLogError(rc,"Execution failed on the proc:%s:%i.",cwStringNullGuard(net.procA[i]->label),net.procA[i]->label_sfx_id);
break;
}
}
}
}
return halt_fl ? ((unsigned)kEofRC) : rc;

View File

@ -472,7 +472,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
@ -711,7 +711,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -979,7 +979,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -1066,7 +1066,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -1168,7 +1168,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -1243,7 +1243,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -2184,7 +2184,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
@ -2225,7 +2225,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -2346,7 +2346,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -2423,7 +2423,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};

View File

@ -80,7 +80,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -99,7 +99,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -152,7 +152,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -175,7 +175,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -412,7 +412,7 @@ namespace cw
return kOkRC;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
return kOkRC;
}
@ -470,7 +470,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -522,7 +522,7 @@ namespace cw
return kOkRC;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
return kOkRC;
}
@ -550,7 +550,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -705,7 +705,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{ return kOkRC; }
@ -787,7 +787,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -902,7 +902,7 @@ namespace cw
return kOkRC;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
return kOkRC;
}
@ -972,7 +972,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -1038,7 +1038,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -1069,7 +1069,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -1132,7 +1132,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -1162,7 +1162,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -1264,7 +1264,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
ftime_t seekSecs = 0;
@ -1329,7 +1329,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -1414,7 +1414,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -1453,7 +1453,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -1507,7 +1507,7 @@ namespace cw
return kOkRC;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
return kOkRC;
}
@ -1550,7 +1550,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -1723,7 +1723,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
@ -1731,6 +1731,7 @@ namespace cw
{
case kInPId:
break;
case kSelectPId:
break;
@ -1739,8 +1740,6 @@ namespace cw
if(var->chIdx != kAnyChIdx )
rc = var_get(var,p->igainV[ var->chIdx ]);
break;
default:
@ -1762,9 +1761,8 @@ namespace cw
rc_t _exec( proc_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
const abuf_t* ibuf = nullptr;
// get the input audio buffer
if((rc = var_get(proc,kInPId, kAnyChIdx, ibuf )) != kOkRC )
goto errLabel;
@ -1802,7 +1800,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -1887,7 +1885,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -1939,7 +1937,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -2118,7 +2116,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
@ -2193,7 +2191,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -2253,7 +2251,7 @@ namespace cw
rc_t destroy( proc_t* proc )
{ return kOkRC; }
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{ return kOkRC; }
rc_t _mix( proc_t* proc, unsigned inPId, unsigned gainPId, abuf_t* obuf )
@ -2316,7 +2314,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -2367,7 +2365,7 @@ namespace cw
return kOkRC;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
if( var->vid == kTriggerPId )
p->trig_fl = true;
@ -2380,7 +2378,10 @@ namespace cw
rc_t rc = kOkRC;
const abuf_t* ibuf = nullptr;
abuf_t* obuf = nullptr;
sample_t mark = p->trig_fl ? 1 : 0;
sample_t mark = 0;
mark = p->trig_fl ? 1 : 0;
p->trig_fl = false;
@ -2414,7 +2415,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -2467,7 +2468,7 @@ namespace cw
rc_t _destroy( proc_t* proc, inst_t* p )
{ return kOkRC; }
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{ return kOkRC; }
rc_t _exec( proc_t* proc, inst_t* p )
@ -2479,7 +2480,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -2586,7 +2587,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -2630,7 +2631,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -2755,7 +2756,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
inst_t* inst = (inst_t*)proc->userPtr;
@ -2840,7 +2841,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -2930,7 +2931,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -2983,7 +2984,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -3103,7 +3104,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
inst_t* inst = (inst_t*)proc->userPtr;
@ -3149,7 +3150,7 @@ namespace cw
fbuf_t* dstBuf = nullptr;
bool enable_fl = true;
unsigned chN = 0;
// get the src buffer
if((rc = var_get(proc,kInPId, kAnyChIdx, srcBuf )) != kOkRC )
goto errLabel;
@ -3184,7 +3185,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -3301,7 +3302,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
inst_t* inst = (inst_t*)proc->userPtr;
@ -3342,7 +3343,7 @@ namespace cw
abuf_t* dstBuf = nullptr;
bool enableFl = false;
unsigned chN = 0;
// get the src buffer
if((rc = var_get(proc,kInPId, kAnyChIdx, srcBuf )) != kOkRC )
goto errLabel;
@ -3386,7 +3387,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = report
};
@ -3489,7 +3490,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
inst_t* inst = (inst_t*)proc->userPtr;
@ -3524,7 +3525,7 @@ namespace cw
const abuf_t* srcBuf = nullptr;
abuf_t* dstBuf = nullptr;
unsigned chN = 0;
// get the src buffer
if((rc = var_get(proc,kInPId, kAnyChIdx, srcBuf )) != kOkRC )
goto errLabel;
@ -3564,7 +3565,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = report
};
@ -3688,7 +3689,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
@ -3752,7 +3753,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -3851,7 +3852,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
return kOkRC;
}
@ -3905,7 +3906,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = report
};
@ -4027,7 +4028,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
return kOkRC;
}
@ -4096,7 +4097,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = report
};
@ -4276,7 +4277,7 @@ namespace cw
return kOkRC;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
inst_t* p = (inst_t*)proc->userPtr;
@ -4356,7 +4357,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -4553,7 +4554,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
/*
@ -4762,7 +4763,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -4870,7 +4871,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -5003,7 +5004,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -5318,7 +5319,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -5447,7 +5448,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -5561,7 +5562,7 @@ namespace cw
return kOkRC;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
return kOkRC;
}
@ -5627,7 +5628,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -5739,7 +5740,7 @@ namespace cw
return kOkRC;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
@ -5836,7 +5837,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -5953,7 +5954,7 @@ namespace cw
rc_t _destroy( proc_t* proc, inst_t* p )
{ return kOkRC; }
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
if( var->vid == kTriggerPId )
{
@ -5997,7 +5998,8 @@ namespace cw
p->store_vid = kInvalidIdx;
}
errLabel:
return rc;
}
@ -6007,7 +6009,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -6049,7 +6051,7 @@ namespace cw
rc_t _destroy( proc_t* proc, inst_t* p )
{ return kOkRC; }
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
// skip the 'stored' value sent through prior to runtime.
if( var->vid == kStorePId /*&& proc->ctx->isInRuntimeFl*/)
@ -6085,7 +6087,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -6183,7 +6185,7 @@ namespace cw
rc_t _destroy( proc_t* proc, inst_t* p )
{ return kOkRC; }
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
switch( var->vid )
{
@ -6212,7 +6214,8 @@ namespace cw
rc = var_set(proc,kOutPId,kAnyChIdx,&p->value);
p->store_fl = false;
}
errLabel:
return rc;
}
@ -6222,7 +6225,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -6298,7 +6301,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
switch( var->vid )
@ -6367,14 +6370,15 @@ namespace cw
var_set(proc,kOutPId,kAnyChIdx,!val);
}
errLabel:
return rc;
}
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -6521,7 +6525,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
inst_t* p = (inst_t*)proc->userPtr;
@ -6692,7 +6696,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -7048,7 +7052,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
if( var->vid == kInPId )
@ -7071,13 +7075,15 @@ namespace cw
rc = _set_output(proc, p );
p->deltaFl = false;
}
errLabel:
return rc;
}
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -7139,7 +7145,7 @@ namespace cw
{
rc_t rc = kOkRC;
inst_t* p = (inst_t*)(proc->userPtr);
if( !p->delta_fl )
return rc;
@ -7259,7 +7265,7 @@ namespace cw
return rc;
}
rc_t value( proc_t* proc, variable_t* var )
rc_t notify( proc_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
inst_t* p = (inst_t*)(proc->userPtr);
@ -7281,7 +7287,7 @@ namespace cw
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.notify = notify,
.exec = exec,
.report = nullptr
};
@ -7376,7 +7382,7 @@ namespace cw
rc_t _destroy( proc_t* proc, inst_t* p )
{ return kOkRC; }
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
if( var->vid == kInPId )
@ -7388,7 +7394,7 @@ namespace cw
rc_t _exec( proc_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
if( p->delta_fl )
rc = _set_preset(proc,p);
@ -7402,7 +7408,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -7539,7 +7545,7 @@ namespace cw
return kOkRC;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
switch( var->vid )
{
@ -7586,7 +7592,9 @@ namespace cw
}
rc_t _exec( proc_t* proc, inst_t* p )
{ return kOkRC; }
{
return kOkRC;
}
rc_t _report( proc_t* proc, inst_t* p )
{ return kOkRC; }
@ -7594,7 +7602,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -7628,7 +7636,7 @@ namespace cw
return kOkRC;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
@ -7651,7 +7659,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -7769,7 +7777,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
@ -7814,7 +7822,7 @@ namespace cw
}
p->msg_idx = 0;
return rc;
}
@ -7824,7 +7832,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -7888,7 +7896,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -7921,7 +7929,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -8071,7 +8079,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -8122,7 +8130,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -8197,7 +8205,7 @@ namespace cw
return kOkRC;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
@ -8273,7 +8281,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
@ -8414,7 +8422,7 @@ namespace cw
return rc;
}
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
rc_t _notify( proc_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
if( proc->ctx->isInRuntimeFl && var->vid == kTriggerPId )
@ -8544,7 +8552,7 @@ namespace cw
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.notify = std_notify<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};

View File

@ -25,8 +25,8 @@ namespace cw
}
template< typename inst_t >
rc_t std_value( proc_t* proc, variable_t* var )
{ return _value(proc,(inst_t*)proc->userPtr, var); }
rc_t std_notify( proc_t* proc, variable_t* var )
{ return _notify(proc,(inst_t*)proc->userPtr, var); }
template< typename inst_t >
rc_t std_exec( proc_t* proc )
@ -35,7 +35,6 @@ namespace cw
template< typename inst_t >
rc_t std_report( proc_t* proc )
{ return _report(proc,(inst_t*)proc->userPtr); }
namespace user_def_proc { extern class_members_t members; }
namespace poly { extern class_members_t members; }

View File

@ -68,7 +68,7 @@ cw::rc_t cw::flow::test( const test::test_args_t& args )
}
// run the network
if((rc = exec( flowH )) != kOkRC )
if((rc = exec( flowH )) != kOkRC && rc != kEofRC )
rc = cwLogError(rc,"Execution failed.");
errLabel:

View File

@ -36,6 +36,7 @@ namespace cw
{ kUiCreateVarDescFl, "no_ui" }, // even if the proc ui is enabled, don't show this var
{ kUiDisableVarDescFl,"ui_disable" },
{ kUiHideVarDescFl, "ui_hide" },
{ kNotifyVarDescFl, "notify" },
{ kInvalidVarDescFl, "<invalid>" }
};
@ -149,7 +150,7 @@ namespace cw
con_var->label,con_var->label_sfx_id );
// Call the value() function on the connected variable
if((rc = var_call_custom_value_func(con_var)) != kOkRC )
if((rc = var_schedule_notification(con_var)) != kOkRC )
break;
}
@ -162,62 +163,37 @@ namespace cw
// This function runs in a multi-thread context.
rc_t _mod_var_map_update( variable_t* var )
{
// if the var is in already modVarMapA[] then there is nothing to do
// (use acquire to prevent rd/wr from moving before this op)
if( var->modN.load(std::memory_order_acquire) > 0 )
return kOkRC;
rc_t rc = kOkRC;
if( cwIsFlag(var->varDesc->flags,kNotifyVarDescFl ) )
{
// if the var is already modVarMapA[] then there is nothing to do
// (use acquire to prevent rd/wr from moving before this op)
if( var->modN.load(std::memory_order_acquire) > 0 )
return kOkRC;
// reserve a slot in proc->modVarMapA[]
// (use acquire to prevent rd/wr from moving before this op)
if( var->proc->modVarMapFullCnt.fetch_add(1,std::memory_order_acquire) >= var->proc->modVarMapN )
return kBufTooSmallRC;
// Get the next empty slot in proc->modVarMapA[]
// (use acquire to prevent rd/wr from moving before this op)
unsigned idx = var->proc->modVarMapHeadIdx.fetch_add(1,std::memory_order_acquire) % var->proc->modVarMapN;
var->proc->modVarMapA[ idx ] = var;
// mark the var as in the list
var->modN.fetch_add(1,std::memory_order_release);
return kOkRC;
}
// Call proc->proc_desc->value() on every var in the proc->modVarMapA[].
// This function is called inside proc->proc_desc->exec().
rc_t _mod_var_map_dispatch( proc_t* proc, bool callback_fl )
{
// get the count of variables to be updated
unsigned n = proc->modVarMapFullCnt.load( std::memory_order_acquire );
if( n )
{
if( callback_fl )
// reserve a slot in proc->modVarMapA[]
// (use acquire to prevent rd/wr from moving before this op)
if( var->proc->modVarMapFullCnt.fetch_add(1,std::memory_order_acquire) >= var->proc->modVarMapN )
{
for(unsigned i=0; i<n; ++i)
{
// get a pointer to the var that has been marked as modified
variable_t* var = proc->modVarMapA[ proc->modVarMapTailIdx ];
// callback to inform the proc that the var has changed
proc->class_desc->members->value( var->proc, var );
// mark this var as having been removed from the modVarMapA[]
var->modN.store(0,std::memory_order_relaxed );
// increment modVarMapA[]'s tail index
proc->modVarMapTailIdx = (proc->modVarMapTailIdx + 1) % proc->modVarMapN;
}
rc = cwLogError(kBufTooSmallRC,"The mod var map overflowed on '%s:%i-%s:%i'",cwStringNullGuard(var->proc->label),var->proc->label_sfx_id,cwStringNullGuard(var->label),var->label_sfx_id);
goto errLabel;
}
// decrement the count of elemnts in the modVarMapA[]
proc->modVarMapFullCnt.fetch_sub(n, std::memory_order_release );
}
// Get the next empty slot in proc->modVarMapA[]
// (use acquire to prevent rd/wr from moving before this op)
unsigned idx = var->proc->modVarMapHeadIdx.fetch_add(1,std::memory_order_acquire) % var->proc->modVarMapN;
return kOkRC;
var->proc->modVarMapA[ idx ] = var;
// mark the var as in the list
var->modN.fetch_add(1,std::memory_order_release);
}
errLabel:
return rc;
}
// 'argTypeFlag' is the type (tflag) of 'val'.
template< typename T >
@ -288,7 +264,7 @@ namespace cw
// call because calls' to 'proc.value()' will see the proc in a incomplete state)
// Note 2: If this call returns an error then the value assignment is cancelled
// and the value does not change.
rc = var_call_custom_value_func( var );
rc = var_schedule_notification( var );
}
//printf("%p set: %s:%s 0x%x\n",var->value, var->proc->label,var->label,var->value->tflag);
@ -1179,6 +1155,52 @@ char* cw::flow::proc_expand_filename( const proc_t* proc, const char* fname )
return fn1;
}
// Call proc->proc_desc->value() on every var in the proc->modVarMapA[].
// This function is called inside proc->proc_desc->exec() and is therefore guaranteed to be executed without
// contention from other threads.
cw::rc_t cw::flow::proc_notify( proc_t* proc, unsigned flags )
{
rc_t rc = kOkRC;
unsigned modN = 0;
if( proc->modVarMapN == 0 )
{
if( cwIsNotFlag(flags,kQuietPnFl) )
rc =cwLogError(kInvalidStateRC,"Calling proc_notify() on the processor '%s:%i' is invalid because it does not have any variables marked for notification.",cwStringNullGuard(proc->label),proc->label_sfx_id);
goto errLabel;
}
// get the count of variables to be updated
modN = proc->modVarMapFullCnt.load( std::memory_order_acquire );
if( modN )
{
if( cwIsFlag(flags,kCallbackPnFl) )
{
for(unsigned i=0; i<modN; ++i)
{
// get a pointer to the var that has been marked as modified
variable_t* var = proc->modVarMapA[ proc->modVarMapTailIdx ];
// callback to inform the proc that the var has changed
proc->class_desc->members->notify( var->proc, var );
// mark this var as having been removed from the modVarMapA[]
var->modN.store(0,std::memory_order_release );
// increment modVarMapA[]'s tail index
proc->modVarMapTailIdx = (proc->modVarMapTailIdx + 1) % proc->modVarMapN;
}
}
// decrement the count of elemnts in the modVarMapA[]
proc->modVarMapFullCnt.fetch_sub(modN, std::memory_order_release );
}
errLabel:
return rc;
}
cw::rc_t cw::flow::var_create( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned id, unsigned chIdx, const object_t* value_cfg, unsigned altTypeFl, variable_t*& varRef )
{
rc_t rc = kOkRC;
@ -1342,16 +1364,14 @@ errLabel:
return chN;
}
cw::rc_t cw::flow::var_call_custom_value_func( variable_t* var )
cw::rc_t cw::flow::var_schedule_notification( variable_t* var )
{
rc_t rc;
if((rc = var->proc->class_desc->members->value( var->proc, var )) != kOkRC )
if((rc = _mod_var_map_update( var )) != kOkRC )
goto errLabel;
if( var->flags & kLogVarFl )
{
if( var->proc->ctx->printLogHdrFl )
{
cwLogPrint("%s","exe cycle: process: id: variable: id vid ch : : : type:value : destination\n");
@ -1383,6 +1403,7 @@ errLabel:
}
cw::rc_t cw::flow::var_flags( proc_t* proc, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned& flags_ref )
{
rc_t rc = kOkRC;

View File

@ -9,7 +9,7 @@ namespace cw
struct variable_str;
typedef rc_t (*member_func_t)( struct proc_str* ctx );
typedef rc_t (*member_value_func_t)( struct proc_str* ctx, struct variable_str* var );
typedef rc_t (*member_notify_func_t)( struct proc_str* ctx, struct variable_str* var );
// var_desc_t attribute flags
enum
@ -23,16 +23,17 @@ namespace cw
kUdpOutVarDescFl = 0x020,
kUiCreateVarDescFl = 0x040,
kUiDisableVarDescFl = 0x080,
kUiHideVarDescFl = 0x100
kUiHideVarDescFl = 0x100,
kNotifyVarDescFl = 0x200,
};
typedef struct class_members_str
{
member_func_t create;
member_func_t destroy;
member_value_func_t value;
member_func_t exec;
member_func_t report;
member_func_t create;
member_func_t destroy;
member_notify_func_t notify;
member_func_t exec;
member_func_t report;
} class_members_t;
typedef struct var_desc_str
@ -486,6 +487,15 @@ namespace cw
// The returned string must be release with a call to mem::free().
char* proc_expand_filename( const proc_t* proc, const char* fname );
// Call this function from inside the proc instance exec() routine, with flags=kCallbackPnFl,
// to get callbacks on variables marked for notification on change. Note that variables must have
// their var. description 'kNotifyVarDescFl' (var. desc flag: 'notify') set in order
// to generate callbacks.
// Set kQuietPnFl to avoid warning messages when this function is called on proc's
// that do not have any variables marked for notification.
enum { kCallbackPnFl=0x01, kQuietPnFl=0x02 };
rc_t proc_notify( proc_t* proc, unsigned flags = kCallbackPnFl );
//------------------------------------------------------------------------------------------------------------------------
//
@ -509,8 +519,8 @@ namespace cw
// Otherwise returns count of channels no including kAnyChIdx. (e.g. mono=1, stereo=2, quad=4 ...)
unsigned var_channel_count( proc_t* proc, const char* var_label, unsigned sfx_id );
// Wrapper around call to var->proc->members->value()
rc_t var_call_custom_value_func( variable_t* var );
// Calls the _mod_var_map_update() on connected vars and implements the var 'log' functionality
rc_t var_schedule_notification( variable_t* var );
// Sets and get the var->flags field
unsigned var_flags( proc_t* proc, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned& flags_ref );

View File

@ -1,4 +1,15 @@
{
poly: {
vars: {
count: { type:uint, flags:["init"], value:1, doc:"Count of network duplicates." },
parallel_fl: { type:bool, flags:["init"], value:false, doc:"True to run voices concurrently." }
preset_sfx_id:{ type:uint, value:-1, doc:"The voice index to assign the prefix to or -1 if there is no preset to assign." },
preset_label: { type:string, value:"", doc:"The network preset to activate on voice channel 'preset_idx'." },
}
}
balance: {
doc: [ "Stereo balance control." ]
vars: {
@ -57,7 +68,7 @@
fname: { type:string, doc:"Audio file name." },
out:{ type:audio, doc:"Audio file output" },
on_off:{ type:bool, value:false, doc:"1=on 0=off" },,
seekSecs:{ type:ftime, value:0.0, doc:"Seek to the specified seconds offset." }
seekSecs:{ type:ftime, flags:["notify"], value:0.0, doc:"Seek to the specified seconds offset." }
eofFl:{ type:bool, value: true, doc:"Set the system 'halt' flag when the audio is completely read."},
}
}
@ -85,11 +96,11 @@
audio_split: {
vars: {
in: { type:audio, flags:["src"], doc:"Audio input." },
select: { type:cfg, flags:["init"], doc:"A list of integers where each value selects an output channel for the associated input channel." }
igain: { type:coeff, value:1.0, doc:"Audio gain for each input channel." }
ogain: { type:coeff, flags["mult"], value:1.0, doc:"Audio gain for each output channel." }
out: { type:audio, flags["mult"], doc:"Audio output." },
in: { type:audio, flags:["src"], doc:"Audio input." },
select: { type:cfg, flags:["init"], doc:"A list of integers where each value selects an output channel for the associated input channel." }
igain: { type:coeff, flags:["notify"], value:1.0, doc:"Audio gain for each input channel." }
ogain: { type:coeff, flags:["mult","notify"], value:1.0, doc:"Audio gain for each output channel." }
out: { type:audio, flags:["mult"], doc:"Audio output." },
}
presets:
@ -120,27 +131,27 @@
audio_mix: {
vars: {
in: { type:audio, flags:["src","mult"], doc:"Audio input." },
igain: { type:coeff, flags:["mult"], value:0.5, doc:"Audio gain for input 0." },
ogain: { type:coeff, value:1.0, doc:"Output gain." },
out: { type:audio, doc:"Audio output. Channel count is max of the input signal channels." },
in: { type:audio, flags:["src","mult"], doc:"Audio input." },
igain: { type:coeff, flags:["notify","mult"], value:0.5, doc:"Audio gain for input 0." },
ogain: { type:coeff, flags:["notify"], value:1.0, doc:"Output gain." },
out: { type:audio, doc:"Audio output. Channel count is max of the input signal channels." },
}
}
audio_marker: {
vars: {
in: { type:audio, flags:["src"], doc:"Audio input."},
trigger: { type:all, value:0, doc:"Marker trigger."},
out: { type:audio, doc:"Audio output."},
in: { type:audio, flags:["src"], doc:"Audio input."},
trigger: { type:all, flags:["notify"], value:0, doc:"Marker trigger."},
out: { type:audio, doc:"Audio output."},
}
}
audio_delay: {
vars: {
in: { type:audio, flags:["src"], doc:"Audio input." },
maxDelayMs: { type:ftime, value:1000.0 doc:"Maximum possible delay in milliseconds." },
delayMs: { type:ftime, doc:"Delay in milliseconds." },
out: { type:audio, doc:"Audio output." },
maxDelayMs: { type:ftime, value:1000.0 doc:"Maximum possible delay in milliseconds." },
delayMs: { type:ftime, flags:["notify"], doc:"Delay in milliseconds." },
out: { type:audio, doc:"Audio output." },
}
}
@ -177,13 +188,13 @@
pv_analysis: {
vars: {
in: { type:audio, flags:["src"], doc:"Audio input." },
enable: { type:bool, value: true, doc:"Enable/disable the processor."}
maxWndSmpN: { type:uint, value: 1024, doc:"Maximum window sample count." },
wndSmpN: { type:uint, value: 512, doc:"Window sample count." },
hopSmpN: { type:uint, value: 128, doc:"Hop sample count." },
hzFl: { type:bool, value: false, doc:"Calculate frequency via the method of phase change of each bin." },
out: { type:spectrum, doc:"Spectrum output." }
in: { type:audio, flags:["src"], doc:"Audio input." },
enable: { type:bool, value: true, doc:"Enable/disable the processor."}
maxWndSmpN: { type:uint, value: 1024, doc:"Maximum window sample count." },
wndSmpN: { type:uint, flags:["notify"],value: 512, doc:"Window sample count." },
hopSmpN: { type:uint, value: 128, doc:"Hop sample count." },
hzFl: { type:bool, value:false, doc:"Calculate frequency via the method of phase change of each bin." },
out: { type:spectrum, doc:"Spectrum output." }
}
presets: {
@ -270,15 +281,15 @@
spec_dist: {
vars: {
in: { type:spectrum, flags:["src"], doc:"Spectrum input." },
enable: { type:bool, value: true, doc:"Enable/disable this processor."},
bypass: { type:bool, value: false, doc:"Copy input to output without transform."},
ceiling: { type:coeff, value: 30.0, doc:"Ceiling parameter."},
expo: { type:coeff, value: 2.0, doc:"Exponent parameter."},
thresh: { type:coeff, value: 54.0, doc:"Threshold parameter."},
upr: { type:coeff, value: -0.7, doc:"Upper slope parameter."},
lwr: { type:coeff, value: 2.0, doc:"Lower slope parameter."},
mix: { type:coeff, value: 0.0, doc:"Basic/Bump Mix parameter."},
in: { type:spectrum, flags:["src"], doc:"Spectrum input." },
enable: { type:bool, flags:["notify"], value: true, doc:"Enable/disable this processor."},
bypass: { type:bool, flags:["notify"], value: false, doc:"Copy input to output without transform."},
ceiling: { type:coeff, flags:["notify"], value: 30.0, doc:"Ceiling parameter."},
expo: { type:coeff, flags:["notify"], value: 2.0, doc:"Exponent parameter."},
thresh: { type:coeff, flags:["notify"], value: 54.0, doc:"Threshold parameter."},
upr: { type:coeff, flags:["notify"], value: -0.7, doc:"Upper slope parameter."},
lwr: { type:coeff, flags:["notify"], value: 2.0, doc:"Lower slope parameter."},
mix: { type:coeff, flags:["notify"], value: 0.0, doc:"Basic/Bump Mix parameter."},
out: { type:spectrum, doc:"Spectrum output." },
@ -412,18 +423,18 @@
compressor: {
vars: {
in: { type:audio, flags:["src"], doc:"Audio input." },
enable: { type:bool, value: true, doc:"Same as bypass with opposite polarity." },
bypass: { type:bool, value: false, doc:"Bypass the compressor."},
igain: { type:coeff, value: 1.0, doc:"Input gain."},
thresh: { type:coeff, value: 90.0, doc:"Attack threshold in dB."},
ratio: { type:coeff, value: 2.0, doc:"Compression ratio."},
atk_ms: { type:coeff, value: 20.0, doc:"Attack time in milliseconds."},
rls_ms: { type:coeff, value: 20.0, doc:"Release time in milliseconds."},
wnd_ms: { type:coeff, value: 200.0, doc:"RMS calc. window length in milliseconds."},
maxWnd_ms: { type:coeff, value: 1000.0, doc:"Maximim (allocated) window length in milliseconds."},
ogain: { type:coeff, value: 1.0, doc:"Output gain."},
out: { type:audio, doc:"Audio output." },
in: { type:audio, flags:["src"], doc:"Audio input." },
enable: { type:bool, flags:["notify"], value: true, doc:"Same as bypass with opposite polarity." },
bypass: { type:bool, flags:["notify"], value: false, doc:"Bypass the compressor."},
igain: { type:coeff, flags:["notify"], value: 1.0, doc:"Input gain."},
thresh: { type:coeff, flags:["notify"], value: 90.0, doc:"Attack threshold in dB."},
ratio: { type:coeff, flags:["notify"], value: 2.0, doc:"Compression ratio."},
atk_ms: { type:coeff, flags:["notify"], value: 20.0, doc:"Attack time in milliseconds."},
rls_ms: { type:coeff, flags:["notify"], value: 20.0, doc:"Release time in milliseconds."},
wnd_ms: { type:coeff, flags:["notify"], value: 200.0, doc:"RMS calc. window length in milliseconds."},
maxWnd_ms: { type:coeff, flags:["notify"], value: 1000.0, doc:"Maximim (allocated) window length in milliseconds."},
ogain: { type:coeff, flags:["notify"], value: 1.0, doc:"Output gain."},
out: { type:audio, doc:"Audio output." },
}
presets: {
@ -529,12 +540,12 @@
limiter: {
vars: {
in: { type:audio, flags:["src"], doc:"Audio input." },
bypass: { type:bool, value: false, doc:"Bypass the limiter."},
igain: { type:coeff, value: 1.0, doc:"Input gain."},
thresh: { type:coeff, value: 0.0, doc:"Linear (0.0-1.0) threshold."},
ogain: { type:coeff, value: 1.0, doc:"Output gain."},
out: { type:audio, doc:"Audio output." },
in: { type:audio, flags:["src"], doc:"Audio input." },
bypass: { type:bool, flags:["notify"], value: false, doc:"Bypass the limiter."},
igain: { type:coeff, flags:["notify"], value: 1.0, doc:"Input gain."},
thresh: { type:coeff, flags:["notify"], value: 0.0, doc:"Linear (0.0-1.0) threshold."},
ogain: { type:coeff, flags:["notify"], value: 1.0, doc:"Output gain."},
out: { type:audio, doc:"Audio output." },
}
presets: {
@ -579,21 +590,12 @@
}
}
poly: {
vars: {
count: { type:uint, flags:["init"], value:1, doc:"Count of network duplicates." },
parallel_fl: { type:bool, flags:["init"], value:false, doc:"True to run voices concurrently." }
preset_sfx_id:{ type:uint, value:-1, doc:"The voice index to assign the prefix to or -1 if there is no preset to assign." },
preset_label: { type:string, value:"", doc:"The network preset to activate on voice channel 'preset_idx'." },
}
}
sample_hold: {
vars: {
in: { type:audio, flags:["src"], doc:"Audio input source." },
period_ms: { type:ftime, value:50, doc:"Sample period in milliseconds." },
out: { type:sample, value:0.0, doc:"First value in the sample period." },
mean: { type:sample, value:0.0, doc:"Mean value of samples in period." },
period_ms: { type:ftime, flags:["notify"], value:50, doc:"Sample period in milliseconds." },
out: { type:sample, value:0.0, doc:"First value in the sample period." },
mean: { type:sample, value:0.0, doc:"Mean value of samples in period." },
}
}
@ -612,16 +614,16 @@
"However, an explicit type may be set using the 'out_type' argument." ]
vars: {
in: { type:numeric, value:0.0, flags["mult"], doc:"Set the current value."},
trigger: { type:all, value:0.0, doc:"Send the currrent value on the next exec cycle."},
out_type: { type:string, value:"", flags:["init"], doc:"The type of the output value."},
out: { type:runtime, flags:["no_src"], doc:"Output numeric value."},
in: { type:numeric, value:0.0, flags:["notify","mult"], doc:"Set the current value."},
trigger: { type:all, value:0.0, flags:["notify"], doc:"Send the currrent value on the next exec cycle."},
out_type: { type:string, value:"", flags:["init"], doc:"The type of the output value."},
out: { type:runtime, flags:["no_src"], doc:"Output numeric value."},
}
}
halt:{
vars: {
in: { type:all, value:0.0, flags:["src"], doc:"Any value halts the network."},
in: { type:all, value:0.0, flags:["src","notify"], doc:"Any value halts the network."},
}
}
@ -632,36 +634,36 @@
// The data type of 'store' must be convertable to the data type of 'out'.
reg: {
vars: {
in: { type:all, flags:["src"], doc:"Input value."},
store: { type:all, doc:"Alternate input value."},
out: { type:runtime, flags:["no_src"], doc:"Output value."},
in: { type:all, flags:["notify","src"], doc:"Input value."},
store: { type:all, flags:["notify"], doc:"Alternate input value."},
out: { type:runtime, flags:["notify","no_src"], doc:"Output value."},
}
}
timer: {
vars: {
srate: { type:srate, value:0, flags["src"], doc:"Sample rate to use as the time base. 0=Use default system sample rate." },
delay_ms: { type:ftime, value:0, doc:"Delay before the first output." },
period_ms: { type:ftime, value:100, doc:"Timer period in milliseconds." },
out: { type:bool, value:false, doc:"Output pulse." },
srate: { type:srate, value:0, flags:["src"], doc:"Sample rate to use as the time base. 0=Use default system sample rate." },
delay_ms: { type:ftime, value:0, flags:["notify"], doc:"Delay before the first output." },
period_ms: { type:ftime, value:100, flags:["notify"], doc:"Timer period in milliseconds." },
out: { type:bool, value:false, doc:"Output pulse." },
}
}
counter: {
vars: {
trigger: { type:all, flags["src"], doc:"Counter increments with each toggle of trigger." },
reset: { type:all, value:0.0, doc:"Reset the counter to the initial value." },
init: { type:numeric, value:0.0, doc:"Counter initial value." },
min: { type:numeric, value:0.0, doc:"Minimum output value." },
max: { type:numeric, value:10.0, doc:"Maximum output value." },
inc: { type:numeric, value:1.0, doc:"Incrment value." },
repeat_fl: { type:bool, value:true, doc:"Repeat on reaching the limits." },
mode: { type:string, value:"modulo", doc:"limit mode: 'modulo'=wrap, 'reverse'=count in opposite direction, 'clip'=repeat limit value."},
out_type: { type:string, value:double, flags:["init"], doc:"The type of the output value." },
upr_lim: { type:bool, value:false, flags:["no_src"], doc:"Outputs 'true' if the upper limit is reached." },
lwr_lim: { type:bool, value:false, flags:["no_src"], doc:"Outputs 'true' if the lower limit is reached." },
limit: { type:bool, value:false, flags:["no_src"], doc:"Outputs 'true' if the upper or lower limit is reached." },
out: { type:runtime, value:0.0, doc:"Counter output value."},
trigger: { type:all, flags:["notify","src"], doc:"Counter increments with each toggle of trigger." },
reset: { type:all, flags:["notify"], value:0.0, doc:"Reset the counter to the initial value." },
init: { type:numeric, value:0.0, doc:"Counter initial value." },
min: { type:numeric, value:0.0, doc:"Minimum output value." },
max: { type:numeric, value:10.0, doc:"Maximum output value." },
inc: { type:numeric, value:1.0, doc:"Incrment value." },
repeat_fl: { type:bool, value:true, doc:"Repeat on reaching the limits." },
mode: { type:string, flags:["notify"], value:"modulo", doc:"limit mode: 'modulo'=wrap, 'reverse'=count in opposite direction, 'clip'=repeat limit value."},
out_type: { type:string, flags:["init"], value:double, doc:"The type of the output value." },
upr_lim: { type:bool, flags:["no_src"], value:false, doc:"Outputs 'true' if the upper limit is reached." },
lwr_lim: { type:bool, flags:["no_src"], value:false, doc:"Outputs 'true' if the lower limit is reached." },
limit: { type:bool, flags:["no_src"], value:false, doc:"Outputs 'true' if the upper or lower limit is reached." },
out: { type:runtime, value:0.0, doc:"Counter output value."},
}
}
@ -670,16 +672,16 @@
list: {
vars: {
cfg_fname: { type:string, flags:["init"], value:"", doc:"List cfg file." },
in: { type:uint, flags:["src"], doc:"List selection index." },
list: { type:cfg, flags:["init"], value:{} doc:"List as a 'cfg' object." },
in: { type:uint, flags:["notify","src"], doc:"List selection index." },
list: { type:cfg, flags:["init"], value:{} doc:"List as a 'cfg' object." },
out: { type:runtime, doc:"List output value." },
value: { type:runtime, flags["mult"], doc:"List 'mult' output per list value." },
value: { type:runtime, flags:["mult"], doc:"List 'mult' output per list value." },
}
}
add: {
vars: {
in: { type:numeric, flags:["src","mult"], doc:"Operands" },
in: { type:numeric, flags:["notify","src","mult"], doc:"Operands" },
otype: { type:string, value:double, flags:["init"], doc:"The type of the output value." },
out: { type:runtime, flags:["no_src"], doc:"Result" },
}
@ -687,7 +689,7 @@
preset: {
vars: {
in: { type:string, flags:["src"], doc:"Preset to select." },
in: { type:string, flags:["src","notify"], doc:"Preset to select." },
}
}
@ -701,12 +703,12 @@
// 2. The only purpose for the 'srateSrc' is to get the sample rate of the system.
vars: {
net: { type:string, doc:"Proc name of the poly network."},
netSfxId: { type:uint, value: 0, doc:"Label sfx id of the source poly instance."},
srateSrc: { type:audio, flags:["src"], doc:"Audio source to derive the sample rate."},
durMs: { type:uint, value:1000, doc:"Cross-fade duration in milliseconds" },
trigger: { type:all, doc:"Start cross-fade." },
preset: { type:string, doc:"Preset to apply to the poly network." },
net: { type:string, doc:"Proc name of the poly network."},
netSfxId: { type:uint, value: 0, doc:"Label sfx id of the source poly instance."},
srateSrc: { type:audio, flags:["src"], doc:"Audio source to derive the sample rate."},
durMs: { type:uint, value:1000, doc:"Cross-fade duration in milliseconds" },
trigger: { type:all, flags:["notify"], doc:"Start cross-fade." },
preset: { type:string,flags:["notify"], doc:"Preset to apply to the poly network." },
gain: { type:coeff, flags:["mult"], value:0, doc:"Cross-fade gain output." }
}
@ -717,7 +719,7 @@
vars: {
in: { type:midi, doc:"MIDI in" },
gain: { type:coeff, value:1.0, doc:"Audio gain." },
chCnt: { type:uint, flags["init"], doc:"Output audio channel count."},
chCnt: { type:uint, flags:["init"], doc:"Output audio channel count."},
out: { type:audio, doc:"Audio out" },
print_fl: { type:bool, value:false, doc:"Print MIDI message to console." },
done_fl: { type:bool, value:false, doc:"Triggers when voice is available."}
@ -752,28 +754,28 @@
test_pitch: { type:uint, value:0, doc:"Pitch to test." },
test_key_pitch: { type:uint, value:48, doc:"Base pitch to use for lowest velocity when in 'test' mode." },
load_thread_cnt: { type:uint, flags["init"], value:16, doc:"Count of threads to use for wave table loading." }
load_thread_cnt: { type:uint, flags:["init"], value:16, doc:"Count of threads to use for wave table loading." }
}
},
print: {
vars: {
in: { type:all, flags:["mult"], doc: "Value to print." },
eol_fl: { type:all, doc: "Trigger an end-of-line." },
text: { type:cfg, doc: "List of labels." },
in: { type:all, flags:["mult"], doc: "Value to print." },
eol_fl: { type:all, flags:["notify"], doc: "Trigger an end-of-line." },
text: { type:cfg, flags:["notify"], doc: "List of labels." },
}
}
midi_msg: {
vars: {
ch: { type:uint, value:0, doc:"MIDI channel input." },
status: { type:uint, value:0, doc:"MIDI status input."},
d0: { type:uint, value:0, doc:"MIDI data byte 0."},
d1: { type:uint, value:0, doc:"MIDI data byte 1."},
trigger: { type:all, value:0, doc:"Send message."},
buf_cnt: { type:uint, value:16, flags:["init"], doc:"Length of internal msg buffer."},
out: { type:midi, doc:"MIDI output."},
ch: { type:uint, flags:["notify"], value:0, doc:"MIDI channel input." },
status: { type:uint, flags:["notify"], value:0, doc:"MIDI status input."},
d0: { type:uint, flags:["notify"], value:0, doc:"MIDI data byte 0."},
d1: { type:uint, flags:["notify"], value:0, doc:"MIDI data byte 1."},
trigger: { type:all, flags:["notify"], value:0, doc:"Send message."},
buf_cnt: { type:uint, value:16, flags:["init"], doc:"Length of internal msg buffer."},
out: { type:midi, doc:"MIDI output."},
}
}
@ -817,8 +819,8 @@
out_ch_cnt:{ type:uint, flags:["init"], doc:"Count of audio output channels."},
in: { type:audio, flags:["src","mult"], doc:"Audio input." },
midi: { type:midi, flags:["mult"], doc:"Per audio channel MIDI message from poly_voice_ctl." },
donefl: { type:bool, flags["mult"], doc:"Per audio channel voice 'available' flags." },
trig: { type:all, doc:"Trigger to advance to next channel."},
donefl: { type:bool, flags:["mult"], doc:"Per audio channel voice 'available' flags." },
trig: { type:all, flags:["notify"], doc:"Trigger to advance to next channel."},
out_ch_idx:{ type:uint, value:0, doc:"Transform preset id. Change indicates that successive notes should go to a new output." },
out: { type:audio, flags:["mult"] doc:"Audio output."},
}
@ -827,16 +829,16 @@
score_player: {
doc: [ "Generate MIDI and score location information from a score file." ]
vars: {
fname: { type:string, flags:["init"], value:"", doc:"Score file name." },
stopping_ms: { type:uint, flags:["init"], value:5000, doc:"Maximum stopping time in milliseconds." },
start: { type:all, value:false, doc:"Start playback" },
stop: { type:all, value:false, doc:"Stop playback" },
b_loc: { type:uint, value:0, doc:"Score begin location." },
e_loc: { type:uint, value:0, doc:"Score end location." },
b_meas: { type:uint, value:0, doc:"Score begin measure." },
e_meas: { type:uint, value:0, doc:"Score end measure." },
done_fl: { type:bool, value:false, doc:"Emits true on done." },
out: { type:record, doc:"Score event record.",
fname: { type:string, flags:["init"], value:"", doc:"Score file name." },
stopping_ms: { type:uint, flags:["init"], value:5000, doc:"Maximum stopping time in milliseconds." },
start: { type:all, flags:["notify"], value:false, doc:"Start playback" },
stop: { type:all, flags:["notify"], value:false, doc:"Stop playback" },
b_loc: { type:uint, flags:["notify"], value:0, doc:"Score begin location." },
e_loc: { type:uint, flags:["notify"], value:0, doc:"Score end location." },
b_meas: { type:uint, flags:["notify"], value:0, doc:"Score begin measure." },
e_meas: { type:uint, flags:["notify"], value:0, doc:"Score end measure." },
done_fl: { type:bool, value:false, doc:"Emits true on done." },
out: { type:record, doc:"Score event record.",
fmt: {
fields: {
midi: { type:m3, doc:"MIDI channel event message" },
@ -871,7 +873,7 @@
score_wnd: { type:uint, flags:["init"], value:7, doc:"Count of locations in the score search window." },
midi_wnd: { type:uint, flags:["init"], value:15, doc:"Count of MIDI events to align in the score search window." },
print_fl: { type:bool, flags:["init"], value:false, doc:"Set to print log of score follower state." },
back_track_fl: { type:bool, flags["init"], value:false, doc:"Set if the score follower is allowed to report locations out of order." },
back_track_fl: { type:bool, flags:["init"], value:false, doc:"Set if the score follower is allowed to report locations out of order." },
loc: { type:uint, doc:"Score location." },
out: { type:record, doc:"Input record with the 'loc' field set ." }
}
@ -921,25 +923,25 @@
cfg: { type:cfg, flags:["init"], doc:"Initial preset configuration." },
fname: { type:string, flags:["init"], value:"", doc:"Preset file name."},
in: { type:record, fmt:{ required:["loc"] }, doc:"Input record with 'loc' field." },
loc: { type:uint, value:0, doc:"Seek to this location." },
reset: { type:bool, value:false, doc:"Reset to initial state."},
per_note_fl: { type:bool, value:false, doc:"Update the selected preset on every note, otherwise update on new location values." },
loc: { type:uint, value:0, doc:"Seek to this location." },
reset: { type:bool, flags:["notify"], value:false, doc:"Reset to initial state."},
per_note_fl: { type:bool, value:false, doc:"Update the selected preset on every note, otherwise update on new location values." },
pri_prob_fl: { type:bool, value: false, doc:"Select primary preset probabilstically." }
pri_uniform_fl: { type:bool, flags:["ui_disable"], value: false, doc:"Use a uniform probability distribution rather than an 'order' weighted distribution." },
pri_dry_on_play_fl: { type: bool, flags:["ui_disable"], value: true, doc:"Select 'dry' if it is the manually selected preset." },
pri_allow_all_fl: { type: bool, flags:["ui_disable"], value: false, doc:"Select from all possible presets rather than the presets with 'order' > 0." },
pri_dry_on_sel_fl: { type: bool, flags:["ui_disable"], value: true, doc:"Select 'dry' if 'allow_all' is selected and 'dry' has 'order' > 0." },
pri_prob_fl: { type:bool, flags:["notify"], value: false, doc:"Select primary preset probabilstically." }
pri_uniform_fl: { type:bool, flags:["notify","ui_disable"], value: false, doc:"Use a uniform probability distribution rather than an 'order' weighted distribution." },
pri_dry_on_play_fl: { type: bool, flags:["notify","ui_disable"], value: true, doc:"Select 'dry' if it is the manually selected preset." },
pri_allow_all_fl: { type: bool, flags:["notify","ui_disable"], value: false, doc:"Select from all possible presets rather than the presets with 'order' > 0." },
pri_dry_on_sel_fl: { type: bool, flags:["notify","ui_disable"], value: true, doc:"Select 'dry' if 'allow_all' is selected and 'dry' has 'order' > 0." },
interp_fl: { type: bool, value: false, doc:"Interpolate between the primary and secondary presets." },
interp_dist: { type: float, flags:["ui_disable"], value: 0.5, doc:"Unit fractionaly distance between primary and secondary preset." },
interp_rand_fl: { type: bool, flags:["ui_disable"], value: true, doc:"Randomly select the distance between the primary and secondary preset." },
interp_fl: { type: bool, flags:["notify"], value: false, doc:"Interpolate between the primary and secondary presets." },
interp_dist: { type: float, flags:["notify","ui_disable"], value: 0.5, doc:"Unit fractionaly distance between primary and secondary preset." },
interp_rand_fl: { type: bool, flags:["notify","ui_disable"], value: true, doc:"Randomly select the distance between the primary and secondary preset." },
sec_prob_fl: { type:bool, flags:["ui_disable"], value: false, doc:"Select secondary preset probabilstically." }
sec_uniform_fl: { type:bool, flags:["ui_disable"], value: false, doc:"Use a uniform probability distribution rather than an 'order' weighted distribution." },
sec_dry_on_play_fl: { type: bool, flags:["ui_disable"], value: true, doc:"Select 'dry' if it is the manually selected preset." },
sec_allow_all_fl: { type: bool, flags:["ui_disable"], value: false, doc:"Select from all possible presets rather than the presets with 'order' > 0." },
sec_dry_on_sel_fl: { type: bool, flags:["ui_disable"], value: true, doc:"Select 'dry' if 'allow_all' is selected and 'dry' has 'order' > 0." },
sec_prob_fl: { type:bool, flags:["notify","ui_disable"], value: false, doc:"Select secondary preset probabilstically." }
sec_uniform_fl: { type:bool, flags:["notify","ui_disable"], value: false, doc:"Use a uniform probability distribution rather than an 'order' weighted distribution." },
sec_dry_on_play_fl: { type: bool, flags:["notify","ui_disable"], value: true, doc:"Select 'dry' if it is the manually selected preset." },
sec_allow_all_fl: { type: bool, flags:["notify","ui_disable"], value: false, doc:"Select from all possible presets rather than the presets with 'order' > 0." },
sec_dry_on_sel_fl: { type: bool, flags:["notify","ui_disable"], value: true, doc:"Select 'dry' if 'allow_all' is selected and 'dry' has 'order' > 0." },
midi_in: { type:midi, flags:["mult","no_ui"], doc:"Per voice MIDI in" },

View File

@ -966,12 +966,18 @@ strings, consider adding a 'const-string' type to eliminate memory allocation of
cannot run as part of a poly. Any processor that calls a global function,
like 'network_apply_preset()' must run a the top level only.
- Consider eliminating the value() custom proc_t function and replace it by setting a 'delta flag' on the
- DONE: Consider eliminating the value() custom proc_t function and replace it by setting a 'delta flag' on the
variables that change. Optionally a linked list of changed variables could be implemented to
avoid having to search for changed variable values - although this list might have to be implemented as a thread safe linked list.
- value() should return a special return-code value to indicate that the
- DONE: value() should return a special return-code value to indicate that the
value should not be updated and distinguish it from an error code - which should stop the system.
Note: This idea is meaningless since variables that are set via connection have no way to 'refuse'
a connected value - since they are implemented as pointers back to the source variabl.e
- The 'two slot' approach to setting variable no longer seems useful.
The only reason not to eliminate it is to possibly use it as a way to test local values
before they are set, but it isn't clear if this actually useful.
- DONE: Allow proc's to send messages to the UI. Implementation: During exec() the proc builds a global list of variables whose values
@ -1014,14 +1020,16 @@ Look at all the places `var_create()` is called can the value arg. be removed?
- DONE: Re-write the currawong circuit with caw.
- Finish audio feedback example - this will probably involve writing an `audio_silence` class.
Update: there is now an audio_silence class.
- Issue a warning if memory is allocated during runtime.
- cwMpScNbQueue is allocating memory. This makes it blocking.
Update: 3/25 - this queue is not currently used
- Check for illegal variable names in class descriptions. (no periods, trailing digits, or trailing underscores)
- Check for unknown fields where the syntax clearly specifies only certain options via the 'readv()' method.
- DONE: Check for unknown fields where the syntax clearly specifies only certain options via the 'readv()' method.
- Verify that all variables have been registered (have valid 'vid's) during post instantiation validation.
(this is apparently not currently happening)
@ -1046,6 +1054,8 @@ Look at all the places `var_create()` is called can the value arg. be removed?
+ mult proc's with more than 3 instances should be put into a list or use a 'disclose' button
+ add a UI label to the var description,
- Class presets cannot address 'mult' variables. Maybe this is ok since 'mult' variables are generally connected to a source?
@ -1062,6 +1072,7 @@ Has this problem been addressed by allowing mult variables to be instantiated in
- Variable attributes should be meaningful. e.g. src,src_opt,mult,init, ....
Should we check for 'src' or 'mult' attribute on var's?
(In other words: Enforce var attributes.)
+ A variable with the 'init' flag should never be changed at runtime.
- How much of the proc initialization implementation can use the preset compile/apply code?
@ -1083,6 +1094,7 @@ Has this problem been addressed by allowing mult variables to be instantiated in
- The signal srate should determine the sample rate used by a given processor.
The system sample rate should only be used a default/fallback value.
Processors that have mandatory signal inputs should never need to also have an srate parameter.
Consider a network with a variable sample rate.
- Implement user-defined-proc preset application.
@ -1106,6 +1118,7 @@ Processors that have mandatory signal inputs should never need to also have an s
Perhaps this could be a 'symbol' data type?
- There should be special logging macros inside procs that automatically log the instance name.
Likewise there should be special cwLogErrorProc(rc,proc), cwLogErrorVar(rc,var) to automatically report the source of the error.
- Look more closely at the way to identify an in-stmt src-net or a out-stmt in-net.
It's not clear there is a difference between specifying `_` and the default behaviour.
@ -1227,6 +1240,19 @@ that can be depicted like this.
This diagram shows a two level network, where the internal
network contains an array of networks.
A processor instance is structured as a collection of variables along with a small set of
functions for maintaining it's state.
Variables act both as a means of holding the time varying state of the processor
and as input and output ports. There is nothing preventing a variable from
being both an input and output port, although in practice then tend to be one
or the other.
As is the case in most dataflow implementations processors act as the nodes
of the graph and edges represent the flow of information between output and
input variables. A _caw_ graph allows fan-out, multiple outputs from a variable,
but not fan-in. A variable acting as in input may have only a single incoming edge.
Networks are executed sequentially, one processor at a time, from top
to bottom. Networks that are members of the same network array,
referred to as silbing networks, may however execute concurrently to
@ -1250,6 +1276,7 @@ is the case because it guarantees that no processors are running when
the preset values are set.
/*********************************
2. If a processor receives data from a sibling network it is possible
that the processors value() function is called from multiple
concurrent threads. Processors which receive data from sibling
@ -1279,6 +1306,8 @@ The purpose of the value() function is to provide a single
easy way of picking up changed incoming values without
having to test for changed values in the exec() function.
It shouldn't be used as an alternate exec() function.
*******/
Note that the create() and destroy() calls for all processors
in the entire graph occur in a single thread and therefore do
@ -1345,6 +1374,37 @@ The new record effectively inherits the contents of the
existing record by reference. No data is copied.
For an example of this see the `vel_table` implementation.
Variable Change Notification
----------------------------
Processors are not directly notified when one of their connected variables changes.
This is the case because _caw_ does not implement a 'message' or 'event'
propagation scheme. When an 'input' variable changes the processor which owns
it is not informed of the change. This limitation exists to prevent the need
for a processor to implement a thread-safe message handling scheme - since it is
possible that variable updates would come from concurrent threads executing
the processors to which precede it in the graph.
By default if a processor needs to notice
when an input variable changes it needs to cache the value and check
if the value has changed on the next execution cycle. For a processor with
many rarely changing variables this can be both messy and wasteful since it is possible
that most of the variable will not change on any given execution cycle.
To handle this case a variable change notfication scheme is built into the system.
When a variable description is marked with the 'notify' tag it is placed on
an internal list (proc_t.modVarMapA[]). Just prior to the processors instance
exec() cycle a call to proc_notify() will result in a callback to the
instances notify() function for every marked variable that was modified since
the last execution of the instance. Note that these callbacks happen
from a single thread, the same one that will subsequently call the exec() function.
The calls to notify() occur in the same order that the variables changed in time,
however there will be only one callback per variable. If a variable changed
multiple times during the cycle only the last value will be recorded.
This limitation however exists for all processor input variables whether they
use the notification scheme or not.
Optional Variables
-------------------
@ -1357,6 +1417,8 @@ midi_out has implemented 'in' and 'rin' as optional
variables. Look there for an example of how to accomplish this.
Presets:
----------------