From 49b4a1430fe8727516fb90e261e88d6efa328b8c Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 17 Sep 2024 16:33:26 -0400 Subject: [PATCH] cwFlow,cwFlowNet,cwFlowTypes,cwFlowProc : 'poly' processor can now handle heterogeneous arrays of networks. --- cwFlow.cpp | 40 ++++---- cwFlowNet.cpp | 234 +++++++++++++++++++++++++++++++---------------- cwFlowNet.h | 15 +-- cwFlowProc.cpp | 160 +++++++++++++++++++++----------- cwFlowTypes.cpp | 17 ++++ cwFlowTypes.h | 20 ++-- cwThreadMach.cpp | 2 +- 7 files changed, 315 insertions(+), 173 deletions(-) diff --git a/cwFlow.cpp b/cwFlow.cpp index 38fe61f..e5e1419 100644 --- a/cwFlow.cpp +++ b/cwFlow.cpp @@ -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; ideviceN; ++i) print_external_device( p->deviceA + i ); - network_print(p->net); + network_print(*p->net); } diff --git a/cwFlowNet.cpp b/cwFlowNet.cpp index e290304..a3226ab 100644 --- a/cwFlowNet.cpp +++ b/cwFlowNet.cpp @@ -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; iproc_arrayN; ++i) + proc_destroy(net->proc_array[i]); - for(unsigned i=0; iproc_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(); + + // 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(procN); + + // for each proc in the network + for(unsigned j=0; jprocsCfg->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(net.proc_arrayAllocN); - net.proc_arrayN = 0; - net.poly_voiceA = mem::allocZ(polyCnt); - - // for each subnet + for(unsigned i=0; i1 ? i : kInvalidId; + + const object_t* cfg = i < netCfgN ? netCfgA[i] : netCfgA[0]; - // for each proc in the network - for(unsigned j=0; jchild_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= 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; } diff --git a/cwFlowNet.h b/cwFlowNet.h index dc20a96..a647cc7 100644 --- a/cwFlowNet.h +++ b/cwFlowNet.h @@ -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 ); diff --git a/cwFlowProc.cpp b/cwFlowProc.cpp index cda9f85..5628aa9 100644 --- a/cwFlowProc.cpp +++ b/cwFlowProc.cpp @@ -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(); - const object_t* networkCfg = nullptr; - variable_t* proxyVarL = nullptr; + rc_t rc = kOkRC; + inst_t* inst = mem::allocZ(); + 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(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; icount; ++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(inst->count); inst->voiceA = mem::allocZ(inst->count); - for(unsigned i=0; icount; ++i) + for(unsigned i=0; net !=nullptr; ++i) { + assert(icount); + 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(); @@ -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; ipoly_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(p->poly_ch_cnt); // create the proxy network networks - for(unsigned i=0; ipoly_ch_cnt; ++i) + for(unsigned i=0; ipoly_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(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(p->netA[i].net.proc_arrayN); + p->netA[i].net.presetsCfg = net->presetsCfg; - for(unsigned j=0,k=0; jnet_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; jproc_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; inet_proc->internal_net->poly_cnt; ++i) + for(unsigned i=0; ipoly_ch_cnt; ++i) { p->netA[i].cur_gain += _signum(p->netA[i].target_gain - p->netA[i].cur_gain) * delta_gain_per_cycle; diff --git a/cwFlowTypes.cpp b/cwFlowTypes.cpp index a36c360..2cdc042 100644 --- a/cwFlowTypes.cpp +++ b/cwFlowTypes.cpp @@ -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; ilabel_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; } diff --git a/cwFlowTypes.h b/cwFlowTypes.h index 0b92c4a..b6c3310 100644 --- a/cwFlowTypes.h +++ b/cwFlowTypes.h @@ -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 ); //------------------------------------------------------------------------------------------------------------------------ diff --git a/cwThreadMach.cpp b/cwThreadMach.cpp index 47b974f..4bac3e7 100644 --- a/cwThreadMach.cpp +++ b/cwThreadMach.cpp @@ -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);