#ifndef cwFlowValue_h #define cwFLowValue_h namespace cw { namespace flow { typedef dsp::coeff_t coeff_t; typedef dsp::sample_t sample_t; typedef dsp::fd_sample_t fd_sample_t; typedef dsp::srate_t srate_t; typedef dsp::ftime_t ftime_t; typedef unsigned uint_t; typedef int int_t; typedef unsigned vid_t; enum { kBaseSfxId = 0, kFbufVectN = 3, // count of signal vectors in fbuf (mag,phs,hz) kAnyChIdx = kInvalidIdx, kLocalValueN = 2, kDefaultFramesPerCycle=64, kDefaultSampleRate=48000 }; typedef struct abuf_str { srate_t srate; // Signal sample rate unsigned chN; // Count of channels unsigned frameN; // Count of sample frames per channel unsigned bufAllocSmpN; // Size of allocated buf[] in samples. sample_t* buf; // buf[ chN ][ frameN ] } abuf_t; typedef struct fbuf_str { unsigned memByteN; // Count of bytes in mem[]. void* mem; // mem[ memByteN ] All dynamically allocated memory used by this fbuf. srate_t srate; // signal sample rate unsigned flags; // See kXXXFbufFl unsigned chN; // count of channels unsigned* maxBinN_V; // maxBinN_V[chN] max value that binN_V[i] is allowed to take unsigned* binN_V; // binN_V[ chN ] count of sample frames per channel unsigned* hopSmpN_V; // hopSmpN_V[ chN ] hop sample count fd_sample_t** magV; // magV[ chN ][ binN ] fd_sample_t** phsV; // phsV[ chN ][ binN ] fd_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) } fbuf_t; typedef struct mbuf_str { const midi::ch_msg_t* msgA; unsigned msgN; } mbuf_t; enum { kInvalidTFl = 0x00000000, kBoolTFl = 0x00000001, kUIntTFl = 0x00000002, kIntTFl = 0x00000004, kFloatTFl = 0x00000008, kDoubleTFl = 0x00000010, kBoolMtxTFl = 0x00000020, kUIntMtxTFl = 0x00000040, kIntMtxTFl = 0x00000080, kFloatMtxTFl = 0x00000100, kDoubleMtxTFl= 0x00000200, kABufTFl = 0x00000400, kFBufTFl = 0x00000800, kMBufTFl = 0x00001000, kRBufTFl = 0x00002000, kStringTFl = 0x00004000, kTimeTFl = 0x00008000, kCfgTFl = 0x00010000, kMidiTFl = 0x00020000, kTypeMask = 0x0003ffff, kRuntimeTFl = 0x80000000, kNumericTFl = kBoolTFl | kUIntTFl | kIntTFl | kFloatTFl | kDoubleTFl, kMtxTFl = kBoolMtxTFl | kUIntMtxTFl | kIntMtxTFl | kFloatMtxTFl | kDoubleMtxTFl, kAllTFl = kTypeMask }; typedef struct mtx_str { union { struct mtx::mtx_str< unsigned >* u; struct mtx::mtx_str< int >* i; struct mtx::mtx_str< float >* f; struct mtx::mtx_str< double >* d; } u; } mtx_t; typedef struct recd_field_str { bool group_fl; // set if this field record is a group char* label; // field or group label union { unsigned index; // index into recd_t.valA of the value associated with this field struct recd_field_str* group_fieldL; } u; struct recd_field_str* link; } recd_field_t; typedef struct recd_type_str { recd_field_t* fieldL; // linked list of field spec's unsigned fieldN; // length of fieldL list (fieldN + base->fieldN) is total field count const struct recd_type_str* base; } recd_type_t; struct value_str; typedef struct recd_str { struct value_str* valA; // varA[ fieldN ] array of field values const struct recd_str* base; // base record fields } recd_t; typedef struct rbuf_str { const recd_type_t* type; // all msgs are formed from this type const recd_t* recdA; // recdA[ recdN ] unsigned recdN; // } rbuf_t; typedef struct value_str { unsigned tflag; union { bool b; uint_t u; int_t i; float f; double d; mtx_t* mtx; abuf_t* abuf; fbuf_t* fbuf; mbuf_t* mbuf; rbuf_t* rbuf; char* s; const object_t* cfg; midi::ch_msg_t* midi; void* p; } u; struct value_str* link; } value_t; //------------------------------------------------------------------------------------------------------------------------ // // 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,kNumericTFl); } inline bool is_matrix( const value_t* v ) { return cwIsFlag(v->tflag,kMtxTFl); } // 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 ); // If 'dst' is null then a new abuf is allocated, filled with the contents of 'src'. // If 'dst' is non-null and there is enough space for the contents of 'src' then only a copy is executed. // If there is not enough space then dst is reallocated. abuf_t* abuf_duplicate( abuf_t* dst, 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, const unsigned* maxBinN_V, const unsigned* binN_V, const unsigned* hopSmpN_V, const fd_sample_t** magV=nullptr, const fd_sample_t** phsV=nullptr, const fd_sample_t** hzV=nullptr ); fbuf_t* fbuf_create( srate_t srate, unsigned chN, unsigned maxBinN, unsigned binN, unsigned hopSmpN, const fd_sample_t** magV=nullptr, const fd_sample_t** phsV=nullptr, const fd_sample_t** hzV=nullptr ); void fbuf_destroy( fbuf_t*& buf ); // Memory allocation will only occur if dst is null, or the size of dst's internal buffer are too small. fbuf_t* fbuf_duplicate( fbuf_t* dst, const fbuf_t* src ); mbuf_t* mbuf_create( const midi::ch_msg_t* msgA=nullptr, unsigned msgN=0 ); void mbuf_destroy( mbuf_t*& buf ); mbuf_t* mbuf_duplicate( const mbuf_t* src ); rbuf_t* rbuf_create( const recd_type_t* type=nullptr, const recd_t* recdA=nullptr, unsigned recdN=0 ); void rbuf_destroy( rbuf_t*& buf ); rbuf_t* rbuf_duplicate( const rbuf_t* src ); void rbuf_setup( rbuf_t* rbuf, recd_type_t* type, recd_t* recdA, unsigned recdN ); inline bool value_is_abuf( const value_t* v ) { return v->tflag & kABufTFl; } inline bool value_is_fbuf( const value_t* v ) { return v->tflag & kFBufTFl; } unsigned value_type_label_to_flag( const char* type_desc ); const char* value_type_flag_to_label( unsigned flag ); void value_release( value_t* v ); void value_duplicate( value_t& dst, const value_t& src ); void value_print( const value_t* value, bool info_fl=false); rc_t value_get( const value_t* val, bool& valRef ); rc_t value_set( value_t* val, bool v ); rc_t value_get( const value_t* val, uint_t& valRef ); rc_t value_set( value_t* val, uint_t v ); rc_t value_get( const value_t* val, int_t& valRef ); rc_t value_set( value_t* val, int_t v ); rc_t value_get( const value_t* val, float& valRef ); rc_t value_set( value_t* val, float v ); rc_t value_get( const value_t* val, double& valRef ); rc_t value_set( value_t* val, double v ); rc_t value_get( const value_t* val, const char*& valRef ); rc_t value_set( value_t* val, const char* v ); rc_t value_get( value_t* val, abuf_t*& valRef ); rc_t value_get( value_t* val, const abuf_t*& valRef ); rc_t value_set( value_t* val, abuf_t* v ); rc_t value_get( value_t* val, fbuf_t*& valRef ); rc_t value_get( value_t* val, const fbuf_t*& valRef ); rc_t value_set( value_t* val, fbuf_t* v ); rc_t value_get( value_t* val, mbuf_t*& valRef ); rc_t value_get( value_t* val, const mbuf_t*& valRef ); rc_t value_set( value_t* val, mbuf_t* v ); rc_t value_get( value_t* val, rbuf_t*& valRef ); rc_t value_get( value_t* val, const rbuf_t*& valRef ); rc_t value_set( value_t* val, rbuf_t* v ); rc_t value_get( value_t* val, const object_t*& valRef ); rc_t value_set( value_t* val, const object_t* v ); rc_t value_get( const value_t* val, midi::ch_msg_t*& valRef ); rc_t value_set( value_t* val, midi::ch_msg_t* v ); //------------------------------------------------------------------------------------------------------------------------ // // Record // typedef struct recd_array_str { recd_type_t* type; value_t* valA; // valA[ allocRecdN * type->fieldN ] recd_t* recdA; unsigned allocRecdN; } recd_array_t; rc_t recd_type_create( recd_type_t*& recd_type_ref, const recd_type_t* base_type, const char* fields_string=nullptr ); void recd_type_destroy( recd_type_t*& recd_type ); rc_t recd_type_add_value_fields( recd_type_t* recd_type, const char* field_labels ); rc_t recd_type_add_group( recd_type_t* recd_type, const char* group_label, const char* field_labels ); // Count of fields combined local and base record types. rc_t recd_type_max_field_count( const recd_type_t* recd_type ); // use '.' notation to separate groups from fields. // Note if this is a 'local' field then the high bit in the returned index will be set. unsigned recd_type_field_index( const recd_type_t* recd_type, const char* field_label); void recd_type_print( const recd_type_t* recd_type ); template< typename T > rc_t recd_get( const recd_type_t* type, const recd_t* recd, unsigned field_idx, T& val_ref ) { if( field_idx < type->fieldN ) return value_get( recd->valA + field_idx, val_ref ); return recd_get( type->base, recd->base, field_idx - type->fieldN, val_ref ); } inline rc_t recd_set_base( const recd_type_t* type, recd_t* recd, const recd_t* base ) { // if we are setting base then the type must have a base type assert( (type->base == nullptr && base==nullptr) || (type->base!=nullptr && base!=nullptr) ); recd->base = base; return kOkRC; } template< typename T > rc_t recd_set( const recd_type_t* type, const recd_t* base, recd_t* recd, unsigned field_idx, const T& val ) { if( field_idx >= type->fieldN ) return cwLogError(kInvalidArgRC,"Only 'local' record value may be set."); // set the base of this record recd_set_base(type,recd,base); return value_set( recd->valA + field_idx, val ); } rc_t recd_print( const recd_type_t* recd_type, const recd_t* r ); rc_t recd_array_create( recd_array_t*& recd_array_ref, recd_type_t* recd_type, unsigned allocRecdN ); rc_t recd_array_destroy( recd_array_t*& recd_array_ref ); rc_t value_test( const test::test_args_t& args ); } } #endif