cwFlow,cwFlowNet,cwFlowTypes,cwFlowProc : 'poly' processor can now handle heterogeneous arrays of networks.

This commit is contained in:
kevin 2024-09-17 16:33:26 -04:00
parent f98dd37e49
commit 49b4a1430f
7 changed files with 315 additions and 173 deletions

View File

@ -780,17 +780,17 @@ cw::rc_t cw::flow::initialize( handle_t h,
}
// instantiate the network
if((rc = network_create(p,p->networkCfg,p->net,proxyVarL)) != kOkRC )
if((rc = network_create(p,&p->networkCfg,1,proxyVarL,1,p->net)) != kOkRC )
{
rc = cwLogError(rc,"Network creation failed.");
goto errLabel;
}
if( p->printNetworkFl )
network_print(p->net);
if( p->printNetworkFl && p->net != nullptr )
network_print(*p->net);
if( p->init_net_preset_label != nullptr )
network_apply_preset( p->net, p->init_net_preset_label );
if( p->init_net_preset_label != nullptr && p->net != nullptr )
network_apply_preset( *p->net, p->init_net_preset_label );
p->isInRuntimeFl = true;
cwLogInfo("Entering runtime.");
@ -866,7 +866,7 @@ cw::rc_t cw::flow::exec_cycle( handle_t h )
}
else
{
rc = exec_cycle(p->net);
rc = exec_cycle(*p->net);
p->cycleIndex += 1;
}
@ -888,52 +888,52 @@ cw::rc_t cw::flow::exec( handle_t h )
cw::rc_t cw::flow::apply_preset( handle_t h, const char* presetLabel )
{
flow_t* p = _handleToPtr(h);
return network_apply_preset(p->net,presetLabel);
return network_apply_preset(*p->net,presetLabel);
}
cw::rc_t cw::flow::apply_dual_preset( handle_t h, const char* presetLabel_0, const char* presetLabel_1, double coeff )
{
flow_t* p = _handleToPtr(h);
return network_apply_dual_preset(p->net,presetLabel_0, presetLabel_1, coeff );
return network_apply_dual_preset(*p->net,presetLabel_0, presetLabel_1, coeff );
}
cw::rc_t cw::flow::apply_preset( handle_t h, const multi_preset_selector_t& mps )
{
flow_t* p = _handleToPtr(h);
return network_apply_preset(p->net,mps);
return network_apply_preset(*p->net,mps);
}
cw::rc_t cw::flow::set_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, bool value )
{ return set_variable_value( _handleToPtr(h)->net, inst_label, var_label, chIdx, value ); }
{ return set_variable_value( *_handleToPtr(h)->net, inst_label, var_label, chIdx, value ); }
cw::rc_t cw::flow::set_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, int value )
{ return set_variable_value( _handleToPtr(h)->net, inst_label, var_label, chIdx, value ); }
{ return set_variable_value( *_handleToPtr(h)->net, inst_label, var_label, chIdx, value ); }
cw::rc_t cw::flow::set_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, unsigned value )
{ return set_variable_value( _handleToPtr(h)->net, inst_label, var_label, chIdx, value ); }
{ return set_variable_value( *_handleToPtr(h)->net, inst_label, var_label, chIdx, value ); }
cw::rc_t cw::flow::set_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, float value )
{ return set_variable_value( _handleToPtr(h)->net, inst_label, var_label, chIdx, value ); }
{ return set_variable_value( *_handleToPtr(h)->net, inst_label, var_label, chIdx, value ); }
cw::rc_t cw::flow::set_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, double value )
{ return set_variable_value( _handleToPtr(h)->net, inst_label, var_label, chIdx, value ); }
{ return set_variable_value( *_handleToPtr(h)->net, inst_label, var_label, chIdx, value ); }
cw::rc_t cw::flow::get_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, bool& valueRef )
{ return get_variable_value( _handleToPtr(h)->net, inst_label, var_label, chIdx, valueRef ); }
{ return get_variable_value( *_handleToPtr(h)->net, inst_label, var_label, chIdx, valueRef ); }
cw::rc_t cw::flow::get_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, int& valueRef )
{ return get_variable_value( _handleToPtr(h)->net, inst_label, var_label, chIdx, valueRef ); }
{ return get_variable_value( *_handleToPtr(h)->net, inst_label, var_label, chIdx, valueRef ); }
cw::rc_t cw::flow::get_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, unsigned& valueRef )
{ return get_variable_value( _handleToPtr(h)->net, inst_label, var_label, chIdx, valueRef ); }
{ return get_variable_value( *_handleToPtr(h)->net, inst_label, var_label, chIdx, valueRef ); }
cw::rc_t cw::flow::get_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, float& valueRef )
{ return get_variable_value( _handleToPtr(h)->net, inst_label, var_label, chIdx, valueRef ); }
{ return get_variable_value( *_handleToPtr(h)->net, inst_label, var_label, chIdx, valueRef ); }
cw::rc_t cw::flow::get_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, double& valueRef )
{ return get_variable_value( _handleToPtr(h)->net, inst_label, var_label, chIdx, valueRef ); }
{ return get_variable_value( *_handleToPtr(h)->net, inst_label, var_label, chIdx, valueRef ); }
@ -950,7 +950,7 @@ void cw::flow::print_network( handle_t h )
for(unsigned i=0; i<p->deviceN; ++i)
print_external_device( p->deviceA + i );
network_print(p->net);
network_print(*p->net);
}

View File

@ -123,25 +123,23 @@ namespace cw
_network_preset_destroy( net.presetA[i] );
mem::release(net.presetA);
}
rc_t _network_destroy( network_t& net )
rc_t _network_destroy_one( network_t*& net )
{
rc_t rc = kOkRC;
for(unsigned i=0; i<net->proc_arrayN; ++i)
proc_destroy(net->proc_array[i]);
for(unsigned i=0; i<net.proc_arrayN; ++i)
proc_destroy(net.proc_array[i]);
mem::release(net->proc_array);
net->proc_arrayN = 0;
mem::release(net.poly_voiceA);
mem::release(net.proc_array);
net.proc_arrayAllocN = 0;
net.proc_arrayN = 0;
_network_preset_array_destroy(*net);
_network_preset_array_destroy(net);
mem::release(net->preset_pairA);
net->preset_pairN = 0;
mem::release(net.preset_pairA);
net.preset_pairN = 0;
net_global_var_t* gv=net.globalVarL;
net_global_var_t* gv=net->globalVarL;
while( gv != nullptr )
{
net_global_var_t* gv0 = gv->link;
@ -150,6 +148,24 @@ namespace cw
mem::release(gv);
gv = gv0;
}
mem::release(net);
return rc;
}
rc_t _network_destroy( network_t*& net )
{
rc_t rc = kOkRC;
while( net != nullptr )
{
network_t* n0 = net->poly_link;
rc_t rc0;
if((rc0 = _network_destroy_one(net)) != kOkRC )
rc = cwLogError(rc0,"A network destroy failed.");
net = n0;
}
return rc;
}
@ -380,6 +396,11 @@ namespace cw
}
}
if( labeled_net == nullptr && net.poly_link != nullptr )
labeled_net = _io_stmt_find_labeled_network(*net.poly_link,net_proc_label );
return labeled_net;
}
@ -707,10 +728,10 @@ namespace cw
else
{
if( textIsEqual(io_stmt.remote_net_label,"_") )
remote_net = &proc->ctx->net;
remote_net = proc->ctx->net;
else
{
if((remote_net = _io_stmt_find_labeled_network(proc->ctx->net,io_stmt.remote_net_label)) == nullptr )
if((remote_net = _io_stmt_find_labeled_network(*proc->ctx->net,io_stmt.remote_net_label)) == nullptr )
{
rc = cwLogError(kSyntaxErrorRC,"The source net '%s' was not found.",cwStringNullGuard(io_stmt.remote_net_label));
goto errLabel;
@ -2860,81 +2881,143 @@ namespace cw
return result;
}
//==================================================================================================================
//
// Network - Create
//
rc_t _network_create( flow_t* p,
const object_t* networkCfg,
unsigned sfx_id,
variable_t* proxyVarL,
network_t*& net_ref )
{
rc_t rc = kOkRC;
unsigned procN = 0;
network_t* net = mem::allocZ<network_t>();
// if the top level network has not been set then set it here.
// (this is necessary so that proc's later in the exec order
// can locate proc's earlier in the exec order)
if(p->net == nullptr )
p->net = net;
if((rc = networkCfg->getv("procs",net->procsCfg)) != kOkRC )
{
rc = cwLogError(rc,"Failed on parsing required network cfg. elements.");
goto errLabel;
}
if((rc = networkCfg->getv_opt("presets",net->presetsCfg)) != kOkRC )
{
rc = cwLogError(rc,"Failed on parsing optional network cfg. elements.");
goto errLabel;
}
procN = net->procsCfg->child_count();
net->proc_array = mem::allocZ<proc_t*>(procN);
// for each proc in the network
for(unsigned j=0; j<procN; ++j)
{
const object_t* proc_cfg = net->procsCfg->child_ele(j);
// create the proc inst instance
if( (rc= _proc_create( p, proc_cfg, sfx_id, *net, proxyVarL, net->proc_array[j] ) ) != kOkRC )
{
rc = cwLogError(rc,"The processor instantiation at proc index %i failed.",j);
goto errLabel;
}
net->proc_arrayN += 1;
}
if((rc = _network_preset_pair_create_table(*net)) != kOkRC )
goto errLabel;
_network_preset_parse_top_level_dict(p, *net, net->presetsCfg );
net_ref = net;
errLabel:
if( rc != kOkRC )
{
if( p->net == net )
p->net = nullptr;
net_ref = nullptr;
_network_destroy(net);
}
return rc;
}
}
}
cw::rc_t cw::flow::network_create( flow_t* p,
const object_t* networkCfg,
network_t& net,
variable_t* proxyVarL,
unsigned polyCnt )
cw::rc_t cw::flow::network_create( flow_t* p,
const object_t* const * netCfgA,
unsigned netCfgN,
variable_t* proxyVarL,
unsigned polyCnt,
network_t*& net_ref )
{
rc_t rc = kOkRC;
if((rc = networkCfg->getv("procs",net.procsCfg)) != kOkRC )
rc_t rc = kOkRC;
network_t* n0 = nullptr;
net_ref = nullptr;
if( !(netCfgN==1 || netCfgN==polyCnt ))
{
rc = cwLogError(rc,"Failed on parsing required network cfg. elements.");
cwLogError(kInvalidArgRC,"The count of network cfg's must be one, or must match the 'poly count'.");
goto errLabel;
}
if((rc = networkCfg->getv_opt("presets",net.presetsCfg)) != kOkRC )
{
rc = cwLogError(rc,"Failed on parsing optional network cfg. elements.");
goto errLabel;
}
net.proc_arrayAllocN = polyCnt * net.procsCfg->child_count();
net.proc_array = mem::allocZ<proc_t*>(net.proc_arrayAllocN);
net.proc_arrayN = 0;
net.poly_voiceA = mem::allocZ<poly_voice_t>(polyCnt);
// for each subnet
for(unsigned i=0; i<polyCnt; ++i)
{
assert( i<polyCnt && net.proc_arrayN < net.proc_arrayAllocN );
network_t* net = nullptr;
// track the first proc in each subnet
net.poly_voiceA[i].proc_idx = net.proc_arrayN;
net.poly_voiceA[i].net = &net;
// All procs in a poly should share the same sfx_id
// otherwise the sfx_id can be automatically generated.
unsigned sfx_id = polyCnt>1 ? i : kInvalidId;
const object_t* cfg = i < netCfgN ? netCfgA[i] : netCfgA[0];
// for each proc in the network
for(unsigned j=0; j<net.procsCfg->child_count(); ++j)
if((rc = _network_create(p, cfg, sfx_id, proxyVarL, net)) != kOkRC )
{
const object_t* proc_cfg = net.procsCfg->child_ele(j);
unsigned sfx_id = polyCnt>1 ? i : kInvalidId;
assert(net.proc_arrayN < net.proc_arrayAllocN );
// create the proc inst instance
if( (rc= _proc_create( p, proc_cfg, sfx_id, net, proxyVarL, net.proc_array[net.proc_arrayN] ) ) != kOkRC )
{
//rc = cwLogError(rc,"The instantiation at proc index %i is invalid.",net.proc_arrayN);
goto errLabel;
}
net.proc_arrayN += 1;
net.poly_voiceA[i].proc_cnt += 1;
rc = cwLogError(rc,"Network create failed on poly index %i.",i);
goto errLabel;
}
// The returned net is always the first in a poly chain
if( net_ref == nullptr )
net_ref = net;
net->poly_idx = i;
if( n0 != nullptr )
n0->poly_link = net;
n0 = net;
}
net.poly_cnt = polyCnt;
if((rc = _network_preset_pair_create_table(net)) != kOkRC )
goto errLabel;
_network_preset_parse_top_level_dict(p, net, net.presetsCfg );
errLabel:
if( rc != kOkRC )
_network_destroy(net);
if( rc != kOkRC && net_ref != nullptr )
_network_destroy(net_ref);
return rc;
}
cw::rc_t cw::flow::network_destroy( network_t& net )
cw::rc_t cw::flow::network_destroy( network_t*& net )
{
return _network_destroy(net);
}
@ -2954,23 +3037,13 @@ const cw::object_t* cw::flow::find_network_preset( const network_t& net, const c
return preset_value;
}
cw::rc_t cw::flow::exec_cycle( network_t& net, unsigned proc_idx, unsigned proc_cnt )
cw::rc_t cw::flow::exec_cycle( network_t& net )
{
rc_t rc = kOkRC;
bool halt_fl = false;
if( proc_cnt == kInvalidCnt )
proc_cnt = net.proc_arrayN;
for(unsigned i=proc_idx; i<proc_idx+proc_cnt; ++i)
for(unsigned i=0; i<net.proc_arrayN; ++i)
{
if( i >= net.proc_arrayN )
{
rc = cwLogError(kEleNotFoundRC,"Network exec cycle failed on an invalid proc index. %i >= %i.",i,net.proc_arrayN );
goto errLabel;
}
if((rc = net.proc_array[i]->class_desc->members->exec(net.proc_array[i])) != kOkRC )
{
if( rc == kEofRC )
@ -2983,7 +3056,6 @@ cw::rc_t cw::flow::exec_cycle( network_t& net, unsigned proc_idx, unsigned proc_
}
}
errLabel:
return halt_fl ? kEofRC : rc;
}

View File

@ -5,18 +5,19 @@ namespace cw
{
namespace flow
{
rc_t network_create( flow_t* p,
const object_t* subnetCfgA, // subnetCfgA[subNetCfgN] per subnet cfg record
network_t& net, // Network object to be filled with new proc instances
variable_t* proxyVarL, //
unsigned polyCnt = 1 // Count of networks to create
rc_t network_create( flow_t* p,
const object_t* const * netCfgA, // subnetCfgA[subNetCfgN] per subnet cfg record
unsigned netCfgN,
variable_t* proxyVarL, //
unsigned polyCnt, // Count of poly networks to create or 1 if the network is not poly
network_t*& net_ref
);
rc_t network_destroy( network_t& net );
rc_t network_destroy( network_t*& net );
const object_t* find_network_preset( const network_t& net, const char* presetLabel );
rc_t exec_cycle( network_t& net, unsigned proc_idx=0, unsigned proc_cnt=kInvalidCnt );
rc_t exec_cycle( network_t& net );
rc_t get_variable( network_t& net, const char* inst_label, const char* var_label, unsigned chIdx, proc_t*& instPtrRef, variable_t*& varPtrRef );

View File

@ -141,7 +141,7 @@ namespace cw
{
typedef struct
{
network_t net;
network_t* net;
} inst_t;
@ -156,7 +156,7 @@ namespace cw
goto errLabel;
}
if((rc = network_create(proc->ctx,networkCfg,p->net,proc->varL)) != kOkRC )
if((rc = network_create(proc->ctx,&networkCfg,1,proc->varL,1,p->net)) != kOkRC )
{
rc = cwLogError(rc,"Creation failed on the subnet internal network.");
goto errLabel;
@ -164,7 +164,7 @@ namespace cw
// Set the internal net pointer in the base proc instance
// so that network based utilities can scan it
proc->internal_net = &p->net;
proc->internal_net = p->net;
errLabel:
return rc;
@ -189,8 +189,9 @@ namespace cw
{
rc_t rc = kOkRC;
if((rc = exec_cycle(p->net)) != kOkRC )
rc = cwLogError(rc,"poly internal network exec failed.");
if(p->net != nullptr )
if((rc = exec_cycle(*p->net)) != kOkRC )
rc = cwLogError(rc,"poly internal network exec failed.");
return rc;
}
@ -228,8 +229,8 @@ namespace cw
typedef struct
{
unsigned count; // count of duplicate subnets in 'net'
network_t net; // internal network containing 'count' duplicate sub-nets
unsigned count; // count of subnets in 'net'
//network_t* net; // internal network containing 'count' duplicate sub-nets
bool parallel_fl; // true if the subnets should be executed in parallel
thread_tasks::handle_t threadTasksH; //
thread_tasks::task_t* taskA; // taskA[ count ]
@ -242,9 +243,7 @@ namespace cw
rc_t rc = kOkRC;
voice_t* v = (voice_t*)arg;
poly_voice_t* pv = v->net->poly_voiceA + v->voice_idx;
if((rc = exec_cycle(*v->net, pv->proc_idx, pv->proc_cnt)) != kOkRC )
if((rc = exec_cycle(*v->net)) != kOkRC )
{
rc = cwLogError(rc,"Parallel subnet exec failed on voice %i.",v->voice_idx);
goto errLabel;
@ -257,35 +256,77 @@ namespace cw
rc_t create( proc_t* proc )
{
rc_t rc = kOkRC;
inst_t* inst = mem::allocZ<inst_t>();
const object_t* networkCfg = nullptr;
variable_t* proxyVarL = nullptr;
rc_t rc = kOkRC;
inst_t* inst = mem::allocZ<inst_t>();
const object_t* networkCfg = nullptr;
variable_t* proxyVarL = nullptr;
const object_t** networkCfgA = nullptr;
unsigned networkCfgN = 1;
network_t* internal_net = nullptr;
proc->userPtr = inst;
if((rc = var_register_and_get( proc, kAnyChIdx,
kParallelFlPId, "parallel_fl", kBaseSfxId, inst->parallel_fl,
kCountPId, "count", kBaseSfxId, inst->count )) != kOkRC )
{
goto errLabel;
}
if( inst->count == 0 )
{
cwLogWarning("The 'poly' %s:%i was given a count of 0.",proc->label,proc->label_sfx_id);
goto errLabel;
}
// get the network cfg
if((rc = proc->proc_cfg->getv("network",networkCfg)) != kOkRC )
{
rc = cwLogError(rc,"The 'network' cfg. was not found.");
goto errLabel;
}
// get the 'parallel flag'
if((rc = var_register_and_get( proc, kAnyChIdx,kParallelFlPId, "parallel_fl", kBaseSfxId, inst->parallel_fl )) != kOkRC )
{
goto errLabel;
}
// if the network is a list of cfgs
if( networkCfg->is_list() )
{
inst->count = networkCfg->child_count();
networkCfgN = inst->count;
}
else
{
// otherwise multiple networks use the same cfg
if((rc = var_register_and_get( proc, kAnyChIdx,kCountPId,"count", kBaseSfxId, inst->count )) != kOkRC )
{
goto errLabel;
}
}
// the network cannot be empty
if( inst->count == 0 )
{
cwLogWarning("The 'poly' %s:%i was given a count of 0.",proc->label,proc->label_sfx_id);
goto errLabel;
}
// allocate the network cfg array
networkCfgA = mem::allocZ<const object_t*>(inst->count);
// by default there is only one cfg.
networkCfgA[0] = networkCfg;
// ... but if there are more than one cfg ...
if( networkCfg->is_list() )
{
// ... fill the network cfg array
for(unsigned i=0; i<inst->count; ++i)
{
networkCfgA[i] = networkCfg->child_ele(i);
if( !networkCfgA[i]->is_dict() )
{
cwLogError(kSyntaxErrorRC,"The network cfg. for the network index %i is not a dictionary.",i);
goto errLabel;
}
}
}
// create the network object - which will hold 'count' subnets - each a duplicate of the
// network described by 'networkCfg'.
if((rc = network_create(proc->ctx,networkCfg,inst->net,proxyVarL,inst->count)) != kOkRC )
if((rc = network_create(proc->ctx,networkCfgA,networkCfgN,proxyVarL,inst->count,internal_net)) != kOkRC )
{
rc = cwLogError(rc,"Creation failed on the internal network.");
goto errLabel;
@ -293,6 +334,8 @@ namespace cw
if( inst->parallel_fl )
{
network_t* net = internal_net;
// create a thread_tasks object
if((rc = thread_tasks::create( inst->threadTasksH, inst->count )) != kOkRC )
{
@ -304,29 +347,37 @@ namespace cw
inst->taskA = mem::allocZ<thread_tasks::task_t>(inst->count);
inst->voiceA = mem::allocZ<voice_t>(inst->count);
for(unsigned i=0; i<inst->count; ++i)
for(unsigned i=0; net !=nullptr; ++i)
{
assert(i<inst->count);
inst->voiceA[i].voice_idx = i;
inst->voiceA[i].net = &inst->net;
inst->voiceA[i].net = net;
inst->taskA[i].func = _voice_thread_func;
inst->taskA[i].arg = inst->voiceA + i;
net = net->poly_link;
}
}
// Set the internal net pointer in the base proc instance
// so that network based utilities can scan it
proc->internal_net = &inst->net;
proc->internal_net = internal_net;
errLabel:
mem::release(networkCfgA);
return rc;
}
rc_t destroy( proc_t* proc )
{
inst_t* p = (inst_t*)proc->userPtr;
network_destroy(p->net);
if( proc->internal_net != nullptr )
network_destroy(proc->internal_net);
thread_tasks::destroy(p->threadTasksH);
mem::release( p->taskA);
@ -355,7 +406,7 @@ namespace cw
}
else
{
if((rc = exec_cycle(p->net)) != kOkRC )
if((rc = exec_cycle(*proc->internal_net)) != kOkRC )
{
rc = cwLogError(rc,"poly internal network exec failed.");
}
@ -3842,6 +3893,8 @@ namespace cw
const char* presetLabel = nullptr;
unsigned netLabelSfxId = kBaseSfxId;
abuf_t* srateSrc = nullptr;
unsigned poly_cnt = 0;
network_t* net = nullptr;
coeff_t dum_dbl;
inst_t* p = mem::allocZ<inst_t>();
@ -3869,13 +3922,17 @@ namespace cw
goto errLabel;
}
if( p->net_proc->internal_net->poly_cnt < 3 )
poly_cnt = p->net_proc->internal_net==nullptr ? 0 : network_poly_count(*p->net_proc->internal_net);
if( poly_cnt < 3 )
{
cwLogError(rc,"The xfade_ctl source network must have at least 3 poly channels. %i < 3",p->net_proc->internal_net->poly_cnt);
cwLogError(rc,"The xfade_ctl source network must have at least 3 poly channels. %i < 3",poly_cnt);
goto errLabel;
}
p->poly_ch_cnt = p->net_proc->internal_net->poly_cnt;
p->poly_ch_cnt = poly_cnt;
net = p->net_proc->internal_net;
// create the gain output variables - one output for each poly-channel
for(unsigned i=1; i<p->poly_ch_cnt; ++i)
@ -3889,29 +3946,30 @@ namespace cw
}
// count of proc's in one poly-ch of the poly network
p->net_proc_cnt = p->net_proc->internal_net->proc_arrayN / p->net_proc->internal_net->poly_cnt;
//p->net_proc_cnt = p->net_proc->internal_net->proc_arrayN / p->net_proc->internal_net->poly_cnt;
p->netA = mem::allocZ<poly_ch_t>(p->poly_ch_cnt);
// create the proxy network networks
for(unsigned i=0; i<p->poly_ch_cnt; ++i)
for(unsigned i=0; i<p->poly_ch_cnt; ++i,net=net->poly_link)
{
p->netA[i].net.proc_arrayAllocN = p->net_proc_cnt;
p->netA[i].net.proc_arrayN = p->netA[i].net.proc_arrayAllocN;
p->netA[i].net.proc_array = mem::allocZ<proc_t*>(p->netA[i].net.proc_arrayAllocN);
p->netA[i].net.presetsCfg = p->net_proc->internal_net->presetsCfg;
p->netA[i].net.presetA = p->net_proc->internal_net->presetA;
p->netA[i].net.presetN = p->net_proc->internal_net->presetN;
assert(net != nullptr );
p->netA[i].net.preset_pairA = p->net_proc->internal_net->preset_pairA;
p->netA[i].net.preset_pairN = p->net_proc->internal_net->preset_pairN;
p->netA[i].net.proc_arrayN = net->proc_arrayN;
p->netA[i].net.proc_array = mem::allocZ<proc_t*>(p->netA[i].net.proc_arrayN);
p->netA[i].net.presetsCfg = net->presetsCfg;
for(unsigned j=0,k=0; j<p->net_proc->internal_net->proc_arrayN; ++j)
if( p->net_proc->internal_net->proc_array[j]->label_sfx_id == i )
p->netA[i].net.presetA = net->presetA;
p->netA[i].net.presetN = net->presetN;
p->netA[i].net.preset_pairA = net->preset_pairA;
p->netA[i].net.preset_pairN = net->preset_pairN;
for(unsigned j=0,k=0; j<net->proc_arrayN; ++j)
if( net->proc_array[j]->label_sfx_id == i )
{
assert( k < p->net_proc_cnt );
p->netA[i].net.proc_array[k++] = p->net_proc->internal_net->proc_array[j];
p->netA[i].net.proc_array[k++] = net->proc_array[j];
}
}
@ -4005,7 +4063,7 @@ namespace cw
}
// update the cross-fade gain outputs
for(unsigned i=0; i<p->net_proc->internal_net->poly_cnt; ++i)
for(unsigned i=0; i<p->poly_ch_cnt; ++i)
{
p->netA[i].cur_gain += _signum(p->netA[i].target_gain - p->netA[i].cur_gain) * delta_gain_per_cycle;

View File

@ -1721,6 +1721,15 @@ errLabel:
return rc;
}
unsigned cw::flow::network_poly_count( const network_t& net )
{
unsigned n =1;
for(const network_t* n0 = net.poly_link; n0!=nullptr; n0=n0->poly_link)
++n;
return n;
}
void cw::flow::proc_destroy( proc_t* proc )
{
if( proc == nullptr )
@ -1793,9 +1802,17 @@ cw::rc_t cw::flow::proc_validate( proc_t* proc )
cw::flow::proc_t* cw::flow::proc_find( network_t& net, const char* proc_label, unsigned sfx_id )
{
for(unsigned i=0; i<net.proc_arrayN; ++i)
{
assert( net.proc_array[i] != nullptr );
if( net.proc_array[i]->label_sfx_id==sfx_id && textIsEqual(proc_label,net.proc_array[i]->label) )
return net.proc_array[i];
}
if( net.poly_link != nullptr )
return proc_find(*net.poly_link, proc_label, sfx_id );
return nullptr;
}

View File

@ -317,25 +317,13 @@ namespace cw
} net_global_var_t;
typedef struct poly_voice_str
{
struct network_str* net; // Network containing the proc's referened by proc_idx, proc_cnt
unsigned proc_idx; // Index into network_t.proc_array[] of first proc in voice
unsigned proc_cnt; // Count of proc's in the voice
rc_t rc; // Result code from last call to exec_cycle()
} poly_voice_t;
typedef struct network_str
{
const object_t* procsCfg; // network proc list
const object_t* presetsCfg; // presets designed for this network
poly_voice_t* poly_voiceA; // poly_voiceA[ poly_cnt ].
unsigned poly_cnt; // count of duplicated networks in the list
struct proc_str** proc_array;
unsigned proc_arrayAllocN;
unsigned proc_arrayN;
network_preset_t* presetA;
@ -346,6 +334,10 @@ namespace cw
unsigned preset_pairN;
net_global_var_t* globalVarL;
struct network_str* poly_link;
unsigned poly_idx;
} network_t;
@ -382,7 +374,7 @@ namespace cw
const char* proj_dir; // default input/output directory
network_t net;
network_t* net;
} flow_t;
@ -473,6 +465,8 @@ namespace cw
unsigned proc_mult_count( const network_t& net, const char* proc_label );
rc_t proc_mult_sfx_id_array( const network_t& net, const char* proc_label, unsigned* idA, unsigned idAllocN, unsigned& idN_ref );
unsigned network_poly_count( const network_t& net );
//------------------------------------------------------------------------------------------------------------------------

View File

@ -321,7 +321,7 @@ cw::rc_t cw::thread_tasks::create( handle_t& hRef, unsigned threadN )
p->threadA[i].owner = p;
p->threadA[i].threadId = i;
// Threads are create in 'paused' mode
// Threads are created in 'paused' mode
if((rc = thread::create( p->threadA[i].threadH, _threadFunc, p->threadA + i, label )) != kOkRC )
{
rc = cwLogError(rc,"Task thread create %i failed.",i);