cmProc4.h/c, cmDspKr.c : Added look-ahead buffer to cmRecdPlay object.

This commit is contained in:
kevin 2013-11-19 11:08:08 -05:00
parent ebef000a27
commit 57d2a86a42
3 changed files with 133 additions and 11 deletions

120
cmProc4.c
View File

@ -4134,11 +4134,11 @@ cmRC_t cmScModulatorDump( cmScModulator* p )
}
//=======================================================================================================================
cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs )
cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs )
{
cmRecdPlay* op = cmObjAlloc(cmRecdPlay,c,p);
if( cmRecdPlayInit(op,srate,fragCnt,chCnt,initFragSecs) != cmOkRC )
if( cmRecdPlayInit(op,srate,fragCnt,chCnt,initFragSecs,maxLaSecs,curLaSecs) != cmOkRC )
cmRecdPlayFree(&op);
return op;
@ -4159,26 +4159,40 @@ cmRC_t cmRecdPlayFree( cmRecdPlay** pp )
}
cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs )
cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs )
{
cmRC_t rc;
unsigned i;
if( curLaSecs > maxLaSecs )
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The initial look-ahead time %f is greater than the maximum look-ahead time %f.",curLaSecs,maxLaSecs);
if((rc = cmRecdPlayFinal(p)) != cmOkRC )
return rc;
if( chCnt == 0 )
return cmOkRC;
p->frags = cmMemAllocZ(cmRecdPlayFrag,fragCnt);
p->fragCnt = fragCnt;
p->srate = srate;
p->chCnt = chCnt;
p->initFragSecs = initFragSecs;
p->maxLaSmpCnt = floor(maxLaSecs*srate);
p->curLaSmpCnt = floor(curLaSecs*srate);
p->laChs = cmMemAllocZ(cmSample_t*,chCnt);
p->laSmpIdx = 0;
for(i=0; i<chCnt; ++i)
p->laChs[i] = cmMemAllocZ(cmSample_t,p->maxLaSmpCnt);
return rc;
}
cmRC_t cmRecdPlayFinal( cmRecdPlay* p )
{
unsigned i,j;
// free the fragments
for(i=0; i<p->fragCnt; ++i)
{
for(j=0; j<p->chCnt; ++j)
@ -4186,9 +4200,17 @@ cmRC_t cmRecdPlayFinal( cmRecdPlay* p )
cmMemFree(p->frags[i].chArray);
}
cmMemFree(p->frags);
p->fragCnt=0;
p->chCnt=0;
// free the look-ahead buffers
for(i=0; i<p->chCnt; ++i)
cmMemFree(p->laChs[i]);
cmMemPtrFree(&p->laChs);
cmMemPtrFree(&p->frags);
p->fragCnt = 0;
p->chCnt = 0;
p->rlist = NULL;
p->plist = NULL;
return cmOkRC;
}
@ -4216,6 +4238,8 @@ cmRC_t cmRecdPlayRewind( cmRecdPlay* p )
{
unsigned i;
p->laSmpIdx = 0;
while( p->plist != NULL )
cmRecdPlayEndPlay(p,p->plist->labelSymId);
@ -4228,6 +4252,7 @@ cmRC_t cmRecdPlayRewind( cmRecdPlay* p )
return cmOkRC;
}
cmRC_t cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId )
{
unsigned i;
@ -4242,6 +4267,39 @@ cmRC_t cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId )
p->frags[i].playIdx = 0;
p->frags[i].rlink = p->rlist;
p->rlist = p->frags + i;
// handle LA buf longer than frag buf.
int cpyCnt = cmMin(p->curLaSmpCnt,p->frags[i].allocCnt);
// go backwards in LA buf from newest sample to find init src offset
int srcOffs = p->laSmpIdx - cpyCnt;
// if the src is before the first sample in the LA buf then wrap to end of buf
if( srcOffs < 0 )
srcOffs += p->maxLaSmpCnt;
assert( 0 <= srcOffs && srcOffs < p->maxLaSmpCnt );
// cnt of samples to copy from LA buf (limited by end of LA buf)
int n0 = cmMin(cpyCnt,p->maxLaSmpCnt - srcOffs);
// if necessary wrap to begin of LA buf for remaining samples
int n1 = cpyCnt>n0 ? n1 = cpyCnt-n0 : 0;
int j;
assert(n0+n1 == cpyCnt );
for(j=0; j<p->chCnt; ++j)
cmVOS_Copy(p->frags[i].chArray[j],n0,p->laChs[j]+srcOffs);
if( n1 > 0 )
{
for(j=0; j<p->chCnt; ++j)
cmVOS_Copy(p->frags[i].chArray[j]+n0,n1,p->laChs[j]);
}
p->frags[i].recdIdx = cpyCnt;
}
return cmOkRC;
@ -4341,8 +4399,53 @@ cmRC_t cmRecdPlayBeginFade( cmRecdPlay* p, unsigned labelSymId, double fadeDbP
cmRC_t cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_t** oChs, unsigned chCnt, unsigned smpCnt )
{
unsigned i;
chCnt = cmMin(chCnt, p->chCnt);
//-------------------------------------------------------------------
// copy incoming audio into the look-head buffers
//
// if the number of incoming samples is longer than the look-head buffer
// then copy exactly maxLaSmpCnt samples from the end of the incoming sample
// buffer to the look-ahead buffer.
unsigned srcOffs = 0;
unsigned srcSmpCnt = smpCnt;
if( srcSmpCnt > p->maxLaSmpCnt )
{
// advance incoming sample buffer so that there are maxLaSmpCnt samples remaining
srcOffs = smpCnt-p->maxLaSmpCnt;
srcSmpCnt = p->maxLaSmpCnt; // decrease the total samples to copy
}
// count of samples from cur posn to end of the LA buffer.
unsigned n0 = cmMin(srcSmpCnt, p->maxLaSmpCnt - p->laSmpIdx );
// count of samples past the end of the LA buffer to be wrapped into begin of buffer
unsigned n1 = srcSmpCnt>n0 ? srcSmpCnt-n0 : 0;
assert(n0+n1 == srcSmpCnt);
// copy first block to end of LA buffer
for(i=0; i<chCnt; ++i)
cmVOS_Copy(p->laChs[i]+p->laSmpIdx,n0,iChs[i] + srcOffs);
p->laSmpIdx += n0;
if( n1!=0)
{
// copy second block to begin of LA buffer
for(i=0; i<chCnt; ++i)
cmVOS_Copy(p->laChs[i],n1,iChs[i] + srcOffs + n0);
p->laSmpIdx = n1;
}
//-------------------------------------------------------------------
// copy incoming audio into the active record buffers
//
cmRecdPlayFrag* fp = p->rlist;
for(; fp!=NULL; fp=fp->rlink)
@ -4357,6 +4460,9 @@ cmRC_t cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_
}
}
//-------------------------------------------------------------------
// copy outgoing audio out of the active play buffers
//
fp = p->plist;
for(; fp!=NULL; fp=fp->rlink)
{

View File

@ -649,14 +649,18 @@ extern "C" {
double srate; // system sample rate
unsigned chCnt; // count of input and output audio channels
double initFragSecs; // size initial memory allocated to each frag in seconds
unsigned maxLaSmpCnt; // samples allocated to each channel of the look-ahead buffers.
unsigned curLaSmpCnt; // current look-ahead time in samples (curLaSmpCnt<=maxLaSmpCnt)
cmSample_t** laChs; // laChs[chCnt][maxLaSmpCnt] - look-ahead buffers
int laSmpIdx; // next look-ahead buffer index to receive a sample
cmRecdPlayFrag* plist; // currently playing frags
cmRecdPlayFrag* rlist; // currently recording frags
} cmRecdPlay;
cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs );
cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs );
cmRC_t cmRecdPlayFree( cmRecdPlay** pp );
cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned flagCnt, unsigned chCnt, double initFragSecs );
cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned flagCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs );
cmRC_t cmRecdPlayFinal( cmRecdPlay* p );
cmRC_t cmRecdPlayRegisterFrag( cmRecdPlay* p, unsigned fragIdx, unsigned labelSymId );

View File

@ -2271,6 +2271,8 @@ enum
kChCntPrId,
kFnPrId,
kSecsPrId,
kMaxLaSecsPrId,
kCurLaSecsPrId,
kFadeRatePrId,
kScLocIdxPrId,
kCmdPrId,
@ -2311,8 +2313,11 @@ cmDspRC_t _cmDspRecdPlayOpenScore( cmDspCtx_t* ctx, cmDspInst_t* inst )
{
unsigned i;
unsigned markerCnt = cmScoreMarkerLabelCount(p->scH);
double initFragSecs = cmDspDouble(inst,kSecsPrId);
double maxLaSecs = cmDspDouble(inst,kMaxLaSecsPrId);
double curLaSecs = cmDspDouble(inst,kCurLaSecsPrId);
if((p->rcdply = cmRecdPlayAlloc(ctx->cmProcCtx, NULL, cmDspSampleRate(ctx), markerCnt, p->chCnt, cmDspDouble(inst,kSecsPrId))) == NULL)
if((p->rcdply = cmRecdPlayAlloc(ctx->cmProcCtx, NULL, cmDspSampleRate(ctx), markerCnt, p->chCnt, initFragSecs, maxLaSecs, curLaSecs)) == NULL)
return cmErrMsg(&inst->classPtr->err,kSubSysFailDspRC,"Unable to create the internal recorder-player object.");
for(i=0; i<markerCnt; ++i)
@ -2343,6 +2348,8 @@ cmDspInst_t* _cmDspRecdPlayAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsig
1, "chs", kChCntPrId, 0,0, kUIntDsvFl | kReqArgDsvFl, "channel count.",
1, "fn", kFnPrId, 0,0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Score file." ,
1, "secs", kSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl | kReqArgDsvFl, "Initial fragment allocation in seconds.",
1, "maxla", kMaxLaSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl, "Maximum look-ahead buffer in seconds.",
1, "curla", kCurLaSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl, "Current look-head buffer in seconds.",
1, "frate", kFadeRatePrId, 0,0, kInDsvFl | kDoubleDsvFl, "Fade rate in dB per second.",
1, "index", kScLocIdxPrId, 0,0, kInDsvFl | kUIntDsvFl, "Score follower location index.",
1, "cmd", kCmdPrId, 0,0, kInDsvFl | kSymDsvFl, "on=reset off=stop.",
@ -2359,6 +2366,8 @@ cmDspInst_t* _cmDspRecdPlayAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsig
p->scLocIdx = 0;
cmDspSetDefaultDouble(ctx,&p->inst, kSecsPrId, 0, 10.0 );
cmDspSetDefaultDouble(ctx,&p->inst, kMaxLaSecsPrId,0, 2.0);
cmDspSetDefaultDouble(ctx,&p->inst, kCurLaSecsPrId,0, 0.5);
cmDspSetDefaultDouble(ctx,&p->inst, kFadeRatePrId, 0, 1.0);
return &p->inst;
@ -2446,6 +2455,9 @@ cmDspRC_t _cmDspRecdPlayRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_
break;
case kCurLaSecsPrId:
break;
case kScLocIdxPrId:
{
unsigned endScLocIdx = cmDspUInt(inst,kScLocIdxPrId) ;
@ -2474,7 +2486,7 @@ cmDspRC_t _cmDspRecdPlayRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_
break;
case kPlayEndScMId:
printf("recd-end\n");
printf("play-end\n");
cmRecdPlayEndPlay(p->rcdply, mp->labelSymId );
break;