cwAudioDevFile.h/cpp, cwIo.cpp : Implemented input cache on audio dev file.

This commit is contained in:
kevin 2023-02-20 15:42:11 -05:00
parent 2fc2f7f4b0
commit 03061f42b7
3 changed files with 122 additions and 29 deletions

View File

@ -48,13 +48,17 @@ namespace cw
unsigned iChCnt; unsigned iChCnt;
bool iEnableFl; bool iEnableFl;
audioPacket_t iPkt; audioPacket_t iPkt;
float* iPktAudioBuf; sample_t* iPktAudioBuf;
unsigned iCbCnt; unsigned iCbCnt;
float** iChArray; // iChArray[2] sample_t** iChArray; // iChArray[ iChCnt ]
float* iChSmpBuf; // sample_t* iChSmpBuf; //
unsigned iErrCnt; // count of errors unsigned iErrCnt; // count of errors
unsigned iFrmCnt; // count of frames read unsigned iFrmCnt; // count of frames read
sample_t* iCacheBuf; // iCacheFrameBuf[ iCacheFrameN * iChCnt ] (interleaved)
unsigned iCacheFrameN; // count of frames in iCacheBuf
unsigned iCacheIdx; // next frame to read (always at channel 0)
char* oFname; char* oFname;
audiofile::handle_t oFileH; audiofile::handle_t oFileH;
unsigned oFlags; unsigned oFlags;
@ -62,10 +66,10 @@ namespace cw
bool oEnableFl; bool oEnableFl;
unsigned oBitsPerSample; unsigned oBitsPerSample;
audioPacket_t oPkt; audioPacket_t oPkt;
float* oPktAudioBuf; sample_t* oPktAudioBuf;
unsigned oCbCnt; unsigned oCbCnt;
float** oChArray; // oChArray[2] sample_t** oChArray; // oChArray[2]
float* oChSmpBuf; // sample_t* oChSmpBuf; //
unsigned oErrCnt; // count of errors unsigned oErrCnt; // count of errors
unsigned oFrmCnt; // count of frames written unsigned oFrmCnt; // count of frames written
@ -169,9 +173,104 @@ namespace cw
mem::release(d->iPktAudioBuf); mem::release(d->iPktAudioBuf);
mem::release(d->iChArray); mem::release(d->iChArray);
mem::release(d->iChSmpBuf); mem::release(d->iChSmpBuf);
mem::release(d->iCacheBuf);
} }
} }
rc_t _fill_input_packet_from_cache( dev_t* d )
{
rc_t rc = kOkRC;
unsigned n = d->framesPerCycle;
unsigned m = d->framesPerCycle;
// set n to the count of frames to copy from the cache into the pkt
if( d->iCacheIdx + n > d->iCacheFrameN )
n = d->iCacheFrameN - d->iCacheIdx;
if( n > 0 )
{
memcpy( d->iPktAudioBuf, d->iCacheBuf + (d->iCacheIdx * d->iChCnt), d->framesPerCycle * d->iChCnt * sizeof(sample_t));
d->iCacheIdx += n;
// set m to the count of frames to zero at the end of the pkt
m = d->framesPerCycle - n;
}
if( m > 0 )
{
memset( d->iPktAudioBuf + (n*d->iChCnt), 0, m * d->iChCnt * sizeof(sample_t));
d->iCacheIdx = d->iCacheFrameN;
}
return rc;
}
rc_t _fill_input_packet_from_file( dev_t* d )
{
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;
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 );
}
// d->iPktAudioBuf[] now contains d->framesPerCycle*d->iChCnt samples
errLabel:
return rc;
}
rc_t _cache_input( dev_t* d, unsigned frameN )
{
rc_t rc = kOkRC;
unsigned n = 0;
d->iCacheFrameN = frameN;
d->iCacheBuf = mem::resize<sample_t>(d->iCacheBuf, d->iCacheFrameN * d->iChCnt);
d->iCacheIdx = 0;
while(n < d->iCacheFrameN )
{
if((rc = _fill_input_packet_from_file(d)) != kOkRC )
{
rc = cwLogError(rc,"Read failed while reading the input cache.");
d->iCacheFrameN = 0; // this will prevent the cache from being used
goto errLabel;
}
unsigned copyFrameN = d->framesPerCycle;
if( n + copyFrameN > d->iCacheFrameN )
copyFrameN = d->iCacheFrameN - n;
memcpy( d->iCacheBuf + n * d->iChCnt, d->iPktAudioBuf, copyFrameN * d->iChCnt * sizeof(sample_t));
n += copyFrameN;
}
if( n % d->iChCnt != 0 )
{
cwLogWarning("The cache buffer seems to have a size mismatch with the input audio file.");
}
errLabel:
return rc;
}
rc_t _open_input( dev_t* d, unsigned devIdx ) rc_t _open_input( dev_t* d, unsigned devIdx )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
@ -217,6 +316,11 @@ namespace cw
for(unsigned i=0; i<d->iChCnt; ++i) for(unsigned i=0; i<d->iChCnt; ++i)
d->iChArray[i] = d->iChSmpBuf + i*d->framesPerCycle; d->iChArray[i] = d->iChSmpBuf + i*d->framesPerCycle;
// if input caching was requested
if( cwIsFlag(d->iFlags,kCacheFl) )
if((rc = _cache_input(d,info.frameCnt)) != kOkRC )
cwLogError(rc,"Cache load failed on '%s'.",cwStringNullGuard(d->iFname));
errLabel: errLabel:
return rc; return rc;
@ -226,34 +330,18 @@ namespace cw
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
unsigned actualFrameCnt = 0;
if( !d->iEnableFl ) if( !d->iEnableFl )
{ {
memset(d->iPkt.audioBytesPtr,0,d->iChCnt*d->framesPerCycle*sizeof(sample_t)); memset(d->iPkt.audioBytesPtr,0,d->iChCnt*d->framesPerCycle*sizeof(sample_t));
} }
else else
{ {
// read the file if( d->iCacheFrameN )
if((rc = readFloat(d->iFileH, d->framesPerCycle, 0, d->iChCnt, d->iChArray, &actualFrameCnt)) == kOkRC ) rc = _fill_input_packet_from_cache(d);
d->iFrmCnt += actualFrameCnt;
else else
{ rc = _fill_input_packet_from_file(d);
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 );
}
} }
errLabel:
return rc; return rc;
} }
@ -377,7 +465,7 @@ namespace cw
dev_t* d = nullptr; dev_t* d = nullptr;
// block on the cond. var - unlock the mutex // block on the cond. var - unlock the mutex
if((rc = mutex::waitOnCondVar(p->mutexH,false,p->threadTimeOutMs)) != kOkRC ) if((rc = mutex::waitOnCondVar(p->mutexH,false,p->threadTimeOutMs/2)) != kOkRC )
{ {
if( rc != kTimeOutRC ) if( rc != kTimeOutRC )
{ {
@ -658,6 +746,7 @@ cw::rc_t cw::audio::device::file::deviceStart( struct driver_str* dr
if((rc0 = _indexToDev( p, devIdx, d )) == kOkRC ) if((rc0 = _indexToDev( p, devIdx, d )) == kOkRC )
{ {
/*
if( d->iFileH.isValid() && cwIsFlag(d->iFlags,kRewindOnStartFl) ) if( d->iFileH.isValid() && cwIsFlag(d->iFlags,kRewindOnStartFl) )
if((rc0 = seek(d->iFileH,0)) != kOkRC ) if((rc0 = seek(d->iFileH,0)) != kOkRC )
rc0 = cwLogError(rc0,"Rewind on start failed on the audio device file input file."); rc0 = cwLogError(rc0,"Rewind on start failed on the audio device file input file.");
@ -665,6 +754,7 @@ cw::rc_t cw::audio::device::file::deviceStart( struct driver_str* dr
if( d->oFileH.isValid() && cwIsFlag(d->oFlags,kRewindOnStartFl) ) if( d->oFileH.isValid() && cwIsFlag(d->oFlags,kRewindOnStartFl) )
if((rc1 = seek(d->oFileH,0)) != kOkRC ) if((rc1 = seek(d->oFileH,0)) != kOkRC )
rc1 = cwLogError(rc1,"Rewind on start failed on the audio device file output file."); rc1 = cwLogError(rc1,"Rewind on start failed on the audio device file output file.");
*/
} }
if((rc0 = rcSelect(rc0,rc1)) == kOkRC ) if((rc0 = rcSelect(rc0,rc1)) == kOkRC )
@ -734,8 +824,6 @@ cw::rc_t cw::audio::device::file::deviceEnable( struct driver_str* drv, unsigne
else else
d->oEnableFl = enableFl; d->oEnableFl = enableFl;
printf("Enable i:%i o:%i\n",d->iEnableFl,d->oEnableFl);
errLabel: errLabel:
return rc; return rc;
} }

View File

@ -33,6 +33,7 @@ namespace cw
enum { enum {
kRewindOnStartFl = 0x01, kRewindOnStartFl = 0x01,
kCacheFl = 0x02
}; };
// A device may have an input, an output or both. // A device may have an input, an output or both.

View File

@ -1878,6 +1878,7 @@ namespace cw
const char* label = nullptr; const char* label = nullptr;
const char* iFname = nullptr; const char* iFname = nullptr;
bool iRwdOnStartFl = false; bool iRwdOnStartFl = false;
bool iCacheFl = true;
const char* oFname = nullptr; const char* oFname = nullptr;
unsigned oChCnt = 0; unsigned oChCnt = 0;
@ -1892,6 +1893,7 @@ namespace cw
if((rc = fnode->getv_opt("enableFl", enableFl, if((rc = fnode->getv_opt("enableFl", enableFl,
"in_fname", iFname, "in_fname", iFname,
"in_rewind_on_start_fl",iRwdOnStartFl, "in_rewind_on_start_fl",iRwdOnStartFl,
"in_cache_fl",iCacheFl,
"out_fname", oFname, "out_fname", oFname,
"out_rewind_on_start_fl",oRwdOnStartFl, "out_rewind_on_start_fl",oRwdOnStartFl,
"out_ch_count", oChCnt )) != kOkRC ) "out_ch_count", oChCnt )) != kOkRC )
@ -1906,6 +1908,8 @@ namespace cw
if( iFname != nullptr ) if( iFname != nullptr )
{ {
unsigned iFlags = iRwdOnStartFl ? audio::device::file::kRewindOnStartFl : 0; unsigned iFlags = iRwdOnStartFl ? audio::device::file::kRewindOnStartFl : 0;
iFlags += iCacheFl ? audio::device::file::kCacheFl : 0;
if((rc = createInDevice( p->audioDevFileH, label, iFname, iFlags )) != kOkRC ) if((rc = createInDevice( p->audioDevFileH, label, iFname, iFlags )) != kOkRC )
{ {