cwAudioDevice*.h,cpp, cwIo.h,cpp, cwIoAudioPanel.cpp : Added deviceEnable(), deviceSeek() to audio device driver.

Change io::cwAudioDeviceIsEnabled() to cwAudioDeviceIsActive().
This commit is contained in:
kevin 2023-02-19 14:16:37 -05:00
parent 4ecbd0d035
commit 20175d29f9
9 changed files with 246 additions and 97 deletions

View File

@ -196,6 +196,43 @@ bool cw::audio::device::isStarted(handle_t h, unsigned devIdx )
return false;
}
cw::rc_t cw::audio::device::execute( handle_t h, unsigned devIdx )
{
rc_t rc = kOkRC;
drv_t* d;
if((d = _indexToDriver(h,devIdx)) == nullptr )
rc = kInvalidArgRC;
else
rc = d->drv->deviceExecute( d->drv, devIdx - d->begIdx );
return rc;
}
cw::rc_t cw::audio::device::enable( handle_t h, unsigned devIdx, bool inputFl, bool enableFl )
{
rc_t rc = kOkRC;
drv_t* d;
if((d = _indexToDriver(h,devIdx)) == nullptr )
rc = kInvalidArgRC;
else
rc = d->drv->deviceEnable( d->drv, devIdx - d->begIdx, inputFl, enableFl );
return rc;
}
cw::rc_t cw::audio::device::seek( handle_t h, unsigned devIdx, bool inputFl, unsigned frameOffset )
{
rc_t rc = kOkRC;
drv_t* d;
if((d = _indexToDriver(h,devIdx)) == nullptr )
rc = kInvalidArgRC;
else
rc = d->drv->deviceSeek( d->drv, devIdx - d->begIdx, inputFl, frameOffset );
return rc;
}
void cw::audio::device::realTimeReport( handle_t h, unsigned devIdx )
{
drv_t* d;
@ -203,17 +240,6 @@ void cw::audio::device::realTimeReport( handle_t h, unsigned devIdx )
d->drv->deviceRealTimeReport( d->drv, devIdx - d->begIdx );
}
cw::rc_t cw::audio::device::execute( handle_t h, unsigned devIdx )
{
rc_t rc = kOkRC;
drv_t* d;
if((d = _indexToDriver(h,devIdx)) != nullptr )
rc = d->drv->deviceExecute( d->drv, devIdx - d->begIdx );
return rc;
}
void cw::audio::device::report( handle_t h )
{
for(unsigned i=0; i<count(h); ++i)

View File

@ -62,7 +62,19 @@ namespace cw
rc_t (*deviceStart)( struct driver_str* drvArg, unsigned devIdx );
rc_t (*deviceStop)( struct driver_str* drvArg, unsigned devIdx );
bool (*deviceIsStarted)( struct driver_str* drvArg, unsigned devIdx );
// deviceExecute() is called to indicate that a device should execute a callback as soon as possible.
// This function is called by one device to synchronize another device.
rc_t (*deviceExecute)( struct driver_str* drvArg, unsigned devIdx );
// An input device that is started but not enabled will source zeros.
// An output device that is started but not enabled will ignore incoming samples (and sink zeros),
// audio device files will not write.
rc_t (*deviceEnable)( struct driver_str* drvArg, unsigned devIdx, bool inputFl, bool enableFl );
// This function is only enabled on audio device files.
rc_t (*deviceSeek)( struct driver_str* drvArg, unsigned devIdx, bool inputFl, unsigned frameOffset );
void (*deviceRealTimeReport)( struct driver_str* drvArg, unsigned devIdx );
} driver_t;
@ -103,10 +115,11 @@ namespace cw
rc_t start( handle_t h, unsigned devIdx );
rc_t stop( handle_t h, unsigned devIdx );
bool isStarted( handle_t h, unsigned devIdx );
void realTimeReport( handle_t h, unsigned devIdx );
rc_t execute( handle_t h, unsigned devIdx );
rc_t enable( handle_t h, unsigned devIdx, bool inputFl, bool enableFl );
rc_t seek( handle_t h, unsigned devIdx, bool inputFl, unsigned frameOffset );
void realTimeReport( handle_t h, unsigned devIdx );
void report( handle_t h );
void realTimeReport( handle_t h );
}

View File

@ -50,6 +50,9 @@ namespace cw
bool iSwapFl; // swap the sample bytes
bool oSwapFl;
bool iEnableFl; // enable the device
bool oEnableFl;
unsigned iSigBits; // significant bits in each sample beginning
unsigned oSigBits; // with the most sig. bit.
@ -566,7 +569,7 @@ namespace cw
//const device::sample_t* rms = sp;
// if no output was given then fill the device buffer with zeros
if( sp == NULL )
if( sp == NULL || drp->oEnableFl == false)
memset(obuf,0,byteCnt);
else
{
@ -675,58 +678,66 @@ namespace cw
if( smpPtr == NULL )
return err;
// setup the return buffer
device::sample_t* dp = smpPtr;
device::sample_t* ep = dp + std::min(smpCnt,err*chCnt);
switch(bits)
if( !drp->iEnableFl )
{
case 8:
{
char* sp = buf;
while(dp < ep)
*dp++ = ((device::sample_t)*sp++) / 0x7f;
}
break;
case 16:
{
short* sp = (short*)buf;
while(dp < ep)
*dp++ = ((device::sample_t)*sp++) / 0x7fff;
}
break;
case 24:
{
// For use with MBox
//_devS24_3BE_to_Float(buf, dp, ep-dp );
int* sp = (int*)buf;
while(dp < ep)
*dp++ = ((device::sample_t)*sp++) / 0x7fffff;
}
break;
case 32:
{
int* sp = (int*)buf;
// The delta1010 (ICE1712) uses only the 24 highest bits according to
//
// http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html
// <snip> The example: ICE1712 chips support 32-bit sample processing,
// but low byte is ignored (playback) or zero (capture).
//
int mv = sigBits==24 ? 0x7fffff00 : 0x7fffffff;
while(dp < ep)
*dp++ = ((device::sample_t)*sp++) / mv;
}
break;
default:
{ cwAssert(0); }
memset(smpPtr,0,smpCnt*sizeof(sample_t));
}
else
{
// setup the return buffer
device::sample_t* dp = smpPtr;
device::sample_t* ep = dp + std::min(smpCnt,err*chCnt);
switch(bits)
{
case 8:
{
char* sp = buf;
while(dp < ep)
*dp++ = ((device::sample_t)*sp++) / 0x7f;
}
break;
case 16:
{
short* sp = (short*)buf;
while(dp < ep)
*dp++ = ((device::sample_t)*sp++) / 0x7fff;
}
break;
case 24:
{
// For use with MBox
//_devS24_3BE_to_Float(buf, dp, ep-dp );
int* sp = (int*)buf;
while(dp < ep)
*dp++ = ((device::sample_t)*sp++) / 0x7fffff;
}
break;
case 32:
{
int* sp = (int*)buf;
// The delta1010 (ICE1712) uses only the 24 highest bits according to
//
// http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html
// <snip> The example: ICE1712 chips support 32-bit sample processing,
// but low byte is ignored (playback) or zero (capture).
//
int mv = sigBits==24 ? 0x7fffff00 : 0x7fffffff;
while(dp < ep)
*dp++ = ((device::sample_t)*sp++) / mv;
}
break;
default:
{ cwAssert(0); }
}
}
return err;
}
@ -1102,6 +1113,7 @@ namespace cw
drp->iPcmH = pcmH;
drp->iBuf = mem::resizeZ<device::sample_t>( drp->iBuf, actFpC * drp->iChCnt );
drp->iFpC = actFpC;
drp->iEnableFl= true;
}
else
{
@ -1112,6 +1124,7 @@ namespace cw
drp->oPcmH = pcmH;
drp->oBuf = mem::resizeZ<device::sample_t>( drp->oBuf, actFpC * drp->oChCnt );
drp->oFpC = actFpC;
drp->oEnableFl= true;
}
if( p->asyncFl == false )
@ -1376,6 +1389,8 @@ cw::rc_t cw::audio::device::alsa::create( handle_t& hRef, struct driver_str*& dr
p->driver.deviceStop = deviceStop;
p->driver.deviceIsStarted = deviceIsStarted;
p->driver.deviceExecute = deviceExecute;
p->driver.deviceEnable = deviceEnable;
p->driver.deviceSeek = deviceSeek;
p->driver.deviceRealTimeReport = deviceRealTimeReport;
@ -1588,6 +1603,27 @@ cw::rc_t cw::audio::device::alsa::deviceExecute(struct driver_str* drv, unsigne
return kOkRC;
}
cw::rc_t cw::audio::device::alsa::deviceEnable( struct driver_str* drv, unsigned devIdx, bool inputFl, bool enableFl )
{
cwAssert(devIdx < deviceCount(drv));
alsa_t* p = static_cast<alsa_t*>(drv->drvArg);
devRecd_t* drp = p->devArray + devIdx;
if( inputFl )
drp->iEnableFl = enableFl;
else
drp->oEnableFl = enableFl;
return kOkRC;
}
cw::rc_t cw::audio::device::alsa::deviceSeek( struct driver_str* drv, unsigned devIdx, bool inputFl, unsigned frameOffset )
{
return kOkRC;
}
void cw::audio::device::alsa::deviceRealTimeReport(struct driver_str* drv, unsigned devIdx )
{
alsa_t* p = static_cast<alsa_t*>(drv->drvArg);

View File

@ -25,6 +25,8 @@ namespace cw
rc_t deviceStop( struct driver_str* drv, unsigned devIdx );
bool deviceIsStarted( struct driver_str* drv, unsigned devIdx );
rc_t deviceExecute( struct driver_str* drv, unsigned devIdx );
rc_t deviceEnable( struct driver_str* drv, unsigned devIdx, bool inputFl, bool enableFl );
rc_t deviceSeek( struct driver_str* drv, unsigned devIdx, bool inputFl, unsigned frameOffset );
void deviceRealTimeReport( struct driver_str* drv, unsigned devIdx );
rc_t report(handle_t h );

View File

@ -46,6 +46,7 @@ namespace cw
audiofile::handle_t iFileH;
unsigned iFlags;
unsigned iChCnt;
bool iEnableFl;
audioPacket_t iPkt;
float* iPktAudioBuf;
unsigned iCbCnt;
@ -58,6 +59,7 @@ namespace cw
audiofile::handle_t oFileH;
unsigned oFlags;
unsigned oChCnt;
bool oEnableFl;
unsigned oBitsPerSample;
audioPacket_t oPkt;
float* oPktAudioBuf;
@ -201,6 +203,7 @@ namespace cw
d->iChArray = mem::resize<sample_t*>(d->iChArray,info.chCnt);
d->iChSmpBuf = mem::resize<sample_t>(d->iChSmpBuf, d->framesPerCycle*info.chCnt );
d->iChCnt = info.chCnt;
d->iEnableFl = true;
d->iErrCnt = 0;
d->iFrmCnt = 0;
d->iPkt.devIdx = d->cbDevIdx;
@ -224,26 +227,32 @@ namespace cw
rc_t rc = kOkRC;
unsigned actualFrameCnt = 0;
// read the file
if((rc = readFloat(d->iFileH, d->framesPerCycle, 0, d->iChCnt, d->iChArray, &actualFrameCnt)) == kOkRC )
d->iFrmCnt += actualFrameCnt;
if( !d->iEnableFl )
{
memset(d->iPkt.audioBytesPtr,0,d->iChCnt*d->framesPerCycle*sizeof(sample_t));
}
else
{
rc = cwLogError(rc,"File read failed on audio device file: %s.",cwStringNullGuard(d->label));
d->iErrCnt += 1;
goto errLabel;
{
// read the file
if((rc = readFloat(d->iFileH, d->framesPerCycle, 0, d->iChCnt, d->iChArray, &actualFrameCnt)) == kOkRC )
d->iFrmCnt += actualFrameCnt;
else
{
rc = cwLogError(rc,"File read failed on audio device file: %s.",cwStringNullGuard(d->label));
d->iErrCnt += 1;
goto errLabel;
}
// interleave into the iPkt audio buffer
vop::interleave( d->iPktAudioBuf, d->iChSmpBuf, actualFrameCnt, d->iChCnt );
if( actualFrameCnt < d->framesPerCycle )
{
for(unsigned i=0; i<d->iChCnt; ++i)
vop::fill( d->iPktAudioBuf + (actualFrameCnt * d->iChCnt) + i, 0, d->framesPerCycle-actualFrameCnt, d->iChCnt );
}
}
// interleave into the iPkt audio buffer
vop::interleave( d->iPktAudioBuf, d->iChSmpBuf, actualFrameCnt, d->iChCnt );
if( actualFrameCnt < d->framesPerCycle )
{
for(unsigned i=0; i<d->iChCnt; ++i)
vop::fill( d->iPktAudioBuf + (actualFrameCnt * d->iChCnt) + i, 0, d->framesPerCycle-actualFrameCnt, d->iChCnt );
}
errLabel:
return rc;
}
@ -280,6 +289,7 @@ namespace cw
d->oPktAudioBuf = mem::resize<sample_t>(d->oPktAudioBuf,d->framesPerCycle*d->oChCnt);
d->oChArray = mem::resize<sample_t*>(d->oChArray,d->oChCnt);
d->oChSmpBuf = mem::resize<sample_t>(d->oChSmpBuf, d->framesPerCycle*d->oChCnt );
d->oEnableFl = true;
d->oFrmCnt = 0;
d->oErrCnt = 0;
d->oPkt.devIdx = d->cbDevIdx;
@ -302,7 +312,7 @@ namespace cw
{
rc_t rc = kOkRC;
if( d->oFileH.isValid() )
if( d->oFileH.isValid() && d->oEnableFl )
{
/*
// deinterleave the audio into d->oChArray[]
@ -460,6 +470,8 @@ cw::rc_t cw::audio::device::file::create( handle_t& hRef, struct driver_str*&
p->driver.deviceStop = deviceStop;
p->driver.deviceIsStarted = deviceIsStarted;
p->driver.deviceExecute = deviceExecute;
p->driver.deviceEnable = deviceEnable;
p->driver.deviceSeek = deviceSeek;
p->driver.deviceRealTimeReport = deviceRealTimeReport;
if((rc = create( p->threadH, _threadCbFunc, p )) != kOkRC )
@ -705,8 +717,53 @@ cw::rc_t cw::audio::device::file::deviceExecute( struct driver_str* dr
mutex::signalCondVar(p->mutexH);
errLabel:
return rc;
return rc;
}
cw::rc_t cw::audio::device::file::deviceEnable( struct driver_str* drv, unsigned devIdx, bool inputFl, bool enableFl )
{
rc_t rc = kOkRC;
dev_mgr_t* p = _driverToPtr(drv);
dev_t* d = nullptr;
if((rc = _indexToDev( p, devIdx, d )) != kOkRC )
goto errLabel;
if( inputFl )
d->iEnableFl = enableFl;
else
d->oEnableFl = enableFl;
printf("Enable i:%i o:%i\n",d->iEnableFl,d->oEnableFl);
errLabel:
return rc;
}
cw::rc_t cw::audio::device::file::deviceSeek( struct driver_str* drv, unsigned devIdx, bool inputFl, unsigned frameOffset )
{
rc_t rc = kOkRC;
dev_mgr_t* p = _driverToPtr(drv);
dev_t* d = nullptr;
if((rc = _indexToDev( p, devIdx, d )) != kOkRC )
goto errLabel;
if( inputFl )
{
if( d->iFileH.isValid() )
if((rc = seek(d->iFileH,frameOffset)) != kOkRC )
rc = cwLogError(rc,"Seek failed on the audio device file input file.");
}
else
{
if( d->oFileH.isValid())
if((rc = seek(d->oFileH,frameOffset)) != kOkRC )
rc = cwLogError(rc,"Seek failed on the audio device file output file.");
}
errLabel:
return rc;
}
void cw::audio::device::file::deviceRealTimeReport( struct driver_str* drv, unsigned devIdx )

View File

@ -26,7 +26,9 @@ namespace cw
rc_t deviceStart( struct driver_str* drv, unsigned devIdx );
rc_t deviceStop( struct driver_str* drv, unsigned devIdx );
bool deviceIsStarted( struct driver_str* drv, unsigned devIdx );
rc_t deviceExecute( struct driver_str* drv, unsigned devIdx );
rc_t deviceExecute( struct driver_str* drv, unsigned devIdx );
rc_t deviceEnable( struct driver_str* drv, unsigned devIdx, bool inputFl, bool enableFl );
rc_t deviceSeek( struct driver_str* drv, unsigned devIdx, bool inputFl, unsigned frameOffset );
void deviceRealTimeReport( struct driver_str* drv, unsigned devIdx );
enum {

View File

@ -82,7 +82,7 @@ namespace cw
typedef struct audioDev_str
{
bool enableFl; // True if this device was enabled by the user
bool activeFl; // True if this device was enabled by the user
bool meterFl; // True if meters are enabled on this device
const char* label; // User label
unsigned userId; // User id
@ -843,7 +843,7 @@ namespace cw
rc_t rc1 = kOkRC;
for(unsigned i=0; i<p->audioDevN; ++i)
if( p->audioDevA[i].enableFl )
if( p->audioDevA[i].activeFl )
{
rc_t rc0 = kOkRC;
if( startFl )
@ -1007,7 +1007,7 @@ namespace cw
if( time::isGTE(p->t0,p->audioMeterNextTime) )
{
for(unsigned i=0; i<p->audioDevN; ++i)
if( p->audioDevA[i].enableFl )
if( p->audioDevA[i].activeFl )
{
audioDev_t* ad = p->audioDevA + i;
rc_t rc0;
@ -1575,7 +1575,7 @@ namespace cw
for(unsigned i=0; i<deviceL_Node->child_count(); ++i)
{
audioDev_t* ad = nullptr; //p->audioDevA + i;
bool enableFl = false;
bool activeFl = false;
bool meterFl = false;
char* userLabel = nullptr;
unsigned userId = kInvalidId;
@ -1605,7 +1605,7 @@ namespace cw
if((node = deviceL_Node->child_ele(i)) != nullptr )
{
if(( rc = node->getv(
"enableFl", enableFl,
"activeFl", activeFl,
"label", userLabel,
"device", devName,
"framesPerCycle", framesPerCycle,
@ -1631,7 +1631,7 @@ namespace cw
}
// if the configuration is enabled
if( enableFl )
if( activeFl )
{
// locate the record assoc'd with devName
if((ad = _audioDeviceNameToRecd(p,devName)) == nullptr )
@ -1734,7 +1734,7 @@ namespace cw
}
// set the device group pointers
ad->enableFl = enableFl;
ad->activeFl = activeFl;
ad->meterFl = meterFl;
ad->label = userLabel;
ad->userId = userId;
@ -1753,7 +1753,7 @@ namespace cw
rc_t rc = kOkRC;
for(unsigned i=0; i<p->audioDevN; ++i)
if( p->audioDevA[i].enableFl && p->audioDevA[i].meterFl )
if( p->audioDevA[i].activeFl && 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);
@ -2613,12 +2613,12 @@ cw::rc_t cw::io::audioDeviceSetUserId( handle_t h, unsigned devIdx, unsigned us
return kInvalidArgRC;
}
bool cw::io::audioDeviceIsEnabled( handle_t h, unsigned devIdx )
bool cw::io::audioDeviceIsActive( handle_t h, unsigned devIdx )
{
io_t* p = _handleToPtr(h);
audioDev_t* ad;
if((ad = _audioDeviceIndexToRecd(p,devIdx)) != nullptr )
return ad->enableFl;
return ad->activeFl;
return false;
}
@ -2646,6 +2646,17 @@ unsigned cw::io::audioDeviceUserId( handle_t h, unsigned devIdx )
return ad->userId;
}
cw::rc_t cw::io::audioDeviceEnable( handle_t h, unsigned devIdx, bool inputFl, bool enableFl )
{
io_t* p = _handleToPtr(h);
return audio::device::enable(p->audioH, devIdx, inputFl, enableFl );
}
cw::rc_t cw::io::audioDeviceSeek( handle_t h, unsigned devIdx, bool inputFl, unsigned frameOffset )
{
io_t* p = _handleToPtr(h);
return audio::device::seek(p->audioH, devIdx, inputFl, frameOffset );
}
double cw::io::audioDeviceSampleRate( handle_t h, unsigned devIdx )
{

4
cwIo.h
View File

@ -228,9 +228,11 @@ namespace cw
unsigned audioDeviceLabelToIndex( handle_t h, const char* label );
const char* audioDeviceLabel( handle_t h, unsigned devIdx );
rc_t audioDeviceSetUserId( handle_t h, unsigned devIdx, unsigned userId );
bool audioDeviceIsEnabled( handle_t h, unsigned devIdx );
bool audioDeviceIsActive( handle_t h, unsigned devIdx );
const char* audioDeviceName( handle_t h, unsigned devIdx );
unsigned audioDeviceUserId( handle_t h, unsigned devIdx );
rc_t audioDeviceEnable( handle_t h, unsigned devIdx, bool inputFl, bool enableFl );
rc_t audioDeviceSeek( handle_t h, unsigned devIdx, bool inputFl, unsigned frameOffset );
double audioDeviceSampleRate( handle_t h, unsigned devIdx );
unsigned audioDeviceFramesPerCycle( handle_t h, unsigned devIdx );
unsigned audioDeviceChannelCount( handle_t h, unsigned devIdx, unsigned inOrOutFlag );

View File

@ -274,7 +274,7 @@ cw::rc_t cw::io::audio_panel::create( handle_t& hRef, io::handle_t ioH, unsigne
// create the audio panels for each audio device
for(unsigned i=0; i<audioDeviceCount(ioH); ++i)
if( io::audioDeviceIsEnabled(ioH,i))
if( io::audioDeviceIsActive(ioH,i))
{
if((rc = _registerDevice(p, baseAppId, i, 0 )) != kOkRC )
{