namespace cw { namespace flow { #define kRealTFl kFloatTFl typedef dsp::real_t real_t; typedef dsp::sample_t sample_t; typedef dsp::srate_t srate_t; typedef unsigned uint_t; typedef int int_t; typedef unsigned vid_t; typedef struct abuf_str { struct value_str* base; srate_t srate; // signal sample rate unsigned chN; // count of channels unsigned frameN; // count of sample frames per channel sample_t* buf; // buf[ chN ][ frameN ] } abuf_t; enum { kFbufVectN = 3, kAnyChIdx = kInvalidIdx }; typedef struct fbuf_str { struct value_str* base; srate_t srate; // signal sample rate unsigned flags; // See kXXXFbufFl unsigned chN; // count of channels unsigned binN; // count of sample frames per channel unsigned hopSmpN; // hop sample count sample_t** magV; // magV[ chN ][ binN ] sample_t** phsV; // phsV[ chN ][ binN ] sample_t** hzV; // hzV[ chN ][ binN ] bool* readyFlV; // readyFlV[chN] true if this channel is ready to be processed (used to sync. fbuf rate to abuf rate) sample_t* buf; // memory used by this buffer (or NULL if magV,phsV,hzV point are proxied to another buffer) } fbuf_t; enum { kInvalidTFl = 0x00000000, kBoolTFl = 0x00000001, kUIntTFl = 0x00000002, kIntTFl = 0x00000004, kFloatTFl = 0x00000008, kDoubleTFl = 0x00000010, kBoolMtxTFl = 0x00000020, kUIntMtxTFl = 0x00000040, kIntMtxTFl = 0x00000080, kRealMtxTFl = 0x00000100, kFloatMtxTFl = 0x00000200, kDoubleMtxTFl= 0x00000400, kABufTFl = 0x00000800, kFBufTFl = 0x00001000, kStringTFl = 0x00002000, kTimeTFl = 0x00004000, kTypeMask = 0x00007fff, }; typedef struct mtx_str { union { struct mtx::mtx_str< unsigned >* u; struct mtx::mtx_str< int >* i; struct mtx::mtx_str< real_t >* r; struct mtx::mtx_str< float >* f; struct mtx::mtx_str< double >* d; } u; } mtx_t; typedef struct value_str { unsigned flags; union { bool b; uint_t u; int_t i; float f; double d; mtx_t* mtx; abuf_t* abuf; fbuf_t* fbuf; char* s; char* fname; } u; struct value_str* link; } value_t; inline bool is_numeric( const value_t* v ) { return cwIsFlag(v->flags,kBoolTFl|kUIntTFl|kIntTFl|kFloatTFl|kDoubleTFl); } inline bool is_matrix( const value_t* v ) { return cwIsFlag(v->flags,kBoolMtxTFl|kUIntMtxTFl|kIntMtxTFl|kFloatMtxTFl|kDoubleMtxTFl); } struct instance_str; struct variable_str; typedef rc_t (*member_func_t)( struct instance_str* ctx ); typedef rc_t (*member_value_func_t)( struct instance_str* ctx, struct variable_str* var ); enum { kSrcVarFl = 0x01 }; typedef struct class_members_str { member_func_t create; member_func_t destroy; member_value_func_t value; member_func_t exec; member_func_t report; } class_members_t; typedef struct var_desc_str { const object_t* cfg; // The cfg object that describes this variable from 'flow_class'. const object_t* val_cfg; // An object containing the default value for this variable. const char* label; // Name of this var. unsigned type; // Value type id (e.g. kBoolTFl, kIntTFl, ...) unsigned flags; // Attributes for this var. (e.g. kSrcVarFl ) const char* docText; // User help string for this var. struct var_desc_str* link; // class_desc->varDescL list link } var_desc_t; typedef struct preset_str { const char* label; const object_t* cfg; struct preset_str* link; } preset_t; typedef struct class_desc_str { const object_t* cfg; // const char* label; // class label; var_desc_t* varDescL; // varDescA[varDescN] value description list preset_t* presetL; // presetA[ presetN ] class_members_t* members; // member functions for this class } class_desc_t; // Note: The concatenation of 'vid' and 'chIdx' should form a unique identifier among all variables // on a given 'instance'. typedef struct variable_str { struct instance_str* inst; // pointer to this variables instance char* label; // this variables label unsigned vid; // this variables numeric id ( cat(vid,chIdx) forms a unique variable identifier on this 'inst' var_desc_t* varDesc; // the variable description for this variable value_t local_value; // the local value instance (actual value if this is not a 'src' variable) value_t* value; // pointer to the value associated with this variable unsigned chIdx; // channel index struct variable_str* var_link; // link to other var's on 'inst' struct variable_str* connect_link; // list of outgoing connections struct variable_str* ch_link; // list of channels that share this variable (rooted on 'any' channel - in order by channel number) } variable_t; typedef struct instance_str { struct flow_str* ctx; // global system context class_desc_t* class_desc; // const char* label; // instance label const object_t* inst_cfg; // instance configuration const char* arg_label; // optional args label const object_t* arg_cfg; // optional args configuration void* userPtr; // instance state variable_t* varL; // list of instance value unsigned varMapChN; // max count of channels among all variables unsigned varMapIdN; unsigned varMapN; // varMapN variable_t** varMapA; // varMapA[ varMapN ] struct instance_str* link; } instance_t; typedef struct flow_str { const object_t* networkCfg; // complete cfg used to create this network const object_t* presetCfg; // presets designed for this network unsigned framesPerCycle; // sample frames per cycle (64) unsigned cycleIndex; // Incremented with each processing cycle unsigned maxCycleCount; // count of cycles to run on flow::exec() or 0 if there is no limit. class_desc_t* classDescA; // unsigned classDescN; // external_device_t* deviceA; // deviceA[ deviceN ] external device description array unsigned deviceN; // struct instance_str* network_head; // first instance struct instance_str* network_tail; // last insance } flow_t; //------------------------------------------------------------------------------------------------------------------------ // // Value Only // abuf_t* abuf_create( srate_t srate, unsigned chN, unsigned frameN ); void abuf_destroy( abuf_t* buf ); abuf_t* abuf_duplicate( const abuf_t* src ); rc_t abuf_set_channel( abuf_t* buf, unsigned chIdx, const sample_t* v, unsigned vN ); const sample_t* abuf_get_channel( abuf_t* buf, unsigned chIdx ); fbuf_t* fbuf_create( srate_t srate, unsigned chN, unsigned binN, unsigned hopSmpN, const sample_t** magV=nullptr, const sample_t** phsV=nullptr, const sample_t** hzV=nullptr ); void fbuf_destroy( fbuf_t* buf ); fbuf_t* fbuf_duplicate( const fbuf_t* src ); inline bool value_is_abuf( const value_t* v ) { return v->flags & kABufTFl; } inline bool value_is_fbuf( const value_t* v ) { return v->flags & kFBufTFl; } unsigned value_type_label_to_flag( const char* type_desc ); //------------------------------------------------------------------------------------------------------------------------ // // Class and Variable Description // 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 ); void class_dict_print( flow_t* p ); //------------------------------------------------------------------------------------------------------------------------ // // Network // void network_print( flow_t* p ); //------------------------------------------------------------------------------------------------------------------------ // // Instance // instance_t* instance_find( flow_t* p, const char* inst_label ); rc_t instance_find( flow_t* p, const char* inst_label, instance_t*& instPtrRef ); external_device_t* external_device_find( flow_t* p, const char* device_label, unsigned typeId, unsigned inOrOutFl ); void instance_print( instance_t* inst ); //------------------------------------------------------------------------------------------------------------------------ // // Variable // // Create a variable but do not assign it a value. Return a pointer to the new variable. // Note: `value_cfg` is optional. Set it to NULL to ignore rc_t var_create( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef ); // Channelizing creates a new var record with an explicit channel index to replace the // automatically generated variable whose channel index is set to 'all'. rc_t var_channelize( instance_t* inst, const char* var_label, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef ); // `value_cfg` is optional. Set it to NULL to ignore rc_t var_register( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef ); //----------------- // // var_register // inline rc_t _var_reg(cw::flow::instance_t*, unsigned int ) { return kOkRC; } template< typename T0, typename T1, typename... ARGS > rc_t _var_reg( instance_t* inst, unsigned chIdx, T0 vid, T1 var_label, ARGS&&... args ) { rc_t rc; variable_t* dummy = nullptr; if((rc = var_register( inst, var_label, vid, chIdx, nullptr, dummy )) == kOkRC ) if((rc = _var_reg( inst, chIdx, std::forward(args)...)) != kOkRC ) return rc; return rc; } // Call var_register() on a list of variables. template< typename... ARGS > rc_t var_register( instance_t* inst, unsigned chIdx, unsigned vid, const char* var_label, ARGS&&... args ) { return _var_reg( inst, chIdx, vid, var_label, std::forward(args)...); } //--------------------- // // var_register_and_get // inline rc_t _var_register_and_get(cw::flow::instance_t*, unsigned int ) { return kOkRC; } template< typename T> rc_t var_register_and_get( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, T& valRef ) { rc_t rc; variable_t* var; if((rc = var_register(inst,var_label,vid,chIdx,nullptr,var)) == kOkRC ) rc = var_get(var,valRef); return rc; } inline rc_t _var_reg_and_get(cw::flow::instance_t*, unsigned int ) { return kOkRC; } template< typename T0, typename T1, typename T2, typename... ARGS > rc_t _var_reg_and_get( instance_t* inst, unsigned chIdx, T0 vid, T1 var_label, T2& valRef, ARGS&&... args ) { rc_t rc; if((rc = var_register_and_get( inst, var_label, vid, chIdx, valRef )) == kOkRC ) if((rc = _var_reg_and_get( inst, chIdx, std::forward(args)...)) != kOkRC ) return rc; return rc; } // Call var_register_and_get() on a list of variables. template< typename... ARGS > rc_t var_register_and_get( instance_t* inst, unsigned chIdx, unsigned vid, const char* var_label, ARGS&&... args ) { return _var_reg_and_get( inst, chIdx, vid, var_label, std::forward(args)...); } //--------------------- // // var_register_and_set // // var_register_and_set(). If the variable has not yet been created then it is created and assigned a value. // If the variable has already been created then 'vid' and the value are updated. // (Note that abuf and fbuf values are not changed by this function only the 'vid' is updated.) rc_t var_register_and_set( instance_t* inst, const char* label, unsigned vid, unsigned chIdx, variable_t*& varRef ); rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned frameN ); rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned binN, unsigned hopSmpN, const sample_t** magV=nullptr, const sample_t** phsV=nullptr, const sample_t** hzV=nullptr ); inline rc_t _var_register_and_set(cw::flow::instance_t*, unsigned int ) { return kOkRC; } template< typename T0, typename T1, typename T2, typename... ARGS > rc_t _var_register_and_set( instance_t* inst, unsigned chIdx, T0 vid, T1 var_label, T2 val, ARGS&&... args ) { rc_t rc; variable_t* var = nullptr; if((rc = var_register_and_set( inst, var_label, vid, chIdx, var)) == kOkRC ) { var_set( var, val ); if((rc = _var_register_and_set( inst, chIdx, std::forward(args)...)) != kOkRC ) return rc; } return rc; } // Call var_register_and_set() on a list of variables. template< typename... ARGS > rc_t var_register_and_set( instance_t* inst, unsigned chIdx, unsigned vid, const char* var_label, ARGS&&... args ) { return _var_register_and_set( inst, chIdx, vid, var_label, std::forward(args)...); } void _var_destroy( variable_t* var ); bool var_exists( instance_t* inst, const char* label, unsigned chIdx ); rc_t var_find( instance_t* inst, const char* var_label, unsigned chIdx, const variable_t*& varRef ); rc_t var_find( instance_t* inst, const char* var_label, unsigned chIdx, variable_t*& varRef ); rc_t var_find( instance_t* inst, unsigned vid, unsigned chIdx, variable_t*& varRef ); rc_t var_get( const variable_t* var, bool& valRef ); rc_t var_get( const variable_t* var, uint_t& valRef ); rc_t var_get( const variable_t* var, int_t& valRef ); rc_t var_get( const variable_t* var, float& valRef ); rc_t var_get( const variable_t* var, double& valRef ); rc_t var_get( const variable_t* var, const char*& valRef ); rc_t var_get( const variable_t* var, const abuf_t*& valRef ); rc_t var_get( variable_t* var, abuf_t*& valRef ); rc_t var_get( const variable_t* var, const fbuf_t*& valRef ); rc_t var_get( variable_t* var, fbuf_t*& valRef ); template< typename T> rc_t var_get( instance_t* inst, unsigned vid, unsigned chIdx, T& valRef) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(inst, vid, chIdx, var )) == kOkRC ) rc = var_get(var,valRef); return rc; } template< typename T > T val_get( instance_t* inst, unsigned vid, unsigned chIdx ) { T value; var_get(inst,vid,chIdx,value); return value; } rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, bool val ); rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, uint_t val ); rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, int_t val ); rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, float val ); rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, double val ); rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, const char* val ); rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, abuf_t* val ); rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, fbuf_t* val ); const preset_t* class_preset_find( class_desc_t* cd, const char* preset_label ); } }