Many updates and changes to cwFlow* and added Compressor processor.
This commit is contained in:
parent
b5bf573748
commit
b8dea27343
@ -25,8 +25,8 @@ libcwSRC += src/libcw/cwSpScBuf.cpp src/libcw/cwSpScQu
|
||||
libcwHDR += src/libcw/cwAudioFile.h src/libcw/cwMidiFile.h
|
||||
libcwSRC += src/libcw/cwAudioFile.cpp src/libcw/cwMidiFile.cpp
|
||||
|
||||
libcwHDR += src/libcw/cwAudioFileOps.h src/libcw/cwAudioTransforms.h src/libcw/cwAudioFileProc.h src/libcw/cwPvAudioFileProc.h
|
||||
libcwSRC += src/libcw/cwAudioFileOps.cpp src/libcw/cwAudioTransforms.cpp src/libcw/cwAudioFileProc.cpp src/libcw/cwPvAudioFileProc.cpp
|
||||
libcwHDR += src/libcw/cwAudioFileOps.h src/libcw/cwAudioTransforms.h src/libcw/cwDspTransforms.h src/libcw/cwAudioFileProc.h src/libcw/cwPvAudioFileProc.h
|
||||
libcwSRC += src/libcw/cwAudioFileOps.cpp src/libcw/cwAudioTransforms.cpp src/libcw/cwDspTransforms.cpp src/libcw/cwAudioFileProc.cpp src/libcw/cwPvAudioFileProc.cpp
|
||||
|
||||
libcwHDR += src/libcw/cwFlow.h src/libcw/cwFlowTypes.h src/libcw/cwFlowProc.h
|
||||
libcwSRC += src/libcw/cwFlow.cpp src/libcw/cwFlowTypes.cpp src/libcw/cwFlowProc.cpp
|
||||
|
163
cwDspTransforms.cpp
Normal file
163
cwDspTransforms.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
#include "cwCommon.h"
|
||||
#include "cwLog.h"
|
||||
#include "cwCommonImpl.h"
|
||||
#include "cwMem.h"
|
||||
#include "cwFile.h"
|
||||
#include "cwText.h"
|
||||
#include "cwObject.h"
|
||||
#include "cwAudioFile.h"
|
||||
#include "cwUtility.h"
|
||||
#include "cwFileSys.h"
|
||||
#include "cwAudioFileOps.h"
|
||||
#include "cwVectOps.h"
|
||||
#include "cwMath.h"
|
||||
#include "cwDspTypes.h"
|
||||
#include "cwDsp.h"
|
||||
#include "cwDspTransforms.h"
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
namespace compressor
|
||||
{
|
||||
void _ms_to_samples( obj_t*p, real_t ms, unsigned& outRef )
|
||||
{
|
||||
outRef = std::max((real_t)1,(real_t)floor(ms * p->srate / 1000.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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->srate = srate;
|
||||
p->procSmpCnt = procSmpCnt;
|
||||
p->threshDb = threshDb;
|
||||
p->ratio_num = ratio_num;
|
||||
|
||||
set_attack_ms(p,atkMs);
|
||||
set_release_ms(p,rlsMs);
|
||||
|
||||
p->inGain = inGain;
|
||||
p->outGain = outGain;
|
||||
p->bypassFl = bypassFl;
|
||||
|
||||
p->rmsWndAllocCnt = (unsigned)std::max(1.0,floor(rmsWndMaxMs * srate / (1000.0 * procSmpCnt)));
|
||||
p->rmsWnd = mem::allocZ<sample_t>(p->rmsWndAllocCnt);
|
||||
set_rms_wnd_ms(p, rmsWndMs );
|
||||
p->rmsWndIdx = 0;
|
||||
|
||||
p->state = kRlsCompId;
|
||||
p->timeConstDb = 10.0;
|
||||
p->accumDb = p->threshDb;
|
||||
|
||||
return kOkRC;
|
||||
}
|
||||
|
||||
cw::rc_t cw::dsp::compressor::destroy( obj_t*& p )
|
||||
{
|
||||
mem::release(p->rmsWnd);
|
||||
mem::release(p);
|
||||
return kOkRC;
|
||||
}
|
||||
|
||||
/*
|
||||
The ratio determines to what degree a signal above the threshold is reduced.
|
||||
Given a 2:1 ratio, a signal 2dB above the threshold will be reduced to 1db above the threshold.
|
||||
Given a 4:1 ratio, a signal 2dB above the threshold will be reduced to 0.25db above the threshold.
|
||||
Gain_reduction_db = (thresh - signal) / ratio_numerator (difference between the threshold and signal level after reduction)
|
||||
Gain Coeff = 10^(gain_reduction_db / 20);
|
||||
|
||||
Total_reduction_db = signal - threshold + Gain_reduc_db
|
||||
(total change in signal level)
|
||||
|
||||
The attack can be viewed as beginning at the threshold and moving to the peak
|
||||
over some period of time. In linear terms this will go from 1.0 to the max gain
|
||||
reductions. In this case we step from thresh to peak at a fixed rate in dB
|
||||
based on the attack time.
|
||||
|
||||
Db: thresh - [thesh:peak] / ratio_num
|
||||
Linear: pow(10, (thresh - [thesh:peak] / ratio_num)/20 );
|
||||
|
||||
During attacks p->accumDb increments toward the p->pkDb.
|
||||
During release p->accumDb decrements toward the threshold.
|
||||
|
||||
(thresh - accumDb) / ratio_num gives the signal level which will be achieved
|
||||
if this value is converted to linear form and applied as a gain coeff.
|
||||
|
||||
See compressor.m
|
||||
*/
|
||||
|
||||
cw::rc_t cw::dsp::compressor::exec( obj_t* p, const sample_t* x, sample_t* y, unsigned n )
|
||||
{
|
||||
|
||||
sample_t xx[n];
|
||||
|
||||
vop::mul(xx,x,p->inGain,n); // apply input gain
|
||||
|
||||
p->rmsWnd[ p->rmsWndIdx ] = vop::rms(xx, n); // calc and store signal RMS
|
||||
p->rmsWndIdx = (p->rmsWndIdx + 1) % p->rmsWndCnt; // advance the RMS storage buffer
|
||||
|
||||
real_t rmsLin = vop::mean(p->rmsWnd,p->rmsWndCnt); // calc avg RMS
|
||||
real_t rmsDb = std::max(-100.0,20 * log10(std::max((real_t)0.00001,rmsLin))); // convert avg RMS to dB
|
||||
rmsDb += 100.0;
|
||||
|
||||
// if the compressor is bypassed
|
||||
if( p->bypassFl )
|
||||
{
|
||||
vop::copy(y,x,n); // copy through - with no input gain
|
||||
return kOkRC;
|
||||
}
|
||||
|
||||
// if the signal is above the threshold
|
||||
if( rmsDb <= p->threshDb )
|
||||
p->state = kRlsCompId;
|
||||
else
|
||||
{
|
||||
if( rmsDb > p->pkDb )
|
||||
p->pkDb = rmsDb;
|
||||
|
||||
p->state = kAtkCompId;
|
||||
}
|
||||
|
||||
switch( p->state )
|
||||
{
|
||||
case kAtkCompId:
|
||||
p->accumDb = std::min(p->pkDb, p->accumDb + p->timeConstDb * n / p->atkSmp );
|
||||
break;
|
||||
|
||||
case kRlsCompId:
|
||||
p->accumDb = std::max(p->threshDb, p->accumDb - p->timeConstDb * n / p->rlsSmp );
|
||||
break;
|
||||
}
|
||||
|
||||
p->gain = pow(10.0,(p->threshDb - p->accumDb) / (p->ratio_num * 20.0));
|
||||
|
||||
vop::mul(y,xx,p->gain * p->outGain,n);
|
||||
|
||||
return kOkRC;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cw::dsp::compressor::set_attack_ms( obj_t* p, real_t ms )
|
||||
{
|
||||
_ms_to_samples(p,ms,p->atkSmp);
|
||||
}
|
||||
|
||||
void cw::dsp::compressor::set_release_ms( obj_t* p, real_t ms )
|
||||
{
|
||||
_ms_to_samples(p,ms,p->rlsSmp);
|
||||
}
|
||||
|
||||
void cw::dsp::compressor::set_rms_wnd_ms( obj_t* p, real_t ms )
|
||||
{
|
||||
p->rmsWndCnt = std::max((unsigned)1,(unsigned)floor(ms * p->srate / (1000.0 * p->procSmpCnt)));
|
||||
|
||||
// do not allow rmsWndCnt to exceed rmsWndAllocCnt
|
||||
if( p->rmsWndCnt > p->rmsWndAllocCnt )
|
||||
p->rmsWndCnt = p->rmsWndAllocCnt;
|
||||
}
|
53
cwDspTransforms.h
Normal file
53
cwDspTransforms.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef cwDspTransforms_h
|
||||
#define cwDspTransforms_h
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
//---------------------------------------------------------------------------------------------------------------------------------
|
||||
// compressor
|
||||
//
|
||||
namespace compressor
|
||||
{
|
||||
enum { kAtkCompId, kRlsCompId };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
real_t srate; // system sample rate
|
||||
unsigned procSmpCnt; // samples per exec cycle
|
||||
real_t inGain; // input gain
|
||||
real_t threshDb; // threshold in dB (max:100 min:0)
|
||||
real_t ratio_num; // numerator of the ratio
|
||||
unsigned atkSmp; // time to reduce the signal by 10.0 db
|
||||
unsigned rlsSmp; // time to increase the signal by 10.0 db
|
||||
real_t outGain; // makeup gain
|
||||
bool bypassFl; // bypass enable
|
||||
sample_t* rmsWnd; // rmsWnd[rmsWndAllocCnt]
|
||||
unsigned rmsWndAllocCnt; //
|
||||
unsigned rmsWndCnt; // current RMS window size (rmsWndCnt must be <= rmsWndAllocCnt)
|
||||
unsigned rmsWndIdx; // next RMS window input index
|
||||
unsigned state; // env. state
|
||||
real_t rmsDb; // current incoming signal RMS (max:100 min:0)
|
||||
real_t gain; // current compressor gain
|
||||
real_t timeConstDb; // the atk/rls will incr/decr by 'timeConstDb' per atkMs/rlsMs.
|
||||
real_t pkDb; //
|
||||
real_t accumDb; //
|
||||
|
||||
} obj_t;
|
||||
|
||||
rc_t create( obj_t*& p, real_t srate, unsigned procSmpCnt, real_t inGain, real_t rmsWndMaxMs, real_t rmsWndMs, real_t threshDb, real_t ratio, real_t atkMs, real_t rlsMs, real_t outGain, bool bypassFl );
|
||||
rc_t destroy( obj_t*& pp );
|
||||
rc_t exec( obj_t* p, const sample_t* x, sample_t* y, unsigned n );
|
||||
|
||||
void set_attack_ms( obj_t* p, real_t ms );
|
||||
void set_release_ms( obj_t* p, real_t ms );
|
||||
void set_thresh_db( obj_t* p, real_t thresh );
|
||||
void set_rms_wnd_ms( obj_t* p, real_t ms );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
13
cwDspTypes.h
Normal file
13
cwDspTypes.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef cwDspTypes_h
|
||||
#define cwDspTypes_h
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
typedef float real_t;
|
||||
typedef real_t sample_t;
|
||||
typedef real_t srate_t;
|
||||
}
|
||||
}
|
||||
#endif
|
428
cwFlow.cpp
428
cwFlow.cpp
@ -7,6 +7,7 @@
|
||||
#include "cwAudioFile.h"
|
||||
#include "cwVectOps.h"
|
||||
#include "cwMtx.h"
|
||||
#include "cwDspTypes.h" // real_t, sample_t
|
||||
#include "cwFlow.h"
|
||||
#include "cwFlowTypes.h"
|
||||
#include "cwFlowProc.h"
|
||||
@ -27,6 +28,7 @@ namespace cw
|
||||
{ "pv_analysis", &pv_analysis::members },
|
||||
{ "pv_synthesis", &pv_synthesis::members },
|
||||
{ "spec_dist", &spec_dist::members },
|
||||
{ "compressor", &compressor::members },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
@ -102,7 +104,7 @@ namespace cw
|
||||
}
|
||||
}
|
||||
|
||||
// parse the value dictionary
|
||||
// parse the variable dictionary
|
||||
if( varD != nullptr )
|
||||
{
|
||||
if( !varD->is_dict() )
|
||||
@ -124,7 +126,7 @@ namespace cw
|
||||
const object_t* var_obj = varD->child_ele(j);
|
||||
const char* type_str = nullptr;
|
||||
unsigned type_flag = 0;
|
||||
bool srcVarFl = false;
|
||||
bool srcVarFl = false;
|
||||
var_desc_t* vd = mem::allocZ<var_desc_t>();
|
||||
|
||||
vd->label = var_obj->pair_label();
|
||||
@ -146,7 +148,7 @@ namespace cw
|
||||
}
|
||||
|
||||
// get the variable description
|
||||
if((rc = var_obj->getv_opt("srcFl", srcVarFl)) != kOkRC )
|
||||
if((rc = var_obj->getv_opt("srcFl", srcVarFl,"value",vd->val_cfg)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"Parsing optional fields failed on class:%s variable: '%s'.", cd->label, vd->label );
|
||||
goto errLabel;
|
||||
@ -206,14 +208,14 @@ namespace cw
|
||||
}
|
||||
|
||||
// locate source value
|
||||
if((rc = var_get( src_inst, suffix, kAnyChIdx, src_var)) != kOkRC )
|
||||
if((rc = var_find( src_inst, suffix, kAnyChIdx, src_var)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"The source var '%s' was not found on the source instance '%s'.", cwStringNullGuard(suffix), cwStringNullGuard(sbuf));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// locate input value
|
||||
if((rc = var_get( in_inst, in_var_label, kAnyChIdx, in_var )) != kOkRC )
|
||||
if((rc = var_find( in_inst, in_var_label, kAnyChIdx, in_var )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"The input value '%s' was not found on the instance '%s'.", cwStringNullGuard(in_var_label), cwStringNullGuard(in_inst->label));
|
||||
goto errLabel;
|
||||
@ -244,6 +246,9 @@ namespace cw
|
||||
|
||||
void _destroy_inst( instance_t* inst )
|
||||
{
|
||||
if( inst == nullptr )
|
||||
return;
|
||||
|
||||
if( inst->class_desc->members->destroy != nullptr && inst->userPtr != nullptr )
|
||||
inst->class_desc->members->destroy( inst );
|
||||
|
||||
@ -252,7 +257,7 @@ namespace cw
|
||||
variable_t* var1 = nullptr;
|
||||
while( var0 != nullptr )
|
||||
{
|
||||
var1 = var0->link;
|
||||
var1 = var0->var_link;
|
||||
_var_destroy(var0);
|
||||
var0 = var1;
|
||||
}
|
||||
@ -262,27 +267,28 @@ namespace cw
|
||||
mem::release(inst);
|
||||
}
|
||||
|
||||
rc_t _var_map_id_to_index( instance_t* inst, unsigned vid, unsigned chIdx, unsigned& idxRef );
|
||||
|
||||
rc_t _create_instance_var_map( instance_t* inst )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
unsigned max_vid = kInvalidId;
|
||||
unsigned max_chIdx = 0;
|
||||
|
||||
rc_t rc = kOkRC;
|
||||
unsigned max_vid = kInvalidId;
|
||||
unsigned max_chIdx = 0;
|
||||
variable_t* var = inst->varL;
|
||||
//variable_t* v0 = nullptr;
|
||||
|
||||
// determine the max variable vid and max channel index value among all variables
|
||||
for(variable_t* var=inst->varL; var!=nullptr; var=var->link)
|
||||
for(; var!=nullptr; var = var->var_link )
|
||||
{
|
||||
|
||||
if( var->vid == kInvalidId )
|
||||
if( var->vid != kInvalidId )
|
||||
{
|
||||
rc = cwLogError(kInvalidStateRC,"The variable '%s' on instance '%s' was not assigned an id.",var->label,inst->label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( max_vid == kInvalidId || var->vid > max_vid )
|
||||
max_vid = var->vid;
|
||||
if( max_vid == kInvalidId || var->vid > max_vid )
|
||||
max_vid = var->vid;
|
||||
|
||||
if( var->chIdx != kAnyChIdx && var->chIdx > max_chIdx )
|
||||
max_chIdx = var->chIdx;
|
||||
if( var->chIdx != kAnyChIdx && var->chIdx > max_chIdx )
|
||||
max_chIdx = var->chIdx;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any variables
|
||||
@ -295,26 +301,27 @@ namespace cw
|
||||
inst->varMapA = mem::allocZ<variable_t*>( inst->varMapN );
|
||||
|
||||
// assign each variable to a location in the map
|
||||
for(variable_t* var=inst->varL; var!=nullptr; var=var->link)
|
||||
{
|
||||
unsigned idx = kInvalidIdx;
|
||||
for(variable_t* var=inst->varL; var!=nullptr; var=var->var_link)
|
||||
if( var->vid != kInvalidId )
|
||||
{
|
||||
unsigned idx = kInvalidIdx;
|
||||
|
||||
if((rc = var_map_id_to_index( inst, var->vid, var->chIdx, idx )) != kOkRC )
|
||||
goto errLabel;
|
||||
if((rc = _var_map_id_to_index( inst, var->vid, var->chIdx, idx )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
|
||||
// verify that there are not multiple variables per map position
|
||||
if( inst->varMapA[ idx ] != nullptr )
|
||||
{
|
||||
variable_t* v0 = inst->varMapA[idx];
|
||||
rc = cwLogError(kInvalidStateRC,"The variable '%s' id:%i ch:%i and '%s' id:%i ch:%i share the same variable map position on instance: %s. This is usually cased by duplicate variable id's.",
|
||||
v0->label,v0->vid,v0->chIdx, var->label,var->vid,var->chIdx,inst->label);
|
||||
goto errLabel;
|
||||
}
|
||||
// verify that there are not multiple variables per map position
|
||||
if( inst->varMapA[ idx ] != nullptr )
|
||||
{
|
||||
variable_t* v0 = inst->varMapA[idx];
|
||||
rc = cwLogError(kInvalidStateRC,"The variable '%s' id:%i ch:%i and '%s' id:%i ch:%i share the same variable map position on instance: %s. This is usually cased by duplicate variable id's.",
|
||||
v0->label,v0->vid,v0->chIdx, var->label,var->vid,var->chIdx,inst->label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// assign this variable to a map position
|
||||
inst->varMapA[ idx ] = var;
|
||||
}
|
||||
// assign this variable to a map position
|
||||
inst->varMapA[ idx ] = var;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -322,85 +329,238 @@ namespace cw
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
rc_t _create_instance( flow_t* p, const object_t* inst_cfg )
|
||||
|
||||
rc_t _preset_channelize_vars( instance_t* inst, const char* type_src_label, const char* preset_label, const object_t* preset_cfg )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
const char* inst_label = nullptr;
|
||||
const char* inst_clas_label = nullptr;
|
||||
const object_t* in_dict = nullptr;
|
||||
const char* arg_label = nullptr;
|
||||
const char* preset_label = nullptr;
|
||||
const object_t* arg_dict = nullptr;
|
||||
const object_t* arg_cfg = nullptr;
|
||||
instance_t* inst = nullptr;
|
||||
class_desc_t* class_desc = nullptr;
|
||||
rc_t rc = kOkRC;
|
||||
|
||||
//cwLogInfo("Channelizing '%s' preset %i vars for '%s'.",type_src_label, preset_cfg==nullptr ? 0 : preset_cfg->child_count(), inst->label );
|
||||
|
||||
// validate the syntax of the preset record
|
||||
if( !preset_cfg->is_dict() )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"The preset record '%s' on %s '%s' is not a dictionary.", preset_label, type_src_label, inst->class_desc->label );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
|
||||
// for each preset variable
|
||||
for(unsigned i=0; i<preset_cfg->child_count(); ++i)
|
||||
{
|
||||
const object_t* value = preset_cfg->child_ele(i)->pair_value();
|
||||
const char* value_label = preset_cfg->child_ele(i)->pair_label();
|
||||
variable_t* dummy = nullptr;
|
||||
|
||||
// verify that a valid value exists
|
||||
if( value == nullptr )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"Unexpected missig value on %s preset '%s' instance '%s' variable '%s'.", type_src_label, preset_label, inst->label, cwStringNullGuard(value_label) );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// if a list of values was given
|
||||
if( value->is_list() )
|
||||
{
|
||||
for(unsigned chIdx=0; chIdx<value->child_count(); ++chIdx)
|
||||
if((rc = var_channelize( inst, value_label, chIdx, value->child_ele(chIdx), dummy )) != kOkRC )
|
||||
goto errLabel;
|
||||
}
|
||||
else // otherwise a single value was given
|
||||
{
|
||||
if((rc = var_channelize( inst, value_label, kAnyChIdx, value, dummy )) != kOkRC )
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
errLabel:
|
||||
if( rc != kOkRC )
|
||||
rc = cwLogError(rc,"Apply %s preset failed on instance:%s class:%s preset:%s.", type_src_label, inst->label, inst->class_desc->label, preset_label );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
rc_t _class_preset_channelize_vars( instance_t* inst, const char* preset_label )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
const preset_t* pr;
|
||||
|
||||
if( preset_label == nullptr )
|
||||
return kOkRC;
|
||||
|
||||
// locate the requestd preset record
|
||||
if((pr = class_preset_find(inst->class_desc, preset_label)) == nullptr )
|
||||
{
|
||||
rc = cwLogError(kInvalidIdRC,"The preset '%s' could not be found for the instance '%s'.", preset_label, inst->label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
rc = _preset_channelize_vars( inst, "class", preset_label, pr->cfg);
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
rc_t _class_apply_presets( instance_t* inst, const object_t* preset_labels )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
const char* s = nullptr;
|
||||
|
||||
// if preset_labels is a string
|
||||
if( preset_labels->is_string() && preset_labels->value(s)==kOkRC )
|
||||
return _class_preset_channelize_vars(inst,s);
|
||||
|
||||
// if the preset_labels is a list
|
||||
if( !preset_labels->is_list() )
|
||||
rc = cwLogError(kSyntaxErrorRC,"The preset list on instance '%s' is neither a list nor a string.",inst->label);
|
||||
else
|
||||
{
|
||||
// for each label listed in the preset label list
|
||||
for(unsigned i=0; i<preset_labels->child_count(); ++i)
|
||||
{
|
||||
const object_t* label_obj = preset_labels->child_ele(i);
|
||||
|
||||
// verify that the label is a strng
|
||||
if( !label_obj->is_string() || label_obj->value(s) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"The preset list does not contain string on instance '%s'.",inst->label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// apply a preset label
|
||||
if((rc = _class_preset_channelize_vars( inst, s)) != kOkRC )
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
rc_t _inst_args_channelize_vars( instance_t* inst, const char* arg_label, const object_t* arg_cfg )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
|
||||
if( arg_cfg == nullptr )
|
||||
return rc;
|
||||
|
||||
return _preset_channelize_vars( inst, "instance", arg_label, arg_cfg );
|
||||
|
||||
}
|
||||
|
||||
typedef struct inst_parse_vars_str
|
||||
{
|
||||
const char* inst_label;
|
||||
const char* inst_clas_label;
|
||||
const object_t* in_dict;
|
||||
const char* arg_label;
|
||||
const object_t* preset_labels;
|
||||
const object_t* arg_cfg;
|
||||
} inst_parse_vars_t;
|
||||
|
||||
rc_t _parse_instance_cfg( flow_t* p, const object_t* inst_cfg, inst_parse_vars_t& pvars )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
const object_t* arg_dict = nullptr;
|
||||
|
||||
// validate the syntax of the inst_cfg pair
|
||||
if( inst_cfg == nullptr || !inst_cfg->is_pair() || inst_cfg->pair_label()==nullptr || inst_cfg->pair_value()==nullptr )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"The instance cfg. is not a valid pair.");
|
||||
rc = cwLogError(kSyntaxErrorRC,"The instance cfg. is not a valid pair. No instance label could be parsed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
inst_label = inst_cfg->pair_label();
|
||||
pvars.inst_label = inst_cfg->pair_label();
|
||||
|
||||
// verify that the instance label is unique
|
||||
if( instance_find(p,inst_label) != nullptr )
|
||||
if( instance_find(p,pvars.inst_label) != nullptr )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"The instance label '%s' has already been used.",inst_label);
|
||||
rc = cwLogError(kSyntaxErrorRC,"The instance label '%s' has already been used.",pvars.inst_label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// get the instance class label
|
||||
if((rc = inst_cfg->getv("class",inst_clas_label)) != kOkRC )
|
||||
if((rc = inst_cfg->getv("class",pvars.inst_clas_label)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"The instance cfg. %s is missing: 'type'.",inst_label);
|
||||
rc = cwLogError(kSyntaxErrorRC,"The instance cfg. %s is missing: 'type'.",pvars.inst_label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// parse the optional args
|
||||
if((rc = inst_cfg->getv_opt("args", arg_dict,
|
||||
"in", in_dict,
|
||||
"argLabel", arg_label,
|
||||
"preset", preset_label)) != kOkRC )
|
||||
"in", pvars.in_dict,
|
||||
"argLabel", pvars.arg_label,
|
||||
"preset", pvars.preset_labels)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"The instance cfg. '%s' missing: 'type'.",inst_label);
|
||||
rc = cwLogError(kSyntaxErrorRC,"The instance cfg. '%s' missing: 'type'.",pvars.inst_label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// if an argument dict was given
|
||||
// if an argument dict was given in the instanec cfg
|
||||
if( arg_dict != nullptr )
|
||||
{
|
||||
bool rptErrFl = true;
|
||||
|
||||
// if no label was given then try 'default'
|
||||
if( arg_label == nullptr)
|
||||
|
||||
// verify the arg. dict is actually a dict.
|
||||
if( !arg_dict->is_dict() )
|
||||
{
|
||||
arg_label = "default";
|
||||
rptErrFl = false;
|
||||
cwLogError(kSyntaxErrorRC,"The instance argument dictionary on instance '%s' is not a dictionary.",pvars.inst_label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if((arg_cfg = arg_dict->find_child(arg_label)) == nullptr )
|
||||
// if no label was given then try 'default'
|
||||
if( pvars.arg_label == nullptr)
|
||||
{
|
||||
pvars.arg_label = "default";
|
||||
rptErrFl = false;
|
||||
}
|
||||
|
||||
// locate the specified argument record
|
||||
if((pvars.arg_cfg = arg_dict->find_child(pvars.arg_label)) == nullptr )
|
||||
{
|
||||
|
||||
// if an explicit arg. label was given but it was not found
|
||||
if( rptErrFl )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"The argument cfg. '%s' was not found on instance cfg. '%s'.",arg_label,inst_label);
|
||||
rc = cwLogError(kSyntaxErrorRC,"The argument cfg. '%s' was not found on instance cfg. '%s'.",pvars.arg_label,pvars.inst_label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// no explicit arg. label was given - make arg_dict the instance arg cff.
|
||||
arg_cfg = arg_dict;
|
||||
arg_label = nullptr;
|
||||
// no explicit arg. label was given - make arg_dict the instance arg cfg.
|
||||
pvars.arg_cfg = arg_dict;
|
||||
pvars.arg_label = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
errLabel:
|
||||
if( rc != kOkRC )
|
||||
rc = cwLogError(kSyntaxErrorRC,"Configuration parsing failed on instance: '%s'.", cwStringNullGuard(pvars.inst_label) );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc_t _create_instance( flow_t* p, const object_t* inst_cfg )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
inst_parse_vars_t pvars = {0};
|
||||
instance_t* inst = nullptr;
|
||||
class_desc_t* class_desc = nullptr;
|
||||
|
||||
// parse the instance configuration
|
||||
if((rc = _parse_instance_cfg( p, inst_cfg, pvars )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
// locate the class desc
|
||||
if(( class_desc = class_desc_find(p,inst_clas_label)) == nullptr )
|
||||
if(( class_desc = class_desc_find(p,pvars.inst_clas_label)) == nullptr )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"The flow class '%s' was not found.",cwStringNullGuard(inst_clas_label));
|
||||
rc = cwLogError(kSyntaxErrorRC,"The flow class '%s' was not found.",cwStringNullGuard(pvars.inst_clas_label));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
@ -408,47 +568,67 @@ namespace cw
|
||||
inst = mem::allocZ<instance_t>();
|
||||
|
||||
inst->ctx = p;
|
||||
inst->label = inst_label;
|
||||
inst->label = pvars.inst_label;
|
||||
inst->inst_cfg = inst_cfg;
|
||||
inst->arg_label = arg_label;
|
||||
inst->arg_cfg = arg_cfg;
|
||||
inst->arg_label = pvars.arg_label;
|
||||
inst->arg_cfg = pvars.arg_cfg;
|
||||
inst->class_desc = class_desc;
|
||||
inst->preset_label = preset_label;
|
||||
|
||||
// Instantiate the variables which have the 'src' attribute. We need these variables
|
||||
// to exist so that they can be connected to their source prior to the instance
|
||||
// custom constructorbeing exected
|
||||
// Instantiate all the variables in the class description
|
||||
for(var_desc_t* vd=class_desc->varDescL; vd!=nullptr; vd=vd->link)
|
||||
{
|
||||
variable_t* var = nullptr;
|
||||
|
||||
if( cwIsFlag(vd->flags,kSrcVarFl) )
|
||||
{
|
||||
if((rc = var_create( inst, vd->label, kInvalidId, kAnyChIdx, var )) != kOkRC )
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
variable_t* var = nullptr;
|
||||
if((rc = var_create( inst, vd->label, kInvalidId, kAnyChIdx, vd->val_cfg, var )) != kOkRC )
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// All the variables that can be used by this instance have now been created
|
||||
// and the chIdx of each variable is set to 'any'.
|
||||
|
||||
// If a 'preset' field was included in the instance cfg then apply the specified class preset
|
||||
if( pvars.preset_labels != nullptr )
|
||||
if((rc = _class_apply_presets(inst, pvars.preset_labels )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
// All the class presets values have now been set and those variables
|
||||
// that were expressed with a list have numeric channel indexes assigned.
|
||||
|
||||
// Apply the instance preset values.
|
||||
if( pvars.arg_cfg != nullptr )
|
||||
if((rc = _inst_args_channelize_vars( inst, pvars.arg_label, pvars.arg_cfg )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
// All the instance arg values have now been set and those variables
|
||||
// that were expressed with a list have numeric channel indexes assigned.
|
||||
|
||||
|
||||
// TODO: Should the 'all' variable be removed for variables that have numeric channel indexes.
|
||||
|
||||
// connect the variable lists in the instance 'in' dictionary
|
||||
if( in_dict != nullptr && in_dict->is_dict() )
|
||||
if( pvars.in_dict != nullptr )
|
||||
{
|
||||
// for each input
|
||||
for(unsigned i=0; i<in_dict->child_count(); ++i)
|
||||
if( !pvars.in_dict->is_dict() )
|
||||
{
|
||||
const object_t* in_pair = in_dict->child_ele(i);
|
||||
cwLogError(kSyntaxErrorRC,"The 'in' dict in instance '%s' is not a valid dictionary.",inst->label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// for each input variable in the 'in' set
|
||||
for(unsigned i=0; i<pvars.in_dict->child_count(); ++i)
|
||||
{
|
||||
const object_t* in_pair = pvars.in_dict->child_ele(i);
|
||||
const char* in_var_label = in_pair->pair_label();
|
||||
const char* src_label = nullptr;
|
||||
const var_desc_t* vd = nullptr;
|
||||
|
||||
// note
|
||||
// locate the var desc of the associated variable
|
||||
if((vd = var_desc_find( class_desc, in_var_label)) == nullptr )
|
||||
{
|
||||
cwLogError(kSyntaxErrorRC,"The value description for the 'in' value '%s' was not found on instance '%s'. Maybe '%s' is not marked as a 'src' attribute in the class variable descripiton.",in_var_label,inst->label,in_var_label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// Note that all variable's found by the above call to var_desc_find() should be 'src'
|
||||
// variables because they are the only ones that have been created so far.
|
||||
// Note that all variable's found by the above call to var_desc_find() should be 'src' variables.
|
||||
assert( cwIsFlag(vd->flags,kSrcVarFl) );
|
||||
|
||||
// if this value is a 'src' value then it must be setup prior to the instance being instantiated
|
||||
@ -459,24 +639,24 @@ namespace cw
|
||||
// locate the pointer to the referenced output abuf and store it in inst->srcABuf[i]
|
||||
if((rc = _setup_input( p, inst, in_var_label, src_label )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"The 'in' buffer at index %i is not valid on instance '%s'.", i, inst_label );
|
||||
rc = cwLogError(kSyntaxErrorRC,"The 'in' buffer at index %i is not valid on instance '%s'.", i, inst->label );
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// complete the instantiation
|
||||
// complete the instantiation
|
||||
|
||||
if((rc = class_desc->members->create( inst )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kInvalidArgRC,"Instantiation failed on instance '%s'.", inst_label );
|
||||
rc = cwLogError(kInvalidArgRC,"Instantiation failed on instance '%s'.", inst->label );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
|
||||
if((rc =_create_instance_var_map( inst )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
|
||||
// insert an instance in the network
|
||||
if( p->network_tail == nullptr )
|
||||
{
|
||||
@ -502,6 +682,9 @@ namespace cw
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
|
||||
if( p == nullptr )
|
||||
return rc;
|
||||
|
||||
instance_t* i0=p->network_head;
|
||||
instance_t* i1=nullptr;
|
||||
|
||||
@ -548,16 +731,18 @@ namespace cw
|
||||
}
|
||||
}
|
||||
|
||||
cw::rc_t cw::flow::create( handle_t& hRef, const object_t& classCfg, const object_t& cfg )
|
||||
cw::rc_t cw::flow::create( handle_t& hRef, const object_t& classCfg, const object_t& networkCfg )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
const object_t* network;
|
||||
bool printClassDictFl = false;
|
||||
bool printNetworkFl = false;
|
||||
|
||||
if(( rc = destroy(hRef)) != kOkRC )
|
||||
return rc;
|
||||
|
||||
flow_t* p = mem::allocZ<flow_t>();
|
||||
p->cfg = &cfg; // TODO: duplicate cfg?
|
||||
p->cfg = &networkCfg; // TODO: duplicate cfg?
|
||||
|
||||
// parse the class description array
|
||||
if((rc = _parse_class_cfg(p,library,&classCfg)) != kOkRC )
|
||||
@ -567,20 +752,27 @@ cw::rc_t cw::flow::create( handle_t& hRef, const object_t& classCfg, const objec
|
||||
}
|
||||
|
||||
// parse the main audio file processor cfg record
|
||||
if((rc = cfg.getv("framesPerCycle", p->framesPerCycle,
|
||||
"network", network)) != kOkRC )
|
||||
if((rc = networkCfg.getv("framesPerCycle", p->framesPerCycle,
|
||||
"network", network)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"Error parsing the required flow configuration parameters.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if((rc = cfg.getv_opt("maxCycleCount", p->maxCycleCount)) != kOkRC )
|
||||
// parse the optional args
|
||||
if((rc = networkCfg.getv_opt("maxCycleCount", p->maxCycleCount,
|
||||
"printClassDictFl", printClassDictFl,
|
||||
"printNetworkFl", printNetworkFl)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"Error parsing the optional flow configuration parameters.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// for each instance in the network
|
||||
// print the class dict
|
||||
if( printClassDictFl )
|
||||
class_dict_print( p );
|
||||
|
||||
// build the network
|
||||
for(unsigned i=0; i<network->child_count(); ++i)
|
||||
{
|
||||
const object_t* inst_cfg = network->child_ele(i);
|
||||
@ -590,18 +782,18 @@ cw::rc_t cw::flow::create( handle_t& hRef, const object_t& classCfg, const objec
|
||||
{
|
||||
rc = cwLogError(rc,"The instantiation at network index %i is invalid.",i);
|
||||
goto errLabel;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// apply preset
|
||||
for(instance_t* inst=p->network_head; inst!=nullptr; inst=inst->link)
|
||||
if( inst->preset_label != nullptr )
|
||||
if((rc = apply_preset( inst, inst->preset_label )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
if( printNetworkFl )
|
||||
network_print(p);
|
||||
|
||||
hRef.set(p);
|
||||
|
||||
errLabel:
|
||||
|
||||
|
||||
if( rc != kOkRC )
|
||||
_destroy(p);
|
||||
|
||||
@ -615,10 +807,16 @@ cw::rc_t cw::flow::exec( handle_t& hRef )
|
||||
|
||||
while( true )
|
||||
{
|
||||
for(instance_t* inst = p->network_head; inst!=nullptr; inst=inst->link)
|
||||
for(instance_t* inst = p->network_head; inst!=nullptr; inst=inst->link)
|
||||
if((rc = inst->class_desc->members->exec(inst)) != kOkRC )
|
||||
break;
|
||||
|
||||
|
||||
if( rc == kEofRC )
|
||||
{
|
||||
rc = kOkRC;
|
||||
break;
|
||||
}
|
||||
|
||||
p->cycleIndex += 1;
|
||||
if( p->maxCycleCount > 0 && p->cycleIndex >= p->maxCycleCount )
|
||||
break;
|
||||
@ -646,7 +844,7 @@ cw::rc_t cw::flow::destroy( handle_t& hRef )
|
||||
|
||||
void cw::flow::print_class_list( handle_t& hRef )
|
||||
{
|
||||
class_desc_print(_handleToPtr(hRef));
|
||||
class_dict_print(_handleToPtr(hRef));
|
||||
}
|
||||
|
||||
void cw::flow::print_network( handle_t& hRef )
|
||||
@ -666,8 +864,6 @@ cw::rc_t cw::flow::test( const object_t* class_cfg, const object_t* cfg )
|
||||
rc = cwLogError(rc,"Flow object create failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
print_network(flowH);
|
||||
|
||||
// run the network
|
||||
if((rc = exec( flowH )) != kOkRC )
|
||||
|
2
cwFlow.h
2
cwFlow.h
@ -11,7 +11,7 @@ namespace cw
|
||||
|
||||
typedef handle<struct flow_str> handle_t;
|
||||
|
||||
rc_t create( handle_t& hRef, const object_t& classCfg, const object_t& cfg );
|
||||
rc_t create( handle_t& hRef, const object_t& classCfg, const object_t& networkCfg );
|
||||
rc_t exec( handle_t& hRef );
|
||||
rc_t destroy( handle_t& hRef );
|
||||
|
||||
|
429
cwFlowProc.cpp
429
cwFlowProc.cpp
@ -6,6 +6,8 @@
|
||||
#include "cwAudioFile.h"
|
||||
#include "cwVectOps.h"
|
||||
#include "cwMtx.h"
|
||||
|
||||
#include "cwDspTypes.h" // real_t, sample_t
|
||||
#include "cwFlow.h"
|
||||
#include "cwFlowTypes.h"
|
||||
#include "cwFlowProc.h"
|
||||
@ -14,6 +16,7 @@
|
||||
#include "cwMath.h"
|
||||
#include "cwDsp.h"
|
||||
#include "cwAudioTransforms.h"
|
||||
#include "cwDspTransforms.h"
|
||||
|
||||
namespace cw
|
||||
{
|
||||
@ -31,8 +34,6 @@ namespace cw
|
||||
|
||||
} inst_t;
|
||||
|
||||
|
||||
|
||||
|
||||
rc_t create( instance_t* ctx )
|
||||
{
|
||||
@ -83,6 +84,8 @@ namespace cw
|
||||
{
|
||||
enum
|
||||
{
|
||||
kFnamePId,
|
||||
kEofFlPId,
|
||||
kOutPId
|
||||
};
|
||||
|
||||
@ -101,20 +104,14 @@ namespace cw
|
||||
inst_t* inst = mem::allocZ<inst_t>();
|
||||
ctx->userPtr = inst;
|
||||
|
||||
// get the audio filename
|
||||
if((rc = ctx->arg_cfg->getv("fn",inst->filename)) != kOkRC )
|
||||
// Register variable and get their current value
|
||||
if((rc = var_register_and_get( ctx, kAnyChIdx,
|
||||
kFnamePId, "fname", inst->filename,
|
||||
kEofFlPId, "eofFl", inst->eofFl )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kInvalidArgRC,"The audio input file has no 'fn' argument.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// get the 'eof' flag
|
||||
if((rc = ctx->arg_cfg->getv_opt("eof",inst->eofFl)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kInvalidArgRC,"The audio input file has no 'fn' argument.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// open the audio file
|
||||
if((rc = audiofile::open(inst->afH,inst->filename,&info)) != kOkRC )
|
||||
{
|
||||
@ -125,7 +122,7 @@ namespace cw
|
||||
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
|
||||
rc = var_abuf_create( ctx, "out", kOutPId, kAnyChIdx, info.srate, info.chCnt, ctx->ctx->framesPerCycle );
|
||||
rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, info.srate, info.chCnt, ctx->ctx->framesPerCycle );
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
@ -162,7 +159,7 @@ namespace cw
|
||||
|
||||
|
||||
// verify that a source buffer exists
|
||||
if((rc = var_abuf_get(ctx,"out",kAnyChIdx,abuf)) != kOkRC )
|
||||
if((rc = var_get(ctx,kOutPId,kAnyChIdx,abuf)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kInvalidStateRC,"The audio file instance '%s' does not have a valid audio output buffer.",ctx->label);
|
||||
}
|
||||
@ -175,7 +172,7 @@ namespace cw
|
||||
|
||||
rc = readFloat(inst->afH, abuf->frameN, 0, abuf->chN, chBuf, &actualFrameN );
|
||||
|
||||
if( inst->eofFl && actualFrameN == 0)
|
||||
if( inst->eofFl && actualFrameN == 0)
|
||||
rc = kEofRC;
|
||||
}
|
||||
|
||||
@ -186,7 +183,8 @@ namespace cw
|
||||
.create = create,
|
||||
.destroy = destroy,
|
||||
.value = value,
|
||||
.exec = exec
|
||||
.exec = exec,
|
||||
.report = nullptr
|
||||
};
|
||||
|
||||
}
|
||||
@ -201,13 +199,15 @@ namespace cw
|
||||
{
|
||||
enum
|
||||
{
|
||||
kInPId
|
||||
kInPId,
|
||||
kFnamePId
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
audiofile::handle_t afH;
|
||||
const char* filename;
|
||||
const char* filename;
|
||||
unsigned durSmpN;
|
||||
} inst_t;
|
||||
|
||||
rc_t create( instance_t* ctx )
|
||||
@ -215,20 +215,14 @@ namespace cw
|
||||
rc_t rc = kOkRC; //
|
||||
unsigned audioFileBits = 0; // set audio file sample format to 'float32'.
|
||||
inst_t* inst = mem::allocZ<inst_t>(); //
|
||||
abuf_t* src_abuf = nullptr;
|
||||
const abuf_t* src_abuf = nullptr;
|
||||
ctx->userPtr = inst;
|
||||
|
||||
// get the audio filename
|
||||
if((rc = ctx->arg_cfg->getv("fn",inst->filename)) != kOkRC )
|
||||
// Register variables and get their current value
|
||||
if((rc = var_register_and_get( ctx, kAnyChIdx,
|
||||
kFnamePId, "fname", inst->filename,
|
||||
kInPId, "in", src_abuf)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kInvalidArgRC,"The audio input file has no 'fn' argument.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// verify that a source buffer exists
|
||||
if((rc = var_abuf_get(ctx,"in",kAnyChIdx,src_abuf)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kInvalidStateRC,"The audio file instance '%s' does not have a valid input connection.",ctx->label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
@ -239,8 +233,6 @@ namespace cw
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
rc = var_init( ctx, kAnyChIdx, kInPId, "in", src_abuf);
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
@ -275,7 +267,7 @@ namespace cw
|
||||
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||
const abuf_t* src_abuf = nullptr;
|
||||
|
||||
if((rc = var_abuf_get(ctx,"in",kAnyChIdx,src_abuf)) != kOkRC )
|
||||
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
|
||||
{
|
||||
@ -286,6 +278,12 @@ namespace cw
|
||||
|
||||
if((rc = audiofile::writeFloat(inst->afH, src_abuf->frameN, src_abuf->chN, chBuf )) != kOkRC )
|
||||
rc = cwLogError(rc,"Audio file write failed on instance: '%s'.", ctx->label );
|
||||
|
||||
// print a minutes counter
|
||||
inst->durSmpN += src_abuf->frameN;
|
||||
if( inst->durSmpN % ((unsigned)src_abuf->srate*60) == 0 )
|
||||
printf("%5.1f %s\n", inst->durSmpN/(src_abuf->srate*60));
|
||||
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -295,7 +293,8 @@ namespace cw
|
||||
.create = create,
|
||||
.destroy = destroy,
|
||||
.value = value,
|
||||
.exec = exec
|
||||
.exec = exec,
|
||||
.report = nullptr
|
||||
};
|
||||
|
||||
}
|
||||
@ -310,12 +309,16 @@ namespace cw
|
||||
|
||||
enum {
|
||||
kInPId,
|
||||
kHopSmpNPId,
|
||||
kWndSmpNPId,
|
||||
kHzFlPId,
|
||||
kOutPId
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pv_t** pvA; // pvA[ srcBuf.chN ]
|
||||
unsigned pvN;
|
||||
unsigned wndSmpN;
|
||||
unsigned hopSmpN;
|
||||
bool hzFl;
|
||||
@ -330,32 +333,19 @@ namespace cw
|
||||
inst_t* inst = mem::allocZ<inst_t>();
|
||||
ctx->userPtr = inst;
|
||||
|
||||
// get the wnd/hop sample count
|
||||
if((rc = ctx->arg_cfg->getv("wndSmpCnt",inst->wndSmpN,
|
||||
"hopSmpCnt",inst->hopSmpN )) != kOkRC )
|
||||
if((rc = var_register_and_get( ctx, kAnyChIdx,
|
||||
kInPId, "in", srcBuf,
|
||||
kHopSmpNPId, "hopSmpN", inst->hopSmpN,
|
||||
kWndSmpNPId, "wndSmpN", inst->wndSmpN,
|
||||
kHzFlPId, "hzFl", inst->hzFl )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"PV Analysis required parameters parse failed on instance '%s'.",ctx->label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// get the optional arg's.
|
||||
if((rc = ctx->arg_cfg->getv_opt("hzFl",inst->hzFl)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"PV Analysis optional parameters parse failed on instance '%s'.",ctx->label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// verify that a source buffer exists
|
||||
if((rc = var_abuf_get(ctx,"in", kAnyChIdx, srcBuf )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"The instance '%s' does not have a valid input connection.",ctx->label);
|
||||
goto errLabel;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
flags = inst->hzFl ? dsp::pv_anl::kCalcHzPvaFl : dsp::pv_anl::kNoCalcHzPvaFl;
|
||||
inst->pvA = mem::allocZ<pv_t*>( srcBuf->chN ); // allocate pv channel array
|
||||
inst->pvN = srcBuf->chN;
|
||||
inst->pvA = mem::allocZ<pv_t*>( inst->pvN ); // allocate pv channel array
|
||||
const sample_t* magV[ srcBuf->chN ];
|
||||
const sample_t* phsV[ srcBuf->chN ];
|
||||
const sample_t* hzV[ srcBuf->chN ];
|
||||
@ -374,11 +364,12 @@ namespace cw
|
||||
hzV[i] = inst->pvA[i]->hzV;
|
||||
}
|
||||
|
||||
if((rc = var_init( ctx, kAnyChIdx, kInPId, "in", srcBuf )) != kOkRC )
|
||||
if((rc = var_register( ctx, kAnyChIdx, kInPId, "in" )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
// create the fbuf 'out'
|
||||
rc = var_fbuf_create( 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, srcBuf->chN, inst->pvA[0]->binCnt, inst->pvA[0]->hopSmpCnt, magV, phsV, hzV );
|
||||
|
||||
}
|
||||
|
||||
errLabel:
|
||||
@ -390,6 +381,11 @@ namespace cw
|
||||
rc_t rc = kOkRC;
|
||||
|
||||
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||
|
||||
for(unsigned i=0; i<inst->pvN; ++i)
|
||||
destroy(inst->pvA[i]);
|
||||
|
||||
mem::release(inst->pvA);
|
||||
mem::release(inst);
|
||||
|
||||
return rc;
|
||||
@ -409,14 +405,14 @@ namespace cw
|
||||
fbuf_t* dstBuf = nullptr;
|
||||
|
||||
// verify that a source buffer exists
|
||||
if((rc = var_abuf_get(ctx,"in", kAnyChIdx, srcBuf )) != kOkRC )
|
||||
if((rc = var_get(ctx,kInPId, kAnyChIdx, srcBuf )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"The instance '%s' does not have a valid input connection.",ctx->label);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// verify that the dst buffer exits
|
||||
if((rc = var_fbuf_get(ctx,"out", kAnyChIdx, dstBuf)) != kOkRC )
|
||||
if((rc = var_get(ctx,kOutPId, kAnyChIdx, dstBuf)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"The instance '%s' does not have a valid output.",ctx->label);
|
||||
goto errLabel;
|
||||
@ -425,11 +421,17 @@ namespace cw
|
||||
// for each input channel
|
||||
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||
{
|
||||
dstBuf->readyFlV[i] = false;
|
||||
|
||||
// call the PV analysis processor
|
||||
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
|
||||
vop::mul(dstBuf->magV[i], dstBuf->binN/2, dstBuf->binN);
|
||||
|
||||
dstBuf->readyFlV[i] = true;
|
||||
|
||||
// rescale the frequency domain magnitude
|
||||
vop::mul(dstBuf->magV[i], dstBuf->binN/2, dstBuf->binN);
|
||||
}
|
||||
}
|
||||
|
||||
errLabel:
|
||||
@ -440,7 +442,8 @@ namespace cw
|
||||
.create = create,
|
||||
.destroy = destroy,
|
||||
.value = value,
|
||||
.exec = exec
|
||||
.exec = exec,
|
||||
.report = nullptr
|
||||
};
|
||||
}
|
||||
|
||||
@ -461,6 +464,7 @@ namespace cw
|
||||
typedef struct
|
||||
{
|
||||
pv_t** pvA; // pvA[ srcBuf.chN ]
|
||||
unsigned pvN;
|
||||
unsigned wndSmpN; //
|
||||
unsigned hopSmpN; //
|
||||
bool hzFl; //
|
||||
@ -474,18 +478,16 @@ namespace cw
|
||||
inst_t* inst = mem::allocZ<inst_t>();
|
||||
ctx->userPtr = inst;
|
||||
|
||||
|
||||
// verify that a source buffer exists
|
||||
if((rc = var_fbuf_get(ctx,"in", kAnyChIdx, srcBuf )) != kOkRC )
|
||||
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->pvA = mem::allocZ<pv_t*>( srcBuf->chN );
|
||||
inst->pvN = srcBuf->chN;
|
||||
inst->pvA = mem::allocZ<pv_t*>( inst->pvN );
|
||||
|
||||
// create a pv anlaysis object for each input channel
|
||||
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||
@ -499,11 +501,11 @@ namespace cw
|
||||
}
|
||||
}
|
||||
|
||||
if((rc = var_init( ctx, kAnyChIdx, kInPId, "in", srcBuf )) != kOkRC )
|
||||
if((rc = var_register( ctx, kAnyChIdx, kInPId, "in" )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
// create the abuf 'out'
|
||||
rc = var_abuf_create( ctx, "out", kOutPId, kAnyChIdx, srcBuf->srate, srcBuf->chN, ctx->ctx->framesPerCycle );
|
||||
rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, srcBuf->srate, srcBuf->chN, ctx->ctx->framesPerCycle );
|
||||
}
|
||||
|
||||
errLabel:
|
||||
@ -515,6 +517,10 @@ namespace cw
|
||||
rc_t rc = kOkRC;
|
||||
|
||||
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||
for(unsigned i=0; i<inst->pvN; ++i)
|
||||
destroy(inst->pvA[i]);
|
||||
|
||||
mem::release(inst->pvA);
|
||||
mem::release(inst);
|
||||
|
||||
return rc;
|
||||
@ -534,18 +540,23 @@ namespace cw
|
||||
abuf_t* dstBuf = nullptr;
|
||||
|
||||
// get the src buffer
|
||||
if((rc = var_fbuf_get(ctx,"in", kAnyChIdx, srcBuf )) != kOkRC )
|
||||
if((rc = var_get(ctx,kInPId, kAnyChIdx, srcBuf )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
// get the dst buffer
|
||||
if((rc = var_abuf_get(ctx,"out", kAnyChIdx, dstBuf)) != kOkRC )
|
||||
if((rc = var_get(ctx,kOutPId, kAnyChIdx, dstBuf)) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||
{
|
||||
dsp::pv_syn::exec( inst->pvA[i], srcBuf->magV[i], srcBuf->phsV[i] );
|
||||
|
||||
abuf_set_channel( dstBuf, i, inst->pvA[i]->ola->outV, inst->pvA[i]->ola->hopSmpCnt );
|
||||
if( srcBuf->readyFlV[i] )
|
||||
dsp::pv_syn::exec( inst->pvA[i], srcBuf->magV[i], srcBuf->phsV[i] );
|
||||
|
||||
const sample_t* ola_out = dsp::ola::execOut(inst->pvA[i]->ola);
|
||||
if( ola_out != nullptr )
|
||||
abuf_set_channel( dstBuf, i, ola_out, inst->pvA[i]->ola->procSmpCnt );
|
||||
|
||||
//abuf_set_channel( dstBuf, i, inst->pvA[i]->ola->outV, dstBuf->frameN );
|
||||
}
|
||||
|
||||
|
||||
@ -557,7 +568,8 @@ namespace cw
|
||||
.create = create,
|
||||
.destroy = destroy,
|
||||
.value = value,
|
||||
.exec = exec
|
||||
.exec = exec,
|
||||
.report = nullptr
|
||||
};
|
||||
}
|
||||
|
||||
@ -585,6 +597,7 @@ namespace cw
|
||||
typedef struct
|
||||
{
|
||||
spec_dist_t** sdA;
|
||||
unsigned sdN;
|
||||
} inst_t;
|
||||
|
||||
|
||||
@ -597,7 +610,7 @@ namespace cw
|
||||
ctx->userPtr = inst;
|
||||
|
||||
// verify that a source buffer exists
|
||||
if((rc = var_fbuf_get(ctx,"in", kAnyChIdx, srcBuf )) != kOkRC )
|
||||
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;
|
||||
@ -605,12 +618,15 @@ namespace cw
|
||||
else
|
||||
{
|
||||
// allocate pv channel array
|
||||
inst->sdA = mem::allocZ<spec_dist_t*>( srcBuf->chN );
|
||||
inst->sdN = srcBuf->chN;
|
||||
inst->sdA = mem::allocZ<spec_dist_t*>( inst->sdN );
|
||||
|
||||
const sample_t* magV[ srcBuf->chN ];
|
||||
const sample_t* phsV[ srcBuf->chN ];
|
||||
const sample_t* hzV[ srcBuf->chN ];
|
||||
|
||||
|
||||
//if((rc = var_register(ctx, kAnyChIdx, kInPId, "in")) != kOkRC )
|
||||
// goto errLabel;
|
||||
|
||||
// create a spec_dist object for each input channel
|
||||
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||
@ -626,14 +642,15 @@ namespace cw
|
||||
phsV[i] = inst->sdA[i]->outPhsV;
|
||||
hzV[i] = nullptr;
|
||||
|
||||
if((rc = var_init( ctx, i,
|
||||
kInPId, "in", srcBuf,
|
||||
kCeilingPId, "ceiling", 30.0f,
|
||||
kExpoPId, "expo", 3.0f,
|
||||
kThreshPId, "thresh", 54.0f,
|
||||
kUprSlopePId,"uprSlope", -0.7f,
|
||||
kLwrSlopePId,"lwrSlope", 2.0f,
|
||||
kMixPId, "mix", 0.0f )) != kOkRC )
|
||||
spec_dist_t* sd = inst->sdA[i];
|
||||
|
||||
if((rc = var_register_and_get( ctx, i,
|
||||
kCeilingPId, "ceiling", sd->ceiling,
|
||||
kExpoPId, "expo", sd->expo,
|
||||
kThreshPId, "thresh", sd->thresh,
|
||||
kUprSlopePId, "upr", sd->uprSlope,
|
||||
kLwrSlopePId, "lwr", sd->lwrSlope,
|
||||
kMixPId, "mix", sd->mix )) != kOkRC )
|
||||
{
|
||||
goto errLabel;
|
||||
}
|
||||
@ -641,7 +658,7 @@ namespace cw
|
||||
}
|
||||
|
||||
// create the output buffer
|
||||
if((rc = var_fbuf_create( 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->chN, srcBuf->binN, srcBuf->hopSmpN, magV, phsV, hzV )) != kOkRC )
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
@ -654,6 +671,10 @@ namespace cw
|
||||
rc_t rc = kOkRC;
|
||||
|
||||
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||
for(unsigned i=0; i<inst->sdN; ++i)
|
||||
destroy(inst->sdA[i]);
|
||||
|
||||
mem::release(inst->sdA);
|
||||
mem::release(inst);
|
||||
|
||||
return rc;
|
||||
@ -661,7 +682,24 @@ namespace cw
|
||||
|
||||
rc_t value( instance_t* ctx, variable_t* var )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
rc_t rc = kOkRC;
|
||||
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||
|
||||
if( var->chIdx != kAnyChIdx && var->chIdx < inst->sdN )
|
||||
{
|
||||
switch( var->vid )
|
||||
{
|
||||
case kCeilingPId: var_get( var, inst->sdA[ var->chIdx ]->ceiling ); break;
|
||||
case kExpoPId: var_get( var, inst->sdA[ var->chIdx ]->expo ); break;
|
||||
case kThreshPId: var_get( var, inst->sdA[ var->chIdx ]->thresh ); break;
|
||||
case kUprSlopePId: var_get( var, inst->sdA[ var->chIdx ]->uprSlope ); break;
|
||||
case kLwrSlopePId: var_get( var, inst->sdA[ var->chIdx ]->lwrSlope ); break;
|
||||
case kMixPId: var_get( var, inst->sdA[ var->chIdx ]->mix ); break;
|
||||
default:
|
||||
cwLogWarning("Unhandled variable id '%i' on instance: %s.", var->vid, ctx->label );
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -671,23 +709,30 @@ namespace cw
|
||||
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||
const fbuf_t* srcBuf = nullptr;
|
||||
fbuf_t* dstBuf = nullptr;
|
||||
unsigned chN = 0;
|
||||
|
||||
// get the src buffer
|
||||
if((rc = var_fbuf_get(ctx,"in", kAnyChIdx, srcBuf )) != kOkRC )
|
||||
if((rc = var_get(ctx,kInPId, kAnyChIdx, srcBuf )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
// get the dst buffer
|
||||
if((rc = var_fbuf_get(ctx,"out", kAnyChIdx, dstBuf)) != kOkRC )
|
||||
if((rc = var_get(ctx,kOutPId, kAnyChIdx, dstBuf)) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||
{
|
||||
dsp::spec_dist::exec( inst->sdA[i], srcBuf->magV[i], srcBuf->phsV[i], srcBuf->binN );
|
||||
|
||||
//if( i == 0 )
|
||||
// printf("%f %f\n", vop::sum(srcBuf->magV[i],srcBuf->binN), vop::sum(dstBuf->magV[i], dstBuf->binN) );
|
||||
chN = std::min(srcBuf->chN,inst->sdN);
|
||||
|
||||
for(unsigned i=0; i<chN; ++i)
|
||||
{
|
||||
dstBuf->readyFlV[i] = false;
|
||||
if( srcBuf->readyFlV[i] )
|
||||
{
|
||||
dsp::spec_dist::exec( inst->sdA[i], srcBuf->magV[i], srcBuf->phsV[i], srcBuf->binN );
|
||||
|
||||
dstBuf->readyFlV[i] = true;
|
||||
//If == 0 )
|
||||
// printf("%f %f\n", vop::sum(srcBuf->magV[i],srcBuf->binN), vop::sum(dstBuf->magV[i], dstBuf->binN) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
@ -697,10 +742,200 @@ namespace cw
|
||||
.create = create,
|
||||
.destroy = destroy,
|
||||
.value = value,
|
||||
.exec = exec
|
||||
.exec = exec,
|
||||
.report = nullptr
|
||||
};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Compressor
|
||||
//
|
||||
namespace compressor
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
kInPId,
|
||||
kBypassPId,
|
||||
kInGainPId,
|
||||
kThreshPId,
|
||||
kRatioPId,
|
||||
kAtkMsPId,
|
||||
kRlsMsPId,
|
||||
kWndMsPId,
|
||||
kMaxWndMsPId,
|
||||
kOutGainPId,
|
||||
kOutPId,
|
||||
kEnvPId
|
||||
};
|
||||
|
||||
|
||||
typedef dsp::compressor::obj_t compressor_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
compressor_t** cmpA;
|
||||
unsigned cmpN;
|
||||
} 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->cmpN = srcBuf->chN;
|
||||
inst->cmpA = mem::allocZ<compressor_t*>( inst->cmpN );
|
||||
|
||||
// create a compressor object for each input channel
|
||||
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||
{
|
||||
real_t igain, maxWnd_ms, wnd_ms, thresh, ratio, atk_ms, rls_ms, ogain, bypassFl;
|
||||
|
||||
|
||||
// get the compressor variable values
|
||||
if((rc = var_register_and_get( ctx, i,
|
||||
kBypassPId, "bypass", bypassFl,
|
||||
kInGainPId, "igain", igain,
|
||||
kThreshPId, "thresh", thresh,
|
||||
kRatioPId, "ratio", ratio,
|
||||
kAtkMsPId, "atk_ms", atk_ms,
|
||||
kRlsMsPId, "rls_ms", rls_ms,
|
||||
kWndMsPId, "wnd_ms", wnd_ms,
|
||||
kMaxWndMsPId, "maxWnd_ms", maxWnd_ms,
|
||||
kOutGainPId, "ogain", ogain )) != kOkRC )
|
||||
{
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// create the compressor instance
|
||||
if((rc = dsp::compressor::create( inst->cmpA[i], srcBuf->srate, srcBuf->frameN, igain, maxWnd_ms, wnd_ms, thresh, ratio, atk_ms, rls_ms, ogain, bypassFl)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(kOpFailRC,"The 'compressor' 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->cmpN; ++i)
|
||||
destroy(inst->cmpA[i]);
|
||||
|
||||
mem::release(inst->cmpA);
|
||||
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 tmp;
|
||||
|
||||
if( var->chIdx != kAnyChIdx && var->chIdx < inst->cmpN )
|
||||
{
|
||||
|
||||
switch( var->vid )
|
||||
{
|
||||
case kBypassPId: var_get( var, inst->cmpA[ var->chIdx ]->bypassFl ); break;
|
||||
case kInGainPId: var_get( var, inst->cmpA[ var->chIdx ]->inGain ); break;
|
||||
case kOutGainPId: var_get( var, inst->cmpA[ var->chIdx ]->outGain ); break;
|
||||
case kRatioPId: var_get( var, inst->cmpA[ var->chIdx ]->ratio_num ); break;
|
||||
case kThreshPId: var_get( var, inst->cmpA[ var->chIdx ]->threshDb ); break;
|
||||
case kAtkMsPId: var_get( var, tmp ); set_attack_ms(inst->cmpA[ var->chIdx ], tmp ); break;
|
||||
case kRlsMsPId: var_get( var, tmp ); set_release_ms(inst->cmpA[ var->chIdx ], tmp ); break;
|
||||
case kWndMsPId: var_get( var, tmp ); set_rms_wnd_ms(inst->cmpA[ var->chIdx ], tmp ); break;
|
||||
default:
|
||||
cwLogWarning("Unhandled variable id '%i' on instance: %s.", var->vid, ctx->label );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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->cmpN);
|
||||
|
||||
for(unsigned i=0; i<chN; ++i)
|
||||
{
|
||||
dsp::compressor::exec( inst->cmpA[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->cmpN; ++i)
|
||||
{
|
||||
compressor_t* c = inst->cmpA[i];
|
||||
cwLogInfo("%s ch:%i : sr:%f bypass:%i procSmpN:%i igain:%f threshdb:%f ratio:%f atkSmp:%i rlsSmp:%i ogain:%f rmsWndN:%i maxRmsWndN%i",
|
||||
ctx->label,i,c->srate,c->bypassFl,c->procSmpCnt,c->inGain,c->threshDb,c->ratio_num,c->atkSmp,c->rlsSmp,c->outGain,c->rmsWndCnt,c->rmsWndAllocCnt
|
||||
);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
class_members_t members = {
|
||||
.create = create,
|
||||
.destroy = destroy,
|
||||
.value = value,
|
||||
.exec = exec,
|
||||
.report = report
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,11 @@ namespace cw
|
||||
{
|
||||
namespace flow
|
||||
{
|
||||
namespace audioFileIn { extern class_members_t members; }
|
||||
namespace audioFileIn { extern class_members_t members; }
|
||||
namespace audioFileOut { extern class_members_t members; }
|
||||
namespace pv_analysis { extern class_members_t members; }
|
||||
namespace pv_synthesis { extern class_members_t members; }
|
||||
namespace spec_dist { extern class_members_t members; }
|
||||
namespace compressor { extern class_members_t members; }
|
||||
}
|
||||
}
|
||||
|
1359
cwFlowTypes.cpp
1359
cwFlowTypes.cpp
File diff suppressed because it is too large
Load Diff
269
cwFlowTypes.h
269
cwFlowTypes.h
@ -3,12 +3,14 @@ namespace cw
|
||||
namespace flow
|
||||
{
|
||||
|
||||
typedef float real_t;
|
||||
typedef real_t sample_t;
|
||||
typedef real_t srate_t;
|
||||
typedef unsigned uint_t;
|
||||
typedef int int_t;
|
||||
|
||||
#define kRealTFl kFloatTFl
|
||||
typedef dsp::real_t real_t;
|
||||
typedef dsp::sample_t sample_t;
|
||||
typedef dsp::srate_t srate_t;
|
||||
typedef unsigned uint_t;
|
||||
typedef int int_t;
|
||||
|
||||
|
||||
typedef unsigned vid_t;
|
||||
|
||||
typedef struct abuf_str
|
||||
@ -37,6 +39,7 @@ namespace cw
|
||||
sample_t** magV; // magV[ chN ][ binN ]
|
||||
sample_t** phsV; // phsV[ chN ][ binN ]
|
||||
sample_t** hzV; // hzV[ chN ][ binN ]
|
||||
bool* readyFlV;// readyFlV[chN] true if this channel is ready to be processed (used to sync. fbuf rate to abuf rate)
|
||||
sample_t* buf; // memory used by this buffer (or NULL if magV,phsV,hzV point are proxied to another buffer)
|
||||
} fbuf_t;
|
||||
|
||||
@ -46,24 +49,22 @@ namespace cw
|
||||
kBoolTFl = 0x00000001,
|
||||
kUIntTFl = 0x00000002,
|
||||
kIntTFl = 0x00000004,
|
||||
kRealTFl = 0x00000008,
|
||||
kF32TFl = 0x00000010,
|
||||
kF64TFl = 0x00000020,
|
||||
kFloatTFl = 0x00000008,
|
||||
kDoubleTFl = 0x00000010,
|
||||
|
||||
kBoolMtxTFl = 0x00000040,
|
||||
kUIntMtxTFl = 0x00000080,
|
||||
kIntMtxTFl = 0x00000100,
|
||||
kRealMtxTFl = 0x00000200,
|
||||
kF32MtxTFl = 0x00000400,
|
||||
kF64MtxTFl = 0x00000800,
|
||||
kBoolMtxTFl = 0x00000020,
|
||||
kUIntMtxTFl = 0x00000040,
|
||||
kIntMtxTFl = 0x00000080,
|
||||
kRealMtxTFl = 0x00000100,
|
||||
kFloatMtxTFl = 0x00000200,
|
||||
kDoubleMtxTFl= 0x00000400,
|
||||
|
||||
kABufTFl = 0x00001000,
|
||||
kFBufTFl = 0x00002000,
|
||||
kStringTFl = 0x00004000,
|
||||
kFNameTFl = 0x00008000,
|
||||
kTimeTFl = 0x00010000,
|
||||
kABufTFl = 0x00000800,
|
||||
kFBufTFl = 0x00001000,
|
||||
kStringTFl = 0x00002000,
|
||||
kTimeTFl = 0x00004000,
|
||||
|
||||
kTypeMask = 0x0001ffff,
|
||||
kTypeMask = 0x00007fff,
|
||||
|
||||
};
|
||||
|
||||
@ -85,7 +86,6 @@ namespace cw
|
||||
bool b;
|
||||
uint_t u;
|
||||
int_t i;
|
||||
real_t r;
|
||||
float f;
|
||||
double d;
|
||||
|
||||
@ -97,20 +97,19 @@ namespace cw
|
||||
char* s;
|
||||
char* fname;
|
||||
|
||||
struct value_str* proxy;
|
||||
} u;
|
||||
|
||||
struct value_str* link;
|
||||
|
||||
} value_t;
|
||||
|
||||
|
||||
inline bool is_numeric( const value_t* v ) { return cwIsFlag(v->flags,kBoolTFl|kUIntTFl|kIntTFl|kFloatTFl|kDoubleTFl); }
|
||||
inline bool is_matrix( const value_t* v ) { return cwIsFlag(v->flags,kBoolMtxTFl|kUIntMtxTFl|kIntMtxTFl|kFloatMtxTFl|kDoubleMtxTFl); }
|
||||
|
||||
struct instance_str;
|
||||
struct variable_str;
|
||||
|
||||
typedef struct ctx_str
|
||||
{
|
||||
} ctx_t;
|
||||
|
||||
|
||||
typedef rc_t (*member_func_t)( struct instance_str* ctx );
|
||||
typedef rc_t (*member_value_func_t)( struct instance_str* ctx, struct variable_str* var );
|
||||
enum
|
||||
@ -124,16 +123,18 @@ namespace cw
|
||||
member_func_t destroy;
|
||||
member_value_func_t value;
|
||||
member_func_t exec;
|
||||
member_func_t report;
|
||||
} class_members_t;
|
||||
|
||||
typedef struct var_desc_str
|
||||
{
|
||||
const object_t* cfg; //
|
||||
const char* label; //
|
||||
unsigned type; // value type id
|
||||
unsigned flags; //
|
||||
const char* docText; //
|
||||
struct var_desc_str* link; //
|
||||
const object_t* cfg; // The cfg object that describes this variable from 'flow_class'.
|
||||
const object_t* val_cfg; // An object containing the default value for this variable.
|
||||
const char* label; // Name of this var.
|
||||
unsigned type; // Value type id (e.g. kBoolTFl, kIntTFl, ...)
|
||||
unsigned flags; // Attributes for this var. (e.g. kSrcVarFl )
|
||||
const char* docText; // User help string for this var.
|
||||
struct var_desc_str* link; // class_desc->varDescL list link
|
||||
} var_desc_t;
|
||||
|
||||
typedef struct preset_str
|
||||
@ -152,7 +153,9 @@ namespace cw
|
||||
class_members_t* members; // member functions for this class
|
||||
} class_desc_t;
|
||||
|
||||
|
||||
|
||||
// Note: The concatenation of 'vid' and 'chIdx' should form a unique identifier among all variables
|
||||
// on a given 'instance'.
|
||||
typedef struct variable_str
|
||||
{
|
||||
struct instance_str* inst; // pointer to this variables instance
|
||||
@ -162,8 +165,9 @@ namespace cw
|
||||
value_t local_value; // the local value instance (actual value if this is not a 'src' variable)
|
||||
value_t* value; // pointer to the value associated with this variable
|
||||
unsigned chIdx; // channel index
|
||||
struct variable_str* link; // link to other var's on 'inst'
|
||||
struct variable_str* var_link; // link to other var's on 'inst'
|
||||
struct variable_str* connect_link; // list of outgoing connections
|
||||
struct variable_str* ch_link; // list of channels that share this variable (rooted on 'any' channel - in order by channel number)
|
||||
} variable_t;
|
||||
|
||||
|
||||
@ -178,7 +182,6 @@ namespace cw
|
||||
|
||||
const char* arg_label; // optional args label
|
||||
const object_t* arg_cfg; // optional args configuration
|
||||
const char* preset_label; // optional preset label
|
||||
|
||||
void* userPtr; // instance state
|
||||
|
||||
@ -214,11 +217,13 @@ namespace cw
|
||||
|
||||
abuf_t* abuf_create( srate_t srate, unsigned chN, unsigned frameN );
|
||||
void abuf_destroy( abuf_t* buf );
|
||||
abuf_t* abuf_duplicate( const abuf_t* src );
|
||||
rc_t abuf_set_channel( abuf_t* buf, unsigned chIdx, const sample_t* v, unsigned vN );
|
||||
const sample_t* abuf_get_channel( abuf_t* buf, unsigned chIdx );
|
||||
|
||||
fbuf_t* fbuf_create( srate_t srate, unsigned chN, 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 );
|
||||
|
||||
inline bool value_is_abuf( const value_t* v ) { return v->flags & kABufTFl; }
|
||||
inline bool value_is_fbuf( const value_t* v ) { return v->flags & kFBufTFl; }
|
||||
@ -233,8 +238,15 @@ namespace cw
|
||||
var_desc_t* var_desc_find( class_desc_t* cd, const char* var_label );
|
||||
rc_t var_desc_find( class_desc_t* cd, const char* label, var_desc_t*& vdRef );
|
||||
|
||||
class_desc_t* class_desc_find( flow_t* p, const char* class_desc_label );
|
||||
void class_desc_print( flow_t* p );
|
||||
class_desc_t* class_desc_find( flow_t* p, const char* class_desc_label );
|
||||
|
||||
void class_dict_print( flow_t* p );
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Network
|
||||
//
|
||||
void network_print( flow_t* p );
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
@ -252,72 +264,163 @@ namespace cw
|
||||
//
|
||||
|
||||
// Create a variable but do not assign it a value. Return a pointer to the new variable.
|
||||
rc_t var_create( instance_t* inst, const char* label, unsigned vid, unsigned chIdx, variable_t*& varRef );
|
||||
// Note: `value_cfg` is optional. Set it to NULL to ignore
|
||||
rc_t var_create( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef );
|
||||
|
||||
// var_init(). If the variable has not yet been created then it is created and assigned a value.
|
||||
// If the variable has already been created then 'vid' and the value are updated.
|
||||
// (Note that abuf and fbuf values are not changed by this function only the 'vid' is updated.)
|
||||
rc_t var_init( instance_t* inst, const char* label, unsigned vid, unsigned chIdx, variable_t*& varRef );
|
||||
rc_t var_init( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, unsigned value );
|
||||
rc_t var_init( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, int value );
|
||||
rc_t var_init( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, real_t value );
|
||||
rc_t var_init( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, const abuf_t* abuf );
|
||||
rc_t var_init( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, const fbuf_t* fbuf );
|
||||
// Channelizing creates a new var record with an explicit channel index to replace the
|
||||
// automatically generated variable whose channel index is set to 'all'.
|
||||
rc_t var_channelize( instance_t* inst, const char* var_label, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef );
|
||||
|
||||
inline rc_t _var_init(cw::flow::instance_t* inst, unsigned int ) { return kOkRC; }
|
||||
// `value_cfg` is optional. Set it to NULL to ignore
|
||||
rc_t var_register( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef );
|
||||
|
||||
template< typename T0, typename T1, typename T2, typename... ARGS >
|
||||
rc_t _var_init( instance_t* inst, unsigned chIdx, T0 vid, T1 var_label, T2 val, ARGS&&... args )
|
||||
|
||||
//-----------------
|
||||
//
|
||||
// var_register
|
||||
//
|
||||
|
||||
inline rc_t _var_reg(cw::flow::instance_t*, unsigned int ) { return kOkRC; }
|
||||
|
||||
template< typename T0, typename T1, typename... ARGS >
|
||||
rc_t _var_reg( instance_t* inst, unsigned chIdx, T0 vid, T1 var_label, ARGS&&... args )
|
||||
{
|
||||
rc_t rc;
|
||||
|
||||
if((rc = var_init( inst, var_label, vid, chIdx, val )) == kOkRC )
|
||||
rc = _var_init( inst, chIdx, std::forward<ARGS>(args)...);
|
||||
variable_t* dummy = nullptr;
|
||||
if((rc = var_register( inst, var_label, vid, chIdx, nullptr, dummy )) == kOkRC )
|
||||
if((rc = _var_reg( inst, chIdx, std::forward<ARGS>(args)...)) != kOkRC )
|
||||
return rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Call var_init() on a list of variables.
|
||||
// Call var_register() on a list of variables.
|
||||
template< typename... ARGS >
|
||||
rc_t var_init( instance_t* inst, unsigned chIdx, unsigned vid, const char* var_label, ARGS&&... args )
|
||||
{ return _var_init( inst, chIdx, vid, var_label, std::forward<ARGS>(args)...); }
|
||||
rc_t var_register( instance_t* inst, unsigned chIdx, unsigned vid, const char* var_label, ARGS&&... args )
|
||||
{ return _var_reg( inst, chIdx, vid, var_label, std::forward<ARGS>(args)...); }
|
||||
|
||||
|
||||
|
||||
//---------------------
|
||||
//
|
||||
// var_register_and_get
|
||||
//
|
||||
|
||||
inline rc_t _var_register_and_get(cw::flow::instance_t*, unsigned int ) { return kOkRC; }
|
||||
|
||||
template< typename T>
|
||||
rc_t var_register_and_get( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, T& valRef )
|
||||
{
|
||||
rc_t rc;
|
||||
variable_t* var;
|
||||
if((rc = var_register(inst,var_label,vid,chIdx,nullptr,var)) == kOkRC )
|
||||
rc = var_get(var,valRef);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
inline rc_t _var_reg_and_get(cw::flow::instance_t*, unsigned int ) { return kOkRC; }
|
||||
|
||||
template< typename T0, typename T1, typename T2, typename... ARGS >
|
||||
rc_t _var_reg_and_get( instance_t* inst, unsigned chIdx, T0 vid, T1 var_label, T2& valRef, ARGS&&... args )
|
||||
{
|
||||
rc_t rc;
|
||||
|
||||
if((rc = var_register_and_get( inst, var_label, vid, chIdx, valRef )) == kOkRC )
|
||||
if((rc = _var_reg_and_get( inst, chIdx, std::forward<ARGS>(args)...)) != kOkRC )
|
||||
return rc;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Call var_register_and_get() on a list of variables.
|
||||
template< typename... ARGS >
|
||||
rc_t var_register_and_get( instance_t* inst, unsigned chIdx, unsigned vid, const char* var_label, ARGS&&... args )
|
||||
{ return _var_reg_and_get( inst, chIdx, vid, var_label, std::forward<ARGS>(args)...); }
|
||||
|
||||
|
||||
|
||||
//---------------------
|
||||
//
|
||||
// var_register_and_set
|
||||
//
|
||||
|
||||
// var_register_and_set(). If the variable has not yet been created then it is created and assigned a value.
|
||||
// If the variable has already been created then 'vid' and the value are updated.
|
||||
// (Note that abuf and fbuf values are not changed by this function only the 'vid' is updated.)
|
||||
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 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; }
|
||||
|
||||
template< typename T0, typename T1, typename T2, typename... ARGS >
|
||||
rc_t _var_register_and_set( instance_t* inst, unsigned chIdx, T0 vid, T1 var_label, T2 val, ARGS&&... args )
|
||||
{
|
||||
rc_t rc;
|
||||
|
||||
variable_t* var = nullptr;
|
||||
if((rc = var_register_and_set( inst, var_label, vid, chIdx, var)) == kOkRC )
|
||||
{
|
||||
var_set( var, val );
|
||||
if((rc = _var_register_and_set( inst, chIdx, std::forward<ARGS>(args)...)) != kOkRC )
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Call var_register_and_set() on a list of variables.
|
||||
template< typename... ARGS >
|
||||
rc_t var_register_and_set( instance_t* inst, unsigned chIdx, unsigned vid, const char* var_label, ARGS&&... args )
|
||||
{ return _var_register_and_set( inst, chIdx, vid, var_label, std::forward<ARGS>(args)...); }
|
||||
|
||||
|
||||
|
||||
void _var_destroy( variable_t* var );
|
||||
|
||||
bool var_exists( instance_t* inst, const char* label, unsigned chIdx );
|
||||
|
||||
rc_t var_get( instance_t* inst, const char* var_label, unsigned chIdx, variable_t*& vRef );
|
||||
rc_t var_get( instance_t* inst, const char* var_label, unsigned chIdx, const variable_t*& vRef );
|
||||
rc_t var_find( instance_t* inst, const char* var_label, unsigned chIdx, const variable_t*& varRef );
|
||||
rc_t var_find( instance_t* inst, const char* var_label, unsigned chIdx, variable_t*& varRef );
|
||||
rc_t var_find( instance_t* inst, unsigned vid, unsigned chIdx, variable_t*& varRef );
|
||||
|
||||
rc_t value_get( instance_t* inst, const char* label, unsigned chIdx, value_t*& vRef );
|
||||
rc_t value_get( instance_t* inst, const char* label, unsigned chIdx, const value_t*& vRef );
|
||||
|
||||
rc_t var_abuf_create( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned frameN );
|
||||
rc_t var_fbuf_create( 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_get( const variable_t* var, bool& valRef );
|
||||
rc_t var_get( const variable_t* var, uint_t& valRef );
|
||||
rc_t var_get( const variable_t* var, int_t& valRef );
|
||||
rc_t var_get( const variable_t* var, float& valRef );
|
||||
rc_t var_get( const variable_t* var, double& valRef );
|
||||
rc_t var_get( const variable_t* var, const char*& valRef );
|
||||
rc_t var_get( const variable_t* var, const abuf_t*& valRef );
|
||||
rc_t var_get( variable_t* var, abuf_t*& valRef );
|
||||
rc_t var_get( const variable_t* var, const fbuf_t*& valRef );
|
||||
rc_t var_get( variable_t* var, fbuf_t*& valRef );
|
||||
|
||||
rc_t var_abuf_get( instance_t* inst, const char* var_label, unsigned chIdx, abuf_t*& abufRef );
|
||||
rc_t var_abuf_get( instance_t* inst, const char* var_label, unsigned chIdx, const abuf_t*& abufRef );
|
||||
rc_t var_fbuf_get( instance_t* inst, const char* var_label, unsigned chIdx, fbuf_t*& fbufRef );
|
||||
rc_t var_fbuf_get( instance_t* inst, const char* var_label, unsigned chIdx, const fbuf_t*& fbufRef );
|
||||
|
||||
|
||||
rc_t var_map_id_to_index( instance_t* inst, unsigned vid, unsigned chIdx, unsigned& idxRef );
|
||||
rc_t var_map_label_to_index( instance_t* inst, const char* var_label, unsigned chIdx, unsigned& idxRef );
|
||||
|
||||
rc_t var_get( instance_t* inst, unsigned vid, unsigned chIdx, uint_t& valRef );
|
||||
rc_t var_get( instance_t* inst, unsigned vid, unsigned chIdx, int_t& valRef );
|
||||
rc_t var_get( instance_t* inst, unsigned vid, unsigned chIdx, real_t& valRef );
|
||||
rc_t var_get( instance_t* inst, unsigned vid, unsigned chIdx, abuf_t*& valRef );
|
||||
rc_t var_get( instance_t* inst, unsigned vid, unsigned chIdx, fbuf_t*& valRef );
|
||||
template< typename T>
|
||||
rc_t var_get( instance_t* inst, unsigned vid, unsigned chIdx, T& valRef)
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
variable_t* var = nullptr;
|
||||
|
||||
if((rc = var_find(inst, vid, chIdx, var )) == kOkRC )
|
||||
rc = var_get(var,valRef);
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, bool val );
|
||||
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, uint_t val );
|
||||
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, int_t val );
|
||||
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, real_t val );
|
||||
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, float val );
|
||||
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, double val );
|
||||
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, const char* val );
|
||||
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, abuf_t* val );
|
||||
rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, fbuf_t* val );
|
||||
|
||||
rc_t var_set( instance_t* inst, const char* var_label, unsigned chIdx, uint_t val );
|
||||
rc_t var_set( instance_t* inst, const char* var_label, unsigned chIdx, int_t val );
|
||||
rc_t var_set( instance_t* inst, const char* var_label, unsigned chIdx, real_t val );
|
||||
|
||||
rc_t apply_preset( instance_t* inst, const char* preset_label );
|
||||
const preset_t* class_preset_find( class_desc_t* cd, const char* preset_label );
|
||||
|
||||
}
|
||||
}
|
||||
|
22
cwLog.h
22
cwLog.h
@ -109,4 +109,26 @@ namespace cw
|
||||
#define cwLogFatal( rc,fmt,...) cwLogFatalH( cw::log::globalHandle(), (rc), (fmt), ##__VA_ARGS__ )
|
||||
|
||||
|
||||
// This log level is intended for debugging individual modules.
|
||||
// By defining cwLOG_MODULE prior to cwLog.h in a given module these logging lines will be enabled.
|
||||
#ifdef cwLOG_MODULE
|
||||
|
||||
#define cwLogVModRC(rc,fmt, vl) cwLogVInfoH( cw::log::globalhandle(), (rc), (fmt), (vl) )
|
||||
#define cwLogModRC( rc,fmt,...) cwLogInfoH( cw::log::globalHandle(), (rc), (fmt), ##__VA_ARGS__ )
|
||||
|
||||
#define cwLogVMod(fmt, vl) cwLogVInfoH( cw::log::globalHandle(), cw::kOkRC, (fmt), (vl) )
|
||||
#define cwLogMod( fmt,...) cwLogInfoH( cw::log::globalHandle(), cw::kOkRC, (fmt), ##__VA_ARGS__ )
|
||||
|
||||
#else
|
||||
|
||||
#define cwLogVModRC(rc,fmt, vl)
|
||||
#define cwLogModRC( rc,fmt,...)
|
||||
|
||||
#define cwLogVMod(fmt, vl)
|
||||
#define cwLogMod( fmt,...)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user