cwAudioDevFile.h/cpp, cwIo.cpp : Implemented input cache on audio dev file.
This commit is contained in:
parent
2fc2f7f4b0
commit
03061f42b7
@ -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;
|
||||||
@ -218,6 +317,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,7 +330,6 @@ namespace cw
|
|||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
unsigned actualFrameCnt = 0;
|
|
||||||
|
|
||||||
if( !d->iEnableFl )
|
if( !d->iEnableFl )
|
||||||
{
|
{
|
||||||
@ -234,26 +337,11 @@ namespace cw
|
|||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
4
cwIo.cpp
4
cwIo.cpp
@ -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 )
|
||||||
@ -1907,6 +1909,8 @@ namespace cw
|
|||||||
{
|
{
|
||||||
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 )
|
||||||
{
|
{
|
||||||
cwLogError(rc,"Create failed on input audio device file '%s'.",cwStringNullGuard(label));
|
cwLogError(rc,"Create failed on input audio device file '%s'.",cwStringNullGuard(label));
|
||||||
|
Loading…
Reference in New Issue
Block a user