Merge branch 'master' of gitea.larke.org:kevin/libcw
This commit is contained in:
commit
a3b395df4a
@ -119,7 +119,7 @@ namespace cw
|
|||||||
|
|
||||||
for(unsigned i=0; i<p->chCnt; ++i)
|
for(unsigned i=0; i<p->chCnt; ++i)
|
||||||
{
|
{
|
||||||
if((rc = dsp::pv_anl::create( p->anlA[i], p->procSmpN, ctx->srcSrate, p->wndSmpN, p->hopSmpN, dsp::pv_anl::kNoCalcHzPvaFl )) != kOkRC )
|
if((rc = dsp::pv_anl::create( p->anlA[i], p->procSmpN, ctx->srcSrate, p->wndSmpN, p->wndSmpN, p->hopSmpN, dsp::pv_anl::kNoCalcHzPvaFl )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"PVOC analysis component create failed.");
|
rc = cwLogError(rc,"PVOC analysis component create failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
@ -234,7 +234,7 @@ namespace cw
|
|||||||
unsigned flags = kCalcHzPvaFl;
|
unsigned flags = kCalcHzPvaFl;
|
||||||
unsigned wndTypeId = wnd_func::kHannWndId;
|
unsigned wndTypeId = wnd_func::kHannWndId;
|
||||||
|
|
||||||
if((rc = create( pva, procSmpCnt, srate, wndSmpCnt, hopSmpCnt, flags )) != kOkRC )
|
if((rc = create( pva, procSmpCnt, srate, wndSmpCnt, wndSmpCnt, hopSmpCnt, flags )) != kOkRC )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,6 +500,10 @@ namespace cw
|
|||||||
unsigned flags;
|
unsigned flags;
|
||||||
unsigned procSmpCnt;
|
unsigned procSmpCnt;
|
||||||
T srate;
|
T srate;
|
||||||
|
|
||||||
|
unsigned maxWndSmpCnt;
|
||||||
|
unsigned maxBinCnt;
|
||||||
|
|
||||||
unsigned wndSmpCnt;
|
unsigned wndSmpCnt;
|
||||||
unsigned hopSmpCnt;
|
unsigned hopSmpCnt;
|
||||||
unsigned binCnt;
|
unsigned binCnt;
|
||||||
@ -514,7 +518,7 @@ namespace cw
|
|||||||
typedef obj_str< double> dobj_t;
|
typedef obj_str< double> dobj_t;
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
rc_t create( struct obj_str<T>*& p, unsigned procSmpCnt, const T& srate, unsigned wndSmpCnt, unsigned hopSmpCnt, unsigned flags )
|
rc_t create( struct obj_str<T>*& p, unsigned procSmpCnt, const T& srate, unsigned maxWndSmpCnt, unsigned wndSmpCnt, unsigned hopSmpCnt, unsigned flags )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
@ -527,6 +531,8 @@ namespace cw
|
|||||||
|
|
||||||
p->flags = flags;
|
p->flags = flags;
|
||||||
p->procSmpCnt = procSmpCnt;
|
p->procSmpCnt = procSmpCnt;
|
||||||
|
p->maxWndSmpCnt = maxWndSmpCnt;
|
||||||
|
p->maxBinCnt = fft::window_sample_count_to_bin_count(maxWndSmpCnt);
|
||||||
p->wndSmpCnt = wndSmpCnt;
|
p->wndSmpCnt = wndSmpCnt;
|
||||||
p->hopSmpCnt = hopSmpCnt;
|
p->hopSmpCnt = hopSmpCnt;
|
||||||
p->binCnt = p->ft->binN;
|
p->binCnt = p->ft->binN;
|
||||||
|
@ -12,6 +12,12 @@
|
|||||||
// fft
|
// fft
|
||||||
//
|
//
|
||||||
|
|
||||||
|
unsigned cw::dsp::fft::window_sample_count_to_bin_count( unsigned wndSmpN )
|
||||||
|
{ return wndSmpN/2 + 1; }
|
||||||
|
|
||||||
|
unsigned cw::dsp::fft::bin_count_to_window_sample_count( unsigned binN )
|
||||||
|
{ return (binN-1) * 2; }
|
||||||
|
|
||||||
cw::rc_t cw::dsp::fft::test()
|
cw::rc_t cw::dsp::fft::test()
|
||||||
{
|
{
|
||||||
typedef float real_t;
|
typedef float real_t;
|
||||||
|
8
cwDsp.h
8
cwDsp.h
@ -196,6 +196,10 @@ namespace cw
|
|||||||
namespace fft
|
namespace fft
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
unsigned window_sample_count_to_bin_count( unsigned wndSmpN );
|
||||||
|
unsigned bin_count_to_window_sample_count( unsigned binN );
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kToPolarFl = 0x01, // convert to polar (magn./phase)
|
kToPolarFl = 0x01, // convert to polar (magn./phase)
|
||||||
@ -231,7 +235,7 @@ namespace cw
|
|||||||
|
|
||||||
p->flags = flags;
|
p->flags = flags;
|
||||||
p->inN = xN;
|
p->inN = xN;
|
||||||
p->binN = xN/2 + 1;
|
p->binN = window_sample_count_to_bin_count(xN);
|
||||||
p->magV = mem::allocZ<T>(p->binN);
|
p->magV = mem::allocZ<T>(p->binN);
|
||||||
p->phsV = mem::allocZ<T>(p->binN);
|
p->phsV = mem::allocZ<T>(p->binN);
|
||||||
|
|
||||||
@ -368,7 +372,7 @@ namespace cw
|
|||||||
p = mem::allocZ< obj_str<T> >(1);
|
p = mem::allocZ< obj_str<T> >(1);
|
||||||
|
|
||||||
p->binN = binN;
|
p->binN = binN;
|
||||||
p->outN = (binN-1)*2;
|
p->outN = fft::bin_count_to_window_sample_count(binN);
|
||||||
|
|
||||||
if( std::is_same<T,float>::value )
|
if( std::is_same<T,float>::value )
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,10 @@ namespace cw
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------
|
||||||
|
// compressor
|
||||||
|
//
|
||||||
|
|
||||||
cw::rc_t cw::dsp::compressor::create( obj_t*& p, real_t srate, unsigned procSmpCnt, real_t inGain, real_t rmsWndMaxMs, real_t rmsWndMs, real_t threshDb, real_t ratio_num, real_t atkMs, real_t rlsMs, real_t outGain, bool bypassFl )
|
cw::rc_t cw::dsp::compressor::create( obj_t*& p, real_t srate, unsigned procSmpCnt, real_t inGain, real_t rmsWndMaxMs, real_t rmsWndMs, real_t threshDb, real_t ratio_num, real_t atkMs, real_t rlsMs, real_t outGain, bool bypassFl )
|
||||||
{
|
{
|
||||||
p = mem::allocZ<obj_t>();
|
p = mem::allocZ<obj_t>();
|
||||||
@ -162,7 +166,111 @@ void cw::dsp::compressor::set_rms_wnd_ms( obj_t* p, real_t ms )
|
|||||||
p->rmsWndCnt = p->rmsWndAllocCnt;
|
p->rmsWndCnt = p->rmsWndAllocCnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------
|
||||||
|
// Limiter
|
||||||
|
//
|
||||||
|
|
||||||
|
cw::rc_t cw::dsp::limiter::create( obj_t*& p, real_t srate, unsigned procSmpCnt, real_t thresh, real_t igain, real_t ogain, bool bypassFl )
|
||||||
|
{
|
||||||
|
p = mem::allocZ<obj_t>();
|
||||||
|
|
||||||
|
p->procSmpCnt = procSmpCnt;
|
||||||
|
p->thresh = thresh;
|
||||||
|
p->igain = igain;
|
||||||
|
p->ogain = ogain;
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::dsp::limiter::destroy( obj_t*& p )
|
||||||
|
{
|
||||||
|
mem::release(p);
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::dsp::limiter::exec( obj_t* p, const sample_t* x, sample_t* y, unsigned n )
|
||||||
|
{
|
||||||
|
if( p->bypassFl )
|
||||||
|
{
|
||||||
|
vop::copy(y,x,n); // copy through - with no input gain
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
real_t T = p->thresh * p->ogain;
|
||||||
|
|
||||||
|
for(unsigned i=0; i<n; ++i)
|
||||||
|
{
|
||||||
|
sample_t mx = 0.999;
|
||||||
|
sample_t s = x[i] < 0.0 ? -mx : mx;
|
||||||
|
sample_t v = fabsf(x[i]) * p->igain;
|
||||||
|
|
||||||
|
if( v >= mx )
|
||||||
|
y[i] = s;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( v < p->thresh )
|
||||||
|
{
|
||||||
|
y[i] = s * T * v/p->thresh;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// apply a linear limiting function
|
||||||
|
y[i] = s * (T + (1.0f-T) * (v-p->thresh)/(1.0f-p->thresh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------
|
||||||
|
// dc-filter
|
||||||
|
//
|
||||||
|
|
||||||
|
cw::rc_t cw::dsp::dc_filter::create( obj_t*& p, real_t srate, unsigned procSmpCnt, real_t gain, bool bypassFl )
|
||||||
|
{
|
||||||
|
p = mem::allocZ<obj_t>();
|
||||||
|
|
||||||
|
p->gain = gain;
|
||||||
|
p->bypassFl = bypassFl;
|
||||||
|
p->b0 = 1;
|
||||||
|
p->b[0] = -1;
|
||||||
|
p->a[0] = -0.999;
|
||||||
|
p->d[0] = 0;
|
||||||
|
p->d[1] = 0;
|
||||||
|
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::dsp::dc_filter::destroy( obj_t*& pp )
|
||||||
|
{
|
||||||
|
mem::release(pp);
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::dsp::dc_filter::exec( obj_t* p, const sample_t* x, sample_t* y, unsigned n )
|
||||||
|
{
|
||||||
|
|
||||||
|
if( p->bypassFl )
|
||||||
|
vop::copy(y,x,n);
|
||||||
|
else
|
||||||
|
vop::filter<sample_t,real_t>(y,n,x,n,p->b0, p->b, p->a, p->d, 1 );
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::dsp::dc_filter::set( obj_t* p, real_t gain, bool bypassFl )
|
||||||
|
{
|
||||||
|
p->gain = gain;
|
||||||
|
p->bypassFl = bypassFl;
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------
|
||||||
|
// Recorder
|
||||||
|
//
|
||||||
|
|
||||||
cw::rc_t cw::dsp::recorder::create( obj_t*& pRef, real_t srate, real_t max_secs, unsigned chN )
|
cw::rc_t cw::dsp::recorder::create( obj_t*& pRef, real_t srate, real_t max_secs, unsigned chN )
|
||||||
{
|
{
|
||||||
|
@ -46,6 +46,40 @@ namespace cw
|
|||||||
void set_rms_wnd_ms( obj_t* p, real_t ms );
|
void set_rms_wnd_ms( obj_t* p, real_t ms );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace limiter
|
||||||
|
{
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned procSmpCnt;
|
||||||
|
real_t igain; // applied before thresholding
|
||||||
|
real_t thresh; // linear (0.0-1.0) threshold.
|
||||||
|
real_t ogain; // applied after thresholding
|
||||||
|
bool bypassFl;
|
||||||
|
} obj_t;
|
||||||
|
|
||||||
|
rc_t create( obj_t*& p, real_t srate, unsigned procSmpCnt, real_t thresh, real_t igain, real_t ogain, bool bypassFl );
|
||||||
|
rc_t destroy( obj_t*& pp );
|
||||||
|
rc_t exec( obj_t* p, const sample_t* x, sample_t* y, unsigned n );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace dc_filter
|
||||||
|
{
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
real_t d[2]; //
|
||||||
|
real_t b[1]; //
|
||||||
|
real_t a[1]; // a[dn] feedback coeff's
|
||||||
|
real_t b0; // feedforward coeff 0
|
||||||
|
bool bypassFl;
|
||||||
|
real_t gain;
|
||||||
|
} obj_t;
|
||||||
|
|
||||||
|
rc_t create( obj_t*& p, real_t srate, unsigned procSmpCnt, real_t gain, bool bypassFl );
|
||||||
|
rc_t destroy( obj_t*& pp );
|
||||||
|
rc_t exec( obj_t* p, const sample_t* x, sample_t* y, unsigned n );
|
||||||
|
rc_t set( obj_t* p, real_t gain, bool bypassFl );
|
||||||
|
}
|
||||||
|
|
||||||
namespace recorder
|
namespace recorder
|
||||||
{
|
{
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -37,7 +37,9 @@ namespace cw
|
|||||||
{ "pv_synthesis", &pv_synthesis::members },
|
{ "pv_synthesis", &pv_synthesis::members },
|
||||||
{ "spec_dist", &spec_dist::members },
|
{ "spec_dist", &spec_dist::members },
|
||||||
{ "compressor", &compressor::members },
|
{ "compressor", &compressor::members },
|
||||||
|
{ "limiter", &limiter::members },
|
||||||
{ "audio_delay", &audio_delay::members },
|
{ "audio_delay", &audio_delay::members },
|
||||||
|
{ "dc_filter", &dc_filter::members },
|
||||||
{ "balance", &balance::members },
|
{ "balance", &balance::members },
|
||||||
{ nullptr, nullptr }
|
{ nullptr, nullptr }
|
||||||
};
|
};
|
||||||
|
356
cwFlowProc.cpp
356
cwFlowProc.cpp
@ -1396,8 +1396,9 @@ namespace cw
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
kInPId,
|
kInPId,
|
||||||
kHopSmpNPId,
|
kMaxWndSmpNPId,
|
||||||
kWndSmpNPId,
|
kWndSmpNPId,
|
||||||
|
kHopSmpNPId,
|
||||||
kHzFlPId,
|
kHzFlPId,
|
||||||
kOutPId
|
kOutPId
|
||||||
};
|
};
|
||||||
@ -1406,6 +1407,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
pv_t** pvA; // pvA[ srcBuf.chN ]
|
pv_t** pvA; // pvA[ srcBuf.chN ]
|
||||||
unsigned pvN;
|
unsigned pvN;
|
||||||
|
unsigned maxWndSmpN;
|
||||||
unsigned wndSmpN;
|
unsigned wndSmpN;
|
||||||
unsigned hopSmpN;
|
unsigned hopSmpN;
|
||||||
bool hzFl;
|
bool hzFl;
|
||||||
@ -1422,8 +1424,9 @@ namespace cw
|
|||||||
|
|
||||||
if((rc = var_register_and_get( ctx, kAnyChIdx,
|
if((rc = var_register_and_get( ctx, kAnyChIdx,
|
||||||
kInPId, "in", srcBuf,
|
kInPId, "in", srcBuf,
|
||||||
kHopSmpNPId, "hopSmpN", inst->hopSmpN,
|
kMaxWndSmpNPId, "maxWndSmpN", inst->maxWndSmpN,
|
||||||
kWndSmpNPId, "wndSmpN", inst->wndSmpN,
|
kWndSmpNPId, "wndSmpN", inst->wndSmpN,
|
||||||
|
kHopSmpNPId, "hopSmpN", inst->hopSmpN,
|
||||||
kHzFlPId, "hzFl", inst->hzFl )) != kOkRC )
|
kHzFlPId, "hzFl", inst->hzFl )) != kOkRC )
|
||||||
{
|
{
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -1441,7 +1444,7 @@ namespace cw
|
|||||||
// create a pv anlaysis object for each input channel
|
// create a pv anlaysis object for each input channel
|
||||||
for(unsigned i=0; i<srcBuf->chN; ++i)
|
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||||
{
|
{
|
||||||
if((rc = create( inst->pvA[i], ctx->ctx->framesPerCycle, srcBuf->srate, inst->wndSmpN, inst->hopSmpN, flags )) != kOkRC )
|
if((rc = create( inst->pvA[i], ctx->ctx->framesPerCycle, srcBuf->srate, inst->maxWndSmpN, inst->wndSmpN, inst->hopSmpN, flags )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kOpFailRC,"The PV analysis object create failed on the instance '%s'.",ctx->label);
|
rc = cwLogError(kOpFailRC,"The PV analysis object create failed on the instance '%s'.",ctx->label);
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -1456,7 +1459,7 @@ namespace cw
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
// create the fbuf 'out'
|
// create the fbuf 'out'
|
||||||
rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, srcBuf->srate, srcBuf->chN, inst->pvA[0]->binCnt, inst->pvA[0]->hopSmpCnt, magV, phsV, hzV );
|
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 );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1515,7 +1518,7 @@ namespace cw
|
|||||||
if( dsp::pv_anl::exec( inst->pvA[i], srcBuf->buf + i*srcBuf->frameN, srcBuf->frameN ) )
|
if( dsp::pv_anl::exec( inst->pvA[i], srcBuf->buf + i*srcBuf->frameN, srcBuf->frameN ) )
|
||||||
{
|
{
|
||||||
// rescale the frequency domain magnitude
|
// rescale the frequency domain magnitude
|
||||||
vop::mul(dstBuf->magV[i], dstBuf->binN/2, dstBuf->binN);
|
vop::mul(dstBuf->magV[i], dstBuf->binN_V[i]/2, dstBuf->binN_V[i]);
|
||||||
|
|
||||||
dstBuf->readyFlV[i] = true;
|
dstBuf->readyFlV[i] = true;
|
||||||
|
|
||||||
@ -1580,9 +1583,9 @@ namespace cw
|
|||||||
// create a pv anlaysis object for each input channel
|
// create a pv anlaysis object for each input channel
|
||||||
for(unsigned i=0; i<srcBuf->chN; ++i)
|
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||||
{
|
{
|
||||||
unsigned wndSmpN = (srcBuf->binN-1)*2;
|
unsigned wndSmpN = (srcBuf->binN_V[i]-1)*2;
|
||||||
|
|
||||||
if((rc = create( inst->pvA[i], ctx->ctx->framesPerCycle, srcBuf->srate, wndSmpN, srcBuf->hopSmpN )) != kOkRC )
|
if((rc = create( inst->pvA[i], ctx->ctx->framesPerCycle, srcBuf->srate, wndSmpN, srcBuf->hopSmpN_V[i] )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kOpFailRC,"The PV synthesis object create failed on the instance '%s'.",ctx->label);
|
rc = cwLogError(kOpFailRC,"The PV synthesis object create failed on the instance '%s'.",ctx->label);
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -1719,7 +1722,7 @@ namespace cw
|
|||||||
// create a spec_dist object for each input channel
|
// create a spec_dist object for each input channel
|
||||||
for(unsigned i=0; i<srcBuf->chN; ++i)
|
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||||
{
|
{
|
||||||
if((rc = create( inst->sdA[i], srcBuf->binN )) != kOkRC )
|
if((rc = create( inst->sdA[i], srcBuf->binN_V[i] )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kOpFailRC,"The 'spec dist' object create failed on the instance '%s'.",ctx->label);
|
rc = cwLogError(kOpFailRC,"The 'spec dist' object create failed on the instance '%s'.",ctx->label);
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -1746,7 +1749,7 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create the output buffer
|
// create the output buffer
|
||||||
if((rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, srcBuf->srate, srcBuf->chN, srcBuf->binN, srcBuf->hopSmpN, magV, phsV, hzV )) != kOkRC )
|
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 )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1820,7 +1823,7 @@ namespace cw
|
|||||||
dstBuf->readyFlV[i] = false;
|
dstBuf->readyFlV[i] = false;
|
||||||
if( srcBuf->readyFlV[i] )
|
if( srcBuf->readyFlV[i] )
|
||||||
{
|
{
|
||||||
dsp::spec_dist::exec( inst->sdA[i], srcBuf->magV[i], srcBuf->phsV[i], srcBuf->binN );
|
dsp::spec_dist::exec( inst->sdA[i], srcBuf->magV[i], srcBuf->phsV[i], srcBuf->binN_V[i] );
|
||||||
|
|
||||||
dstBuf->readyFlV[i] = true;
|
dstBuf->readyFlV[i] = true;
|
||||||
//If == 0 )
|
//If == 0 )
|
||||||
@ -1897,7 +1900,8 @@ namespace cw
|
|||||||
// create a compressor object for each input channel
|
// create a compressor object for each input channel
|
||||||
for(unsigned i=0; i<srcBuf->chN; ++i)
|
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||||
{
|
{
|
||||||
real_t igain, maxWnd_ms, wnd_ms, thresh, ratio, atk_ms, rls_ms, ogain, bypassFl;
|
real_t igain, maxWnd_ms, wnd_ms, thresh, ratio, atk_ms, rls_ms, ogain;
|
||||||
|
bool bypassFl;
|
||||||
|
|
||||||
|
|
||||||
// get the compressor variable values
|
// get the compressor variable values
|
||||||
@ -2033,6 +2037,184 @@ namespace cw
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Limiter
|
||||||
|
//
|
||||||
|
namespace limiter
|
||||||
|
{
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kInPId,
|
||||||
|
kBypassPId,
|
||||||
|
kInGainPId,
|
||||||
|
kThreshPId,
|
||||||
|
kOutGainPId,
|
||||||
|
kOutPId,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef dsp::limiter::obj_t limiter_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
limiter_t** limA;
|
||||||
|
unsigned limN;
|
||||||
|
} inst_t;
|
||||||
|
|
||||||
|
|
||||||
|
rc_t create( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
const abuf_t* srcBuf = nullptr; //
|
||||||
|
inst_t* inst = mem::allocZ<inst_t>();
|
||||||
|
|
||||||
|
ctx->userPtr = inst;
|
||||||
|
|
||||||
|
// verify that a source buffer exists
|
||||||
|
if((rc = var_register_and_get(ctx, kAnyChIdx,kInPId,"in",srcBuf )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"The instance '%s' does not have a valid input connection.",ctx->label);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// allocate pv channel array
|
||||||
|
inst->limN = srcBuf->chN;
|
||||||
|
inst->limA = mem::allocZ<limiter_t*>( inst->limN );
|
||||||
|
|
||||||
|
// create a limiter object for each input channel
|
||||||
|
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||||
|
{
|
||||||
|
real_t igain, thresh, ogain;
|
||||||
|
bool bypassFl;
|
||||||
|
|
||||||
|
|
||||||
|
// get the limiter variable values
|
||||||
|
if((rc = var_register_and_get( ctx, i,
|
||||||
|
kBypassPId, "bypass", bypassFl,
|
||||||
|
kInGainPId, "igain", igain,
|
||||||
|
kThreshPId, "thresh", thresh,
|
||||||
|
kOutGainPId, "ogain", ogain )) != kOkRC )
|
||||||
|
{
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the limiter instance
|
||||||
|
if((rc = dsp::limiter::create( inst->limA[i], srcBuf->srate, srcBuf->frameN, igain, thresh, ogain, bypassFl)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kOpFailRC,"The 'limiter' object create failed on the instance '%s'.",ctx->label);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the output audio buffer
|
||||||
|
if((rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, srcBuf->srate, srcBuf->chN, srcBuf->frameN )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t destroy( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
for(unsigned i=0; i<inst->limN; ++i)
|
||||||
|
destroy(inst->limA[i]);
|
||||||
|
|
||||||
|
mem::release(inst->limA);
|
||||||
|
mem::release(inst);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t value( instance_t* ctx, variable_t* var )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
real_t rtmp;
|
||||||
|
bool btmp;
|
||||||
|
|
||||||
|
if( var->chIdx != kAnyChIdx && var->chIdx < inst->limN )
|
||||||
|
{
|
||||||
|
limiter_t* c = inst->limA[ var->chIdx ];
|
||||||
|
|
||||||
|
switch( var->vid )
|
||||||
|
{
|
||||||
|
case kBypassPId: rc = var_get( var, btmp ); c->bypassFl=btmp; break;
|
||||||
|
case kInGainPId: rc = var_get( var, rtmp ); c->igain=rtmp; break;
|
||||||
|
case kOutGainPId: rc = var_get( var, rtmp ); c->ogain=rtmp; break;
|
||||||
|
case kThreshPId: rc = var_get( var, rtmp ); c->thresh=rtmp; break;
|
||||||
|
default:
|
||||||
|
cwLogWarning("Unhandled variable id '%i' on instance: %s.", var->vid, ctx->label );
|
||||||
|
}
|
||||||
|
//printf("lim byp:%i igain:%f ogain:%f rat:%f thresh:%f atk:%i rls:%i wnd:%i : rc:%i val:%f\n",
|
||||||
|
// c->bypassFl, c->inGain, c->outGain,c->ratio_num,c->threshDb,c->atkSmp,c->rlsSmp,c->rmsWndCnt,rc,tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t exec( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
const abuf_t* srcBuf = nullptr;
|
||||||
|
abuf_t* dstBuf = nullptr;
|
||||||
|
unsigned chN = 0;
|
||||||
|
|
||||||
|
// get the src buffer
|
||||||
|
if((rc = var_get(ctx,kInPId, kAnyChIdx, srcBuf )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// get the dst buffer
|
||||||
|
if((rc = var_get(ctx,kOutPId, kAnyChIdx, dstBuf)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
chN = std::min(srcBuf->chN,inst->limN);
|
||||||
|
|
||||||
|
for(unsigned i=0; i<chN; ++i)
|
||||||
|
{
|
||||||
|
dsp::limiter::exec( inst->limA[i], srcBuf->buf + i*srcBuf->frameN, dstBuf->buf + i*srcBuf->frameN, srcBuf->frameN );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t report( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
for(unsigned i=0; i<inst->limN; ++i)
|
||||||
|
{
|
||||||
|
limiter_t* c = inst->limA[i];
|
||||||
|
cwLogInfo("%s ch:%i : bypass:%i procSmpN:%i igain:%f threshdb:%f ogain:%f",
|
||||||
|
ctx->label,i,c->bypassFl,c->procSmpCnt,c->igain,c->thresh,c->ogain );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
class_members_t members = {
|
||||||
|
.create = create,
|
||||||
|
.destroy = destroy,
|
||||||
|
.value = value,
|
||||||
|
.exec = exec,
|
||||||
|
.report = report
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// audio_delay
|
// audio_delay
|
||||||
@ -2177,7 +2359,159 @@ namespace cw
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// DC Filter
|
||||||
|
//
|
||||||
|
namespace dc_filter
|
||||||
|
{
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kInPId,
|
||||||
|
kBypassPId,
|
||||||
|
kGainPId,
|
||||||
|
kOutPId,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef dsp::dc_filter::obj_t dc_filter_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
dc_filter_t** dcfA;
|
||||||
|
unsigned dcfN;
|
||||||
|
} inst_t;
|
||||||
|
|
||||||
|
|
||||||
|
rc_t create( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
const abuf_t* srcBuf = nullptr; //
|
||||||
|
inst_t* inst = mem::allocZ<inst_t>();
|
||||||
|
|
||||||
|
ctx->userPtr = inst;
|
||||||
|
|
||||||
|
// verify that a source buffer exists
|
||||||
|
if((rc = var_register_and_get(ctx, kAnyChIdx,kInPId,"in",srcBuf )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"The instance '%s' does not have a valid input connection.",ctx->label);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// allocate channel array
|
||||||
|
inst->dcfN = srcBuf->chN;
|
||||||
|
inst->dcfA = mem::allocZ<dc_filter_t*>( inst->dcfN );
|
||||||
|
|
||||||
|
// create a dc_filter object for each input channel
|
||||||
|
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||||
|
{
|
||||||
|
real_t gain;
|
||||||
|
bool bypassFl;
|
||||||
|
|
||||||
|
|
||||||
|
// get the dc_filter variable values
|
||||||
|
if((rc = var_register_and_get( ctx, i,
|
||||||
|
kBypassPId, "bypass", bypassFl,
|
||||||
|
kGainPId, "gain", gain )) != kOkRC )
|
||||||
|
{
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the dc_filter instance
|
||||||
|
if((rc = dsp::dc_filter::create( inst->dcfA[i], srcBuf->srate, srcBuf->frameN, gain, bypassFl)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kOpFailRC,"The 'dc_filter' object create failed on the instance '%s'.",ctx->label);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the output audio buffer
|
||||||
|
if((rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, srcBuf->srate, srcBuf->chN, srcBuf->frameN )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t destroy( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
for(unsigned i=0; i<inst->dcfN; ++i)
|
||||||
|
destroy(inst->dcfA[i]);
|
||||||
|
|
||||||
|
mem::release(inst->dcfA);
|
||||||
|
mem::release(inst);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t value( instance_t* ctx, variable_t* var )
|
||||||
|
{
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t exec( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
const abuf_t* srcBuf = nullptr;
|
||||||
|
abuf_t* dstBuf = nullptr;
|
||||||
|
unsigned chN = 0;
|
||||||
|
|
||||||
|
// get the src buffer
|
||||||
|
if((rc = var_get(ctx,kInPId, kAnyChIdx, srcBuf )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// get the dst buffer
|
||||||
|
if((rc = var_get(ctx,kOutPId, kAnyChIdx, dstBuf)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
chN = std::min(srcBuf->chN,inst->dcfN);
|
||||||
|
|
||||||
|
for(unsigned i=0; i<chN; ++i)
|
||||||
|
{
|
||||||
|
real_t gain = val_get<real_t>( ctx, kGainPId, i );
|
||||||
|
bool bypassFl = val_get<bool>( ctx, kBypassPId, i );
|
||||||
|
|
||||||
|
dsp::dc_filter::set( inst->dcfA[i], gain, bypassFl );
|
||||||
|
|
||||||
|
dsp::dc_filter::exec( inst->dcfA[i], srcBuf->buf + i*srcBuf->frameN, dstBuf->buf + i*srcBuf->frameN, srcBuf->frameN );
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t report( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
for(unsigned i=0; i<inst->dcfN; ++i)
|
||||||
|
{
|
||||||
|
dc_filter_t* c = inst->dcfA[i];
|
||||||
|
cwLogInfo("%s ch:%i : bypass:%i gain:%f",
|
||||||
|
ctx->label,i,c->bypassFl,c->gain );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
class_members_t members = {
|
||||||
|
.create = create,
|
||||||
|
.destroy = destroy,
|
||||||
|
.value = value,
|
||||||
|
.exec = exec,
|
||||||
|
.report = report
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,9 @@ namespace cw
|
|||||||
namespace pv_synthesis { extern class_members_t members; }
|
namespace pv_synthesis { extern class_members_t members; }
|
||||||
namespace spec_dist { extern class_members_t members; }
|
namespace spec_dist { extern class_members_t members; }
|
||||||
namespace compressor { extern class_members_t members; }
|
namespace compressor { extern class_members_t members; }
|
||||||
|
namespace limiter { extern class_members_t members; }
|
||||||
namespace audio_delay { extern class_members_t members; }
|
namespace audio_delay { extern class_members_t members; }
|
||||||
|
namespace dc_filter { extern class_members_t members; }
|
||||||
namespace balance { extern class_members_t members; }
|
namespace balance { extern class_members_t members; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
110
cwFlowTypes.cpp
110
cwFlowTypes.cpp
@ -175,7 +175,11 @@ namespace cw
|
|||||||
if( v->u.fbuf == nullptr )
|
if( v->u.fbuf == nullptr )
|
||||||
printf("fbuf: <null>");
|
printf("fbuf: <null>");
|
||||||
else
|
else
|
||||||
printf("fbuf: chN:%i binN:%i hopSmpN:%i srate:%8.1f", v->u.fbuf->chN, v->u.fbuf->binN, v->u.fbuf->hopSmpN, v->u.fbuf->srate );
|
{
|
||||||
|
printf("fbuf: chN:%i srate:%8.1f ", v->u.fbuf->chN, v->u.fbuf->srate );
|
||||||
|
for(unsigned i; i<v->u.fbuf->chN; ++i)
|
||||||
|
printf("(binN:%i hopSmpN:%i) ", v->u.fbuf->binN_V[i], v->u.fbuf->hopSmpN_V[i] );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kBoolMtxTFl:
|
case kBoolMtxTFl:
|
||||||
@ -899,25 +903,38 @@ const cw::flow::sample_t* cw::flow::abuf_get_channel( abuf_t* abuf, unsigned c
|
|||||||
return abuf->buf + (chIdx*abuf->frameN);
|
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, unsigned binN, unsigned hopSmpN, 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;
|
||||||
|
}
|
||||||
|
|
||||||
fbuf_t* f = mem::allocZ<fbuf_t>();
|
fbuf_t* f = mem::allocZ<fbuf_t>();
|
||||||
|
|
||||||
f->srate = srate;
|
f->srate = srate;
|
||||||
f->chN = chN;
|
f->maxBinN = maxBinN;
|
||||||
f->binN = binN;
|
f->chN = chN;
|
||||||
f->hopSmpN = hopSmpN;
|
f->binN_V = mem::allocZ<unsigned>(chN);;
|
||||||
f->magV = mem::allocZ<sample_t*>(chN);
|
f->hopSmpN_V = mem::allocZ<unsigned>(chN);
|
||||||
f->phsV = mem::allocZ<sample_t*>(chN);
|
f->magV = mem::allocZ<sample_t*>(chN);
|
||||||
f->hzV = mem::allocZ<sample_t*>(chN);
|
f->phsV = mem::allocZ<sample_t*>(chN);
|
||||||
f->readyFlV= mem::allocZ<bool>(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 );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if( magV != nullptr || phsV != nullptr || hzV != nullptr )
|
if( magV != nullptr || phsV != nullptr || hzV != nullptr )
|
||||||
{
|
{
|
||||||
for(unsigned chIdx=0; chIdx<chN; ++chIdx)
|
for(unsigned chIdx=0; chIdx<chN; ++chIdx)
|
||||||
{
|
{
|
||||||
f->magV[ chIdx ] = (sample_t*)magV[chIdx];
|
f->magV[ chIdx ] = (sample_t*)magV[chIdx];
|
||||||
f->phsV[ chIdx ] = (sample_t*)phsV[chIdx];
|
f->phsV[ chIdx ] = (sample_t*)phsV[chIdx];
|
||||||
f->hzV[ chIdx ] = (sample_t*)hzV[chIdx];
|
f->hzV[ chIdx ] = (sample_t*)hzV[chIdx];
|
||||||
@ -925,30 +942,48 @@ cw::flow::fbuf_t* cw::flow::fbuf_create( srate_t srate, unsigned chN, unsigned
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sample_t* buf = mem::allocZ<sample_t>( chN * kFbufVectN * binN );
|
sample_t* buf = mem::allocZ<sample_t>( kFbufVectN * maxBinN );
|
||||||
|
sample_t* m = buf;
|
||||||
for(unsigned chIdx=0,j=0; chIdx<chN; ++chIdx,j+=kFbufVectN*binN)
|
for(unsigned chIdx=0; chIdx<chN; ++chIdx)
|
||||||
{
|
{
|
||||||
f->magV[chIdx] = buf + j + 0 * binN;
|
f->magV[chIdx] = m + 0 * f->binN_V[chIdx];
|
||||||
f->phsV[chIdx] = buf + j + 1 * binN;
|
f->phsV[chIdx] = m + 1 * f->binN_V[chIdx];
|
||||||
f->hzV[ chIdx] = buf + j + 2 * binN;
|
f->hzV[ chIdx] = m + 2 * f->binN_V[chIdx];
|
||||||
|
m += f->binN_V[chIdx];
|
||||||
|
assert( m <= buf + kFbufVectN * maxBinN );
|
||||||
}
|
}
|
||||||
|
|
||||||
f->buf = buf;
|
f->buf = buf;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
unsigned binN_V[ chN ];
|
||||||
|
unsigned hopSmpN_V[ chN ];
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cw::flow::fbuf_destroy( fbuf_t*& fbuf )
|
void cw::flow::fbuf_destroy( fbuf_t*& fbuf )
|
||||||
{
|
{
|
||||||
if( fbuf == nullptr )
|
if( fbuf == nullptr )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mem::release( fbuf->magV);
|
mem::release( fbuf->binN_V );
|
||||||
mem::release( fbuf->phsV);
|
mem::release( fbuf->hopSmpN_V);
|
||||||
mem::release( fbuf->hzV);
|
//mem::release( fbuf->magV);
|
||||||
|
//mem::release( fbuf->phsV);
|
||||||
|
//mem::release( fbuf->hzV);
|
||||||
mem::release( fbuf->buf);
|
mem::release( fbuf->buf);
|
||||||
mem::release( fbuf->readyFlV);
|
mem::release( fbuf->readyFlV);
|
||||||
mem::release( fbuf);
|
mem::release( fbuf);
|
||||||
@ -956,12 +991,16 @@ void cw::flow::fbuf_destroy( fbuf_t*& fbuf )
|
|||||||
|
|
||||||
cw::flow::fbuf_t* cw::flow::fbuf_duplicate( const fbuf_t* src )
|
cw::flow::fbuf_t* cw::flow::fbuf_duplicate( const fbuf_t* src )
|
||||||
{
|
{
|
||||||
fbuf_t* fbuf = fbuf_create( src->srate, src->chN, src->binN, src->hopSmpN );
|
fbuf_t* fbuf = fbuf_create( src->srate, src->maxBinN, src->chN, src->binN_V, src->hopSmpN_V );
|
||||||
|
|
||||||
for(unsigned i=0; i<fbuf->chN; ++i)
|
for(unsigned i=0; i<fbuf->chN; ++i)
|
||||||
{
|
{
|
||||||
vop::copy( fbuf->magV[i], src->magV[i], fbuf->binN );
|
fbuf->binN_V[i] = src->binN_V[i];
|
||||||
vop::copy( fbuf->phsV[i], src->phsV[i], fbuf->binN );
|
fbuf->hopSmpN_V[i] = src->hopSmpN_V[i];
|
||||||
vop::copy( fbuf->hzV[i], src->hzV[i], fbuf->binN );
|
|
||||||
|
vop::copy( fbuf->magV[i], src->magV[i], fbuf->binN_V[i] );
|
||||||
|
vop::copy( fbuf->phsV[i], src->phsV[i], fbuf->binN_V[i] );
|
||||||
|
vop::copy( fbuf->hzV[i], src->hzV[i], fbuf->binN_V[i] );
|
||||||
}
|
}
|
||||||
return fbuf;
|
return fbuf;
|
||||||
}
|
}
|
||||||
@ -1325,11 +1364,11 @@ cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* va
|
|||||||
return rc;
|
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 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 maxBinN, unsigned chN, const unsigned* binN_V, const unsigned* hopSmpN_V, const sample_t** magV, const sample_t** phsV, const sample_t** hzV )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
fbuf_t* fbuf;
|
fbuf_t* fbuf;
|
||||||
if((fbuf = fbuf_create( srate, chN, binN, hopSmpN, magV, phsV, hzV )) == nullptr )
|
if((fbuf = fbuf_create( srate, maxBinN, chN, binN_V, hopSmpN_V, magV, phsV, hzV )) == nullptr )
|
||||||
return cwLogError(kOpFailRC,"fbuf create failed on instance:'%s' variable:'%s'.", inst->label, var_label);
|
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 )
|
if((rc = _var_register_and_set( inst, var_label, vid, chIdx, fbuf )) != kOkRC )
|
||||||
@ -1338,6 +1377,15 @@ cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* var_label
|
|||||||
return rc;
|
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 )
|
||||||
|
{
|
||||||
|
unsigned binN_V[ chN ];
|
||||||
|
unsigned hopSmpN_V[ chN ];
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::flow::var_get( const variable_t* var, bool& valRef )
|
cw::rc_t cw::flow::var_get( const variable_t* var, bool& valRef )
|
||||||
{ return _val_get_driver(var,valRef); }
|
{ return _val_get_driver(var,valRef); }
|
||||||
|
@ -24,7 +24,7 @@ namespace cw
|
|||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kFbufVectN = 3,
|
kFbufVectN = 3, // count of signal vectors in fbuf (mag,phs,hz)
|
||||||
kAnyChIdx = kInvalidIdx,
|
kAnyChIdx = kInvalidIdx,
|
||||||
kLocalValueN = 2
|
kLocalValueN = 2
|
||||||
};
|
};
|
||||||
@ -32,16 +32,17 @@ namespace cw
|
|||||||
typedef struct fbuf_str
|
typedef struct fbuf_str
|
||||||
{
|
{
|
||||||
struct value_str* base;
|
struct value_str* base;
|
||||||
srate_t srate; // signal sample rate
|
srate_t srate; // signal sample rate
|
||||||
unsigned flags; // See kXXXFbufFl
|
unsigned flags; // See kXXXFbufFl
|
||||||
unsigned chN; // count of channels
|
unsigned maxBinN; // max value that any value in binN_V[] is allowed to take
|
||||||
unsigned binN; // count of sample frames per channel
|
unsigned chN; // count of channels
|
||||||
unsigned hopSmpN; // hop sample count
|
unsigned* binN_V; // binN_V[ chN ] count of sample frames per channel
|
||||||
sample_t** magV; // magV[ chN ][ binN ]
|
unsigned* hopSmpN_V; // hopSmpN_V[ chN ] hop sample count
|
||||||
sample_t** phsV; // phsV[ chN ][ binN ]
|
sample_t** magV; // magV[ chN ][ binN ]
|
||||||
sample_t** hzV; // hzV[ chN ][ binN ]
|
sample_t** phsV; // phsV[ 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** hzV; // hzV[ chN ][ binN ]
|
||||||
sample_t* buf; // memory used by this buffer (or NULL if magV,phsV,hzV point are proxied to another buffer)
|
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;
|
} fbuf_t;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -233,7 +234,8 @@ namespace cw
|
|||||||
rc_t abuf_set_channel( abuf_t* buf, unsigned chIdx, const sample_t* v, unsigned vN );
|
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 );
|
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 );
|
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 );
|
||||||
void fbuf_destroy( fbuf_t*& buf );
|
void fbuf_destroy( fbuf_t*& buf );
|
||||||
fbuf_t* fbuf_duplicate( const fbuf_t* src );
|
fbuf_t* fbuf_duplicate( const fbuf_t* src );
|
||||||
|
|
||||||
@ -368,7 +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* 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 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 );
|
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 );
|
||||||
|
|
||||||
inline rc_t _var_register_and_set(cw::flow::instance_t*, unsigned int ) { return kOkRC; }
|
inline rc_t _var_register_and_set(cw::flow::instance_t*, unsigned int ) { return kOkRC; }
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ namespace cw
|
|||||||
|
|
||||||
kFragListId,
|
kFragListId,
|
||||||
kFragPanelId,
|
kFragPanelId,
|
||||||
|
kFragMeasId,
|
||||||
kFragBegLocId,
|
kFragBegLocId,
|
||||||
kFragEndLocId,
|
kFragEndLocId,
|
||||||
|
|
||||||
@ -169,6 +170,7 @@ namespace cw
|
|||||||
|
|
||||||
{ kPanelDivId, kFragListId, "fragListId" },
|
{ kPanelDivId, kFragListId, "fragListId" },
|
||||||
{ kFragListId, kFragPanelId, "fragPanelId" },
|
{ kFragListId, kFragPanelId, "fragPanelId" },
|
||||||
|
{ kFragPanelId, kFragMeasId, "fragMeasId" },
|
||||||
{ kFragPanelId, kFragBegLocId, "fragBegLocId" },
|
{ kFragPanelId, kFragBegLocId, "fragBegLocId" },
|
||||||
{ kFragPanelId, kFragEndLocId, "fragEndLocId" },
|
{ kFragPanelId, kFragEndLocId, "fragEndLocId" },
|
||||||
{ kFragPanelId, kFragPresetRowId, "fragPresetRowId" },
|
{ kFragPanelId, kFragPresetRowId, "fragPresetRowId" },
|
||||||
@ -1475,7 +1477,7 @@ namespace cw
|
|||||||
unsigned fragId = kInvalidId;
|
unsigned fragId = kInvalidId;
|
||||||
unsigned uuId = kInvalidId;
|
unsigned uuId = kInvalidId;
|
||||||
|
|
||||||
// get the fragment id (uuid) of the selected fragment
|
// get the fragment id (uuid) of the selected (high-lighted) fragment
|
||||||
if((fragId = preset_sel::ui_select_fragment_id(app->psH)) == kInvalidId )
|
if((fragId = preset_sel::ui_select_fragment_id(app->psH)) == kInvalidId )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kInvalidStateRC,"There is no selected fragment to delete.");
|
rc = cwLogError(kInvalidStateRC,"There is no selected fragment to delete.");
|
||||||
|
@ -325,6 +325,17 @@ namespace cw
|
|||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const event_t* _loc_to_event( score_t* p, unsigned loc )
|
||||||
|
{
|
||||||
|
const event_t* e = p->base;
|
||||||
|
for(; e!=nullptr; e=e->link)
|
||||||
|
if( e->loc == loc )
|
||||||
|
return e;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -467,10 +478,31 @@ bool cw::score::is_loc_valid( handle_t h, unsigned locId )
|
|||||||
return locId < p->maxLocId;
|
return locId < p->maxLocId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned cw::score::loc_to_measure( handle_t h, unsigned locId )
|
||||||
|
{
|
||||||
|
score_t* p = _handleToPtr(h);
|
||||||
|
const event_t* e;
|
||||||
|
if((e = _loc_to_event(p,locId)) == nullptr )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return kInvalidId;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cw::score::loc_to_next_note_on_measure( handle_t h, unsigned locId )
|
||||||
|
{
|
||||||
|
score_t* p = _handleToPtr(h);
|
||||||
|
const event_t* e = _loc_to_event(p,locId);
|
||||||
|
|
||||||
|
while( e != nullptr )
|
||||||
|
if( midi::isNoteOn(e->status))
|
||||||
|
return e->meas;
|
||||||
|
|
||||||
|
return kInvalidId;
|
||||||
|
}
|
||||||
|
|
||||||
const cw::score::event_t* cw::score::uid_to_event( handle_t h, unsigned uid )
|
const cw::score::event_t* cw::score::uid_to_event( handle_t h, unsigned uid )
|
||||||
{
|
{
|
||||||
|
//hscore_t* p = _handleToPtr(h);
|
||||||
score_t* p = _handleToPtr(h);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,12 @@ namespace cw
|
|||||||
|
|
||||||
unsigned loc_count( handle_t h );
|
unsigned loc_count( handle_t h );
|
||||||
bool is_loc_valid( handle_t h, unsigned locId );
|
bool is_loc_valid( handle_t h, unsigned locId );
|
||||||
|
unsigned loc_to_measure( handle_t h, unsigned locId );
|
||||||
|
unsigned loc_to_next_note_on_measure( handle_t h, unsigned locId );
|
||||||
|
|
||||||
const event_t* uid_to_event( handle_t h, unsigned uid );
|
const event_t* uid_to_event( handle_t h, unsigned uid );
|
||||||
|
|
||||||
|
|
||||||
// Format the event as a string for printing.
|
// Format the event as a string for printing.
|
||||||
rc_t event_to_string( handle_t h, unsigned uid, char* buf, unsigned buf_byte_cnt );
|
rc_t event_to_string( handle_t h, unsigned uid, char* buf, unsigned buf_byte_cnt );
|
||||||
|
|
||||||
|
@ -298,7 +298,7 @@ namespace cw
|
|||||||
|
|
||||||
for(unsigned i=0; i<p->pvoc_ctx.srcChN; ++i)
|
for(unsigned i=0; i<p->pvoc_ctx.srcChN; ++i)
|
||||||
{
|
{
|
||||||
if((rc = dsp::pv_anl::create( p->anlA[i], p->pvoc_ctx.procSmpN, ctx->srcSrate, p->pvoc_ctx.wndSmpN, p->pvoc_ctx.hopSmpN, dsp::pv_anl::kNoCalcHzPvaFl )) != kOkRC )
|
if((rc = dsp::pv_anl::create( p->anlA[i], p->pvoc_ctx.procSmpN, ctx->srcSrate, p->pvoc_ctx.wndSmpN, p->pvoc_ctx.wndSmpN, p->pvoc_ctx.hopSmpN, dsp::pv_anl::kNoCalcHzPvaFl )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"PVOC analysis component create failed.");
|
rc = cwLogError(rc,"PVOC analysis component create failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
54
cwVectOps.h
54
cwVectOps.h
@ -402,6 +402,60 @@ namespace cw
|
|||||||
return rms;
|
return rms;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Direct form II algorithm based on the MATLAB implmentation
|
||||||
|
// http://www.mathworks.com/access/helpdesk/help/techdoc/ref/filter.html#f83-1015962
|
||||||
|
// The only difference between this function and the equivalent MATLAB filter() function
|
||||||
|
// is that the first feedforward coeff is given as a seperate value. The first b coefficient
|
||||||
|
// in this function is therefore the same as the second coefficient in the MATLAB function.
|
||||||
|
// and the first a[] coefficient (which is generally set to 1.0) is skipped.
|
||||||
|
// Example:
|
||||||
|
// Matlab: b=[.5 .4 .3] a=[1 .2 .1]
|
||||||
|
// Equiv: b0 = .5 b=[ .4 .3] a=[ .2 .1];
|
||||||
|
//
|
||||||
|
// y[yn] - output vector
|
||||||
|
// x[xn] - input vector. xn must be <= yn. if xn < yn then the end of y[] is set to zero.
|
||||||
|
// b0 - signal scale. This can also be seen as b[0] (which is not included in b[])
|
||||||
|
// b[dn] - feedforward coeff's b[1..dn-1]
|
||||||
|
// a[dn] - feedback coeff's a[1..dn-1]
|
||||||
|
// d[dn+1] - delay registers - note that this array must be one element longer than the coeff arrays.
|
||||||
|
//
|
||||||
|
|
||||||
|
template< typename S, typename T >
|
||||||
|
S* filter( S* y,
|
||||||
|
unsigned yn,
|
||||||
|
const S* x,
|
||||||
|
unsigned xn,
|
||||||
|
T b0,
|
||||||
|
const T* b,
|
||||||
|
const T* a,
|
||||||
|
T* d,
|
||||||
|
unsigned dn )
|
||||||
|
{
|
||||||
|
unsigned i,j;
|
||||||
|
S y0 = 0;
|
||||||
|
unsigned n = yn<xn ? yn : xn;
|
||||||
|
|
||||||
|
for(i=0; i<n; ++i)
|
||||||
|
{
|
||||||
|
y[i] = (x[i] * b0) + d[0];
|
||||||
|
|
||||||
|
y0 = y[i];
|
||||||
|
|
||||||
|
for(j=0; j<dn; ++j)
|
||||||
|
d[j] = (b[j] * x[i]) - (a[j] * y0) + d[j+1];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if fewer input samples than output samples - zero the end of the output buffer
|
||||||
|
if( yn > xn )
|
||||||
|
fill(y+i,yn-i,0);
|
||||||
|
|
||||||
|
return y;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user