|
@@ -4134,11 +4134,11 @@ cmRC_t cmScModulatorDump( cmScModulator* p )
|
4134
|
4134
|
}
|
4135
|
4135
|
|
4136
|
4136
|
//=======================================================================================================================
|
4137
|
|
-cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs )
|
|
4137
|
+cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs )
|
4138
|
4138
|
{
|
4139
|
4139
|
cmRecdPlay* op = cmObjAlloc(cmRecdPlay,c,p);
|
4140
|
4140
|
|
4141
|
|
- if( cmRecdPlayInit(op,srate,fragCnt,chCnt,initFragSecs) != cmOkRC )
|
|
4141
|
+ if( cmRecdPlayInit(op,srate,fragCnt,chCnt,initFragSecs,maxLaSecs,curLaSecs) != cmOkRC )
|
4142
|
4142
|
cmRecdPlayFree(&op);
|
4143
|
4143
|
|
4144
|
4144
|
return op;
|
|
@@ -4159,26 +4159,40 @@ cmRC_t cmRecdPlayFree( cmRecdPlay** pp )
|
4159
|
4159
|
|
4160
|
4160
|
}
|
4161
|
4161
|
|
4162
|
|
-cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs )
|
|
4162
|
+cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs )
|
4163
|
4163
|
{
|
4164
|
|
-
|
4165
|
4164
|
cmRC_t rc;
|
|
4165
|
+ unsigned i;
|
|
4166
|
+
|
|
4167
|
+ if( curLaSecs > maxLaSecs )
|
|
4168
|
+ return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The initial look-ahead time %f is greater than the maximum look-ahead time %f.",curLaSecs,maxLaSecs);
|
4166
|
4169
|
|
4167
|
4170
|
if((rc = cmRecdPlayFinal(p)) != cmOkRC )
|
4168
|
4171
|
return rc;
|
4169
|
4172
|
|
|
4173
|
+ if( chCnt == 0 )
|
|
4174
|
+ return cmOkRC;
|
|
4175
|
+
|
4170
|
4176
|
p->frags = cmMemAllocZ(cmRecdPlayFrag,fragCnt);
|
4171
|
4177
|
p->fragCnt = fragCnt;
|
4172
|
4178
|
p->srate = srate;
|
4173
|
4179
|
p->chCnt = chCnt;
|
4174
|
4180
|
p->initFragSecs = initFragSecs;
|
|
4181
|
+ p->maxLaSmpCnt = floor(maxLaSecs*srate);
|
|
4182
|
+ p->curLaSmpCnt = floor(curLaSecs*srate);
|
|
4183
|
+ p->laChs = cmMemAllocZ(cmSample_t*,chCnt);
|
|
4184
|
+ p->laSmpIdx = 0;
|
4175
|
4185
|
|
|
4186
|
+ for(i=0; i<chCnt; ++i)
|
|
4187
|
+ p->laChs[i] = cmMemAllocZ(cmSample_t,p->maxLaSmpCnt);
|
|
4188
|
+
|
4176
|
4189
|
return rc;
|
4177
|
4190
|
}
|
4178
|
4191
|
|
4179
|
4192
|
cmRC_t cmRecdPlayFinal( cmRecdPlay* p )
|
4180
|
4193
|
{
|
4181
|
4194
|
unsigned i,j;
|
|
4195
|
+ // free the fragments
|
4182
|
4196
|
for(i=0; i<p->fragCnt; ++i)
|
4183
|
4197
|
{
|
4184
|
4198
|
for(j=0; j<p->chCnt; ++j)
|
|
@@ -4186,9 +4200,17 @@ cmRC_t cmRecdPlayFinal( cmRecdPlay* p )
|
4186
|
4200
|
|
4187
|
4201
|
cmMemFree(p->frags[i].chArray);
|
4188
|
4202
|
}
|
4189
|
|
- cmMemFree(p->frags);
|
4190
|
|
- p->fragCnt=0;
|
4191
|
|
- p->chCnt=0;
|
|
4203
|
+
|
|
4204
|
+ // free the look-ahead buffers
|
|
4205
|
+ for(i=0; i<p->chCnt; ++i)
|
|
4206
|
+ cmMemFree(p->laChs[i]);
|
|
4207
|
+
|
|
4208
|
+ cmMemPtrFree(&p->laChs);
|
|
4209
|
+ cmMemPtrFree(&p->frags);
|
|
4210
|
+ p->fragCnt = 0;
|
|
4211
|
+ p->chCnt = 0;
|
|
4212
|
+ p->rlist = NULL;
|
|
4213
|
+ p->plist = NULL;
|
4192
|
4214
|
return cmOkRC;
|
4193
|
4215
|
}
|
4194
|
4216
|
|
|
@@ -4216,6 +4238,8 @@ cmRC_t cmRecdPlayRewind( cmRecdPlay* p )
|
4216
|
4238
|
{
|
4217
|
4239
|
unsigned i;
|
4218
|
4240
|
|
|
4241
|
+ p->laSmpIdx = 0;
|
|
4242
|
+
|
4219
|
4243
|
while( p->plist != NULL )
|
4220
|
4244
|
cmRecdPlayEndPlay(p,p->plist->labelSymId);
|
4221
|
4245
|
|
|
@@ -4228,6 +4252,7 @@ cmRC_t cmRecdPlayRewind( cmRecdPlay* p )
|
4228
|
4252
|
return cmOkRC;
|
4229
|
4253
|
}
|
4230
|
4254
|
|
|
4255
|
+
|
4231
|
4256
|
cmRC_t cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId )
|
4232
|
4257
|
{
|
4233
|
4258
|
unsigned i;
|
|
@@ -4242,6 +4267,39 @@ cmRC_t cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId )
|
4242
|
4267
|
p->frags[i].playIdx = 0;
|
4243
|
4268
|
p->frags[i].rlink = p->rlist;
|
4244
|
4269
|
p->rlist = p->frags + i;
|
|
4270
|
+
|
|
4271
|
+ // handle LA buf longer than frag buf.
|
|
4272
|
+ int cpyCnt = cmMin(p->curLaSmpCnt,p->frags[i].allocCnt);
|
|
4273
|
+
|
|
4274
|
+ // go backwards in LA buf from newest sample to find init src offset
|
|
4275
|
+ int srcOffs = p->laSmpIdx - cpyCnt;
|
|
4276
|
+
|
|
4277
|
+ // if the src is before the first sample in the LA buf then wrap to end of buf
|
|
4278
|
+ if( srcOffs < 0 )
|
|
4279
|
+ srcOffs += p->maxLaSmpCnt;
|
|
4280
|
+
|
|
4281
|
+ assert( 0 <= srcOffs && srcOffs < p->maxLaSmpCnt );
|
|
4282
|
+
|
|
4283
|
+ // cnt of samples to copy from LA buf (limited by end of LA buf)
|
|
4284
|
+ int n0 = cmMin(cpyCnt,p->maxLaSmpCnt - srcOffs);
|
|
4285
|
+
|
|
4286
|
+ // if necessary wrap to begin of LA buf for remaining samples
|
|
4287
|
+ int n1 = cpyCnt>n0 ? n1 = cpyCnt-n0 : 0;
|
|
4288
|
+ int j;
|
|
4289
|
+
|
|
4290
|
+ assert(n0+n1 == cpyCnt );
|
|
4291
|
+
|
|
4292
|
+ for(j=0; j<p->chCnt; ++j)
|
|
4293
|
+ cmVOS_Copy(p->frags[i].chArray[j],n0,p->laChs[j]+srcOffs);
|
|
4294
|
+
|
|
4295
|
+ if( n1 > 0 )
|
|
4296
|
+ {
|
|
4297
|
+ for(j=0; j<p->chCnt; ++j)
|
|
4298
|
+ cmVOS_Copy(p->frags[i].chArray[j]+n0,n1,p->laChs[j]);
|
|
4299
|
+ }
|
|
4300
|
+
|
|
4301
|
+ p->frags[i].recdIdx = cpyCnt;
|
|
4302
|
+
|
4245
|
4303
|
}
|
4246
|
4304
|
|
4247
|
4305
|
return cmOkRC;
|
|
@@ -4341,8 +4399,53 @@ cmRC_t cmRecdPlayBeginFade( cmRecdPlay* p, unsigned labelSymId, double fadeDbP
|
4341
|
4399
|
|
4342
|
4400
|
cmRC_t cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_t** oChs, unsigned chCnt, unsigned smpCnt )
|
4343
|
4401
|
{
|
|
4402
|
+ unsigned i;
|
|
4403
|
+
|
4344
|
4404
|
chCnt = cmMin(chCnt, p->chCnt);
|
4345
|
4405
|
|
|
4406
|
+ //-------------------------------------------------------------------
|
|
4407
|
+ // copy incoming audio into the look-head buffers
|
|
4408
|
+ //
|
|
4409
|
+
|
|
4410
|
+ // if the number of incoming samples is longer than the look-head buffer
|
|
4411
|
+ // then copy exactly maxLaSmpCnt samples from the end of the incoming sample
|
|
4412
|
+ // buffer to the look-ahead buffer.
|
|
4413
|
+ unsigned srcOffs = 0;
|
|
4414
|
+ unsigned srcSmpCnt = smpCnt;
|
|
4415
|
+ if( srcSmpCnt > p->maxLaSmpCnt )
|
|
4416
|
+ {
|
|
4417
|
+ // advance incoming sample buffer so that there are maxLaSmpCnt samples remaining
|
|
4418
|
+ srcOffs = smpCnt-p->maxLaSmpCnt;
|
|
4419
|
+ srcSmpCnt = p->maxLaSmpCnt; // decrease the total samples to copy
|
|
4420
|
+ }
|
|
4421
|
+
|
|
4422
|
+ // count of samples from cur posn to end of the LA buffer.
|
|
4423
|
+ unsigned n0 = cmMin(srcSmpCnt, p->maxLaSmpCnt - p->laSmpIdx );
|
|
4424
|
+
|
|
4425
|
+ // count of samples past the end of the LA buffer to be wrapped into begin of buffer
|
|
4426
|
+ unsigned n1 = srcSmpCnt>n0 ? srcSmpCnt-n0 : 0;
|
|
4427
|
+
|
|
4428
|
+ assert(n0+n1 == srcSmpCnt);
|
|
4429
|
+
|
|
4430
|
+ // copy first block to end of LA buffer
|
|
4431
|
+ for(i=0; i<chCnt; ++i)
|
|
4432
|
+ cmVOS_Copy(p->laChs[i]+p->laSmpIdx,n0,iChs[i] + srcOffs);
|
|
4433
|
+
|
|
4434
|
+ p->laSmpIdx += n0;
|
|
4435
|
+
|
|
4436
|
+ if( n1!=0)
|
|
4437
|
+ {
|
|
4438
|
+ // copy second block to begin of LA buffer
|
|
4439
|
+ for(i=0; i<chCnt; ++i)
|
|
4440
|
+ cmVOS_Copy(p->laChs[i],n1,iChs[i] + srcOffs + n0);
|
|
4441
|
+
|
|
4442
|
+ p->laSmpIdx = n1;
|
|
4443
|
+
|
|
4444
|
+ }
|
|
4445
|
+
|
|
4446
|
+ //-------------------------------------------------------------------
|
|
4447
|
+ // copy incoming audio into the active record buffers
|
|
4448
|
+ //
|
4346
|
4449
|
cmRecdPlayFrag* fp = p->rlist;
|
4347
|
4450
|
|
4348
|
4451
|
for(; fp!=NULL; fp=fp->rlink)
|
|
@@ -4357,6 +4460,9 @@ cmRC_t cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_
|
4357
|
4460
|
}
|
4358
|
4461
|
}
|
4359
|
4462
|
|
|
4463
|
+ //-------------------------------------------------------------------
|
|
4464
|
+ // copy outgoing audio out of the active play buffers
|
|
4465
|
+ //
|
4360
|
4466
|
fp = p->plist;
|
4361
|
4467
|
for(; fp!=NULL; fp=fp->rlink)
|
4362
|
4468
|
{
|