|
@@ -4,6 +4,7 @@
|
4
|
4
|
#include "cmErr.h"
|
5
|
5
|
#include "cmMem.h"
|
6
|
6
|
#include "cmMallocDebug.h"
|
|
7
|
+#include "cmTime.h"
|
7
|
8
|
#include "cmAudioPort.h"
|
8
|
9
|
#include "cmApBuf.h"
|
9
|
10
|
#include "cmThread.h"
|
|
@@ -64,15 +65,17 @@ typedef struct
|
64
|
65
|
|
65
|
66
|
typedef struct
|
66
|
67
|
{
|
67
|
|
- unsigned chCnt;
|
68
|
|
- cmApCh* chArray;
|
|
68
|
+ unsigned chCnt;
|
|
69
|
+ cmApCh* chArray;
|
69
|
70
|
|
70
|
|
- unsigned n; // length of b[] (multiple of dspFrameCnt) bufCnt*framesPerCycle
|
71
|
|
- double srate; // device sample rate;
|
|
71
|
+ unsigned n; // length of b[] (multiple of dspFrameCnt) bufCnt*framesPerCycle
|
|
72
|
+ double srate; // device sample rate;
|
72
|
73
|
|
73
|
|
- unsigned faultCnt;
|
74
|
|
- unsigned framesPerCycle;
|
75
|
|
- unsigned dspFrameCnt;
|
|
74
|
+ unsigned faultCnt;
|
|
75
|
+ unsigned framesPerCycle;
|
|
76
|
+ unsigned dspFrameCnt;
|
|
77
|
+ cmTimeSpec_t timeStamp; // base (starting) time stamp for this device
|
|
78
|
+ unsigned ioFrameCnt; // count of frames input or output for this device
|
76
|
79
|
|
77
|
80
|
} cmApIO;
|
78
|
81
|
|
|
@@ -169,13 +172,16 @@ void _cmApIoInitialize( cmApIO* ioPtr, double srate, unsigned framesPerCycle, un
|
169
|
172
|
|
170
|
173
|
n += (n % dspFrameCnt); // force buffer size to be a multiple of dspFrameCnt
|
171
|
174
|
|
172
|
|
- ioPtr->chArray = chCnt==0 ? NULL : cmMemAllocZ( cmApCh, chCnt );
|
173
|
|
- ioPtr->chCnt = chCnt;
|
174
|
|
- ioPtr->n = n;
|
175
|
|
- ioPtr->faultCnt = 0;
|
176
|
|
- ioPtr->framesPerCycle = framesPerCycle;
|
177
|
|
- ioPtr->srate = srate;
|
178
|
|
- ioPtr->dspFrameCnt = dspFrameCnt;
|
|
175
|
+ ioPtr->chArray = chCnt==0 ? NULL : cmMemAllocZ( cmApCh, chCnt );
|
|
176
|
+ ioPtr->chCnt = chCnt;
|
|
177
|
+ ioPtr->n = n;
|
|
178
|
+ ioPtr->faultCnt = 0;
|
|
179
|
+ ioPtr->framesPerCycle = framesPerCycle;
|
|
180
|
+ ioPtr->srate = srate;
|
|
181
|
+ ioPtr->dspFrameCnt = dspFrameCnt;
|
|
182
|
+ ioPtr->timeStamp.tv_sec = 0;
|
|
183
|
+ ioPtr->timeStamp.tv_nsec = 0;
|
|
184
|
+ ioPtr->ioFrameCnt = 0;
|
179
|
185
|
|
180
|
186
|
for(i=0; i<chCnt; ++i )
|
181
|
187
|
_cmApChInitialize( ioPtr->chArray + i, n, meterBufN );
|
|
@@ -277,6 +283,24 @@ cmAbRC_t cmApBufPrimeOutput( unsigned devIdx, unsigned audioCycleCnt )
|
277
|
283
|
return kOkAbRC;
|
278
|
284
|
}
|
279
|
285
|
|
|
286
|
+void cmApBufOnPortEnable( unsigned devIdx, bool enableFl )
|
|
287
|
+{
|
|
288
|
+ if( devIdx == cmInvalidIdx || enableFl==false)
|
|
289
|
+ return;
|
|
290
|
+
|
|
291
|
+ cmApIO* iop = _cmApBuf.devArray[devIdx].ioArray + kOutApIdx;
|
|
292
|
+ iop->timeStamp.tv_sec = 0;
|
|
293
|
+ iop->timeStamp.tv_nsec = 0;
|
|
294
|
+ iop->ioFrameCnt = 0;
|
|
295
|
+
|
|
296
|
+ iop = _cmApBuf.devArray[devIdx].ioArray + kInApIdx;
|
|
297
|
+ iop->timeStamp.tv_sec = 0;
|
|
298
|
+ iop->timeStamp.tv_nsec = 0;
|
|
299
|
+ iop->ioFrameCnt = 0;
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+}
|
|
303
|
+
|
280
|
304
|
cmAbRC_t cmApBufUpdate(
|
281
|
305
|
cmApAudioPacket_t* inPktArray,
|
282
|
306
|
unsigned inPktCnt,
|
|
@@ -293,6 +317,10 @@ cmAbRC_t cmApBufUpdate(
|
293
|
317
|
cmApAudioPacket_t* pp = inPktArray + i;
|
294
|
318
|
cmApIO* ip = _cmApBuf.devArray[pp->devIdx].ioArray + kInApIdx; // dest io recd
|
295
|
319
|
|
|
320
|
+ // if the base time stamp has not yet been set - then set it
|
|
321
|
+ if( ip->timeStamp.tv_sec==0 && ip->timeStamp.tv_nsec==0 )
|
|
322
|
+ ip->timeStamp = pp->timeStamp;
|
|
323
|
+
|
296
|
324
|
// for each source packet channel and enabled dest channel
|
297
|
325
|
for(j=0; j<pp->chCnt; ++j)
|
298
|
326
|
{
|
|
@@ -369,6 +397,9 @@ cmAbRC_t cmApBufUpdate(
|
369
|
397
|
cmApAudioPacket_t* pp = outPktArray + i;
|
370
|
398
|
cmApIO* op = _cmApBuf.devArray[pp->devIdx].ioArray + kOutApIdx; // dest io recd
|
371
|
399
|
|
|
400
|
+ // if the base timestamp has not yet been set then set it.
|
|
401
|
+ if( op->timeStamp.tv_sec==0 && op->timeStamp.tv_nsec==0 )
|
|
402
|
+ op->timeStamp = pp->timeStamp;
|
372
|
403
|
|
373
|
404
|
// for each dest packet channel and enabled source channel
|
374
|
405
|
for(j=0; j<pp->chCnt; ++j)
|
|
@@ -637,7 +668,26 @@ void cmApBufGet( unsigned devIdx, unsigned flags, cmApSample_t* bufArray[], unsi
|
637
|
668
|
|
638
|
669
|
}
|
639
|
670
|
|
640
|
|
-void cmApBufGetIO( unsigned iDevIdx, cmApSample_t* iBufArray[], unsigned iBufChCnt, unsigned oDevIdx, cmApSample_t* oBufArray[], unsigned oBufChCnt )
|
|
671
|
+void _cmApBufCalcTimeStamp( double srate, const cmTimeSpec_t* baseTimeStamp, unsigned frmCnt, cmTimeSpec_t* retTimeStamp )
|
|
672
|
+{
|
|
673
|
+ if( retTimeStamp==NULL )
|
|
674
|
+ return;
|
|
675
|
+
|
|
676
|
+ double secs = frmCnt / srate;
|
|
677
|
+ unsigned int_secs = floor(secs);
|
|
678
|
+ double frac_secs = secs - int_secs;
|
|
679
|
+
|
|
680
|
+ retTimeStamp->tv_nsec = floor(baseTimeStamp->tv_nsec + frac_secs * 1000000000);
|
|
681
|
+ retTimeStamp->tv_sec = baseTimeStamp->tv_sec + int_secs;
|
|
682
|
+
|
|
683
|
+ if( retTimeStamp->tv_nsec > 1000000000 )
|
|
684
|
+ {
|
|
685
|
+ retTimeStamp->tv_nsec -= 1000000000;
|
|
686
|
+ retTimeStamp->tv_sec += 1;
|
|
687
|
+ }
|
|
688
|
+}
|
|
689
|
+
|
|
690
|
+void cmApBufGetIO( unsigned iDevIdx, cmApSample_t* iBufArray[], unsigned iBufChCnt, cmTimeSpec_t* iTimeStampPtr, unsigned oDevIdx, cmApSample_t* oBufArray[], unsigned oBufChCnt, cmTimeSpec_t* oTimeStampPtr )
|
641
|
691
|
{
|
642
|
692
|
cmApBufGet( iDevIdx, kInApFl, iBufArray, iBufChCnt );
|
643
|
693
|
cmApBufGet( oDevIdx, kOutApFl,oBufArray, oBufChCnt );
|
|
@@ -651,6 +701,9 @@ void cmApBufGetIO( unsigned iDevIdx, cmApSample_t* iBufArray[], unsigned iBufC
|
651
|
701
|
unsigned minChCnt = cmMin(iBufChCnt,oBufChCnt);
|
652
|
702
|
unsigned frmCnt = cmMin(ip->dspFrameCnt,op->dspFrameCnt);
|
653
|
703
|
unsigned byteCnt = frmCnt * sizeof(cmApSample_t);
|
|
704
|
+
|
|
705
|
+ _cmApBufCalcTimeStamp(ip->srate, &ip->timeStamp, ip->ioFrameCnt, iTimeStampPtr );
|
|
706
|
+ _cmApBufCalcTimeStamp(op->srate, &op->timeStamp, op->ioFrameCnt, oTimeStampPtr );
|
654
|
707
|
|
655
|
708
|
for(i=0; i<minChCnt; ++i)
|
656
|
709
|
{
|
|
@@ -681,6 +734,8 @@ void cmApBufGetIO( unsigned iDevIdx, cmApSample_t* iBufArray[], unsigned iBufC
|
681
|
734
|
const cmApIO* op = _cmApBuf.devArray[oDevIdx].ioArray + kOutApIdx;
|
682
|
735
|
unsigned byteCnt = op->dspFrameCnt * sizeof(cmApSample_t);
|
683
|
736
|
|
|
737
|
+ _cmApBufCalcTimeStamp(op->srate, &op->timeStamp, op->ioFrameCnt, oTimeStampPtr );
|
|
738
|
+
|
684
|
739
|
for(; i<oBufChCnt; ++i)
|
685
|
740
|
if( oBufArray[i] != NULL )
|
686
|
741
|
memset( oBufArray[i], 0, byteCnt );
|
|
@@ -703,12 +758,13 @@ void cmApBufAdvance( unsigned devIdx, unsigned flags )
|
703
|
758
|
{
|
704
|
759
|
cmApCh* cp = ioPtr->chArray + i;
|
705
|
760
|
cp->oi = (cp->oi + ioPtr->dspFrameCnt) % ioPtr->n;
|
706
|
|
- //cp->fn -= ioPtr->dspFrameCnt;
|
707
|
761
|
cmThUIntDecr(&cp->fn,ioPtr->dspFrameCnt);
|
708
|
762
|
}
|
709
|
763
|
|
710
|
|
- //ioPtr->oi = (ioPtr->oi + ioPtr->dspFrameCnt) % ioPtr->n;
|
711
|
|
- //ioPtr->fn -= ioPtr->dspFrameCnt;
|
|
764
|
+ // count the number of samples input from this device
|
|
765
|
+ if( ioPtr->timeStamp.tv_sec!=0 && ioPtr->timeStamp.tv_nsec!=0 )
|
|
766
|
+ cmThUIntIncr(&ioPtr->ioFrameCnt,ioPtr->dspFrameCnt);
|
|
767
|
+
|
712
|
768
|
}
|
713
|
769
|
|
714
|
770
|
if( flags & kOutApFl )
|
|
@@ -718,13 +774,12 @@ void cmApBufAdvance( unsigned devIdx, unsigned flags )
|
718
|
774
|
{
|
719
|
775
|
cmApCh* cp = ioPtr->chArray + i;
|
720
|
776
|
cp->ii = (cp->ii + ioPtr->dspFrameCnt) % ioPtr->n;
|
721
|
|
- //cp->fn += ioPtr->dspFrameCnt;
|
722
|
777
|
cmThUIntIncr(&cp->fn,ioPtr->dspFrameCnt);
|
723
|
778
|
}
|
724
|
779
|
|
725
|
|
-
|
726
|
|
- //ioPtr->ii = (ioPtr->ii + ioPtr->dspFrameCnt) % ioPtr->n;
|
727
|
|
- //ioPtr->fn += ioPtr->dspFrameCnt;
|
|
780
|
+ // count the number of samples output from this device
|
|
781
|
+ if( ioPtr->timeStamp.tv_sec!=0 && ioPtr->timeStamp.tv_nsec!=0 )
|
|
782
|
+ cmThUIntIncr(&ioPtr->ioFrameCnt,ioPtr->dspFrameCnt);
|
728
|
783
|
}
|
729
|
784
|
}
|
730
|
785
|
|