Initial working version of poly_merge and xfade_ctl.

cwFlowNet._connect_vars() changed to cwFlowTypes.var_connect().
cwFlowTest._set_var_value_from_cfg() to cwFlowTypes.var_set_from_preset().
var_channelize() now connects matching channels when they are available.
Added type 'numeric'.
Updated proc_template() to automatically allocate and extract inst_t.
Added a system sample rate.
This commit is contained in:
kevin 2024-05-02 13:59:19 -04:00
parent b57693f4e4
commit 040d902c6b
6 changed files with 637 additions and 502 deletions

View File

@ -53,7 +53,7 @@ namespace cw
{ "audio_meter", &audio_meter::members },
{ "audio_marker", &audio_marker::members },
{ "xfade_ctl", &xfade_ctl::members },
{ "poly_mixer", &poly_mixer::members },
{ "poly_merge", &poly_merge::members },
{ "sample_hold", &sample_hold::members },
{ "number", &number::members },
{ "timer", &timer::members },
@ -244,78 +244,6 @@ namespace cw
}
/*
rc_t _setup_input( flow_t* p, instance_t* in_inst, const char* in_var_label, const char* src_proc_label, const char* src_var_label )
{
rc_t rc = kOkRC;
unsigned src_charN = textLength(src_label_arg);
variable_t* src_var = nullptr;
instance_t* src_inst = nullptr;
variable_t* in_var = nullptr;
char sbuf[ src_charN+1 ];
// copy the id into the buf
strncpy(sbuf,src_label_arg,src_charN+1);
// advance suffix to the '.'
char* suffix = sbuf;
while( *suffix && *suffix != '.')
++suffix;
// if a '.' suffix was found
if( *suffix )
{
*suffix = 0;
++suffix;
}
// locate source instance
if((rc = instance_find(p, sbuf, kBaseSfxId, src_inst )) != kOkRC )
{
rc = cwLogError(kSyntaxErrorRC,"The source instance '%s' was not found.", cwStringNullGuard(sbuf) );
goto errLabel;
}
// locate source value
if((rc = var_find( src_inst, suffix, kBaseSfxId, kAnyChIdx, src_var)) != kOkRC )
{
rc = cwLogError(rc,"The source var '%s' was not found on the source instance '%s'.", cwStringNullGuard(suffix), cwStringNullGuard(sbuf));
goto errLabel;
}
// locate input value
if((rc = var_find( in_inst, in_var_label, kBaseSfxId, kAnyChIdx, in_var )) != kOkRC )
{
rc = cwLogError(rc,"The input value '%s' was not found on the instance '%s'.", cwStringNullGuard(in_var_label), cwStringNullGuard(in_inst->label));
goto errLabel;
}
// verify that the src_value type is included in the in_value type flags
if( cwIsNotFlag(in_var->varDesc->type, src_var->varDesc->type) )
{
rc = cwLogError(kSyntaxErrorRC,"The type flags don't match on input:%s %s source:%s %s .", in_inst->label, in_var_label, src_inst->label, suffix);
goto errLabel;
}
if( src_var->value == nullptr )
{
rc = cwLogError(kSyntaxErrorRC,"The source value is null on the connection input:'%s' %s source:'%s' '%s' .", in_inst->label, in_var_label, src_inst->label, suffix);
goto errLabel;
}
_connect_vars( src_var, in_var );
//cwLogInfo("'%s:%s' connected to source '%s:%s' %p.", in_inst->label, in_var_label, src_inst->label, suffix, in_var->value );
errLabel:
return rc;
}
*/
rc_t _destroy( flow_t* p)
{
@ -406,20 +334,24 @@ cw::rc_t cw::flow::create( handle_t& hRef,
}
// parse the main audio file processor cfg record
if((rc = flowCfg.getv("framesPerCycle", p->framesPerCycle,
"network", networkCfg)) != kOkRC )
if((rc = flowCfg.getv("network", networkCfg)) != kOkRC )
{
rc = cwLogError(kSyntaxErrorRC,"Error parsing the required flow configuration parameters.");
goto errLabel;
}
p->framesPerCycle = kDefaultFramesPerCycle;
p->sample_rate = kDefaultSampleRate;
// parse the optional args
if((rc = flowCfg.getv_opt("maxCycleCount", p->maxCycleCount,
if((rc = flowCfg.getv_opt("framesPerCycle", p->framesPerCycle,
"sample_rate", p->sample_rate,
"maxCycleCount", p->maxCycleCount,
"multiPriPresetProbFl", p->multiPriPresetProbFl,
"multiSecPresetProbFl", p->multiSecPresetProbFl,
"multiPresetInterpFl", p->multiPresetInterpFl,
"printClassDictFl", printClassDictFl,
"printNetworkFl", printNetworkFl)) != kOkRC )
"multiPresetInterpFl", p->multiPresetInterpFl,
"printClassDictFl", printClassDictFl,
"printNetworkFl", printNetworkFl)) != kOkRC )
{
rc = cwLogError(kSyntaxErrorRC,"Error parsing the optional flow configuration parameters.");
goto errLabel;

View File

@ -63,20 +63,6 @@ namespace cw
rc_t _var_map_id_to_index( instance_t* inst, unsigned vid, unsigned chIdx, unsigned& idxRef );
void _connect_vars( variable_t* src_var, variable_t* in_var )
{
// connect in_var into src_var's outgoing var chain
in_var->dst_link = src_var->dst_tail;
src_var->dst_tail = in_var;
if( src_var->dst_head == nullptr )
src_var->dst_head = in_var;
assert( src_var->value != nullptr );
in_var->value = src_var->value;
in_var->src_var = src_var;
}
rc_t _create_instance_var_map( instance_t* inst )
{
rc_t rc = kOkRC;
@ -146,6 +132,7 @@ namespace cw
}
/*
void _complete_input_connections( instance_t* inst )
{
for(variable_t* var=inst->varL; var!=nullptr; var=var->var_link)
@ -173,7 +160,8 @@ namespace cw
}
}
}
*/
rc_t _set_log_flags(instance_t* proc, const object_t* log_labels)
{
rc_t rc = kOkRC;
@ -1223,7 +1211,7 @@ namespace cw
// get the var class desc. for the in-var
if(( in_stmt.in_var_desc = var_desc_find(inst->class_desc,in_stmt.in_var_ele.label)) == nullptr )
{
rc = cwLogError(rc,"Unable to locate the var class desc for the in-var from '%s'.",cwStringNullGuard(in_stmt.in_var_ele.label));
rc = cwLogError(kEleNotFoundRC,"Unable to locate the var class desc for the in-var from '%s'.",cwStringNullGuard(in_stmt.in_var_ele.label));
goto errLabel;
}
@ -1446,7 +1434,7 @@ namespace cw
}
//
_connect_vars( src_var, in_var );
var_connect( src_var, in_var );
}
}
@ -1661,7 +1649,7 @@ namespace cw
}
// the custom creation function may have added channels to in-list vars fix up those connections here.
_complete_input_connections(inst);
//_complete_input_connections(inst);
// set the log flags again so that vars created by the instance can be included in the log output
if((rc = _set_log_flags(inst,pstate.log_labels)) != kOkRC )
@ -2033,7 +2021,8 @@ cw::rc_t cw::flow::exec_cycle( network_t& net )
for(unsigned i=0; i<net.proc_arrayN; ++i)
{
if((rc = net.proc_array[i]->class_desc->members->exec(net.proc_array[i])) != kOkRC )
{
{
rc = cwLogError(rc,"Execution failed on the proc:%s:%i.",cwStringNullGuard(net.proc_array[i]->label),net.proc_array[i]->label_sfx_id);
break;
}
}

View File

@ -31,6 +31,39 @@ namespace cw
namespace flow
{
template< typename inst_t >
rc_t std_destroy( instance_t* proc )
{
inst_t* p = (inst_t*)proc->userPtr;
rc_t rc = _destroy(proc,p);
mem::release(proc->userPtr);
return rc;
}
template< typename inst_t >
rc_t std_create( instance_t* proc )
{
rc_t rc = kOkRC;
proc->userPtr = mem::allocZ<inst_t>();
if((rc = _create(proc,(inst_t*)proc->userPtr)) != kOkRC )
std_destroy<inst_t>(proc);
return rc;
}
template< typename inst_t >
rc_t std_value( instance_t* proc, variable_t* var )
{ return _value(proc,(inst_t*)proc->userPtr, var); }
template< typename inst_t >
rc_t std_exec( instance_t* proc )
{ return _exec(proc,(inst_t*)proc->userPtr); }
template< typename inst_t >
rc_t std_report( instance_t* proc )
{ return _report(proc,(inst_t*)proc->userPtr); }
//------------------------------------------------------------------------------------------------------------------
//
// Template
@ -43,50 +76,46 @@ namespace cw
} inst_t;
rc_t create( instance_t* proc )
rc_t _create( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
inst_t* p = mem::allocZ<inst_t>();
proc->userPtr = p;
// Custom create code goes here
return rc;
}
rc_t destroy( instance_t* proc )
rc_t _destroy( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
inst_t* p = (inst_t*)proc->userPtr;
// Custom clean-up code goes here
mem::release(p);
return rc;
}
rc_t value( instance_t* proc, variable_t* var )
rc_t _value( instance_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
}
rc_t exec( instance_t* proc )
rc_t _exec( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
//inst_t* p = (inst_t*)proc->userPtr;
return rc;
}
rc_t _report( instance_t* proc, inst_t* p )
{ return kOkRC; }
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.exec = exec,
.report = nullptr
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
}
@ -972,7 +1001,7 @@ namespace cw
// print a minutes counter
inst->durSmpN += src_abuf->frameN;
if( inst->durSmpN % ((unsigned)src_abuf->srate*60) == 0 )
if( src_abuf->srate!=0 && inst->durSmpN % ((unsigned)src_abuf->srate*60) == 0 )
printf("audio file out: %5.1f min\n", inst->durSmpN/(src_abuf->srate*60));
}
@ -1720,15 +1749,29 @@ namespace cw
ctx->userPtr = inst;
// Register variables and get their current value
if((rc = var_register_and_get( ctx, kAnyChIdx, kChCntPid, "chCnt", kBaseSfxId, chCnt)) != kOkRC )
if((rc = var_register_and_get( ctx, kAnyChIdx,
kChCntPid, "chCnt", kBaseSfxId, chCnt,
kSratePId, "srate", kBaseSfxId, srate)) != kOkRC )
{
goto errLabel;
}
// Sample rate logic:
// The sample rate may be set directly, or sourced.
// If the srate is 0 then this indicates that the system sample rate should be used.
// if the sample rate is sourced and 0 it is a configuration error.
// if no sample rate was given then use the system sample rate.
if( srate == 0 )
srate = ctx->ctx->sample_rate;
// register each oscillator variable
for(unsigned i=0; i<chCnt; ++i)
{
unsigned ch_srate = 0;
if((rc = var_register_and_get( ctx, i,
kSratePId, "srate", kBaseSfxId, srate,
kSratePId, "srate", kBaseSfxId, ch_srate,
kFreqHzPId, "hz", kBaseSfxId, hz,
kPhasePId, "phase", kBaseSfxId, phase,
kDcPId, "dc", kBaseSfxId, dc,
@ -1737,8 +1780,15 @@ namespace cw
goto errLabel;
}
// if no srate was set on this channel then use the default sample rate
if( ch_srate == 0 )
if((rc = var_set(ctx,kSratePId,i,srate)) != kOkRC )
goto errLabel;
}
// create one output audio buffer
rc = var_register_and_set( ctx, "out", kBaseSfxId, kOutPId, kAnyChIdx, srate, chCnt, ctx->ctx->framesPerCycle );
rc = var_register_and_set( ctx, "out", kBaseSfxId,
kOutPId, kAnyChIdx, srate, chCnt, ctx->ctx->framesPerCycle );
inst->phaseA = mem::allocZ<double>( chCnt );
@ -3286,22 +3336,25 @@ namespace cw
kSrateRefPId,
kDurMsPId,
kTriggerPId,
kPresetPId,
kGainPId,
};
typedef struct
{
unsigned xfadeDurMs; // crossfade duration in milliseconds
instance_t* net_proc; // source 'poly' network
network_t net; // internal proxy network
unsigned xfadeDurMs; // crossfade duration in milliseconds
instance_t* net_proc; // source 'poly' network
network_t net; // internal proxy network
unsigned poly_ch_cnt; // set to 2 (one for 'cur' poly-ch., one for 'next' poly-ch.)
unsigned net_proc_cnt; // count of proc's in a single poly-channel (net_proc->proc_arrayN/poly_cnt)
unsigned net_proc_cnt; // count of proc's in a single poly-channel (net_proc->proc_arrayN/poly_cnt)
unsigned cur_poly_ch_idx; //
unsigned next_poly_ch_idx; //
float* target_gainA; // target_gainA[net_proc->poly_cnt]
float* cur_gainA; // cur_gainA[net_proc->poly_cnt]
double srate;
bool preset_delta_fl;
bool trigFl;
bool trigVal;
} inst_t;
void _trigger_xfade( inst_t* p )
@ -3333,16 +3386,17 @@ namespace cw
p->target_gainA[ p->cur_poly_ch_idx ] = 1;
// if the next channel is not already at 0 send it in that direction
p->target_gainA[ p->next_poly_ch_idx ] = 0;
p->target_gainA[ p->next_poly_ch_idx ] = 0;
//printf("xfad:%i %i : %i\n",p->cur_poly_ch_idx, p->next_poly_ch_idx,p->poly_ch_cnt);
}
rc_t create( instance_t* ctx )
{
rc_t rc = kOkRC;
const char* netLabel = nullptr;
const char* presetLabel = nullptr;
unsigned netLabelSfxId = kBaseSfxId;
bool trigFl = false;
variable_t* gainVar = nullptr;
@ -3353,15 +3407,15 @@ namespace cw
ctx->userPtr = p;
p->poly_ch_cnt = 2;
if((rc = var_register_and_get(ctx,kAnyChIdx,
kNetLabelPId, "net", kBaseSfxId, netLabel,
kNetLabelSfxPId, "netSfxId", kBaseSfxId, netLabelSfxId,
kSrateRefPId, "srateSrc", kBaseSfxId, srateSrc,
kDurMsPId, "durMs", kBaseSfxId, p->xfadeDurMs,
kTriggerPId, "trigger", kBaseSfxId, trigFl,
kGainPId, "gain", kBaseSfxId, dum_dbl)) != kOkRC )
kTriggerPId, "trigger", kBaseSfxId, p->trigVal,
kPresetPId, "preset", kBaseSfxId, presetLabel,
kGainPId, "gain", kBaseSfxId, dum_dbl)) != kOkRC )
{
goto errLabel;
}
@ -3378,7 +3432,9 @@ namespace cw
cwLogError(rc,"The xfade_ctl source network must have at least 3 poly channels. %i < 3",p->net_proc->internal_net->poly_cnt);
goto errLabel;
}
p->poly_ch_cnt = p->net_proc->internal_net->poly_cnt;
// create the gain output variables - one output for each poly-channel
for(unsigned i=1; i<p->net_proc->internal_net->poly_cnt; ++i)
@ -3396,11 +3452,11 @@ namespace cw
// create the proxy network
p->net.proc_arrayAllocN = p->net_proc_cnt * p->poly_ch_cnt;
p->net.proc_arrayN = p->net.proc_arrayAllocN;
p->net.proc_array = mem::allocZ<instance_t*>(p->net.proc_arrayAllocN);
p->target_gainA = mem::allocZ<float>(p->net_proc->internal_net->poly_cnt);
p->cur_gainA = mem::allocZ<float>(p->net_proc->internal_net->poly_cnt);
p->srate = srateSrc->srate;
p->net.proc_arrayN = p->net.proc_arrayAllocN;
p->net.proc_array = mem::allocZ<instance_t*>(p->net.proc_arrayAllocN);
p->target_gainA = mem::allocZ<float>(p->net_proc->internal_net->poly_cnt);
p->cur_gainA = mem::allocZ<float>(p->net_proc->internal_net->poly_cnt);
p->srate = srateSrc->srate;
// make the proxy network public - xfad_ctl now looks like the source network
// because it has the same proc instances
@ -3431,7 +3487,27 @@ namespace cw
}
rc_t value( instance_t* ctx, variable_t* var )
{ return kOkRC; }
{
rc_t rc = kOkRC;
inst_t* p = (inst_t*)ctx->userPtr;
if(var->vid == kTriggerPId )
{
bool v;
if((rc = var_get(var,v)) == kOkRC )
{
if( !p->trigFl )
p->trigFl = p->trigVal != v;
p->trigVal = v;
}
//printf("tr:%i %i %i\n",v,p->trigVal,p->trigFl);
}
return kOkRC;
}
// return sign of expression as a float
float _signum( float v ) { return (0.0f < v) - (v < 0.0f); }
@ -3440,14 +3516,12 @@ namespace cw
{
rc_t rc = kOkRC;
inst_t* p = (inst_t*)ctx->userPtr;
bool trigFl = false;
// check if a cross-fade has been triggered
if((rc = var_get(ctx,kTriggerPId,kAnyChIdx,trigFl)) == kOkRC )
if(p->trigFl )
{
p->trigFl = false;
_trigger_xfade(p);
var_set(ctx,kTriggerPId,kAnyChIdx,false);
}
// time in sample frames to complete a xfade
@ -3482,95 +3556,181 @@ namespace cw
//------------------------------------------------------------------------------------------------------------------
//
// poly_mixer
// poly_merge
//
namespace poly_mixer
namespace poly_merge
{
enum {
enum
{
kOutGainPId,
kOutPId,
kInBasePId,
};
typedef struct
{
unsigned inBaseVId;
unsigned gainBaseVId;
unsigned inAudioVarCnt;
unsigned gainVarCnt;
unsigned baseGainPId;
} inst_t;
rc_t create( instance_t* ctx )
rc_t _create( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
/*
const abuf_t* abuf0 = nullptr; //
const abuf_t* abuf1 = nullptr;
unsigned outChN = 0;
double dum;
rc_t rc = kOkRC;
unsigned inAudioChCnt = 0;
srate_t srate = 0;
unsigned audioFrameN = 0;
unsigned sfxIdAllocN = instance_var_count(proc);
unsigned sfxIdA[ sfxIdAllocN ];
// register the output gain variable
if((rc = var_register(proc,kAnyChIdx,kOutGainPId,"out_gain",kBaseSfxId)) != kOkRC )
goto errLabel;
// get the source audio buffer
if((rc = var_register_and_get(ctx, kAnyChIdx,
kIn0PId,"in0",kBaseSfxId,abuf0,
kIn1PId,"in1",kBaseSfxId,abuf1 )) != kOkRC )
// get the the sfx_id's of the input audio variables
if((rc = var_mult_sfx_id_array(proc, "in", sfxIdA, sfxIdAllocN, p->inAudioVarCnt )) != kOkRC )
goto errLabel;
// for each input audio variable
for(unsigned i=0; i<p->inAudioVarCnt; ++i)
{
abuf_t* abuf;
// register the input audio variable
if((rc = var_register_and_get(proc,kAnyChIdx,kInBasePId+i,"in",sfxIdA[i],abuf)) != kOkRC )
goto errLabel;
// the sample rate of off input audio signals must be the same
if( srate != 0 && abuf->srate != srate )
{
rc = cwLogError(kInvalidArgRC,"All signals on a poly merge must have the same sample rate.");
goto errLabel;
}
srate = abuf->srate;
// the count of frames in all audio signals must be the same
if( audioFrameN != 0 && abuf->frameN != audioFrameN )
{
rc = cwLogError(kInvalidArgRC,"All signals on a poly merge must have the same frame count.");
goto errLabel;
}
audioFrameN = abuf->frameN;
inAudioChCnt += abuf->chN;
}
// Get the sfx-id's of the input gain variables
if((rc = var_mult_sfx_id_array(proc, "gain", sfxIdA, sfxIdAllocN, p->gainVarCnt )) != kOkRC )
goto errLabel;
// There must be one gain variable for each audio input or exactly one gain variable
if( p->gainVarCnt != p->inAudioVarCnt && p->gainVarCnt != 1 )
{
rc = cwLogError(kInvalidArgRC,"The count of gain variables must be the same as the count of audio variables are there must be one gain variable.");
goto errLabel;
}
assert( abuf0->frameN == abuf1->frameN );
// set the baseInGainPId
p->baseGainPId = kInBasePId + p->inAudioVarCnt;
outChN = std::max(abuf0->chN, abuf1->chN);
// register each of the input gain variables
for(unsigned i=0; i<p->gainVarCnt; ++i)
{
coeff_t dum;
if((rc = var_register(proc,kAnyChIdx,p->baseGainPId + i,"gain",sfxIdA[i])) != kOkRC )
goto errLabel;
}
// register the gain
var_register_and_get( ctx, kAnyChIdx, kGain0PId, "gain0", kBaseSfxId, dum );
var_register_and_get( ctx, kAnyChIdx, kGain1PId, "gain1", kBaseSfxId, dum );
rc = var_register_and_set( proc, "out", kBaseSfxId, kOutPId, kAnyChIdx, srate, inAudioChCnt, audioFrameN );
// create the output audio buffer
rc = var_register_and_set( ctx, "out", kBaseSfxId, kOutPId, kAnyChIdx, abuf0->srate, outChN, abuf0->frameN );
*/
errLabel:
return rc;
}
rc_t destroy( instance_t* ctx )
{ return kOkRC; }
rc_t _destroy( instance_t* proc, inst_t* p )
{
return kOkRC;
}
rc_t value( instance_t* ctx, variable_t* var )
{ return kOkRC; }
rc_t _value( instance_t* proc, inst_t* p, variable_t* var )
{
return kOkRC;
}
unsigned _merge_in_one_audio_var( instance_t* proc, const abuf_t* ibuf, abuf_t* obuf, unsigned outChIdx, coeff_t gain )
{
// for each channel
for(unsigned i=0; i<ibuf->chN && outChIdx<obuf->chN; ++i)
{
sample_t* isig = ibuf->buf + i * ibuf->frameN;
sample_t* osig = obuf->buf + outChIdx * obuf->frameN;
// apply the gain
for(unsigned j=0; j<ibuf->frameN; ++j)
osig[j] = gain * isig[j];
outChIdx += 1;
}
return outChIdx;
}
rc_t exec( instance_t* ctx )
rc_t _exec( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
/*
abuf_t* obuf = nullptr;
//const abuf_t* ibuf0 = nullptr;
//const abuf_t* ibuf1 = nullptr;
unsigned oChIdx = 0;
coeff_t igain = 1;
coeff_t ogain = 1;
if((rc = var_get(ctx,kOutPId, kAnyChIdx, obuf)) != kOkRC )
// get the output audio buffer
if((rc = var_get(proc,kOutPId, kAnyChIdx, obuf)) != kOkRC )
goto errLabel;
//if((rc = var_get(ctx,kIn0PId, kAnyChIdx, ibuf0 )) != kOkRC )
// goto errLabel;
//if((rc = var_get(ctx,kIn1PId, kAnyChIdx, ibuf1 )) != kOkRC )
// goto errLabel;
// get the output audio gain
if((rc = var_get(proc,kOutGainPId, kAnyChIdx, ogain)) != kOkRC )
goto errLabel;
// for each audio input variable
for(unsigned i=0; i<p->inAudioVarCnt; ++i)
{
const abuf_t* ibuf = nullptr;
// get the input audio buffer
if((rc = var_get(proc,kInBasePId+i, kAnyChIdx, ibuf )) != kOkRC )
goto errLabel;
// get the input gain
if( i < p->gainVarCnt )
var_get(proc,p->baseGainPId+i,kAnyChIdx,igain);
// merge the input audio signal into the output audio buffer
oChIdx = _merge_in_one_audio_var( proc, ibuf, obuf, oChIdx, igain * ogain );
}
vop::zero(obuf->buf, obuf->frameN*obuf->chN );
_mix( ctx, kIn0PId, kGain0PId, obuf );
_mix( ctx, kIn1PId, kGain1PId, obuf );
*/
errLabel:
return rc;
}
rc_t _report( instance_t* proc, inst_t* p )
{ return kOkRC; }
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.exec = exec,
.report = nullptr
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
}
@ -3878,6 +4038,9 @@ namespace cw
goto errLabel;
}
if( srate == 0 )
var_set(proc,kSratePId,kAnyChIdx,proc->ctx->sample_rate);
if((rc = var_register_and_set(proc,kAnyChIdx,
kOutPId, "out", kBaseSfxId,false)) != kOkRC )
{
@ -4745,12 +4908,14 @@ namespace cw
};
}
//------------------------------------------------------------------------------------------------------------------
//
// preset
//
namespace preset
{
enum { kInPId };
enum { kPresetLabelCharN=255 };
@ -4758,101 +4923,113 @@ namespace cw
typedef struct
{
char preset_label[ kPresetLabelCharN+1];
bool delta_fl;
} inst_t;
rc_t _set_preset( instance_t* proc, inst_t* p, const char* preset_label )
rc_t _set_preset( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
unsigned presetLabelCharN = 0;
const char* preset_label = nullptr;
if( preset_label == nullptr )
// get the preset label
if((rc = var_get(proc, kInPId, kAnyChIdx, preset_label)) != kOkRC )
{
if((rc = var_get(proc, kInPId, kAnyChIdx, preset_label)) != kOkRC )
{
rc = cwLogError(rc,"The variable 'in read failed.");
goto errLabel;
}
rc = cwLogError(rc,"The variable 'in read failed.");
goto errLabel;
}
if( preset_label == nullptr )
// at this point a valid preset-label must exist
if( preset_label == nullptr || (presetLabelCharN=textLength(preset_label))==0 )
{
rc = cwLogError(kInvalidArgRC,"Preset application failed due to blank preset label.");
goto errLabel;
}
// if the preset-label has not changed since the last preset application - then there is nothing to do
if( textIsEqual(preset_label,p->preset_label) )
goto errLabel;
// verify the preset-label is not too long
if( presetLabelCharN > kPresetLabelCharN )
{
rc = cwLogError(kBufTooSmallRC,"The preset label '%s' is to long.",cwStringNullGuard(preset_label));
goto errLabel;
}
cwRuntimeCheck(proc->net != nullptr );
// apply the preset
if((rc = network_apply_preset(*proc->net, preset_label)) != kOkRC )
{
rc = cwLogError(rc,"Appy preset '%s' failed.",cwStringNullGuard(preset_label));
goto errLabel;
}
if( textLength(preset_label) >= kPresetLabelCharN )
strncpy(p->preset_label,preset_label,kPresetLabelCharN);
else
{
rc = cwLogError(kBufTooSmallRC,"The preset label '%s' is to long.",cwStringNullGuard(preset_label));
goto errLabel;
}
// store the applied preset-label
textCopy(p->preset_label,kPresetLabelCharN,preset_label,presetLabelCharN);
errLabel:
return rc;
}
rc_t create( instance_t* proc )
rc_t _create( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
inst_t* p = mem::allocZ<inst_t>();
proc->userPtr = p;
// Custom create code goes here
const char* label = nullptr;
p->preset_label[0] = 0;
p->delta_fl = true;
if((rc = var_register_and_get(proc,kAnyChIdx,kInPId,"in",kBaseSfxId,label)) != kOkRC )
goto errLabel;
// we can't apply a preset here because the network is not yet constructed
errLabel:
return rc;
}
rc_t destroy( instance_t* proc )
rc_t _destroy( instance_t* proc, inst_t* p )
{ return kOkRC; }
rc_t _value( instance_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
inst_t* p = (inst_t*)proc->userPtr;
// Custom clean-up code goes here
mem::release(p);
if( var->vid == kInPId )
p->delta_fl = true;
return rc;
}
rc_t value( instance_t* proc, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
}
rc_t exec( instance_t* proc )
rc_t _exec( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
//inst_t* p = (inst_t*)proc->userPtr;
if( p->delta_fl )
rc = _set_preset(proc,p);
return rc;
}
rc_t _report( instance_t* proc, inst_t* p )
{ return kOkRC; }
class_members_t members = {
.create = create,
.destroy = destroy,
.value = value,
.exec = exec,
.report = nullptr
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
}
} // flow
} // cw

View File

@ -26,7 +26,7 @@ namespace cw
namespace audio_meter { extern class_members_t members; }
namespace audio_marker { extern class_members_t members; }
namespace xfade_ctl { extern class_members_t members; }
namespace poly_mixer { extern class_members_t members; }
namespace poly_merge { extern class_members_t members; }
namespace sample_hold { extern class_members_t members; }
namespace number { extern class_members_t members; }
namespace timer { extern class_members_t members; }

View File

@ -46,7 +46,7 @@ namespace cw
{ kFloatTFl, "coeff"},
{ kDoubleTFl, "ftime" },
{ kUIntTFl | kIntTFl | kFloatTFl | kDoubleTFl, "numeric" },
{ kBoolTFl | kUIntTFl | kIntTFl | kFloatTFl | kDoubleTFl, "numeric" },
{ kRuntimeTFl, "runtime" },
@ -473,7 +473,6 @@ namespace cw
val->u.s = mem::duplStr(v);
val->tflag = kStringTFl;
break;
default:
rc = cwLogError(kTypeMismatchRC,"A string could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag);
}
@ -662,30 +661,8 @@ namespace cw
return _val_get(var->value,valRef);
}
rc_t _var_find_to_set( instance_t* inst, unsigned vid, unsigned chIdx, unsigned typeFl, variable_t*& varRef )
{
rc_t rc = kOkRC;
varRef = nullptr;
//
if((rc = var_find(inst,vid,chIdx,varRef)) == kOkRC )
{
// validate the type of the variable against the description
/*
if( !cwIsFlag(varRef->varDesc->type,typeFl ) )
rc = cwLogError(kTypeMismatchRC,"Type mismatch. Instance:%s:%i variable:%s:%i with type %s (0x%x) does not match requested type: %s (0x%x).",
varRef->inst->label,varRef->inst->label_sfx_id,
varRef->label,
varRef->label_sfx_id,_typeFlagToLabel(varRef->varDesc->type),varRef->varDesc->type,
_typeFlagToLabel(typeFl),typeFl);
*/
}
return rc;
}
// Variable lookup: Exact match on vid and chIdx
rc_t _var_find_on_vid_and_ch( instance_t* inst, unsigned vid, unsigned chIdx, variable_t*& varRef )
@ -737,6 +714,9 @@ namespace cw
return kOkRC;
}
void _var_print_addr( const char* title, const variable_t* v )
{ printf("%s:%s:%i.%s:%i ",title,v->inst->label,v->inst->label_sfx_id,v->label,v->label_sfx_id); }
void _var_print( const variable_t* var )
{
const char* conn_label = is_connected_to_source_proc(var) ? "extern" : " ";
@ -751,6 +731,12 @@ namespace cw
if( var->src_var != nullptr )
printf(" src:%s:%i.%s:%i",var->src_var->inst->label,var->src_var->inst->label_sfx_id,var->src_var->label,var->src_var->label_sfx_id);
if( var->dst_head != nullptr )
{
for(variable_t* v = var->dst_head; v!=nullptr; v=v->dst_link)
printf(" dst:%s:%i.%s:%i",v->inst->label,v->inst->label_sfx_id,v->label,v->label_sfx_id);
}
printf("\n");
}
@ -766,7 +752,7 @@ namespace cw
// so that it points to the correct value.
con_var->value = var->value;
cwLogMod("%s:%i %s:%i -> %s:%i %s:%i\n",
cwLogMod("%s:%i %s:%i -> %s:%i %s:%i",
var->inst->label,var->inst->label_sfx_id,
var->label,var->label_sfx_id,
con_var->inst->label,con_var->inst->label_sfx_id,
@ -782,23 +768,28 @@ namespace cw
// 'typeFlag' is the type (tflag) of 'val'.
// 'argTypeFlag' is the type (tflag) of 'val'.
template< typename T >
rc_t _var_set_template( variable_t* var, unsigned argTypeFlag, T val )
{
rc_t rc;
rc_t rc = kOkRC;
// it is not legal to set the value of a variable that is connected to a 'source' variable.
if( var->src_var != nullptr )
return cwLogError(kInvalidStateRC, "The variable '%s:%i %s:%i' cannot be set because it is connected to a source variable.", var->inst->label,var->inst->label_sfx_id, var->label, var->label_sfx_id);
// var->type is the allowable type for this var's value.
// It may be set to kInvalidTFl if the type has not yet been determined.
unsigned value_type_flag = var->type;
// Pick the slot in local_value[] that we will use to try out this new value.
unsigned next_local_value_idx = (var->local_value_idx + 1) % kLocalValueN;
// store the pointer to the current value of this variable
value_t* original_value = var->value;
unsigned original_value_idx = var->local_value_idx;
// verify that this is a legal assignment
if((rc = _validate_var_assignment( var, argTypeFlag )) != kOkRC )
goto errLabel;
// release the previous value in the next slot
_value_release(&var->local_value[next_local_value_idx]);
@ -808,9 +799,13 @@ namespace cw
{
// if the var desc is a single type then use that ....
if( math::isPowerOfTwo(var->varDesc->type) )
{
value_type_flag = var->varDesc->type;
}
else // ... Otherwise select a type from the one of the possible flags given by the var desc
{
value_type_flag = var->varDesc->type & argTypeFlag;
}
// if the incoming type is not in the set of allowable types then it is an error
if( value_type_flag == 0 )
@ -824,7 +819,7 @@ namespace cw
// set the type of the LHS to force the incoming value to be coerced to this type
var->local_value[ next_local_value_idx ].tflag = value_type_flag;
// set the new local value
// set the new local value in var->local_value[next_local_value_idx]
if((rc = _val_set(var->local_value + next_local_value_idx, val )) != kOkRC )
{
rc = cwLogError(rc,"Value set failed on '%s:%i %s:%i",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id);
@ -843,7 +838,7 @@ namespace cw
// call because calls' to 'proc.value()' will see the instance in a incomplete state)
// Note 2: If this call returns an error then the value assignment is cancelled
// and the value does not change.
var_call_custom_value_func( var );
rc = var_call_custom_value_func( var );
}
//printf("%p set: %s:%s 0x%x\n",var->value, var->inst->label,var->label,var->value->tflag);
@ -875,8 +870,9 @@ namespace cw
// if this variable is fed from the output of an external proc - then it's local value cannot be set
if(is_connected_to_source_proc(var) )
return kOkRC;
{
return cwLogError(kInvalidStateRC,"Cannot set the value on a connected variables.");
}
// if this assignment targets a specific channel ...
if( var->chIdx != kAnyChIdx )
@ -936,137 +932,6 @@ namespace cw
return rc;
}
rc_t _set_var_value_from_cfg( variable_t* var, const object_t* value )
{
rc_t rc = kOkRC;
// Determine the flow variable type of cfg. argument 'value'.
unsigned value_flag = 0;
switch( value->type->id )
{
case kCharTId:
case kUInt8TId:
case kUInt16TId:
case kUInt32TId:
value_flag = kUIntTFl;
break;
case kInt8TId:
case kInt16TId:
case kInt32TId:
value_flag = kIntTFl;
break;
case kInt64TId:
case kUInt64TId:
rc = cwLogError(kInvalidArgRC,"The flow system does not currently implement 64bit integers.");
goto errLabel;
break;
case kFloatTId:
value_flag = kFloatTFl;
break;
case kDoubleTId:
value_flag = kDoubleTFl;
break;
case kBoolTId:
value_flag = kBoolTFl;
break;
case kStringTId:
case kCStringTId:
value_flag = kStringTFl;
break;
default:
value_flag = kCfgTFl;
}
/*
if( !cwIsFlag(var->varDesc->type & kTypeMask, value_flag) )
{
rc = cwLogError(kTypeMismatchRC,"The var desc class type 0x%x does not permit the var to be instantiated with the type %s (0x%x).",var->varDesc->type,_typeFlagToLabel(value_flag),value_flag);
goto errLabel;
}
*/
switch( value_flag )
{
case kBoolTFl:
{
bool v;
// assign the value of 'value' to to 'v' (do type conversion if necessary)
if((rc = value->value(v)) == kOkRC )
// set the value of 'var' where 'v' is the new value and 'value_flag' is the type of 'v'.
rc = _var_set_driver( var, value_flag, v );
}
break;
case kUIntTFl:
{
unsigned v;
if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, v );
}
break;
case kIntTFl:
{
int v;
if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, v );
}
break;
case kFloatTFl:
{
float v;
if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, v );
}
break;
case kDoubleTFl:
{
double v;
if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, v );
}
break;
case kStringTFl:
{
const char* v;
if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, v );
}
break;
case kCfgTFl:
{
//const object_t* v;
//if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, value );
}
break;
default:
rc = cwLogError(kOpFailRC,"The variable type 0x%x cannot yet be set via a cfg.", var->varDesc->type );
goto errLabel;
}
errLabel:
if( rc != kOkRC )
rc = cwLogError(kSyntaxErrorRC,"The %s:%i.%s:%i could not extract a type:%s from a configuration value.",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,_typeFlagToLabel(var->varDesc->type & kTypeMask));
return rc;
}
rc_t _var_map_id_to_index( instance_t* inst, unsigned vid, unsigned chIdx, unsigned& idxRef )
{
@ -1130,22 +995,6 @@ namespace cw
}
/*
void _var_set_value_to_typed_null( variable_t* var, unsigned type_flag )
{
for(unsigned i=0; i<kLocalValueN; ++i)
{
assert( var->local_value[i].tflag == kInvalidTFl );
// set the var-value to a typed null value - this will force later settings to be coerced to this type
set_null( var->local_value[i], type_flag );
}
var->value = var->local_value;
}
*/
rc_t _var_set_type( variable_t* var, unsigned type_flag )
{
rc_t rc = kOkRC;
@ -1155,7 +1004,8 @@ namespace cw
rc = cwLogError(kOpFailRC,"It is invalid to change the type of a statically (non-runtime) type variable.");
goto errLabel;
}
// Duplicate the varDesc with the 'type' field set to type_flag
if( var->localVarDesc == nullptr )
{
var->localVarDesc = mem::allocZ<var_desc_t>();
@ -1165,8 +1015,6 @@ namespace cw
var->localVarDesc->type = type_flag;
var->varDesc = var->localVarDesc;
//_var_set_value_to_typed_null(var,type_flag);
errLabel:
return rc;
@ -1215,10 +1063,10 @@ namespace cw
// if no value was given then set the value to the value given in the class
if( value_cfg == nullptr )
value_cfg = var->varDesc->val_cfg;
// if value_cfg is valid set the variable value
if( value_cfg != nullptr && cwIsNotFlag(vd->type,kRuntimeTFl))
if((rc = _set_var_value_from_cfg( var, value_cfg )) != kOkRC )
if((rc = var_set_from_preset( var, value_cfg )) != kOkRC )
goto errLabel;
var->var_link = inst->varL;
@ -1244,28 +1092,9 @@ namespace cw
return rc;
}
rc_t _preset_set_var_value( instance_t* inst, const char* var_label, unsigned sfx_id, unsigned chIdx, const object_t* value )
{
rc_t rc = kOkRC;
variable_t* var = nullptr;
// get the variable
if((rc = var_find( inst, var_label, sfx_id, chIdx, var )) != kOkRC )
goto errLabel;
rc = _set_var_value_from_cfg( var, value );
errLabel:
if( rc != kOkRC )
rc = cwLogError(rc,"The value of instance:%s:%i variable:%s:%i could not be set via a preset.", inst->label, inst->label_sfx_id, var_label, sfx_id );
return rc;
}
}
}
cw::flow::abuf_t* cw::flow::abuf_create( srate_t srate, unsigned chN, unsigned frameN )
{
abuf_t* a = mem::allocZ<abuf_t>();
@ -1455,6 +1284,7 @@ cw::flow::class_desc_t* cw::flow::class_desc_find( flow_t* p, const char* label
return nullptr;
}
cw::flow::var_desc_t* cw::flow::var_desc_find( class_desc_t* cd, const char* label )
{
var_desc_t* vd = cd->varDescL;
@ -1472,6 +1302,15 @@ cw::rc_t cw::flow::var_desc_find( class_desc_t* cd, const char* label, var_desc_
return kOkRC;
}
const cw::flow::preset_t* cw::flow::class_preset_find( class_desc_t* cd, const char* preset_label )
{
const preset_t* pr;
for(pr=cd->presetL; pr!=nullptr; pr=pr->link)
if( textCompare(pr->label,preset_label) == 0 )
return pr;
return nullptr;
}
void cw::flow::class_dict_print( flow_t* p )
{
@ -1530,16 +1369,19 @@ cw::rc_t cw::flow::instance_validate( instance_t* inst )
continue;
}
// the assigned value must have exactly one type
if(!math::isPowerOfTwo( var->value->tflag ) )
{
rc = cwLogError(kInvalidStateRC,"The var '%s:%i' has the invalid type flag:0x%x",var->label,var->label_sfx_id,var->value->tflag);
continue;
}
if( !(var->varDesc->type & var->value->tflag) )
// if var is using a local value (not connected to a source variable) then the type of the value must be valid with the variable class
if( !is_connected_to_source_proc(var) && !(var->varDesc->type & var->value->tflag) )
{
rc = cwLogError(kInvalidStateRC, "The value type flag '%s' (0x%x) of the var '%s:%i' is not found in the variable class type flags: '%s' (0x%x)",
rc = cwLogError(kInvalidStateRC, "The value type flag '%s' (0x%x) of '%s:%i-%s:%i' is not found in the variable class type flags: '%s' (0x%x)",
_typeFlagToLabel(var->value->tflag),var->value->tflag,
var->inst->label,var->inst->label_sfx_id,
var->label,var->label_sfx_id,
_typeFlagToLabel(var->varDesc->type),var->varDesc->type);
continue;
@ -1651,12 +1493,14 @@ cw::rc_t cw::flow::var_channelize( instance_t* inst, const char* var_label, uns
var = _var_find_on_label_and_ch( inst, var_label, sfx_id, chIdx );
// 'src' variables cannot be channelized
/*
if( cwIsFlag(base_var->varDesc->flags,kSrcVarFl) )
{
rc = cwLogError(rc,"'src' variables cannot be channelized.");
goto errLabel;
}
*/
// if the requested var was not found then create a new variable with the requested channel index
if( var == nullptr && chIdx != kAnyChIdx )
{
@ -1667,12 +1511,46 @@ cw::rc_t cw::flow::var_channelize( instance_t* inst, const char* var_label, uns
// if no value was set then set the value from the 'any' channel
if( value_cfg == nullptr )
{
// Set the value of the new variable to the value of the 'any' channel
_value_duplicate( var->local_value[ var->local_value_idx], base_var->local_value[ base_var->local_value_idx ] );
// if the base-var is connected to a source ...
if( is_connected_to_source_proc(base_var) )
{
// ... then connect the new var to a source also
// Attempt to find a matching channel on the source
variable_t* src_ch_var = base_var->src_var;
variable_t* last_src_ch_var = base_var->src_var;
unsigned src_ch_cnt = 0;
for(; src_ch_var!=nullptr; src_ch_var=src_ch_var->ch_link)
{
last_src_ch_var = src_ch_var;
if( src_ch_var->chIdx == var->chIdx )
break;
// If the 'any' channel value was set to point to it's local value then do same with this value
if( base_var->local_value + base_var->local_value_idx == base_var->value )
var->value = var->local_value + var->local_value_idx;
src_ch_cnt += 1;
}
// if there is more than one channel available and the src and dst var's do not have matching ch indexes
// then there is a possibility that this is an unexpected connection between different channels.
if( src_ch_var == nullptr && src_ch_cnt>1 && last_src_ch_var->chIdx != var->chIdx )
cwLogWarning("A connection is being made where channel src and dst. channels don't match and more than one src channel is available.");
// if no matching channel is found connect to the last valid source channel
// (Connecting to the last valid source is better than connecting to base_var->src_var
// because if a var has more than a base var it is unlikely to update the base_var.)
var_connect( last_src_ch_var, var );
}
else
{
// Set the value of the new variable to the value of the 'any' channel
_value_duplicate( var->local_value[ var->local_value_idx], base_var->local_value[ base_var->local_value_idx ] );
// If the 'any' channel value was set to point to it's local value then do same with this value
if( base_var->local_value + base_var->local_value_idx == base_var->value )
var->value = var->local_value + var->local_value_idx;
}
}
}
@ -1683,7 +1561,7 @@ cw::rc_t cw::flow::var_channelize( instance_t* inst, const char* var_label, uns
if( value_cfg != nullptr )
{
//cwLogInfo("%s ch:%i",var_label,chIdx);
rc = _set_var_value_from_cfg( var, value_cfg );
rc = var_set_from_preset( var, value_cfg );
}
else
{
@ -1708,9 +1586,18 @@ cw::rc_t cw::flow::var_call_custom_value_func( variable_t* var )
goto errLabel;
if( var->flags & kLogVarFl )
{
{
printf("%10s:%5i", var->inst->label,var->inst->label_sfx_id);
_var_print(var);
if( var->chIdx == kAnyChIdx )
_var_print(var);
else
{
printf("\n");
for(variable_t* ch_var = var; ch_var!=nullptr; ch_var=ch_var->ch_link)
_var_print(ch_var);
}
}
errLabel:
@ -1761,24 +1648,6 @@ cw::rc_t cw::flow::var_clr_flags( instance_t* inst, unsigned chIdx, const char*
errLabel:
return rc;
}
/*
cw::rc_t cw::flow::var_set_type( instance_t* inst, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned type_flag )
{
rc_t rc = kOkRC;
variable_t* var = nullptr;
if((rc = _var_find_on_label_and_ch(inst,var_label,sfx_id,chIdx,var)) != kOkRC )
goto errLabel;
rc = _var_set_type(var,type_flag);
errLabel:
if( rc != kOkRC )
rc = cwLogError(rc,"Type set failed on the variable:'%s:%i",cwStringNullGuard(var_label),sfx_id);
return rc;
}
*/
bool cw::flow::var_exists( instance_t* inst, const char* label, unsigned sfx_id, unsigned chIdx )
{ return _var_find_on_label_and_ch(inst,label,sfx_id,chIdx) != nullptr; }
@ -1846,7 +1715,7 @@ cw::rc_t cw::flow::var_find( instance_t* inst, unsigned vid, unsigned chIdx, var
}
}
// if we get here var must be non-null
// if we get here var must be non-null - (was the var registered?)
assert( var != nullptr && rc == kOkRC );
varRef = var;
@ -1927,7 +1796,7 @@ cw::rc_t cw::flow::var_register( instance_t* inst, const char* var_label, unsign
{
// if a value was given - then update the value
if( value_cfg != nullptr )
if((rc = _set_var_value_from_cfg( var, value_cfg )) != kOkRC )
if((rc = var_set_from_preset( var, value_cfg )) != kOkRC )
goto errLabel;
}
else // an exact match was not found - channelize the variable
@ -1968,6 +1837,37 @@ bool cw::flow::is_connected_to_source_proc( const variable_t* var )
bool cw::flow::is_a_source_var( const variable_t* var )
{ return var->dst_head != nullptr; }
void cw::flow::var_connect( variable_t* src_var, variable_t* in_var )
{
assert( in_var->dst_link == nullptr );
// connect in_var into src_var's outgoing var chain
if( src_var->dst_head == nullptr )
src_var->dst_head = in_var;
else
src_var->dst_tail->dst_link = in_var;
src_var->dst_tail = in_var;
in_var->value = src_var->value;
in_var->src_var = src_var;
//printf("Connect: ");
//_var_print_addr("src",src_var);
//_var_print_addr("dst",in_var);
//_var_print_addr("HEAD",src_var->dst_head);
//if( src_var->dst_head->dst_link != nullptr )
// _var_print_addr("LINK",src_var->dst_head->dst_link);
//_var_print_addr("TAIL",src_var->dst_tail);
//printf("\n");
}
cw::rc_t cw::flow::var_mult_sfx_id_array( instance_t* inst, const char* var_label, unsigned* idA, unsigned idAllocN, unsigned& idN_ref )
{
rc_t rc = kOkRC;
@ -2104,6 +2004,132 @@ cw::rc_t cw::flow::var_get( variable_t* var, mbuf_t*& valRef )
cw::rc_t cw::flow::var_get( const variable_t* var, const object_t*& valRef )
{ return _val_get_driver(var,valRef); }
cw::rc_t cw::flow::var_set_from_preset( variable_t* var, const object_t* value )
{
rc_t rc = kOkRC;
//
// Determine the flow variable type of cfg. argument 'value'.
//
unsigned value_flag = 0;
switch( value->type->id )
{
case kCharTId:
case kUInt8TId:
case kUInt16TId:
case kUInt32TId:
value_flag = kUIntTFl;
break;
case kInt8TId:
case kInt16TId:
case kInt32TId:
value_flag = kIntTFl;
break;
case kInt64TId:
case kUInt64TId:
rc = cwLogError(kInvalidArgRC,"The flow system does not currently implement 64bit integers.");
goto errLabel;
break;
case kFloatTId:
value_flag = kFloatTFl;
break;
case kDoubleTId:
value_flag = kDoubleTFl;
break;
case kBoolTId:
value_flag = kBoolTFl;
break;
case kStringTId:
case kCStringTId:
value_flag = kStringTFl;
break;
default:
value_flag = kCfgTFl;
}
//
// Convert the cfg value to a c++ typed value and then call _var_set_driver() with the c++ value.
//
switch( value_flag )
{
case kBoolTFl:
{
bool v;
// assign the value of 'value' to to 'v' (do type conversion if necessary)
if((rc = value->value(v)) == kOkRC )
// set the value of 'var' where 'v' is the new value and 'value_flag' is the type of 'v'.
rc = _var_set_driver( var, value_flag, v );
}
break;
case kUIntTFl:
{
unsigned v;
if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, v );
}
break;
case kIntTFl:
{
int v;
if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, v );
}
break;
case kFloatTFl:
{
float v;
if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, v );
}
break;
case kDoubleTFl:
{
double v;
if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, v );
}
break;
case kStringTFl:
{
const char* v;
if((rc = value->value(v)) == kOkRC )
rc = _var_set_driver( var, value_flag, v );
}
break;
case kCfgTFl:
{
rc = _var_set_driver( var, value_flag, value );
}
break;
default:
rc = cwLogError(kOpFailRC,"The variable type 0x%x cannot yet be set via a cfg.", var->varDesc->type );
goto errLabel;
}
errLabel:
if( rc != kOkRC )
rc = cwLogError(kSyntaxErrorRC,"The %s:%i.%s:%i could not extract a type:%s from a configuration value.",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,_typeFlagToLabel(var->varDesc->type & kTypeMask));
return rc;
}
cw::rc_t cw::flow::var_set( variable_t* var, const value_t* val )
{
rc_t rc = kOkRC;
@ -2144,7 +2170,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, cons
rc_t rc = kOkRC;
variable_t* var = nullptr;
if((rc = _var_find_to_set(inst, vid, chIdx, val->tflag, var )) == kOkRC )
if((rc = var_find(inst, vid, chIdx, var )) == kOkRC )
rc = var_set(var,val);
return rc;
@ -2155,7 +2181,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, bool
rc_t rc = kOkRC;
variable_t* var = nullptr;
if((rc = _var_find_to_set(inst, vid, chIdx, kBoolTFl, var )) == kOkRC )
if((rc = var_find(inst, vid, chIdx, var )) == kOkRC )
rc = _var_set_driver( var, kBoolTFl, val );
return rc;
@ -2166,7 +2192,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, uint
rc_t rc = kOkRC;
variable_t* var = nullptr;
if((rc = _var_find_to_set(inst, vid, chIdx, kUIntTFl, var )) == kOkRC )
if((rc = var_find(inst, vid, chIdx, var )) == kOkRC )
rc = _var_set_driver( var, kUIntTFl, val );
return rc;
@ -2177,7 +2203,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, int_
rc_t rc = kOkRC;
variable_t* var = nullptr;
if((rc = _var_find_to_set(inst, vid, chIdx, kIntTFl, var )) == kOkRC )
if((rc = var_find(inst, vid, chIdx, var )) == kOkRC )
rc = _var_set_driver( var, kIntTFl, val );
return rc;
@ -2188,7 +2214,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, floa
rc_t rc = kOkRC;
variable_t* var = nullptr;
if((rc = _var_find_to_set(inst, vid, chIdx, kFloatTFl, var )) == kOkRC )
if((rc = var_find(inst, vid, chIdx, var )) == kOkRC )
rc = _var_set_driver( var, kFloatTFl, val );
return rc;
@ -2199,7 +2225,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, doub
rc_t rc = kOkRC;
variable_t* var = nullptr;
if((rc = _var_find_to_set(inst, vid, chIdx, kDoubleTFl, var )) == kOkRC )
if((rc = var_find(inst, vid, chIdx, var )) == kOkRC )
rc = _var_set_driver( var, kDoubleTFl, val );
return rc;
@ -2210,7 +2236,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, cons
rc_t rc = kOkRC;
variable_t* var = nullptr;
if((rc = _var_find_to_set(inst, vid, chIdx, kStringTFl, var )) == kOkRC )
if((rc = var_find(inst, vid, chIdx, var )) == kOkRC )
rc = _var_set_driver( var, kStringTFl, val );
return rc;
@ -2221,20 +2247,11 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, cons
rc_t rc = kOkRC;
variable_t* var = nullptr;
if((rc = _var_find_to_set(inst, vid, chIdx, kCfgTFl, var )) == kOkRC )
if((rc = var_find(inst, vid, chIdx, var )) == kOkRC )
rc = _var_set_driver( var, kCfgTFl, val );
return rc;
}
const cw::flow::preset_t* cw::flow::class_preset_find( class_desc_t* cd, const char* preset_label )
{
const preset_t* pr;
for(pr=cd->presetL; pr!=nullptr; pr=pr->link)
if( textCompare(pr->label,preset_label) == 0 )
return pr;
return nullptr;
}

View File

@ -18,7 +18,9 @@ namespace cw
kBaseSfxId = 0,
kFbufVectN = 3, // count of signal vectors in fbuf (mag,phs,hz)
kAnyChIdx = kInvalidIdx,
kLocalValueN = 2
kLocalValueN = 2,
kDefaultFramesPerCycle=64,
kDefaultSampleRate=48000
};
typedef struct abuf_str
@ -78,8 +80,9 @@ namespace cw
kTypeMask = 0x0000ffff,
kRuntimeTFl = 0x80000000
kRuntimeTFl = 0x80000000,
kNumericFlags = kBoolMtxTFl | kUIntMtxTFl | kIntMtxTFl | kFloatMtxTFl | kDoubleMtxTFl
};
typedef struct mtx_str
@ -111,7 +114,7 @@ namespace cw
char* s;
const object_t* cfg;
void* p;
void* p;
} u;
@ -119,10 +122,6 @@ namespace cw
} value_t;
inline void set_null( value_t& v, unsigned tflag ) { v.tflag=tflag; v.u.p=nullptr; }
inline bool is_numeric( const value_t* v ) { return cwIsFlag(v->tflag,kBoolTFl|kUIntTFl|kIntTFl|kFloatTFl|kDoubleTFl); }
inline bool is_matrix( const value_t* v ) { return cwIsFlag(v->tflag,kBoolMtxTFl|kUIntMtxTFl|kIntMtxTFl|kFloatMtxTFl|kDoubleMtxTFl); }
struct instance_str;
struct variable_str;
@ -187,7 +186,8 @@ namespace cw
struct instance_str* inst; // pointer to this variables instance
char* label; // this variables label
unsigned label_sfx_id; // the label suffix id of this variable or kInvalidIdx if this has no suffix
unsigned label_sfx_id; // the label suffix id of this variable or kBaseSfxId if this has no suffix
unsigned vid; // this variables numeric id ( cat(vid,chIdx) forms a unique variable identifier on this 'inst'
unsigned chIdx; // channel index
unsigned flags; // kLogVarFl
@ -262,6 +262,7 @@ namespace cw
unsigned framesPerCycle; // sample frames per cycle (64)
srate_t sample_rate; // default sample rate (48000.0)
bool multiPriPresetProbFl; // If set then probability is used to choose presets on multi-preset application
bool multiSecPresetProbFl; //
bool multiPresetInterpFl; // If set then interpolation is applied between two selectedd presets on multi-preset application
@ -282,6 +283,14 @@ namespace cw
//
// Value Only
//
inline void set_null( value_t& v, unsigned tflag ) { v.tflag=tflag; v.u.p=nullptr; }
inline bool is_numeric( const value_t* v ) { return cwIsFlag(v->tflag,kBoolTFl|kUIntTFl|kIntTFl|kFloatTFl|kDoubleTFl); }
inline bool is_matrix( const value_t* v ) { return cwIsFlag(v->tflag,kNumericFlags); }
// if all of the src flags are set in the dst flags then the two types are convertable.
inline bool can_convert( unsigned src_tflag, unsigned dst_tflag ) { return (src_tflag&dst_tflag)==src_tflag; }
abuf_t* abuf_create( srate_t srate, unsigned chN, unsigned frameN );
void abuf_destroy( abuf_t*& buf );
@ -309,11 +318,13 @@ namespace cw
//
// Class and Variable Description
//
class_desc_t* class_desc_find( flow_t* p, const char* class_desc_label );
var_desc_t* var_desc_find( class_desc_t* cd, const char* var_label );
rc_t var_desc_find( class_desc_t* cd, const char* label, var_desc_t*& vdRef );
class_desc_t* class_desc_find( flow_t* p, const char* class_desc_label );
const preset_t* class_preset_find( class_desc_t* cd, const char* preset_label );
void class_dict_print( flow_t* p );
@ -341,7 +352,6 @@ namespace cw
// Count of all var instances on this proc. This is a count of the length of inst->varL.
unsigned instance_var_count( instance_t* inst );
//------------------------------------------------------------------------------------------------------------------------
//
@ -358,9 +368,6 @@ namespace cw
// automatically generated variable whose channel index is set to 'all'.
rc_t var_channelize( instance_t* inst, const char* var_label, unsigned sfx_id, unsigned chIdx, const object_t* value_cfg, unsigned vid, variable_t*& varRef );
// Set the var. type at runtime.
//rc_t var_set_type( instance_t* inst, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned type_flags );
// Wrapper around call to var->inst->members->value()
rc_t var_call_custom_value_func( variable_t* var );
@ -377,7 +384,11 @@ namespace cw
// Return true if this var is acting as a source for another var.
bool is_a_source_var( const variable_t* var );
// Connect in_var to src_var.
void var_connect( variable_t* src_var, variable_t* in_var );
// Get all the label-sfx-id's associated with a give var label
rc_t var_mult_sfx_id_array( instance_t* inst, const char* var_label, unsigned* idA, unsigned idAllocN, unsigned& idN_ref );
//-----------------
@ -502,6 +513,10 @@ namespace cw
rc_t var_channel_count( instance_t* inst, const char* label, unsigned sfx_idx, unsigned& chCntRef );
rc_t var_channel_count( const variable_t* var, unsigned& chCntRef );
//
// var_get() coerces the value of the variable to the type of the returned value.
//
rc_t var_get( const variable_t* var, bool& valRef );
rc_t var_get( const variable_t* var, uint_t& valRef );
@ -537,6 +552,12 @@ namespace cw
return value;
}
//
// var_set() coerces the incoming value to the type of the variable (var->type)
//
rc_t var_set_from_preset( variable_t* var, const object_t* val );
rc_t var_set( variable_t* var, const value_t* val );
rc_t var_set( variable_t* var, bool val );
rc_t var_set( variable_t* var, uint_t val );
@ -560,7 +581,6 @@ namespace cw
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, fbuf_t* val );
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, const object_t* val );
const preset_t* class_preset_find( class_desc_t* cd, const char* preset_label );
}
}