From 57d2a86a42a4f745cbb070eab3bb99156f4b775f Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 19 Nov 2013 11:08:08 -0500 Subject: [PATCH] cmProc4.h/c, cmDspKr.c : Added look-ahead buffer to cmRecdPlay object. --- cmProc4.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++--- cmProc4.h | 8 +++- dsp/cmDspKr.c | 16 ++++++- 3 files changed, 133 insertions(+), 11 deletions(-) diff --git a/cmProc4.c b/cmProc4.c index b312df6..f6a18a6 100644 --- a/cmProc4.c +++ b/cmProc4.c @@ -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; ilaChs[i] = cmMemAllocZ(cmSample_t,p->maxLaSmpCnt); + return rc; } cmRC_t cmRecdPlayFinal( cmRecdPlay* p ) { unsigned i,j; + // free the fragments for(i=0; ifragCnt; ++i) { for(j=0; jchCnt; ++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; ichCnt; ++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; jchCnt; ++j) + cmVOS_Copy(p->frags[i].chArray[j],n0,p->laChs[j]+srcOffs); + + if( n1 > 0 ) + { + for(j=0; jchCnt; ++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; ilaChs[i]+p->laSmpIdx,n0,iChs[i] + srcOffs); + + p->laSmpIdx += n0; + + if( n1!=0) + { + // copy second block to begin of LA buffer + for(i=0; ilaChs[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) { diff --git a/cmProc4.h b/cmProc4.h index 36b88d2..8ad104e 100644 --- a/cmProc4.h +++ b/cmProc4.h @@ -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 ); diff --git a/dsp/cmDspKr.c b/dsp/cmDspKr.c index 178016b..a19bb2f 100644 --- a/dsp/cmDspKr.c +++ b/dsp/cmDspKr.c @@ -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; iscLocIdx = 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;