From 4e3100333d2da96af35da479fc2d71c389cda461 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 4 Jun 2024 08:45:05 -0400 Subject: [PATCH] cwFlowTypes.h/cpp : Added var_duplicate() and updated abuf_create()/duplicate() and fbuf_create()/duplicate() to avoid allocation when possible. --- cwFlowTypes.cpp | 133 ++++++++++++++++++++++++++++++++++++++++-------- cwFlowTypes.h | 31 +++++++---- 2 files changed, 134 insertions(+), 30 deletions(-) diff --git a/cwFlowTypes.cpp b/cwFlowTypes.cpp index 43e71da..3a02df4 100644 --- a/cwFlowTypes.cpp +++ b/cwFlowTypes.cpp @@ -148,12 +148,12 @@ namespace cw case kABufTFl: - dst.u.abuf = src.u.abuf == nullptr ? nullptr : abuf_duplicate(src.u.abuf); + dst.u.abuf = src.u.abuf == nullptr ? nullptr : abuf_duplicate(dst.u.abuf,src.u.abuf); dst.tflag = src.tflag; break; case kFBufTFl: - dst.u.fbuf = src.u.fbuf == nullptr ? nullptr : fbuf_duplicate(src.u.fbuf); + dst.u.fbuf = src.u.fbuf == nullptr ? nullptr : fbuf_duplicate(dst.u.fbuf,src.u.fbuf); dst.tflag = src.tflag; break; @@ -1062,7 +1062,7 @@ namespace cw if( cwIsNotFlag(var->classVarDesc->type,kRuntimeTFl) ) { - rc = cwLogError(kOpFailRC,"It is invalid to change the type of a statically (non-runtime) type variable."); + rc = cwLogError(kOpFailRC,"It is invalid to change the type of a static (non-runtime) type variable."); goto errLabel; } @@ -1182,6 +1182,11 @@ namespace cw } } +void cw::flow::value_duplicate( value_t& dst, const value_t& src ) +{ + _value_duplicate(dst,src); +} + void cw::flow::value_print( const value_t* value, bool info_fl) { _value_print(value,info_fl); @@ -1190,11 +1195,12 @@ void cw::flow::value_print( const value_t* value, bool info_fl) cw::flow::abuf_t* cw::flow::abuf_create( srate_t srate, unsigned chN, unsigned frameN ) { - abuf_t* a = mem::allocZ(); - a->srate = srate; - a->chN = chN; - a->frameN = frameN; - a->buf = mem::allocZ( chN*frameN ); + abuf_t* a = mem::allocZ(); + a->srate = srate; + a->chN = chN; + a->frameN = frameN; + a->bufAllocSmpN = chN*frameN; + a->buf = mem::allocZ(a->bufAllocSmpN); return a; } @@ -1208,9 +1214,21 @@ void cw::flow::abuf_destroy( abuf_t*& abuf ) mem::release(abuf); } -cw::flow::abuf_t* cw::flow::abuf_duplicate( const abuf_t* src ) +cw::flow::abuf_t* cw::flow::abuf_duplicate( abuf_t* dst, const abuf_t* src ) { - return abuf_create( src->srate, src->chN, src->frameN ); + abuf_t* abuf = nullptr; + + if( dst != nullptr && dst->bufAllocSmpN < src->bufAllocSmpN ) + mem::release(dst->buf); + + if( dst == nullptr || dst->buf == nullptr ) + abuf = abuf_create( src->srate, src->chN, src->frameN ); + else + abuf = dst; + + vop::copy(abuf->buf,src->buf,src->chN*src->frameN); + + return abuf; } @@ -1235,6 +1253,79 @@ const cw::flow::sample_t* cw::flow::abuf_get_channel( abuf_t* abuf, unsigned c return abuf->buf + (chIdx*abuf->frameN); } + +cw::flow::fbuf_t* cw::flow::fbuf_create( srate_t srate, unsigned chN, const unsigned* maxBinN_V, const unsigned* binN_V, const unsigned* hopSmpN_V, const fd_sample_t** magV, const fd_sample_t** phsV, const fd_sample_t** hzV ) +{ + for(unsigned i=0; i maxBinN_V[i] ) + { + cwLogError(kInvalidArgRC,"A channel bin count (%i) execeeds the max bin count (%i).",binN_V[i],maxBinN_V[i]); + return nullptr;; + } + + fbuf_t* f = mem::allocZ(); + + bool proxy_fl = magV != nullptr || phsV != nullptr || hzV != nullptr; + + // Calculate the total count of bins for each data vector. + unsigned maxTotalBinN = proxy_fl ? 0 : vop::sum(maxBinN_V, chN); + + // calc the total size of memory required for all internal data structures + f->memByteN + = sizeof(unsigned) * chN*kFbufVectN // maxBinN_V[],binN_V[],hopSmpN_V[] + + sizeof(fd_sample_t*) * chN*kFbufVectN // magV[],phsV[],hzV[] (pointer to bin buffers) + + sizeof(bool) * chN*1 // readyFlV[] + + sizeof(fd_sample_t) * maxTotalBinN*kFbufVectN; // bin buffer memory + + // allocate mory + f->mem = mem::allocZ(f->memByteN); + + unsigned* base_maxBinV = (unsigned*)f->mem; + fd_sample_t** base_bufV = (fd_sample_t**)(base_maxBinV + kFbufVectN * chN); + bool* base_boolV = (bool*)(base_bufV + kFbufVectN * chN); + fd_sample_t* base_buf = (fd_sample_t*)(base_boolV + chN); + + + f->srate = srate; + f->chN = chN; + f->maxBinN_V = base_maxBinV; + f->binN_V = f->maxBinN_V + chN; + f->hopSmpN_V = f->binN_V + chN; + f->magV = base_bufV; + f->phsV = f->magV + chN; + f->hzV = f->phsV + chN; + f->readyFlV = base_boolV; + + vop::copy( f->binN_V, binN_V, chN ); + vop::copy( f->maxBinN_V, maxBinN_V, chN ); + vop::copy( f->hopSmpN_V, hopSmpN_V, chN ); + + if( proxy_fl ) + { + for(unsigned chIdx=0; chIdxmagV[ chIdx ] = (fd_sample_t*)magV[chIdx]; + f->phsV[ chIdx ] = (fd_sample_t*)phsV[chIdx]; + f->hzV[ chIdx ] = (fd_sample_t*)hzV[chIdx]; + } + } + else + { + fd_sample_t* m = base_buf; + for(unsigned chIdx=0; chIdxmagV[chIdx] = m + 0 * f->binN_V[chIdx]; + f->phsV[chIdx] = m + 1 * f->binN_V[chIdx]; + f->hzV[ chIdx] = m + 2 * f->binN_V[chIdx]; + m += f->maxBinN_V[chIdx]; + assert( m <= base_buf + kFbufVectN * maxTotalBinN ); + } + } + + return f; +} + +/* cw::flow::fbuf_t* cw::flow::fbuf_create( srate_t srate, unsigned chN, const unsigned* maxBinN_V, const unsigned* binN_V, const unsigned* hopSmpN_V, const fd_sample_t** magV, const fd_sample_t** phsV, const fd_sample_t** hzV ) { for(unsigned i=0; imaxBinN_V ); - mem::release( fbuf->binN_V ); - mem::release( fbuf->hopSmpN_V); - mem::release( fbuf->magV); - mem::release( fbuf->phsV); - mem::release( fbuf->hzV); - mem::release( fbuf->buf); - mem::release( fbuf->readyFlV); + mem::release( fbuf->mem); mem::release( fbuf); } -cw::flow::fbuf_t* cw::flow::fbuf_duplicate( const fbuf_t* src ) +cw::flow::fbuf_t* cw::flow::fbuf_duplicate( fbuf_t* dst, const fbuf_t* src ) { - fbuf_t* fbuf = fbuf_create( src->srate, src->chN, src->maxBinN_V, src->binN_V, src->hopSmpN_V ); + fbuf_t* fbuf = nullptr; + + if( dst != nullptr && dst->memByteN < src->memByteN ) + fbuf_destroy(dst); + + if( dst == nullptr ) + fbuf = fbuf_create( src->srate, src->chN, src->maxBinN_V, src->binN_V, src->hopSmpN_V ); + else + fbuf = dst; for(unsigned i=0; ichN; ++i) { diff --git a/cwFlowTypes.h b/cwFlowTypes.h index 7a01b46..5b13b7d 100644 --- a/cwFlowTypes.h +++ b/cwFlowTypes.h @@ -25,26 +25,29 @@ namespace cw typedef struct abuf_str { - 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 ] + 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; // max value that binN_V[i] is allowed to take + 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) - fd_sample_t* buf; // memory used by this buffer (or NULL if magV,phsV,hzV point are proxied to another buffer) } fbuf_t; typedef struct mbuf_str @@ -192,7 +195,7 @@ namespace cw // on a given 'instance'. typedef struct variable_str { - struct proc_str* proc; // pointer to this variables instance + struct proc_str* proc; // pointer to this variables instance char* label; // this variables label unsigned label_sfx_id; // the label suffix id of this variable or kBaseSfxId if this has no suffix @@ -373,14 +376,20 @@ namespace cw 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 ); + + // 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 ); - fbuf_t* fbuf_duplicate( const fbuf_t* src ); + + // 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 ); @@ -392,6 +401,8 @@ namespace cw unsigned value_type_label_to_flag( const char* type_desc ); const char* value_type_flag_to_label( unsigned flag ); + void value_duplicate( value_t& dst, const value_t& src ); + void value_print( const value_t* value, bool info_fl=false); //------------------------------------------------------------------------------------------------------------------------