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.
This commit is contained in:
kevin 2022-12-27 18:09:31 -05:00
parent a2f459c5fb
commit cbaff98964
6 changed files with 279 additions and 126 deletions

View File

@ -385,14 +385,14 @@ cw::rc_t cw::afop::file_processor( const char* srcFn, const char* dstFn, proc_fu
for(unsigned i = 0; i<proc_ctx.srcChN; ++i)
{
srcChFileBuf[i] = srcFileBuf + (i*proc_ctx.srcHopSmpN );
dsp::shift_buf::create( srcShiftBufA[i], proc_ctx.srcHopSmpN, proc_ctx.srcWndSmpN, proc_ctx.srcHopSmpN );
dsp::shift_buf::create( srcShiftBufA[i], proc_ctx.srcHopSmpN, proc_ctx.srcWndSmpN, proc_ctx.srcWndSmpN, proc_ctx.srcHopSmpN );
}
// For each dest. channel - setup the dest file buffer and create the dst shift buffer
for(unsigned i = 0; i<proc_ctx.dstChN; ++i)
{
oChBuf[i] = procFileBuf + (i*proc_ctx.dstHopSmpN );
dsp::shift_buf::create( dstShiftBufA[i], proc_ctx.dstHopSmpN, proc_ctx.dstWndSmpN, proc_ctx.dstHopSmpN );
dsp::shift_buf::create( dstShiftBufA[i], proc_ctx.dstHopSmpN, proc_ctx.dstWndSmpN, proc_ctx.dstWndSmpN, proc_ctx.dstHopSmpN );
}
// create the data recorder

View File

@ -39,14 +39,14 @@ namespace cw
unsigned wndLabelToId( const char* label )
{ return cw::labelToId( wndLabelArray, label, kInvalidWndId ); }
rc_t _test( const char* windowLabel, const double* wndV, unsigned wndN )
rc_t _test( const char* windowLabel, const double* wndV, unsigned maxWndN, unsigned wndN )
{
rc_t rc = kOkRC;
wnd_func::fobj_t* p = nullptr;
unsigned wndId = wndLabelToId( windowLabel );
if((rc = create(p,wndId,wndN,3)) == kOkRC )
if((rc = create(p,wndId,maxWndN,wndN,3)) == kOkRC )
{
vop::print(p->wndV, 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<sample_t>(iSmpCnt);
sample_t* y = mem::allocZ<sample_t>(oSmpCnt);

View File

@ -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<sample_t>*& p, unsigned wndId, unsigned wndSmpCnt, double kaiserSideLobeRejectDb )
rc_t _apply_window( struct obj_str<sample_t>*& p )
{
rc_t rc = kOkRC;
p = mem::allocZ< struct obj_str< sample_t > >();
p->wndV = mem::allocZ<sample_t>(wndSmpCnt);
p->outV = mem::allocZ<sample_t>(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<sample_t>(kaiserSideLobeRejectDb);
sample_t beta = (p->flags & kSlRejIsBetaWndFl) ? p->kaiserSLRejectDb : kaiser_beta_from_sidelobe_reject<sample_t>(p->kaiserSLRejectDb);
kaiser<sample_t>(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<sample_t>*& 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<sample_t>(maxWndSmpCnt);
p->outV = mem::allocZ<sample_t>(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<sample_t>* 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<sample_t> >();
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<sample_t>( 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<double> dobj_t;
template< typename sample_t >
rc_t create( struct obj_str<sample_t>*& p, unsigned procSmpCnt, unsigned wndSmpCnt, unsigned hopSmpCnt )
rc_t create( struct obj_str<sample_t>*& p, unsigned procSmpCnt, unsigned maxWndSmpCnt, unsigned wndSmpCnt, unsigned hopSmpCnt )
{
rc_t rc = kOkRC;
p = mem::allocZ< struct obj_str<sample_t> >();
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<sample_t>( 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<sample_t>* 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<T> >();
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<T>* 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<T>( 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);

View File

@ -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<inst_t>();
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; i<abuf->chN; ++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; j<obuf->frameN; ++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<inst_t>();
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; i<srcBuf->chN; ++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;

View File

@ -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<chN; ++i)
if( binN_V[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<fbuf_t>();
f->srate = srate;
f->maxBinN = maxBinN;
f->chN = chN;
f->binN_V = mem::allocZ<unsigned>(chN);;
f->maxBinN_V = mem::allocZ<unsigned>(chN);
f->binN_V = mem::allocZ<unsigned>(chN);
f->hopSmpN_V = mem::allocZ<unsigned>(chN);
f->magV = mem::allocZ<sample_t*>(chN);
f->phsV = mem::allocZ<sample_t*>(chN);
f->hzV = mem::allocZ<sample_t*>(chN);
f->readyFlV = mem::allocZ<bool>(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<sample_t>( kFbufVectN * maxBinN );
unsigned maxTotalBinsN = vop::sum( maxBinN_V, chN );
sample_t* buf = mem::allocZ<sample_t>( kFbufVectN * maxTotalBinsN );
sample_t* m = buf;
for(unsigned chIdx=0; chIdx<chN; ++chIdx)
{
f->magV[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; i<fbuf->chN; ++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);
}

View File

@ -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; }