Added audio_meter and cwIo and flow support for metering.
Also updated spec_dist,pv_anl, pv_syn to use fd_real_t.
This commit is contained in:
parent
9782c1b3c9
commit
11636a3f43
@ -289,11 +289,8 @@ cw::rc_t cw::dsp::recorder::destroy( obj_t*& pRef)
|
|||||||
{
|
{
|
||||||
obj_t* p = pRef;
|
obj_t* p = pRef;
|
||||||
|
|
||||||
if( p != nullptr )
|
mem::release(p->buf);
|
||||||
{
|
mem::release(p);
|
||||||
mem::release(p->buf);
|
|
||||||
mem::release(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
pRef = nullptr;
|
pRef = nullptr;
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
@ -363,3 +360,132 @@ cw::rc_t cw::dsp::recorder::write( obj_t* p, const char* fname )
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------
|
||||||
|
// Audio Meter
|
||||||
|
//
|
||||||
|
namespace cw {
|
||||||
|
namespace dsp {
|
||||||
|
namespace audio_meter {
|
||||||
|
sample_t _sum_square( const sample_t* v, unsigned vn, bool& clipFlRef )
|
||||||
|
{
|
||||||
|
sample_t sum = 0;
|
||||||
|
for(unsigned i=0; i<vn; ++i)
|
||||||
|
{
|
||||||
|
sample_t x = v[i]*v[i];
|
||||||
|
sum += x;
|
||||||
|
clipFlRef = x > 1.0;
|
||||||
|
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::dsp::audio_meter::create( obj_t*& p, real_t srate, real_t maxWndMs, real_t wndMs, real_t peakThreshDb )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
if( maxWndMs < wndMs )
|
||||||
|
{
|
||||||
|
cwLogWarning("Audio meter Max. window length (%f ms) is less than requested window length (%f ms). Setting max window length to %f ms.",maxWndMs,wndMs,wndMs);
|
||||||
|
maxWndMs = wndMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = mem::allocZ<obj_t>();
|
||||||
|
p->maxWndMs = maxWndMs;
|
||||||
|
p->maxWndSmpN = (unsigned)((maxWndMs * srate)/1000.0);
|
||||||
|
p->wndV = mem::allocZ<sample_t>(p->maxWndSmpN);
|
||||||
|
p->srate = srate;
|
||||||
|
p->peakThreshDb = peakThreshDb;
|
||||||
|
p->wi = 0;
|
||||||
|
|
||||||
|
set_window_ms( p, wndMs );
|
||||||
|
reset(p);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::dsp::audio_meter::destroy( obj_t*& pp )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
mem::release(pp->wndV);
|
||||||
|
mem::release(pp);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::dsp::audio_meter::exec( obj_t* p, const sample_t* xV, unsigned xN )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
unsigned n = 0;
|
||||||
|
|
||||||
|
// copy the incoming audio samples to the buffer
|
||||||
|
while( xN )
|
||||||
|
{
|
||||||
|
unsigned n0 = std::min( p->maxWndSmpN - p->wi, xN );
|
||||||
|
|
||||||
|
vop::copy(p->wndV + p->wi, xV + n, n0 );
|
||||||
|
|
||||||
|
n += n0;
|
||||||
|
xN -= n0;
|
||||||
|
|
||||||
|
p->wi = (p->wi + n0) % p->maxWndSmpN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the starting and ending locations of the RMS sub-buffers
|
||||||
|
|
||||||
|
unsigned i0 = 0, i1 = 0;
|
||||||
|
unsigned n0 = 0, n1 = 0;
|
||||||
|
|
||||||
|
if( p->wi >= p->wndSmpN )
|
||||||
|
{
|
||||||
|
i0 = p->wi - p->wndSmpN;
|
||||||
|
n0 = p->wndSmpN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i1 = 0;
|
||||||
|
n1 = p->wi;
|
||||||
|
n0 = p->wndSmpN - n1;
|
||||||
|
i0 = p->maxWndSmpN - n0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calc the squared-sum of the RMS buffers
|
||||||
|
sample_t sum = _sum_square(p->wndV + i0, n0, p->clipFl);
|
||||||
|
if( n1 )
|
||||||
|
sum += _sum_square(p->wndV + i1, n1, p->clipFl );
|
||||||
|
|
||||||
|
p->outLin = std::sqrt( sum / (n0+n1) ); // linear RMS
|
||||||
|
p->outDb = ampl_to_db(p->outLin); // RMS dB
|
||||||
|
|
||||||
|
p->peakFl = p->outDb > p->peakThreshDb; // set peak flag
|
||||||
|
p->clipFl = vop::max(xV,xN) >= 1.0; // set clip flag
|
||||||
|
|
||||||
|
p->peakCnt += p->peakFl ? 1 : 0; // count peak violations
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cw::dsp::audio_meter::reset( obj_t* p )
|
||||||
|
{
|
||||||
|
p->peakFl = false;
|
||||||
|
p->clipFl = false;
|
||||||
|
p->peakCnt = 0;
|
||||||
|
p->clipCnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cw::dsp::audio_meter::set_window_ms( obj_t* p, real_t wndMs )
|
||||||
|
{
|
||||||
|
unsigned wndSmpN = (unsigned)((wndMs * p->srate)/1000.0);
|
||||||
|
|
||||||
|
if( wndSmpN <= p->maxWndSmpN )
|
||||||
|
p->wndSmpN = wndSmpN;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cwLogWarning("The audio meter window length (%f ms) exceeds the max. window length (%f ms). The window length was reduced to (%f ms).",wndMs,p->maxWndMs,p->maxWndMs);
|
||||||
|
p->wndSmpN = p->maxWndSmpN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -97,6 +97,32 @@ namespace cw
|
|||||||
rc_t exec( obj_t* p, const sample_t* buf, unsigned chN, unsigned frameN );
|
rc_t exec( obj_t* p, const sample_t* buf, unsigned chN, unsigned frameN );
|
||||||
rc_t exec( obj_t* p, const sample_t* chA[], unsigned chN, unsigned frameN );
|
rc_t exec( obj_t* p, const sample_t* chA[], unsigned chN, unsigned frameN );
|
||||||
rc_t write( obj_t* p, const char* fname );
|
rc_t write( obj_t* p, const char* fname );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace audio_meter
|
||||||
|
{
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned maxWndMs;
|
||||||
|
unsigned maxWndSmpN;
|
||||||
|
unsigned wndSmpN;
|
||||||
|
sample_t* wndV;
|
||||||
|
real_t srate;
|
||||||
|
real_t peakThreshDb;
|
||||||
|
real_t outLin;
|
||||||
|
real_t outDb;
|
||||||
|
bool peakFl;
|
||||||
|
bool clipFl;
|
||||||
|
unsigned peakCnt;
|
||||||
|
unsigned clipCnt;
|
||||||
|
unsigned wi;
|
||||||
|
} obj_t;
|
||||||
|
|
||||||
|
rc_t create( obj_t*& p, real_t srate, real_t maxWndMs, real_t wndMs, real_t peakThreshDb );
|
||||||
|
rc_t destroy( obj_t*& pp );
|
||||||
|
rc_t exec( obj_t* p, const sample_t* x, unsigned n );
|
||||||
|
void reset( obj_t* p );
|
||||||
|
void set_window_ms( obj_t* p, real_t wndMs );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
183
cwFlowProc.cpp
183
cwFlowProc.cpp
@ -1437,7 +1437,7 @@ namespace cw
|
|||||||
//
|
//
|
||||||
namespace pv_analysis
|
namespace pv_analysis
|
||||||
{
|
{
|
||||||
typedef struct dsp::pv_anl::obj_str<sample_t> pv_t;
|
typedef struct dsp::pv_anl::obj_str<sample_t,fd_real_t> pv_t;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kInPId,
|
kInPId,
|
||||||
@ -1477,9 +1477,9 @@ namespace cw
|
|||||||
inst->pvN = srcBuf->chN;
|
inst->pvN = srcBuf->chN;
|
||||||
inst->pvA = mem::allocZ<pv_t*>( inst->pvN ); // allocate pv channel array
|
inst->pvA = mem::allocZ<pv_t*>( inst->pvN ); // allocate pv channel array
|
||||||
|
|
||||||
const sample_t* magV[ srcBuf->chN ];
|
const fd_real_t* magV[ srcBuf->chN ];
|
||||||
const sample_t* phsV[ srcBuf->chN ];
|
const fd_real_t* phsV[ srcBuf->chN ];
|
||||||
const sample_t* hzV[ srcBuf->chN ];
|
const fd_real_t* hzV[ srcBuf->chN ];
|
||||||
unsigned maxBinNV[ srcBuf->chN ];
|
unsigned maxBinNV[ srcBuf->chN ];
|
||||||
unsigned binNV[ srcBuf->chN ];
|
unsigned binNV[ srcBuf->chN ];
|
||||||
unsigned hopNV[ srcBuf->chN ];
|
unsigned hopNV[ srcBuf->chN ];
|
||||||
@ -1625,7 +1625,7 @@ namespace cw
|
|||||||
//
|
//
|
||||||
namespace pv_synthesis
|
namespace pv_synthesis
|
||||||
{
|
{
|
||||||
typedef struct dsp::pv_syn::obj_str<sample_t> pv_t;
|
typedef struct dsp::pv_syn::obj_str<sample_t,fd_real_t> pv_t;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kInPId,
|
kInPId,
|
||||||
@ -1751,7 +1751,7 @@ namespace cw
|
|||||||
//
|
//
|
||||||
namespace spec_dist
|
namespace spec_dist
|
||||||
{
|
{
|
||||||
typedef struct dsp::spec_dist::obj_str<sample_t,sample_t> spec_dist_t;
|
typedef struct dsp::spec_dist::obj_str<fd_real_t,fd_real_t> spec_dist_t;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -1794,9 +1794,9 @@ namespace cw
|
|||||||
inst->sdN = srcBuf->chN;
|
inst->sdN = srcBuf->chN;
|
||||||
inst->sdA = mem::allocZ<spec_dist_t*>( inst->sdN );
|
inst->sdA = mem::allocZ<spec_dist_t*>( inst->sdN );
|
||||||
|
|
||||||
const sample_t* magV[ srcBuf->chN ];
|
const fd_real_t* magV[ srcBuf->chN ];
|
||||||
const sample_t* phsV[ srcBuf->chN ];
|
const fd_real_t* phsV[ srcBuf->chN ];
|
||||||
const sample_t* hzV[ srcBuf->chN ];
|
const fd_real_t* hzV[ srcBuf->chN ];
|
||||||
|
|
||||||
//if((rc = var_register(ctx, kAnyChIdx, kInPId, "in")) != kOkRC )
|
//if((rc = var_register(ctx, kAnyChIdx, kInPId, "in")) != kOkRC )
|
||||||
// goto errLabel;
|
// goto errLabel;
|
||||||
@ -1864,6 +1864,7 @@ namespace cw
|
|||||||
double val = 0;
|
double val = 0;
|
||||||
spec_dist_t* sd = inst->sdA[ var->chIdx ];
|
spec_dist_t* sd = inst->sdA[ var->chIdx ];
|
||||||
|
|
||||||
|
|
||||||
switch( var->vid )
|
switch( var->vid )
|
||||||
{
|
{
|
||||||
case kBypassPId: rc = var_get( var, val ); sd->bypassFl = val; break;
|
case kBypassPId: rc = var_get( var, val ); sd->bypassFl = val; break;
|
||||||
@ -1877,8 +1878,8 @@ namespace cw
|
|||||||
cwLogWarning("Unhandled variable id '%i' on instance: %s.", var->vid, ctx->label );
|
cwLogWarning("Unhandled variable id '%i' on instance: %s.", var->vid, ctx->label );
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("%i sd: ceil:%f expo:%f thresh:%f upr:%f lwr:%f mix:%f : rc:%i val:%f\n",
|
//printf("%i sd: ceil:%f expo:%f thresh:%f upr:%f lwr:%f mix:%f : rc:%i val:%f var:%s \n",
|
||||||
// var->chIdx,sd->ceiling, sd->expo, sd->thresh, sd->uprSlope, sd->lwrSlope, sd->mix, rc, val );
|
// var->chIdx,sd->ceiling, sd->expo, sd->thresh, sd->uprSlope, sd->lwrSlope, sd->mix, rc, val, var->label );
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -2596,8 +2597,164 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// audio_meter
|
||||||
|
//
|
||||||
|
namespace audio_meter
|
||||||
|
{
|
||||||
|
|
||||||
}
|
enum
|
||||||
}
|
{
|
||||||
|
kInPId,
|
||||||
|
kDbFlPId,
|
||||||
|
kWndMsPId,
|
||||||
|
kPeakDbPId,
|
||||||
|
kOutPId,
|
||||||
|
kPeakFlPId,
|
||||||
|
kClipFlPId
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef dsp::audio_meter::obj_t audio_meter_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
audio_meter_t** mtrA;
|
||||||
|
unsigned mtrN;
|
||||||
|
} 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->mtrN = srcBuf->chN;
|
||||||
|
inst->mtrA = mem::allocZ<audio_meter_t*>( inst->mtrN );
|
||||||
|
|
||||||
|
// create a audio_meter object for each input channel
|
||||||
|
for(unsigned i=0; i<srcBuf->chN; ++i)
|
||||||
|
{
|
||||||
|
real_t wndMs, peakThreshDb;
|
||||||
|
bool dbFl;
|
||||||
|
|
||||||
|
// get the audio_meter variable values
|
||||||
|
if((rc = var_register_and_get( ctx, i,
|
||||||
|
kDbFlPId, "dbFl", dbFl,
|
||||||
|
kWndMsPId, "wndMs", wndMs,
|
||||||
|
kPeakDbPId, "peakDb", peakThreshDb )) != kOkRC )
|
||||||
|
{
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the audio_meter variable values
|
||||||
|
if((rc = var_register( ctx, i,
|
||||||
|
kOutPId, "out",
|
||||||
|
kPeakFlPId, "peakFl",
|
||||||
|
kClipFlPId, "clipFl" )) != kOkRC )
|
||||||
|
{
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned maxWndMs = std::max(wndMs,1000.0f);
|
||||||
|
|
||||||
|
// create the audio_meter instance
|
||||||
|
if((rc = dsp::audio_meter::create( inst->mtrA[i], srcBuf->srate, maxWndMs, wndMs, peakThreshDb)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kOpFailRC,"The 'audio_meter' object create failed on the instance '%s'.",ctx->label);
|
||||||
|
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->mtrN; ++i)
|
||||||
|
destroy(inst->mtrA[i]);
|
||||||
|
|
||||||
|
mem::release(inst->mtrA);
|
||||||
|
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;
|
||||||
|
unsigned chN = 0;
|
||||||
|
|
||||||
|
// get the src buffer
|
||||||
|
if((rc = var_get(ctx,kInPId, kAnyChIdx, srcBuf )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
chN = std::min(srcBuf->chN,inst->mtrN);
|
||||||
|
|
||||||
|
for(unsigned i=0; i<chN; ++i)
|
||||||
|
{
|
||||||
|
dsp::audio_meter::exec( inst->mtrA[i], srcBuf->buf + i*srcBuf->frameN, srcBuf->frameN );
|
||||||
|
var_set(ctx, kOutPId, i, inst->mtrA[i]->outDb );
|
||||||
|
var_set(ctx, kPeakFlPId, i, inst->mtrA[i]->peakFl );
|
||||||
|
var_set(ctx, kClipFlPId, i, inst->mtrA[i]->clipFl );
|
||||||
|
}
|
||||||
|
|
||||||
|
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->mtrN; ++i)
|
||||||
|
{
|
||||||
|
audio_meter_t* c = inst->mtrA[i];
|
||||||
|
cwLogInfo("%s ch:%i : %f %f db : pk:%i %i clip:%i %i ",
|
||||||
|
ctx->label,i,c->outLin,c->outDb,c->peakFl,c->peakCnt,c->clipFl,c->clipCnt );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
class_members_t members = {
|
||||||
|
.create = create,
|
||||||
|
.destroy = destroy,
|
||||||
|
.value = value,
|
||||||
|
.exec = exec,
|
||||||
|
.report = report
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // flow
|
||||||
|
} // cw
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,5 +20,6 @@ namespace cw
|
|||||||
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 dc_filter { extern class_members_t members; }
|
||||||
namespace balance { extern class_members_t members; }
|
namespace balance { extern class_members_t members; }
|
||||||
|
namespace audio_meter { extern class_members_t members; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
179
cwIo.cpp
179
cwIo.cpp
@ -82,6 +82,7 @@ namespace cw
|
|||||||
typedef struct audioDev_str
|
typedef struct audioDev_str
|
||||||
{
|
{
|
||||||
bool enableFl; // True if this device was enabled by the user
|
bool enableFl; // True if this device was enabled by the user
|
||||||
|
bool meterFl; // True if meters are enabled on this device
|
||||||
const char* label; // User label
|
const char* label; // User label
|
||||||
unsigned userId; // User id
|
unsigned userId; // User id
|
||||||
char* devName; // System device name
|
char* devName; // System device name
|
||||||
@ -827,6 +828,8 @@ namespace cw
|
|||||||
// Audio
|
// Audio
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Start or stop all the audio devices in p->audioDevA[]
|
// Start or stop all the audio devices in p->audioDevA[]
|
||||||
rc_t _audioDeviceStartStop( io_t* p, bool startFl )
|
rc_t _audioDeviceStartStop( io_t* p, bool startFl )
|
||||||
{
|
{
|
||||||
@ -1124,6 +1127,68 @@ namespace cw
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc_t _audioDeviceParams( io_t* p, unsigned devIdx, unsigned flags, audioDev_t*& adRef, unsigned& audioBufFlagsRef )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
if((adRef = _audioDeviceIndexToRecd(p,devIdx)) == nullptr )
|
||||||
|
rc = kInvalidArgRC;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audioBufFlagsRef = 0;
|
||||||
|
if( cwIsFlag(flags,kInFl) )
|
||||||
|
audioBufFlagsRef += audio::buf::kInFl;
|
||||||
|
|
||||||
|
if( cwIsFlag(flags,kOutFl) )
|
||||||
|
audioBufFlagsRef += audio::buf::kOutFl;
|
||||||
|
|
||||||
|
if( cwIsFlag(flags,kEnableFl) )
|
||||||
|
audioBufFlagsRef += audio::buf::kEnableFl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _audioDeviceEnableMeter( io_t* p, unsigned devIdx, unsigned inOutEnaFlags )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
audioDev_t* ad = nullptr;
|
||||||
|
unsigned audioBufFlags = 0;
|
||||||
|
|
||||||
|
if((rc = _audioDeviceParams( p, devIdx, inOutEnaFlags, ad, audioBufFlags )) != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Enable tone failed.");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool enaFl = inOutEnaFlags & kEnableFl;
|
||||||
|
bool enaState0Fl = _audioDeviceIsMeterEnabled(ad, kInFl | kOutFl);
|
||||||
|
|
||||||
|
audioBufFlags += audio::buf::kMeterFl;
|
||||||
|
|
||||||
|
if( inOutEnaFlags & kInFl )
|
||||||
|
ad->iagd->flags = cwEnaFlag(ad->iagd->flags,kMeterFl,enaFl);
|
||||||
|
|
||||||
|
if( inOutEnaFlags & kOutFl )
|
||||||
|
ad->oagd->flags = cwEnaFlag(ad->oagd->flags,kMeterFl,enaFl);
|
||||||
|
|
||||||
|
audio::buf::setFlag( p->audioBufH, devIdx, kInvalidIdx, audioBufFlags );
|
||||||
|
|
||||||
|
bool enaState1Fl= _audioDeviceIsMeterEnabled(ad, kInFl | kOutFl);
|
||||||
|
|
||||||
|
if( enaState1Fl and !enaState0Fl )
|
||||||
|
p->audioMeterDevEnabledN += 1;
|
||||||
|
else
|
||||||
|
if( p->audioMeterDevEnabledN > 0 && !enaState1Fl && enaState0Fl )
|
||||||
|
p->audioMeterDevEnabledN -= 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rc != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Enable meters failed.");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
// Add an audioGroup pointer to groupA[] and return the new count of elements in the array.
|
// Add an audioGroup pointer to groupA[] and return the new count of elements in the array.
|
||||||
unsigned _audioDeviceUpdateGroupArray( audioGroup_t** groupA, unsigned groupN, unsigned curGroupN, audioGroup_t* ag )
|
unsigned _audioDeviceUpdateGroupArray( audioGroup_t** groupA, unsigned groupN, unsigned curGroupN, audioGroup_t* ag )
|
||||||
{
|
{
|
||||||
@ -1438,6 +1503,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
audioDev_t* ad = nullptr; //p->audioDevA + i;
|
audioDev_t* ad = nullptr; //p->audioDevA + i;
|
||||||
bool enableFl = false;
|
bool enableFl = false;
|
||||||
|
bool meterFl = false;
|
||||||
char* userLabel = nullptr;
|
char* userLabel = nullptr;
|
||||||
unsigned userId = kInvalidId;
|
unsigned userId = kInvalidId;
|
||||||
char* devName = nullptr;
|
char* devName = nullptr;
|
||||||
@ -1477,6 +1543,7 @@ namespace cw
|
|||||||
|
|
||||||
if((rc = node->getv_opt(
|
if((rc = node->getv_opt(
|
||||||
"userId", userId,
|
"userId", userId,
|
||||||
|
"meterFl", meterFl,
|
||||||
"inGroup", inGroupLabel,
|
"inGroup", inGroupLabel,
|
||||||
"outGroup", outGroupLabel )) != kOkRC )
|
"outGroup", outGroupLabel )) != kOkRC )
|
||||||
{
|
{
|
||||||
@ -1578,6 +1645,7 @@ namespace cw
|
|||||||
|
|
||||||
// set the device group pointers
|
// set the device group pointers
|
||||||
ad->enableFl = enableFl;
|
ad->enableFl = enableFl;
|
||||||
|
ad->meterFl = meterFl;
|
||||||
ad->label = userLabel;
|
ad->label = userLabel;
|
||||||
ad->userId = userId;
|
ad->userId = userId;
|
||||||
ad->iGroup = iag;
|
ad->iGroup = iag;
|
||||||
@ -1590,6 +1658,23 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc_t _audioDeviceEnableMeters( io_t* p )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
for(unsigned i=0; i<p->audioDevN; ++i)
|
||||||
|
if( p->audioDevA[i].enableFl && p->audioDevA[i].meterFl )
|
||||||
|
if((rc = _audioDeviceEnableMeter(p, p->audioDevA[i].devIdx, kEnableFl | kInFl | kOutFl )) != kOkRC )
|
||||||
|
{
|
||||||
|
cwLogError(rc,"Audio enable on device '%s' failed.",p->audioDevA[i].label);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Allocate the sample ptr buffers for each audio group.
|
// Allocate the sample ptr buffers for each audio group.
|
||||||
rc_t _audioGroupAllocBuffer( io_t* p )
|
rc_t _audioGroupAllocBuffer( io_t* p )
|
||||||
{
|
{
|
||||||
@ -1656,6 +1741,13 @@ namespace cw
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize enabled audio meters
|
||||||
|
if((rc = _audioDeviceEnableMeters(p)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Audio device enabled failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1839,30 +1931,6 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _audioDeviceParams( handle_t h, unsigned devIdx, unsigned flags, io_t*& pRef, audioDev_t*& adRef, unsigned& audioBufFlagsRef )
|
|
||||||
{
|
|
||||||
rc_t rc = kOkRC;
|
|
||||||
|
|
||||||
pRef = _handleToPtr(h);
|
|
||||||
|
|
||||||
if((adRef = _audioDeviceIndexToRecd(pRef,devIdx)) == nullptr )
|
|
||||||
rc = kInvalidArgRC;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
audioBufFlagsRef = 0;
|
|
||||||
if( cwIsFlag(flags,kInFl) )
|
|
||||||
audioBufFlagsRef += audio::buf::kInFl;
|
|
||||||
|
|
||||||
if( cwIsFlag(flags,kOutFl) )
|
|
||||||
audioBufFlagsRef += audio::buf::kOutFl;
|
|
||||||
|
|
||||||
if( cwIsFlag(flags,kEnableFl) )
|
|
||||||
audioBufFlagsRef += audio::buf::kEnableFl;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -2386,43 +2454,8 @@ unsigned cw::io::audioDeviceChannelCount( handle_t h, unsigned devIdx, unsigne
|
|||||||
|
|
||||||
cw::rc_t cw::io::audioDeviceEnableMeters( handle_t h, unsigned devIdx, unsigned inOutEnaFlags )
|
cw::rc_t cw::io::audioDeviceEnableMeters( handle_t h, unsigned devIdx, unsigned inOutEnaFlags )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
io_t* p = _handleToPtr(h);
|
||||||
io_t* p = nullptr;
|
return _audioDeviceEnableMeter(p, devIdx, inOutEnaFlags );
|
||||||
audioDev_t* ad = nullptr;
|
|
||||||
unsigned audioBufFlags = 0;
|
|
||||||
|
|
||||||
if((rc = _audioDeviceParams( h, devIdx, inOutEnaFlags, p, ad, audioBufFlags )) != kOkRC )
|
|
||||||
rc = cwLogError(rc,"Enable tone failed.");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool enaFl = inOutEnaFlags & kEnableFl;
|
|
||||||
bool enaState0Fl = _audioDeviceIsMeterEnabled(ad, kInFl | kOutFl);
|
|
||||||
|
|
||||||
audioBufFlags += audio::buf::kMeterFl;
|
|
||||||
|
|
||||||
|
|
||||||
if( inOutEnaFlags & kInFl )
|
|
||||||
ad->iagd->flags = cwEnaFlag(ad->iagd->flags,kMeterFl,enaFl);
|
|
||||||
|
|
||||||
if( inOutEnaFlags & kOutFl )
|
|
||||||
ad->oagd->flags = cwEnaFlag(ad->oagd->flags,kMeterFl,enaFl);
|
|
||||||
|
|
||||||
audio::buf::setFlag( p->audioBufH, devIdx, kInvalidIdx, audioBufFlags );
|
|
||||||
|
|
||||||
bool enaState1Fl= _audioDeviceIsMeterEnabled(ad, kInFl | kOutFl);
|
|
||||||
|
|
||||||
if( enaState1Fl and !enaState0Fl )
|
|
||||||
p->audioMeterDevEnabledN += 1;
|
|
||||||
else
|
|
||||||
if( p->audioMeterDevEnabledN > 0 && !enaState1Fl && enaState0Fl )
|
|
||||||
p->audioMeterDevEnabledN -= 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rc != kOkRC )
|
|
||||||
rc = cwLogError(rc,"Enable meters failed.");
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2460,11 +2493,11 @@ const cw::io::sample_t* cw::io::audioDeviceMeters( handle_t h, unsigned devIdx,
|
|||||||
cw::rc_t cw::io::audioDeviceEnableTone( handle_t h, unsigned devIdx, unsigned inOutEnaFlags )
|
cw::rc_t cw::io::audioDeviceEnableTone( handle_t h, unsigned devIdx, unsigned inOutEnaFlags )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
io_t* p = nullptr;
|
io_t* p = _handleToPtr(h);
|
||||||
audioDev_t* ad = nullptr;
|
audioDev_t* ad = nullptr;
|
||||||
unsigned audioBufFlags = 0;
|
unsigned audioBufFlags = 0;
|
||||||
|
|
||||||
if((rc = _audioDeviceParams( h, devIdx, inOutEnaFlags, p, ad, audioBufFlags )) != kOkRC )
|
if((rc = _audioDeviceParams( p, devIdx, inOutEnaFlags, ad, audioBufFlags )) != kOkRC )
|
||||||
rc = cwLogError(rc,"Enable tone failed.");
|
rc = cwLogError(rc,"Enable tone failed.");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2479,11 +2512,11 @@ cw::rc_t cw::io::audioDeviceToneFlags( handle_t h, unsigned devIdx, unsigned inO
|
|||||||
{
|
{
|
||||||
|
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
io_t* p = nullptr;
|
io_t* p = _handleToPtr(h);
|
||||||
audioDev_t* ad = nullptr;
|
audioDev_t* ad = nullptr;
|
||||||
unsigned audioBufFlags = 0;
|
unsigned audioBufFlags = 0;
|
||||||
|
|
||||||
if((rc = _audioDeviceParams( h, devIdx, inOrOutFlag, p, ad, audioBufFlags )) != kOkRC )
|
if((rc = _audioDeviceParams( p, devIdx, inOrOutFlag, ad, audioBufFlags )) != kOkRC )
|
||||||
rc = cwLogError(rc,"Get tone flags failed.");
|
rc = cwLogError(rc,"Get tone flags failed.");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2497,11 +2530,11 @@ cw::rc_t cw::io::audioDeviceToneFlags( handle_t h, unsigned devIdx, unsigned inO
|
|||||||
cw::rc_t cw::io::audioDeviceEnableMute( handle_t h, unsigned devIdx, unsigned inOutEnaFlags )
|
cw::rc_t cw::io::audioDeviceEnableMute( handle_t h, unsigned devIdx, unsigned inOutEnaFlags )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
io_t* p = nullptr;
|
io_t* p = _handleToPtr(h);
|
||||||
audioDev_t* ad = nullptr;
|
audioDev_t* ad = nullptr;
|
||||||
unsigned audioBufFlags = 0;
|
unsigned audioBufFlags = 0;
|
||||||
|
|
||||||
if((rc = _audioDeviceParams( h, devIdx, inOutEnaFlags, p, ad, audioBufFlags )) != kOkRC )
|
if((rc = _audioDeviceParams( p, devIdx, inOutEnaFlags, ad, audioBufFlags )) != kOkRC )
|
||||||
rc = cwLogError(rc,"Enable mute failed.");
|
rc = cwLogError(rc,"Enable mute failed.");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2515,11 +2548,11 @@ cw::rc_t cw::io::audioDeviceEnableMute( handle_t h, unsigned devIdx, unsigned in
|
|||||||
cw::rc_t cw::io::audioDeviceMuteFlags( handle_t h, unsigned devIdx, unsigned inOrOutFlag, bool* muteFlA, unsigned chCnt )
|
cw::rc_t cw::io::audioDeviceMuteFlags( handle_t h, unsigned devIdx, unsigned inOrOutFlag, bool* muteFlA, unsigned chCnt )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
io_t* p = nullptr;
|
io_t* p = _handleToPtr(h);
|
||||||
audioDev_t* ad = nullptr;
|
audioDev_t* ad = nullptr;
|
||||||
unsigned audioBufFlags = 0;
|
unsigned audioBufFlags = 0;
|
||||||
|
|
||||||
if((rc = _audioDeviceParams( h, devIdx, inOrOutFlag, p, ad, audioBufFlags )) != kOkRC )
|
if((rc = _audioDeviceParams( p, devIdx, inOrOutFlag, ad, audioBufFlags )) != kOkRC )
|
||||||
rc = cwLogError(rc,"Get mute flags failed.");
|
rc = cwLogError(rc,"Get mute flags failed.");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2534,11 +2567,11 @@ cw::rc_t cw::io::audioDeviceMuteFlags( handle_t h, unsigned devIdx, unsigned inO
|
|||||||
cw::rc_t cw::io::audioDeviceSetGain( handle_t h, unsigned devIdx, unsigned inOrOutFlag, double gain )
|
cw::rc_t cw::io::audioDeviceSetGain( handle_t h, unsigned devIdx, unsigned inOrOutFlag, double gain )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
io_t* p = nullptr;
|
io_t* p = _handleToPtr(h);
|
||||||
audioDev_t* ad = nullptr;
|
audioDev_t* ad = nullptr;
|
||||||
unsigned audioBufFlags = 0;
|
unsigned audioBufFlags = 0;
|
||||||
|
|
||||||
if((rc = _audioDeviceParams( h, devIdx, inOrOutFlag, p, ad, audioBufFlags )) != kOkRC )
|
if((rc = _audioDeviceParams( p, devIdx, inOrOutFlag, ad, audioBufFlags )) != kOkRC )
|
||||||
rc = cwLogError(rc,"Set gain failed.");
|
rc = cwLogError(rc,"Set gain failed.");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2551,11 +2584,11 @@ cw::rc_t cw::io::audioDeviceSetGain( handle_t h, unsigned devIdx, unsigned inOrO
|
|||||||
cw::rc_t cw::io::audioDeviceGain( handle_t h, unsigned devIdx, unsigned inOrOutFlag, double* gainA, unsigned chCnt )
|
cw::rc_t cw::io::audioDeviceGain( handle_t h, unsigned devIdx, unsigned inOrOutFlag, double* gainA, unsigned chCnt )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
io_t* p = nullptr;
|
io_t* p = _handleToPtr(h);
|
||||||
audioDev_t* ad = nullptr;
|
audioDev_t* ad = nullptr;
|
||||||
unsigned audioBufFlags = 0;
|
unsigned audioBufFlags = 0;
|
||||||
|
|
||||||
if((rc = _audioDeviceParams( h, devIdx, inOrOutFlag, p, ad, audioBufFlags )) != kOkRC )
|
if((rc = _audioDeviceParams( p, devIdx, inOrOutFlag, ad, audioBufFlags )) != kOkRC )
|
||||||
rc = cwLogError(rc,"Get gain failed.");
|
rc = cwLogError(rc,"Get gain failed.");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user