diff --git a/cwDspTransforms.cpp b/cwDspTransforms.cpp index 26e3250..412bc52 100644 --- a/cwDspTransforms.cpp +++ b/cwDspTransforms.cpp @@ -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 ) { p = mem::allocZ(); @@ -162,7 +166,111 @@ void cw::dsp::compressor::set_rms_wnd_ms( obj_t* p, real_t ms ) 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(); + + 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; iigain; + + 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(); + + 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(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 ) { diff --git a/cwDspTransforms.h b/cwDspTransforms.h index 1ce6db1..fd0c455 100644 --- a/cwDspTransforms.h +++ b/cwDspTransforms.h @@ -46,6 +46,40 @@ namespace cw 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 { typedef struct diff --git a/cwFlow.cpp b/cwFlow.cpp index cc689e5..34ac885 100644 --- a/cwFlow.cpp +++ b/cwFlow.cpp @@ -37,7 +37,9 @@ namespace cw { "pv_synthesis", &pv_synthesis::members }, { "spec_dist", &spec_dist::members }, { "compressor", &compressor::members }, + { "limiter", &limiter::members }, { "audio_delay", &audio_delay::members }, + { "dc_filter", &dc_filter::members }, { "balance", &balance::members }, { nullptr, nullptr } }; diff --git a/cwFlowProc.h b/cwFlowProc.h index 532ed0b..a5d053a 100644 --- a/cwFlowProc.h +++ b/cwFlowProc.h @@ -16,7 +16,9 @@ namespace cw namespace pv_synthesis { extern class_members_t members; } namespace spec_dist { 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 dc_filter { extern class_members_t members; } namespace balance { extern class_members_t members; } } }