From cbaff98964d5d4634d210db4db46bd0b75f87749 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 27 Dec 2022 18:09:31 -0500 Subject: [PATCH] Allow frequency domain transforms to have a variable window sample count. Audio file in processor now has a 'seekSecs' and 'onOffFl' parameter. Audio mixer now works as a stereo mixer. PV Analysis proc now can have variable window length. --- cwAudioFileProc.cpp | 4 +- cwAudioTransforms.cpp | 21 +++--- cwAudioTransforms.h | 146 ++++++++++++++++++++++++++++----------- cwFlowProc.cpp | 155 ++++++++++++++++++++++++++++++++---------- cwFlowTypes.cpp | 69 ++++++++++--------- cwFlowTypes.h | 10 +-- 6 files changed, 279 insertions(+), 126 deletions(-) diff --git a/cwAudioFileProc.cpp b/cwAudioFileProc.cpp index 3abd850..51c1518 100644 --- a/cwAudioFileProc.cpp +++ b/cwAudioFileProc.cpp @@ -385,14 +385,14 @@ cw::rc_t cw::afop::file_processor( const char* srcFn, const char* dstFn, proc_fu for(unsigned i = 0; iwndV, p->wndN, "%f ", windowLabel); @@ -70,13 +70,13 @@ namespace cw rc_t rc = kOkRC; - _test( "hann", hann_15, 15); - _test( "hann", hann_16, 16); - _test( "hamming", hamm_15, 15); - _test( "hamming", hamm_16, 16); - _test( "triangle", tri_15, 15); - _test( "triangle", tri_16, 16); - _test( "unity", ones_5, 5); + _test( "hann", hann_15, 15, 15); + _test( "hann", hann_16, 16, 16); + _test( "hamming", hamm_15, 15, 15); + _test( "hamming", hamm_16, 16, 16); + _test( "triangle", tri_15, 15, 15); + _test( "triangle", tri_16, 16, 16); + _test( "unity", ones_5, 5, 5); if( rc != kOkRC ) cwLogError(rc,"Window test failed."); @@ -168,6 +168,7 @@ namespace cw unsigned procSmpCnt = 5; // count of samples to be fed to the shift buffer on each cycle unsigned hopSmpCnt = 6; // count of samples between shift buffer outputs + unsigned maxWndSmpCnt= 7; unsigned wndSmpCnt = 7; // count of samples in each shift buffer output unsigned iSmpCnt = 49; // count of samples in the input test signal @@ -177,7 +178,7 @@ namespace cw shift_buf::fobj_t* p = nullptr; - if((rc = shift_buf::create(p,procSmpCnt,wndSmpCnt,hopSmpCnt)) == kOkRC ) + if((rc = shift_buf::create(p,procSmpCnt,maxWndSmpCnt,wndSmpCnt,hopSmpCnt)) == kOkRC ) { sample_t* x = mem::allocZ(iSmpCnt); sample_t* y = mem::allocZ(oSmpCnt); diff --git a/cwAudioTransforms.h b/cwAudioTransforms.h index b717e3e..7566b51 100644 --- a/cwAudioTransforms.h +++ b/cwAudioTransforms.h @@ -36,6 +36,7 @@ namespace cw { unsigned wndTypeId; // unsigned flags; // + unsigned maxWndN; // sample_t* wndV; // wndV[ wndN ] unsigned wndN; // length of wndV[] and outV[] sample_t* outV; // outV[ wndN ] @@ -49,19 +50,10 @@ namespace cw unsigned wndLabelToId( const char* label ); // window type label to id template< typename sample_t > - rc_t create( struct obj_str*& p, unsigned wndId, unsigned wndSmpCnt, double kaiserSideLobeRejectDb ) + rc_t _apply_window( struct obj_str*& p ) { - rc_t rc = kOkRC; - - p = mem::allocZ< struct obj_str< sample_t > >(); - - p->wndV = mem::allocZ(wndSmpCnt); - p->outV = mem::allocZ(wndSmpCnt); - p->wndN = wndSmpCnt; - p->wndTypeId = wndId & kWndIdMask; - p->flags = wndId & ~kWndIdMask; - - + rc_t rc = kOkRC; + switch( p->wndTypeId ) { case kHannWndId: @@ -78,7 +70,7 @@ namespace cw case kKaiserWndId: { - sample_t beta = (p->flags & kSlRejIsBetaWndFl) ? kaiserSideLobeRejectDb : kaiser_beta_from_sidelobe_reject(kaiserSideLobeRejectDb); + sample_t beta = (p->flags & kSlRejIsBetaWndFl) ? p->kaiserSLRejectDb : kaiser_beta_from_sidelobe_reject(p->kaiserSLRejectDb); kaiser(p->wndV,p->wndN, beta); } break; @@ -92,20 +84,19 @@ namespace cw break; default: - rc = cwLogError(kInvalidArgRC,"The window id '%i' (0x%x) is not valid.", wndId, wndId ); + rc = cwLogError(kInvalidArgRC,"The window id '%i' (0x%x) is not valid.", p->wndTypeId, p->wndTypeId ); } - sample_t den = 0; sample_t num = 1; if( cwIsFlag(p->flags,kNormBySumWndFl) ) { den = vop::sum(p->wndV, p->wndN); - num = wndSmpCnt; + num = p->wndN; } if( cwIsFlag(p->flags,kNormByLengthWndFl) ) - den += wndSmpCnt; + den += p->wndN; if( den > 0 ) { @@ -113,11 +104,30 @@ namespace cw vop::div(p->wndV,den,p->wndN); } + return rc; + } + + template< typename sample_t > + rc_t create( struct obj_str*& p, unsigned wndId, unsigned maxWndSmpCnt, unsigned wndSmpCnt, double kaiserSideLobeRejectDb ) + { + rc_t rc = kOkRC; + + p = mem::allocZ< struct obj_str< sample_t > >(); + + p->wndV = mem::allocZ(maxWndSmpCnt); + p->outV = mem::allocZ(maxWndSmpCnt); + p->wndN = wndSmpCnt; + p->maxWndN = maxWndSmpCnt; + p->wndTypeId = wndId & kWndIdMask; + p->flags = wndId & ~kWndIdMask; + p->kaiserSLRejectDb = kaiserSideLobeRejectDb; + + rc = _apply_window(p); + if( rc != kOkRC ) destroy(p); return rc; - } template< typename sample_t > @@ -151,6 +161,28 @@ namespace cw return rc; } + template< typename sample_t > + rc_t set_window_sample_count( struct obj_str* p, unsigned wndSmpCnt ) + { + rc_t rc = kOkRC; + + if( wndSmpCnt > p->maxWndN ) + return cwLogError( kInvalidArgRC, "The window function sample count (%i) cannot be larger than the max window function sample count (%i).", wndSmpCnt, p->maxWndN ); + + if( wndSmpCnt != p->wndN ) + { + p->wndN = wndSmpCnt; + + if((rc = _apply_window(p)) == kOkRC ) + { + // zero the end of the window buffer + vop::zero(p->wndV + p->wndN, p->maxWndN - p->wndN ); + } + } + return rc; + } + + rc_t test( const cw::object_t* args ); } @@ -191,7 +223,7 @@ namespace cw p = mem::allocZ< struct obj_str >(); - if((rc = wnd_func::create( p->wf, wndTypeId, wndSmpCnt, 0)) != kOkRC ) + if((rc = wnd_func::create( p->wf, wndTypeId, wndSmpCnt, wndSmpCnt, 0)) != kOkRC ) return rc; p->bufV = mem::allocZ( wndSmpCnt ); @@ -285,7 +317,6 @@ namespace cw return sp; } - rc_t test( const cw::object_t* args ); } @@ -303,6 +334,7 @@ namespace cw sample_t* outV; // output window outV[ outN ] unsigned outN; // outN == wndSmpCnt unsigned procSmpCnt; // input sample count + unsigned maxWndSmpCnt; // maximum value for wndSmpCnt unsigned wndSmpCnt; // output sample count unsigned hopSmpCnt; // count of samples to shift the buffer by on each call to cmShiftExec() sample_t* inPtr; // ptr to location in outV[] to recv next sample @@ -313,21 +345,26 @@ namespace cw typedef obj_str dobj_t; template< typename sample_t > - rc_t create( struct obj_str*& p, unsigned procSmpCnt, unsigned wndSmpCnt, unsigned hopSmpCnt ) + rc_t create( struct obj_str*& p, unsigned procSmpCnt, unsigned maxWndSmpCnt, unsigned wndSmpCnt, unsigned hopSmpCnt ) { rc_t rc = kOkRC; p = mem::allocZ< struct obj_str >(); + + p->maxWndSmpCnt = maxWndSmpCnt; + if((rc = set_window_sample_count(p,wndSmpCnt )) != kOkRC ) + return rc; if( hopSmpCnt > wndSmpCnt ) - return cwLogError( kInvalidArgRC, "The window sample count (%i) must be greater than or equal to the hop sample count (%i).", wndSmpCnt, hopSmpCnt ); + return cwLogError( kInvalidArgRC, "The shift buffer window sample count (%i) must be greater than or equal to the hop sample count (%i).", wndSmpCnt, hopSmpCnt ); // The worst case storage requirement is where there are wndSmpCnt-1 samples in outV[] and procSmpCnt new samples arrive. - p->bufSmpCnt = wndSmpCnt + procSmpCnt; + p->bufSmpCnt = maxWndSmpCnt + procSmpCnt; p->bufV = mem::allocZ( p->bufSmpCnt ); p->outV = p->bufV; - p->outN = wndSmpCnt; - p->wndSmpCnt = wndSmpCnt; + //p->outN = wndSmpCnt; + //p->maxWndSmpCnt = maxWndSmpCnt; + //p->wndSmpCnt = wndSmpCnt; p->procSmpCnt = procSmpCnt; p->hopSmpCnt = hopSmpCnt; p->inPtr = p->outV; @@ -389,6 +426,18 @@ namespace cw return p->fl; } + template< typename sample_t > + rc_t set_window_sample_count( struct obj_str* p, unsigned wndSmpCnt ) + { + if( wndSmpCnt > p->maxWndSmpCnt ) + return cwLogError( kInvalidArgRC, "The shift buffer window sample count (%i) cannot be larger than the max window sample count (%i).", p->wndSmpCnt, p->maxWndSmpCnt ); + + p->wndSmpCnt = wndSmpCnt; + p->outN = wndSmpCnt; + + return kOkRC; + } + rc_t test( const cw::object_t* args ); } @@ -524,9 +573,9 @@ namespace cw p = mem::allocZ< struct obj_str >(); - shift_buf::create( p->sb, procSmpCnt, wndSmpCnt, hopSmpCnt ); - wnd_func::create( p->wf, wnd_func::kHannWndId | wnd_func::kNormByLengthWndFl, wndSmpCnt, 0 ); - fft::create( p->ft, wndSmpCnt, fft::kToPolarFl); + shift_buf::create( p->sb, procSmpCnt, maxWndSmpCnt, wndSmpCnt, hopSmpCnt ); + wnd_func::create( p->wf, wnd_func::kHannWndId | wnd_func::kNormByLengthWndFl, maxWndSmpCnt, wndSmpCnt, 0 ); + fft::create( p->ft, maxWndSmpCnt, fft::kToPolarFl); phs_to_frq::create(p->pf, srate, p->ft->binN, hopSmpCnt ); p->flags = flags; @@ -577,6 +626,17 @@ namespace cw return fl; } + + template< typename T > + rc_t set_window_length( struct obj_str* p, unsigned wndSmpCnt ) + { + rc_t rc; + + if((rc = shift_buf::set_window_sample_count( p->sb, wndSmpCnt )) == kOkRC ) + rc = wnd_func::set_window_sample_count( p->wf, wndSmpCnt ); + + return rc; + } } //--------------------------------------------------------------------------------------------------------------------------------- @@ -638,7 +698,7 @@ namespace cw p->magV = mem::allocZ( p->binCnt ); - wnd_func::create( p->wf, wndTypeId, wndSmpCnt, 0); + wnd_func::create( p->wf, wndTypeId, wndSmpCnt, wndSmpCnt, 0); ifft::create( p->ft, p->binCnt ); ola::create( p->ola, wndSmpCnt, hopSmpCnt, procSmpCnt, wndTypeId ); @@ -911,29 +971,35 @@ namespace cw // convert db back to magnitude vop::db_to_ampl(X1m, X1m, binN ); + // convert the mean input magnitude to db double idb = 20*log10(u0); // get the mean output magnitude spectra double u1 = vop::mean(X1m,binN); - - if( idb > -150.0 ) + + if( p->mix > 0 ) { - // set the output gain such that the mean output magnitude - // will match the mean input magnitude - p->ogain = u0/u1; + if( idb > -150.0 ) + { + // set the output gain such that the mean output magnitude + // will match the mean input magnitude + p->ogain = u0/u1; + } + else + { + T0 a0 = 0.9; + p->ogain *= a0; + } } - else - { - T0 a0 = 0.9; - p->ogain *= a0; - } - + + // apply the output gain if( p->bypassFl ) vop::copy( p->outMagV, magV, binN ); else vop::mul( p->outMagV, X1m, std::min((T1)4.0,p->ogain), binN); + //vop::mul( p->outMagV, X1m, p->ogain, binN); vop::copy( p->outPhsV, phsV, binN); diff --git a/cwFlowProc.cpp b/cwFlowProc.cpp index d5256c2..f9856a9 100644 --- a/cwFlowProc.cpp +++ b/cwFlowProc.cpp @@ -366,6 +366,8 @@ namespace cw { kFnamePId, kEofFlPId, + kOnOffFlPId, + kSeekSecsPId, kOutPId }; @@ -380,13 +382,19 @@ namespace cw { rc_t rc = kOkRC; audiofile::info_t info; - + real_t seekSecs; inst_t* inst = mem::allocZ(); ctx->userPtr = inst; + if((rc = var_register( ctx, kAnyChIdx, kOnOffFlPId, "on_off" )) != kOkRC ) + { + goto errLabel; + } + // Register variable and get their current value if((rc = var_register_and_get( ctx, kAnyChIdx, kFnamePId, "fname", inst->filename, + kSeekSecsPId, "seekSecs", seekSecs, kEofFlPId, "eofFl", inst->eofFl )) != kOkRC ) { goto errLabel; @@ -399,6 +407,13 @@ namespace cw goto errLabel; } + if((rc = seek( inst->afH, (unsigned)lround(seekSecs*info.srate) )) != kOkRC ) + { + rc = cwLogError(kInvalidArgRC,"The audio file '%s' could not seek to offset %f seconds.",seekSecs); + goto errLabel; + } + + cwLogInfo("Audio '%s' srate:%f chs:%i frames:%i %f seconds.",inst->filename,info.srate,info.chCnt,info.frameCnt, info.frameCnt/info.srate ); // create one output audio buffer - with the same configuration as the source audio file @@ -427,7 +442,21 @@ namespace cw rc_t value( instance_t* ctx, variable_t* var ) { rc_t rc = kOkRC; - return rc; + real_t seekSecs = 0; + inst_t* inst = (inst_t*)ctx->userPtr; + + if((rc = var_get(ctx,kSeekSecsPId,kAnyChIdx,seekSecs)) != kOkRC ) + goto errLabel; + + if((rc = seek( inst->afH, (unsigned)lround(seekSecs * audiofile::sampleRate(inst->afH) ) )) != kOkRC ) + { + rc = cwLogError(kInvalidArgRC,"The audio file '%s' could not seek to offset %f seconds.",seekSecs); + goto errLabel; + } + + + errLabel: + return kOkRC; } rc_t exec( instance_t* ctx ) @@ -436,7 +465,11 @@ namespace cw unsigned actualFrameN = 0; inst_t* inst = (inst_t*)ctx->userPtr; abuf_t* abuf = nullptr; + bool onOffFl = false; + // get the 'on-off; flag + if((rc = var_get(ctx,kOnOffFlPId,kAnyChIdx,onOffFl)) != kOkRC ) + goto errLabel; // verify that a source buffer exists if((rc = var_get(ctx,kOutPId,kAnyChIdx,abuf)) != kOkRC ) @@ -448,14 +481,23 @@ namespace cw sample_t* chBuf[ abuf->chN ]; for(unsigned i=0; ichN; ++i) + { chBuf[i] = abuf->buf + (i*abuf->frameN); - - rc = readFloat(inst->afH, abuf->frameN, 0, abuf->chN, chBuf, &actualFrameN ); + + // if the on/off flag is not set - then fill the output buffer with zeros + if( !onOffFl ) + vop::zero(chBuf[i],abuf->frameN); + } + + // if the on/off flag is set then read from audio file + if( onOffFl ) + rc = readFloat(inst->afH, abuf->frameN, 0, abuf->chN, chBuf, &actualFrameN ); if( inst->eofFl && actualFrameN == 0) rc = kEofRC; } - + + errLabel: return rc; } @@ -503,7 +545,7 @@ namespace cw if((rc = var_register_and_get( ctx, kAnyChIdx, kFnamePId, "fname", inst->filename, kBitsPId, "bits", audioFileBits, - kInPId, "in", src_abuf)) != kOkRC ) + kInPId, "in", src_abuf )) != kOkRC ) { goto errLabel; } @@ -548,7 +590,7 @@ namespace cw rc_t rc = kOkRC; inst_t* inst = (inst_t*)ctx->userPtr; const abuf_t* src_abuf = nullptr; - + if((rc = var_get(ctx,kInPId,kAnyChIdx,src_abuf)) != kOkRC ) rc = cwLogError(kInvalidStateRC,"The audio file instance '%s' does not have a valid input connection.",ctx->label); else @@ -1175,7 +1217,8 @@ namespace cw const abuf_t* abuf0 = nullptr; // const abuf_t* abuf1 = nullptr; unsigned outChN = 0; - + double dum; + // get the source audio buffer if((rc = var_register_and_get(ctx, kAnyChIdx, kIn0PId,"in0",abuf0, @@ -1189,8 +1232,8 @@ namespace cw outChN = std::max(abuf0->chN, abuf1->chN); // register the gain - var_register( ctx, kAnyChIdx, kGain0PId, "gain0" ); - var_register( ctx, kAnyChIdx, kGain1PId, "gain1" ); + var_register_and_get( ctx, kAnyChIdx, kGain0PId, "gain0", dum ); + var_register_and_get( ctx, kAnyChIdx, kGain1PId, "gain1", dum ); // create the output audio buffer rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, abuf0->srate, outChN, abuf0->frameN ); @@ -1224,7 +1267,7 @@ namespace cw sample_t* osig = obuf->buf + i*obuf->frameN; real_t gain = 1; - if((rc = var_get(ctx, gainPId, i, gain)) != kOkRC ) + if((rc = var_get(ctx, gainPId, kAnyChIdx, gain)) != kOkRC ) goto errLabel; for(unsigned j=0; jframeN; ++j) @@ -1241,18 +1284,20 @@ namespace cw { rc_t rc = kOkRC; abuf_t* obuf = nullptr; - const abuf_t* ibuf0 = nullptr; - const abuf_t* ibuf1 = nullptr; + //const abuf_t* ibuf0 = nullptr; + //const abuf_t* ibuf1 = nullptr; if((rc = var_get(ctx,kOutPId, kAnyChIdx, obuf)) != kOkRC ) goto errLabel; - if((rc = var_get(ctx,kIn0PId, kAnyChIdx, ibuf0 )) != 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; + //if((rc = var_get(ctx,kIn1PId, kAnyChIdx, ibuf1 )) != kOkRC ) + // goto errLabel; + vop::zero(obuf->buf, obuf->frameN*obuf->chN ); + _mix( ctx, kIn0PId, kGain0PId, obuf ); _mix( ctx, kIn1PId, kGain1PId, obuf ); @@ -1422,14 +1467,9 @@ namespace cw inst_t* inst = mem::allocZ(); ctx->userPtr = inst; - if((rc = var_register_and_get( ctx, kAnyChIdx, - kInPId, "in", srcBuf, - kMaxWndSmpNPId, "maxWndSmpN", inst->maxWndSmpN, - kWndSmpNPId, "wndSmpN", inst->wndSmpN, - kHopSmpNPId, "hopSmpN", inst->hopSmpN, - kHzFlPId, "hzFl", inst->hzFl )) != kOkRC ) + if((rc = var_register_and_get( ctx, kAnyChIdx,kInPId, "in", srcBuf )) != kOkRC ) { - goto errLabel; + cwLogError(kInvalidArgRC,"Unable to access the 'src' buffer."); } else { @@ -1440,27 +1480,50 @@ namespace cw const sample_t* magV[ srcBuf->chN ]; const sample_t* phsV[ srcBuf->chN ]; const sample_t* hzV[ srcBuf->chN ]; - + unsigned maxBinNV[ srcBuf->chN ]; + unsigned binNV[ srcBuf->chN ]; + unsigned hopNV[ srcBuf->chN ]; + // create a pv anlaysis object for each input channel for(unsigned i=0; ichN; ++i) { - if((rc = create( inst->pvA[i], ctx->ctx->framesPerCycle, srcBuf->srate, inst->maxWndSmpN, inst->wndSmpN, inst->hopSmpN, flags )) != kOkRC ) + + unsigned maxWndSmpN = 0; + unsigned wndSmpN = 0; + unsigned hopSmpN = 0; + bool hzFl = false; + + if((rc = var_register_and_get( ctx, i, + kMaxWndSmpNPId, "maxWndSmpN", maxWndSmpN, + kWndSmpNPId, "wndSmpN", wndSmpN, + kHopSmpNPId, "hopSmpN", hopSmpN, + kHzFlPId, "hzFl", hzFl )) != kOkRC ) + { + goto errLabel; + } + + if((rc = create( inst->pvA[i], ctx->ctx->framesPerCycle, srcBuf->srate, maxWndSmpN, wndSmpN, hopSmpN, flags )) != kOkRC ) { rc = cwLogError(kOpFailRC,"The PV analysis object create failed on the instance '%s'.",ctx->label); goto errLabel; } - magV[i] = inst->pvA[i]->magV; - phsV[i] = inst->pvA[i]->phsV; - hzV[i] = inst->pvA[i]->hzV; + maxBinNV[i] = inst->pvA[i]->maxBinCnt; + binNV[i] = inst->pvA[i]->binCnt; + hopNV[i] = hopSmpN; + + magV[i] = inst->pvA[i]->magV; + phsV[i] = inst->pvA[i]->phsV; + hzV[i] = inst->pvA[i]->hzV; } - if((rc = var_register( ctx, kAnyChIdx, kInPId, "in" )) != kOkRC ) - goto errLabel; - - // create the fbuf 'out' - rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, srcBuf->srate, inst->pvA[0]->maxBinCnt, srcBuf->chN, inst->pvA[0]->binCnt, inst->pvA[0]->hopSmpCnt, magV, phsV, hzV ); + // create the fbuf 'out' + if((rc = var_register_and_set(ctx, "out", kOutPId, kAnyChIdx, srcBuf->srate, srcBuf->chN, maxBinNV, binNV, hopNV, magV, phsV, hzV )) != kOkRC ) + { + cwLogError(kOpFailRC,"The output freq. buffer could not be created."); + goto errLabel; + } } errLabel: @@ -1485,6 +1548,24 @@ namespace cw rc_t value( instance_t* ctx, variable_t* var ) { rc_t rc = kOkRC; + inst_t* inst = (inst_t*)ctx->userPtr; + + if( var->chIdx != kAnyChIdx && var->chIdx < inst->pvN ) + { + unsigned val = 0; + pv_t* pva = inst->pvA[ var->chIdx ]; + + switch( var->vid ) + { + case kWndSmpNPId: + rc = var_get( var, val ); + dsp::pv_anl::set_window_length(pva,val); + //printf("WL:%i %i\n",val,var->chIdx); + break; + } + + } + return rc; } @@ -1751,7 +1832,7 @@ namespace cw } // create the output buffer - if((rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, srcBuf->srate, srcBuf->maxBinN, srcBuf->chN, srcBuf->binN_V, srcBuf->hopSmpN_V, magV, phsV, hzV )) != kOkRC ) + if((rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, srcBuf->srate, srcBuf->chN, srcBuf->maxBinN_V, srcBuf->binN_V, srcBuf->hopSmpN_V, magV, phsV, hzV )) != kOkRC ) goto errLabel; } @@ -1796,8 +1877,8 @@ namespace cw cwLogWarning("Unhandled variable id '%i' on instance: %s.", var->vid, ctx->label ); } - //printf("sd: ceil:%f expo:%f thresh:%f upr:%f lwr:%f mix:%f : rc:%i val:%f\n", - // sd->ceiling, sd->expo, sd->thresh, sd->uprSlope, sd->lwrSlope, sd->mix, rc, val ); + //printf("%i sd: ceil:%f expo:%f thresh:%f upr:%f lwr:%f mix:%f : rc:%i val:%f\n", + // var->chIdx,sd->ceiling, sd->expo, sd->thresh, sd->uprSlope, sd->lwrSlope, sd->mix, rc, val ); } return rc; diff --git a/cwFlowTypes.cpp b/cwFlowTypes.cpp index 202599f..d10086e 100644 --- a/cwFlowTypes.cpp +++ b/cwFlowTypes.cpp @@ -217,7 +217,7 @@ namespace cw case kFloatTFl: valRef = val->u.f!=0; break; case kDoubleTFl: valRef = val->u.d!=0; break; default: - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a bool."); + rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a bool.",val->flags); } return rc; } @@ -233,7 +233,7 @@ namespace cw case kFloatTFl: valRef = (uint_t)val->u.f; break; case kDoubleTFl: valRef = (uint_t)val->u.d; break; default: - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a uint_t."); + rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a uint_t.",val->flags); } return rc; } @@ -249,7 +249,7 @@ namespace cw case kFloatTFl: valRef = (int_t)val->u.f; break; case kDoubleTFl: valRef = (int_t)val->u.d; break; default: - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a int_t."); + rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a int_t.",val->flags); } return rc; } @@ -265,7 +265,7 @@ namespace cw case kFloatTFl: valRef = (float)val->u.f; break; case kDoubleTFl: valRef = (float)val->u.d; break; default: - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a float."); + rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a float.", val->flags); } return rc; } @@ -281,7 +281,7 @@ namespace cw case kFloatTFl: valRef = (double)val->u.f; break; case kDoubleTFl: valRef = val->u.d; break; default: - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a double."); + rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a double.",val->flags); } return rc; } @@ -293,7 +293,7 @@ namespace cw valRef = val->u.s; else { - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a string."); + rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a string.",val->flags); valRef = nullptr; } @@ -307,7 +307,7 @@ namespace cw valRef = val->u.abuf; else { - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to an abuf_t."); + rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to an abuf_t.",val->flags); valRef = nullptr; } return rc; @@ -330,7 +330,7 @@ namespace cw else { valRef = nullptr; - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to an fbuf_t."); + rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to an fbuf_t.",val->flags); } return rc; } @@ -903,33 +903,30 @@ 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 maxBinN, unsigned chN, const unsigned* binN_V, const unsigned* hopSmpN_V, const sample_t** magV, const sample_t** phsV, const sample_t** hzV ) +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 sample_t** magV, const sample_t** phsV, const sample_t** hzV ) { - unsigned curMaxBinN = vop::max(binN_V,chN); - - if( curMaxBinN > maxBinN ) - { - cwLogWarning("A channel bin count (%i) execeeds the max bin count (%i). Max. bin count increased to:%i.",curMaxBinN,maxBinN,curMaxBinN); - maxBinN = curMaxBinN; - } + 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(); f->srate = srate; - f->maxBinN = maxBinN; f->chN = chN; - f->binN_V = mem::allocZ(chN);; + f->maxBinN_V = mem::allocZ(chN); + f->binN_V = mem::allocZ(chN); f->hopSmpN_V = mem::allocZ(chN); f->magV = mem::allocZ(chN); f->phsV = mem::allocZ(chN); f->hzV = mem::allocZ(chN); f->readyFlV = mem::allocZ(chN); - vop::copy( f->binN_V, binN_V, chN ); - vop::copy( f->hopSmpN_V, hopSmpN_V, chN ); - - + vop::copy( f->maxBinN_V, maxBinN_V, chN ); + vop::copy( f->hopSmpN_V, hopSmpN_V, chN ); if( magV != nullptr || phsV != nullptr || hzV != nullptr ) { @@ -942,15 +939,17 @@ cw::flow::fbuf_t* cw::flow::fbuf_create( srate_t srate, unsigned maxBinN, unsign } else { - sample_t* buf = mem::allocZ( kFbufVectN * maxBinN ); + unsigned maxTotalBinsN = vop::sum( maxBinN_V, chN ); + + sample_t* buf = mem::allocZ( kFbufVectN * maxTotalBinsN ); sample_t* m = 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->binN_V[chIdx]; - assert( m <= buf + kFbufVectN * maxBinN ); + m += f->maxBinN_V[chIdx]; + assert( m <= buf + kFbufVectN * maxTotalBinsN ); } f->buf = buf; @@ -961,14 +960,16 @@ cw::flow::fbuf_t* cw::flow::fbuf_create( srate_t srate, unsigned maxBinN, unsign } -cw::flow::fbuf_t* cw::flow::fbuf_create( srate_t srate, unsigned maxBinN, unsigned chN, unsigned binN, unsigned hopSmpN, const sample_t** magV, const sample_t** phsV, const sample_t** hzV ) +cw::flow::fbuf_t* cw::flow::fbuf_create( srate_t srate, unsigned chN, unsigned maxBinN, unsigned binN, unsigned hopSmpN, const sample_t** magV, const sample_t** phsV, const sample_t** hzV ) { + unsigned maxBinN_V[ chN ]; unsigned binN_V[ chN ]; unsigned hopSmpN_V[ chN ]; + vop::fill( maxBinN_V, chN, maxBinN ); vop::fill( binN_V, chN, binN ); vop::fill( hopSmpN_V, chN, binN ); - return fbuf_create( srate, maxBinN, chN, binN_V, hopSmpN_V, magV, phsV, hzV ); + return fbuf_create( srate, chN, maxBinN_V, binN_V, hopSmpN_V, magV, phsV, hzV ); } @@ -979,6 +980,7 @@ void cw::flow::fbuf_destroy( fbuf_t*& fbuf ) if( fbuf == nullptr ) return; + mem::release( fbuf->maxBinN_V ); mem::release( fbuf->binN_V ); mem::release( fbuf->hopSmpN_V); //mem::release( fbuf->magV); @@ -991,10 +993,11 @@ void cw::flow::fbuf_destroy( fbuf_t*& fbuf ) cw::flow::fbuf_t* cw::flow::fbuf_duplicate( const fbuf_t* src ) { - fbuf_t* fbuf = fbuf_create( src->srate, src->maxBinN, src->chN, src->binN_V, src->hopSmpN_V ); + fbuf_t* fbuf = fbuf_create( src->srate, src->chN, src->maxBinN_V, src->binN_V, src->hopSmpN_V ); for(unsigned i=0; ichN; ++i) { + fbuf->maxBinN_V[i] = src->maxBinN_V[i]; fbuf->binN_V[i] = src->binN_V[i]; fbuf->hopSmpN_V[i] = src->hopSmpN_V[i]; @@ -1364,11 +1367,11 @@ cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* va return rc; } -cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned maxBinN, unsigned chN, const unsigned* binN_V, const unsigned* hopSmpN_V, const sample_t** magV, const sample_t** phsV, const sample_t** hzV ) +cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, const unsigned* maxBinN_V, const unsigned* binN_V, const unsigned* hopSmpN_V, const sample_t** magV, const sample_t** phsV, const sample_t** hzV ) { rc_t rc = kOkRC; fbuf_t* fbuf; - if((fbuf = fbuf_create( srate, maxBinN, chN, binN_V, hopSmpN_V, magV, phsV, hzV )) == nullptr ) + if((fbuf = fbuf_create( srate, chN, maxBinN_V, binN_V, hopSmpN_V, magV, phsV, hzV )) == nullptr ) return cwLogError(kOpFailRC,"fbuf create failed on instance:'%s' variable:'%s'.", inst->label, var_label); if((rc = _var_register_and_set( inst, var_label, vid, chIdx, fbuf )) != kOkRC ) @@ -1377,13 +1380,15 @@ cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* var_label return rc; } -cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned maxBinN, unsigned chN, unsigned binN, unsigned hopSmpN, const sample_t** magV, const sample_t** phsV, const sample_t** hzV ) +cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned maxBinN, unsigned binN, unsigned hopSmpN, const sample_t** magV, const sample_t** phsV, const sample_t** hzV ) { + unsigned maxBinN_V[ chN ]; unsigned binN_V[ chN ]; unsigned hopSmpN_V[ chN ]; + vop::fill(maxBinN_V,chN,maxBinN); vop::fill(binN_V,chN,binN); vop::fill(hopSmpN_V,chN, hopSmpN ); - return var_register_and_set(inst,var_label,vid,chIdx,srate,maxBinN, chN,binN_V, hopSmpN_V, magV, phsV, hzV); + return var_register_and_set(inst,var_label,vid,chIdx,srate, chN, maxBinN_V, binN_V, hopSmpN_V, magV, phsV, hzV); } diff --git a/cwFlowTypes.h b/cwFlowTypes.h index f13ea8c..91bdd9e 100644 --- a/cwFlowTypes.h +++ b/cwFlowTypes.h @@ -34,8 +34,8 @@ namespace cw struct value_str* base; srate_t srate; // signal sample rate unsigned flags; // See kXXXFbufFl - unsigned maxBinN; // max value that any value in binN_V[] is allowed to take unsigned chN; // count of channels + unsigned* maxBinN_V; // 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 sample_t** magV; // magV[ chN ][ binN ] @@ -234,8 +234,8 @@ namespace cw 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 maxBinN, unsigned chN, const unsigned* binN_V, const unsigned* hopSmpN_V, const sample_t** magV=nullptr, const sample_t** phsV=nullptr, const sample_t** hzV=nullptr ); - fbuf_t* fbuf_create( srate_t srate, unsigned maxBinN, unsigned chN, unsigned binN, unsigned hopSmpN, const sample_t** magV=nullptr, const sample_t** phsV=nullptr, const sample_t** hzV=nullptr ); + fbuf_t* fbuf_create( srate_t srate, unsigned chN, const unsigned* maxBinN_V, const unsigned* binN_V, const unsigned* hopSmpN_V, const sample_t** magV=nullptr, const sample_t** phsV=nullptr, const sample_t** hzV=nullptr ); + fbuf_t* fbuf_create( srate_t srate, unsigned chN, unsigned maxBinN, 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 ); @@ -370,8 +370,8 @@ namespace cw 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 maxBinN, unsigned chN, const unsigned* binN_V, const unsigned* hopSmpN_V, const sample_t** magV=nullptr, const sample_t** phsV=nullptr, const sample_t** hzV=nullptr ); - rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned maxBinN, unsigned chN, unsigned binN, unsigned hopSmpN, const sample_t** magV=nullptr, const sample_t** phsV=nullptr, const sample_t** hzV=nullptr ); + rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, const unsigned* maxBinN_V, const unsigned* binN_V, const unsigned* hopSmpN_V, const sample_t** magV=nullptr, const sample_t** phsV=nullptr, const sample_t** hzV=nullptr ); + rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned maxBinN, 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; }