cmRtSys.h : Added 'no-block-mode' to run a program independent of the audio

clock. Added cmRtSysEnableNoBlockMode().
This commit is contained in:
kpl_harpo 2014-04-08 09:02:39 -04:00
parent 102725929c
commit 9f422e58e8
2 changed files with 66 additions and 18 deletions

View File

@ -51,6 +51,9 @@ typedef struct
kRtCmdId_t cmdId; // written by app thread, read by rt thread kRtCmdId_t cmdId; // written by app thread, read by rt thread
unsigned cbEnableFl; // written by rt thread, read by app thread unsigned cbEnableFl; // written by rt thread, read by app thread
bool noBlockEnaFl; //
unsigned noBlockSleepMs;
double* iMeterArray; // double* iMeterArray; //
double* oMeterArray; // double* oMeterArray; //
@ -295,6 +298,7 @@ void _cmRtDspExecCallback( _cmRtCfg_t* cp )
// 1) Buffers associated with disabled input/output channels will be set to NULL in iChArray[]/oChArray[]. // 1) Buffers associated with disabled input/output channels will be set to NULL in iChArray[]/oChArray[].
// 2) Buffers associated with channels marked for pass-through will be set to NULL in oChArray[]. // 2) Buffers associated with channels marked for pass-through will be set to NULL in oChArray[].
// 3) All samples returned in oChArray[] buffers will be set to zero. // 3) All samples returned in oChArray[] buffers will be set to zero.
if( cp->noBlockEnaFl == false )
cmApBufGetIO(cp->ss.args.inDevIdx, cp->ctx.iChArray, cp->ctx.iChCnt, &cp->ctx.iTimeStamp, cmApBufGetIO(cp->ss.args.inDevIdx, cp->ctx.iChArray, cp->ctx.iChCnt, &cp->ctx.iTimeStamp,
cp->ss.args.outDevIdx, cp->ctx.oChArray, cp->ctx.oChCnt, &cp->ctx.oTimeStamp ); cp->ss.args.outDevIdx, cp->ctx.oChArray, cp->ctx.oChCnt, &cp->ctx.oTimeStamp );
@ -344,8 +348,11 @@ void _cmRtDspExecCallback( _cmRtCfg_t* cp )
} }
// advance the audio buffer // advance the audio buffer
if( cp->noBlockEnaFl == false )
{
cmApBufAdvance( cp->ss.args.outDevIdx, kOutApFl ); cmApBufAdvance( cp->ss.args.outDevIdx, kOutApFl );
cmApBufAdvance( cp->ss.args.inDevIdx, kInApFl ); cmApBufAdvance( cp->ss.args.inDevIdx, kInApFl );
}
// handle periodic status messages to the host // handle periodic status messages to the host
if( (cp->statusUpdateSmpIdx += cp->ss.args.dspFramesPerCycle) >= cp->statusUpdateSmpCnt ) if( (cp->statusUpdateSmpIdx += cp->ss.args.dspFramesPerCycle) >= cp->statusUpdateSmpCnt )
@ -390,6 +397,7 @@ bool _cmRtThreadCallback(void* arg)
{ {
cmRtRC_t rc; cmRtRC_t rc;
_cmRtCfg_t* cp = (_cmRtCfg_t*)arg; _cmRtCfg_t* cp = (_cmRtCfg_t*)arg;
bool noBlockFl = false;
// lock the cmRtSys mutex // lock the cmRtSys mutex
if((rc = cmThreadMutexLock(cp->engMutexH)) != kOkRtRC ) if((rc = cmThreadMutexLock(cp->engMutexH)) != kOkRtRC )
@ -402,16 +410,22 @@ bool _cmRtThreadCallback(void* arg)
while( cp->runFl ) while( cp->runFl )
{ {
// if the buffer is NOT ready or the cmRtSys is disabled // if the buffer is NOT ready or the cmRtSys is disabled
if(_cmRtBufIsReady(cp) == false || cp->cbEnableFl==false ) if(_cmRtBufIsReady(cp) == false || cp->cbEnableFl==false )
{ {
// block on the cond var and unlock the mutex // block on the cond var and unlock the mutex
if( noBlockFl )
cmSleepMs(cp->noBlockSleepMs);
else
{
if( cmThreadMutexWaitOnCondVar(cp->engMutexH,false) != kOkRtRC ) if( cmThreadMutexWaitOnCondVar(cp->engMutexH,false) != kOkRtRC )
{ {
cmThreadMutexUnlock(cp->engMutexH); cmThreadMutexUnlock(cp->engMutexH);
_cmRtError(cp->p,rc,"The cmRtSys cond. var. wait failed."); _cmRtError(cp->p,rc,"The cmRtSys cond. var. wait failed.");
return false; return false;
} }
}
// //
// the cond var was signaled and the mutex is now locked // the cond var was signaled and the mutex is now locked
@ -419,12 +433,13 @@ bool _cmRtThreadCallback(void* arg)
++cp->status.wakeupCnt; ++cp->status.wakeupCnt;
} }
noBlockFl = cp->noBlockEnaFl;
// be sure we are still enabled and the buffer is still ready // be sure we are still enabled and the buffer is still ready
while( cp->runFl && _cmRtBufIsReady(cp) ) while( cp->runFl && _cmRtBufIsReady(cp) )
{ {
++cp->status.audioCbCnt; ++cp->status.audioCbCnt;
// make the cmRtSys callback // make the cmRtSys callback
_cmRtDspExecCallback( cp ); _cmRtDspExecCallback( cp );
@ -496,7 +511,6 @@ void _cmRtSysAudioUpdate( cmApAudioPacket_t* inPktArray, unsigned inPktCnt, cm
// transfer incoming/outgoing samples from/to the audio device // transfer incoming/outgoing samples from/to the audio device
cmApBufUpdate(inPktArray,inPktCnt,outPktArray,outPktCnt); cmApBufUpdate(inPktArray,inPktCnt,outPktArray,outPktCnt);
// generate a test signal // generate a test signal
//_cmRtGenSignal( cmApAudioPacket_t* outPktArray, unsigned outPktCnt, bool sineFl ); //_cmRtGenSignal( cmApAudioPacket_t* outPktArray, unsigned outPktCnt, bool sineFl );
//return; //return;
@ -513,6 +527,17 @@ void _cmRtSysAudioUpdate( cmApAudioPacket_t* inPktArray, unsigned inPktCnt, cm
_cmRtError(cp->p,kMutexErrRtRC,"CmRtSys signal cond. var. failed."); _cmRtError(cp->p,kMutexErrRtRC,"CmRtSys signal cond. var. failed.");
} }
if( cp->noBlockEnaFl )
{
cmApBufGetIO(cp->ss.args.inDevIdx, cp->ctx.iChArray, cp->ctx.iChCnt, &cp->ctx.iTimeStamp,
cp->ss.args.outDevIdx, cp->ctx.oChArray, cp->ctx.oChCnt, &cp->ctx.oTimeStamp );
cmApBufAdvance( cp->ss.args.outDevIdx, kOutApFl );
cmApBufAdvance( cp->ss.args.inDevIdx, kInApFl );
}
} }
} }
@ -902,7 +927,7 @@ cmRtRC_t cmRtSysCfg( cmRtSysH_t h, const cmRtSysSubSys_t* ss, unsigned rtSubIdx
cp->status.oMeterCnt = cp->ctx.oChCnt; cp->status.oMeterCnt = cp->ctx.oChCnt;
cp->iMeterArray = cmMemAllocZ( double, cp->status.iMeterCnt ); cp->iMeterArray = cmMemAllocZ( double, cp->status.iMeterCnt );
cp->oMeterArray = cmMemAllocZ( double, cp->status.oMeterCnt ); cp->oMeterArray = cmMemAllocZ( double, cp->status.oMeterCnt );
//cp->udpH = cfg->udpH; cp->noBlockEnaFl = false;
// create the real-time system thread // create the real-time system thread
if((rc = cmThreadCreate( &cp->threadH, _cmRtThreadCallback, cp, ss->args.rpt )) != kOkThRC ) if((rc = cmThreadCreate( &cp->threadH, _cmRtThreadCallback, cp, ss->args.rpt )) != kOkThRC )
@ -1237,6 +1262,25 @@ cmRtSysCtx_t* cmRtSysContext( cmRtSysH_t h, unsigned rtSubIdx )
return &p->ssArray[rtSubIdx].ctx; return &p->ssArray[rtSubIdx].ctx;
} }
cmRtRC_t cmRtSysEnableNoBlockMode( cmRtSysH_t h, unsigned rtSubIdx, bool enaFl, unsigned noBlockSleepMs )
{
cmRt_t* p = _cmRtHandleToPtr(h);
cmRtRC_t rc = kOkRtRC;
if((rc = _cmRtSysVerifyInit(p,true)) != kOkRtRC )
return rc;
if( rtSubIdx >= p->ssCnt )
return cmErrMsg(&p->err,kInvalidArgRtRC,"Invalid 'rtSubIdx'. Enable non-block mode failed.");
p->ssArray[rtSubIdx].noBlockSleepMs = noBlockSleepMs;
p->ssArray[rtSubIdx].noBlockEnaFl = enaFl;
return kOkRtRC;
}
unsigned cmRtSysSubSystemCount( cmRtSysH_t h ) unsigned cmRtSysSubSystemCount( cmRtSysH_t h )
{ {
cmRt_t* p = _cmRtHandleToPtr(h); cmRt_t* p = _cmRtHandleToPtr(h);

View File

@ -313,6 +313,10 @@ extern "C" {
// Return a pointer the context record associated with a sub-system // Return a pointer the context record associated with a sub-system
cmRtSysCtx_t* cmRtSysContext( cmRtSysH_t h, unsigned rtSubIdx ); cmRtSysCtx_t* cmRtSysContext( cmRtSysH_t h, unsigned rtSubIdx );
// Enable non-block mode. In this mode audio I/O is disabled
// and the DSP callback is made every noBlockSleepMs milliseconds.
cmRtRC_t cmRtSysEnableNoBlockMode( cmRtSysH_t h, unsigned rtSubIdx, bool enaFl, unsigned noBlockSleepMs );
// Return the count of audio sub-systems. // Return the count of audio sub-systems.
// This is the same as the count of cfg recds passed to cmRtSystemInitialize(). // This is the same as the count of cfg recds passed to cmRtSystemInitialize().
unsigned cmRtSysSubSystemCount( cmRtSysH_t h ); unsigned cmRtSysSubSystemCount( cmRtSysH_t h );