diff --git a/pasdk/test_dsp/framework/aspDecOpCircBuf_master.c b/pasdk/test_dsp/framework/aspDecOpCircBuf_master.c
index 21264a6512e6b53c447214420dac690043773260..f2331ae9240009e7683777ffe1bd3f93bfeeae0c 100644 (file)
);
#endif
+#if 0
// Init last audio frame configuration info
static Void cbInitLastAfInfo(
PAF_AudioFrame *pAfRd // last audio frame stored in CB instance
);
+#endif
// Update last audio frame configuration info
static Void cbUpdateLastAfInfo(
);
// Generate mute AF on circular buffer read using the last AF configuration info
-static Void cbReadMuteWithLastAfInfo (
+static Void cbReadMuteWithLastAfInfo(
PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer control
PAF_AudioFrame *pAfRd // audio frame into which to read
);
PAF_AST_DecOpCircBuf *pCb
)
{
+#if 0 // FL: unused
PAF_AudioFrame *pAfCb;
PAF_AudioData *pPcmBuf;
UInt8 *pMetaBuf;
pCb->strFrameLen = DEF_STR_FRAME_LEN;
// initialize circular buffer maximum number of audio frames
- pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD;//ASP_DECOP_CB_MAX_NUM_AF_PCM;
+ pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD; //ASP_DECOP_CB_MAX_NUM_AF_PCM;
pCb->afWrtIdx = ASP_DECOP_CB_INIT_LAG_PCM;
pCb->afRdIdx = 0;
pCb->pcmRdIdx = 0;
// reset stats
pCb->readAfWriterInactiveCnt = 0;
+ pCb->readAfNdCnt = 0;
pCb->wrtAfReaderInactiveCnt = 0;
pCb->wrtAfZeroSampsCnt = 0;
pCb->errUndCnt = 0;
}
}
Cache_wait();
+#endif
+
+ // set source select
+ pCb->sourceSel = PAF_SOURCE_UNKNOWN;
+
+ #ifdef CB_RW_OP_CAP_PP // debug
+ // Get address in global variables
+ gCB_samples_op = pCb->cb_samples_op;
+ gCB_op_owner = pCb->cb_op_owner;
+ gCB_opCnt = &pCb->cb_opCnt;
+ gCB_afRdIdx = pCb->cb_afRdIdx;
+ gCB_afWrtIdx = pCb->cb_afWrtIdx;
+ gCB_numAfCb = pCb->cb_numAfCb;
+ #endif
+
+ // Write back circular buffer configuration
+ Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
+ Cache_wait();
return ASP_DECOP_CB_SOK;
}
-
#if 0 // FL: moved to ARM
// debug
//Int8 gCbInitSourceSelCnt=0;
// reset stats
pCb->readAfWriterInactiveCnt = 0;
+ pCb->readAfNdCnt = 0;
pCb->wrtAfReaderInactiveCnt = 0;
pCb->wrtAfZeroSampsCnt = 0;
pCb->errUndCnt = 0;
}
#endif
+// Initialize circular buffer for Stream reads
+Int cbInitStreamRead(
+ PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control
+ Int8 cbIdx // decoder output circular buffer index
+)
+{
+ IArg key;
+ GateMP_Handle gateHandle;
+ PAF_AST_DecOpCircBuf *pCb;
+
+ // Get gate handle
+ gateHandle = pCbCtl->gateHandle;
+ // Enter gate
+ key = GateMP_enter(gateHandle);
+
+ // Get circular buffer base pointer
+ pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
+
+ // Invalidate circular buffer configuration
+ Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
+ Cache_wait();
+
+ // Set output frame length
+ pCb->strFrameLen = pCb->cbStatus.strFrameLen;
+
+ // Write back circular buffer configuration
+ Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
+ Cache_wait();
+
+ // Leave the gate
+ GateMP_leave(gateHandle, key);
+
+ //return ret;
+ return ASP_DECOP_CB_SOK;
+}
+
// Start reads from circular buffer
Int cbReadStart(
PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control
)
{
IArg key;
- GateMP_Handle gateHandle;
- PAF_AST_DecOpCircBuf *pCb;
- PAF_AudioFrame *pAfCb;
- PAF_ChannelMask_HD streamMask;
+ GateMP_Handle gateHandle; // CB gate handle to arbitrate CB r/w access
+ PAF_AST_DecOpCircBuf *pCb; // pointer to CB
+ PAF_AudioFrame *pAfCb; // pointer to current CB AF
+ PAF_ChannelMask_HD streamMask; // CB AF stream mask
+ Int16 numSampsRd; // number of samples to read from current CB AF
+ Int16 totNumSampsRd; // total number of samples read from CB
+ Int16 pcmWrtIdx; // read audio frame PCM write index
+ Int8 prvMdWrtIdx; // read audio frame metadata write index
Int8 i;
Int16 j;
- Int8 numMetadata = 0;
// Get gate handle
gateHandle = pCbCtl->gateHandle;
//Log_info1("cbReadAf:afCb=0x%04x", (IArg)pCb->afCb); // debug
+ //
// Check (writerActiveFlag,drainFlag)=(1,1)
+ //
if ((pCb->writerActiveFlag == 1) && (pCb->drainFlag == 1))
{
//
// writer is active AND draining circular buffer
//
- //Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, drainFlag=%d", pCb->writerActiveFlag, pCb->drainFlag); // FL: debug
- SW_BREAKPOINT; // FL: debug
+ //Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, drainFlag=%d", pCb->writerActiveFlag, pCb->drainFlag); // debug
+ SW_BREAKPOINT; // debug
// Leave the gate
GateMP_leave(gateHandle, key);
return ASP_DECOP_CB_READ_INVSTATE;
}
+ //
// Check (writerActiveFlag,drainFlag)=(0,0)
+ //
//if (((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 0)) || (pCb->afLagIdx < pCb->afInitialLag))
if ((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 0))
{
pCb->readAfWriterInactiveCnt++;
+ // Mute output if write inactive and not draining CB
//cbReadAfMute(pAfRd, pCb->strFrameLen);
cbReadMuteWithLastAfInfo(pCb, pAfRd);
// Write back circular buffer configuration.
Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
- Cache_wait();
+ Cache_wait();
// Leave the gate
GateMP_leave(gateHandle, key);
return ASP_DECOP_CB_SOK;
}
+
+ if ((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 1))
+ {
+ //
+ // Writer inactive, but remaining frames in circular buffer.
+ // Update drain flag.
+ //
+
+ if (pCb->numAfCb <= 0)
+ {
+ pCb->drainFlag = 0;
+
+ // Mute output if CB drained
+ cbReadMuteWithLastAfInfo(pCb, pAfRd);
+
+ // Write back circular buffer configuration.
+ Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
+ Cache_wait();
+
+ // Leave the gate
+ GateMP_leave(gateHandle, key);
+
+ return ASP_DECOP_CB_SOK;
+ }
+ }
+ //
+ // Hold off read of PCM samples from CB until Nominal Delay satisfied
+ //
//if ((pCb->primedFlag == 0) || ((pCb->primedFlag==1) && (pCb->deltaSamps > 0))
if ((pCb->primedFlag == 0) || (pCb->deltaSamps > 0))
{
+ pCb->readAfNdCnt++;
+
if (pCb->primedFlag == 1)
{
pCb->deltaSamps = pCb->deltaSamps - pCb->strFrameLen;
return ASP_DECOP_CB_SOK;
}
- // (writerActiveFlag,drainFlag)= (0,0) and (1,1) checked above
- // (writerActiveFlag,drainFlag)=(1,0) and (0,1) are left
+ //
+ // (writerActiveFlag,drainFlag)= (0,0) and (1,1) states checked above
+ // (writerActiveFlag,drainFlag)=(1,0) and (0,1) states are left
// Checking (writerActiveFlag,drainFlag)=(1,0) state here
+ //
if (pCb->writerActiveFlag == 1)
{
// check underflow
if (pCb->numAfCb <= 0)
{
//
- // Increment underflow count.
- // Mute output on underflow.
+ // Increment underflow count
//
- pCb->errUndCnt++;
+ pCb->errAfUndCnt++;
+
+ // Mute output on underflow
//cbReadAfMute(pAfRd, pCb->strFrameLen);
cbReadMuteWithLastAfInfo(pCb, pAfRd);
- //SW_BREAKPOINT; // FL: debug
+ //SW_BREAKPOINT; // debug
+#if 0 // (***) FL: shows timing of CB underflow
// debug
{
static Uint8 toggleState = 0;
GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_107);
toggleState = ~(toggleState);
}
+#endif
#ifdef CB_RW_OP_CAP_PP // debug
if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
// Leave the gate
GateMP_leave(gateHandle, key);
- return ASP_DECOP_CB_READ_UNDERFLOW;
+ return ASP_DECOP_CB_AF_READ_UNDERFLOW;
}
}
+ //
// Checking (writerActiveFlag,drainFlag)=(1,0) state above and here
// Checking (writerActiveFlag,drainFlag)=(0,1) state here
+ //
if ((pCb->writerActiveFlag == 1) || (pCb->drainFlag == 1))
{
//
// Writer active or draining remaining frames in circular buffer.
- // Get next output audio frame.
+ // Read next audio frame.
+ //
+
+ //
+ // Read Audio Frame from CB Audio Frames.
+ // Read PCM & associated metadata from CB AFs until Read AF is filled.
+ //
+ // If multiple CB AFs are read in creating Read AF, CB AF parameters
+ // can *change* between read CB AFs. Since only one Read AF is produced
+ // per CB read, this is a "data collision", i.e. can't have more than
+ // one set of CB AF parameters in Read AF.
+ //
+ // Currently applying parameters from earliest read CB AF to Read Af.
+ // This can result in delay (or skip) w.r.t. application of additional
+ // CB AF parameters not used for creating Read AF. This is reasonable
+ // given there's no way to "interpolate" AF parameters, e.g. how to
+ // interpolation change in in bit-stream metadata type, or CC stream?
//
- // get pointer to current audio frame in circular buffer
+ // Get pointer to current CB Audio Frame
pAfCb = &pCb->afCb[pCb->afRdIdx];
- // Invalidate audio frame
+ // Cache invalidate CB AF
Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
- Cache_inv(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
- for (i=0; i<pAfCb->numPrivateMetadata; i++) // only invalidate numPrivateMetadata
- {
- Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // only update metadata package size
- }
- Cache_wait();
-
- // compute stream mask
- streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
-
- // Invalidate channel pointers
- Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
Cache_wait();
-
- // Invalidate PCM data
- for (i = 0; i < pCb->maxAFChanNum; i++)
- {
- if ((streamMask >> i) & 0x1)
- {
- Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], pCb->strFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
- }
- }
- Cache_wait();
- // read audio frame information updated by decoder
+ // Read CB AF information updated by decoder
pAfRd->sampleDecode = pAfCb->sampleDecode;
PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
pAfRd->sampleRate = pAfCb->sampleRate;
- pAfRd->sampleCount = pCb->strFrameLen;
pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
-
- // read metadata information updated by decoder
- pAfRd->bsMetadata_type = pAfCb->bsMetadata_type; /* non zero if metadata is attached. */
+ // Read CB AF bit-stream metadata information updated by decoder
+ pAfRd->bsMetadata_type = pAfCb->bsMetadata_type; /* non zero if private metadata is attached. */
pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate; /* indicates whether bit-stream metadata update */
- pAfRd->numPrivateMetadata = pAfCb->numPrivateMetadata; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
pAfRd->bsMetadata_offset = pAfCb->bsMetadata_offset; /* offset into audio frame for change in bsMetadata_type field */
- #ifdef CB_RW_OP_CAP_PP // debug
- if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
- {
- if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
- {
- // log sample count
- pCb->cb_samples_op[pCb->cb_opCnt] = pAfRd->sampleCount;
- pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
- // log idxs
- pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
- pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
- pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
- pCb->cb_opCnt++;
- }
- }
- #endif
-
- //// update Last Cb info as per actual stream
- //pCb->lastAf.sampleCount = pCb->strFrameLen; // FL: last AF sample count isn't used (see cbReadMuteWithLastAfInfo())
- //pCb->lastAf.sampleRate = pAfCb->sampleRate; // FL: moved inside cbUpdateLastAfInfo() along with other params from memcpy below
- // Update last audio frame configuration info
- cbUpdateLastAfInfo(pCb, pAfRd);
+ // Compute stream mask for current CB AF.
+ // Mask indicates which channels are present in AF.
+ // Mask needed for cache invalidate and read of PCM samples in AF.
+ streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
- // read PCM samples
+ // Cache invalidate CB AF samsiz (volume scaling exponent) array
+ Cache_inv(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
+ Cache_wait();
+
+ // Read CB AF samsiz array
for (i = 0; i < pCb->maxAFChanNum; i++)
{
if ((streamMask >> i) & 0x1)
{
- for (j = 0; j < pCb->strFrameLen; j++)
- {
- pAfRd->data.sample[i][j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
- }
-
pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
}
}
+
+ // FL: brute force clear of Read AF PCM data
+ // Reset Read AF PCM data
+ //for (i = 0; i < pCb->maxAFChanNum; i++)
+ //{
+ // if ((streamMask >> i) & 0x1)
+ // {
+ // memset(pAfRd->data.sample[i], 0, pCb->strFrameLen);
+ // }
+ //}
+ // FL: This brute force approach shouldn't be necessary if
+ // decoders properly set, and downstream components
+ // properly use, number of private metadata in frame
+ // Reset Read AF metadata
for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++)
{
pAfRd->pafPrivateMetadata[i].offset = 0;
pAfRd->pafPrivateMetadata[i].size = 0;
}
- // read metadata
- for (i = 0; i < pAfCb->numPrivateMetadata; i++) // only read numPrivateMetadata
+ totNumSampsRd = 0; // init total number of samples read from CB
+ pcmWrtIdx = 0; // init Read AF PCM write index
+ prvMdWrtIdx = 0; // init Read AF metadata write index
+ while ((totNumSampsRd < pCb->strFrameLen) && (pCb->numAfCb > 0))
{
- if ((pAfCb->pafPrivateMetadata[i].offset >= pCb->pcmRdIdx)
- &&(pAfCb->pafPrivateMetadata[i].offset < (pCb->pcmRdIdx + pCb->strFrameLen))
- &&(pAfCb->pafPrivateMetadata[i].size))
+ // Compute how many PCM samples can be read from CB AF
+ // Number of samples left in current CB AF: pAfCb->sampleCount - pCb->pcmRdIdx
+ // Number of samples left to write to Read AF: pCb->strFrameLen - totNumSampsRd
+ numSampsRd = (pAfCb->sampleCount - pCb->pcmRdIdx) < (pCb->strFrameLen - totNumSampsRd) ?
+ (pAfCb->sampleCount - pCb->pcmRdIdx) : (pCb->strFrameLen - totNumSampsRd);
+
+ // Cache invalidate CB AF PCM sample channel pointers
+ Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
+ Cache_wait();
+
+ // Cache invalidate CB AF PCM samples
+ for (i = 0; i < pCb->maxAFChanNum; i++)
{
- // the offset is adjusted for segment [pCb->pcmRdIdx, (pCb->pcmRdIdx + pCb->pafFrameLen)]
- pAfRd->pafPrivateMetadata[numMetadata].offset = pAfCb->pafPrivateMetadata[i].offset - pCb->pcmRdIdx;
- pAfRd->pafPrivateMetadata[numMetadata].size = pAfCb->pafPrivateMetadata[i].size;
- memcpy(pAfRd->pafPrivateMetadata[numMetadata].pMdBuf, pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size);
- numMetadata++; //number of metadata associated with current 256 segment of audio samples
+ if ((streamMask >> i) & 0x1)
+ {
+ Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], numSampsRd*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
+ }
}
- else //reset un-used buf
+ Cache_wait();
+
+ // Read PCM samples from CB AF
+ for (i = 0; i < pCb->maxAFChanNum; i++)
{
- pAfRd->pafPrivateMetadata[i].offset = 0;
- pAfRd->pafPrivateMetadata[i].size = 0;
+ if ((streamMask >> i) & 0x1)
+ {
+ for (j = 0; j < numSampsRd; j++)
+ {
+ pAfRd->data.sample[i][pcmWrtIdx+j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
+ }
+ }
}
+ // Cache invalidate CB AF unused metadata
+ for (i = pCb->prvMdRdIdx; i < pAfCb->numPrivateMetadata; i++)
+ {
+ Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // only update metadata package size
+ }
+ Cache_wait();
+
+ // Read CB AF metadata
+ while (((pCb->prvMdRdIdx < pAfCb->numPrivateMetadata) &&
+ (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset >= pCb->pcmRdIdx) &&
+ (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset < (pCb->pcmRdIdx + numSampsRd)) &&
+ (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size)) &&
+ (prvMdWrtIdx < PAF_MAX_NUM_PRIVATE_MD))
+ {
+ // Write Read AF metadata offset.
+ // Compute relative offset of PCM samples being read from CB AF.
+ // Compute absolute offset of PCM samples written to Read AF by
+ // adding relative offset to Read AF PCM write index.
+ pAfRd->pafPrivateMetadata[prvMdWrtIdx].offset =
+ (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset - pCb->pcmRdIdx) + // offset relative to samples being read from CB AF
+ pcmWrtIdx; // absolute offset into samples being written to read AF
+ // Write Read AF metadata size
+ pAfRd->pafPrivateMetadata[prvMdWrtIdx].size = pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size;
+ // Write Read AF metadata payload
+ memcpy(pAfRd->pafPrivateMetadata[prvMdWrtIdx].pMdBuf, pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].pMdBuf, pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size);
+
+ pCb->prvMdRdIdx++; // update CB metadata read index
+ prvMdWrtIdx++; // update CB metadata write index
+ }
+
+ // Update CB control
+ pCb->pcmRdIdx += numSampsRd; // update PCM read index
+ if (pCb->pcmRdIdx >= pAfCb->sampleCount)
+ {
+ // Finished reading PCM samples from current CB AF.
+ // Move to next AF in CB.
+
+ // Update audio frame read index.
+ // Wrap index if required.
+ pCb->afRdIdx++;
+ if (pCb->afRdIdx >= pCb->maxNumAfCb)
+ {
+ pCb->afRdIdx = 0;
+ }
+
+ // Reset PCM read index
+ pCb->pcmRdIdx = 0;
+ // Reset metadata read index
+ pCb->prvMdRdIdx = 0;
+
+ // Update number of audio frames in circular buffer
+ pCb->numAfCb--;
+ }
+
+ // Update PCM write index
+ pcmWrtIdx += numSampsRd;
+
+ // Update total number of samples read
+ totNumSampsRd += numSampsRd;
+
+ if (totNumSampsRd < pCb->strFrameLen)
+ {
+ //
+ // Need to read another AF from CB to obtain all PCM/metadata for Read AF
+ //
+
+ // Get pointer to current CB Audio Frame
+ pAfCb = &pCb->afCb[pCb->afRdIdx];
+
+ // Cache invalidate CB AF
+ Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
+ Cache_wait();
+ }
}
- pAfRd->numPrivateMetadata = numMetadata; //number of metadata associated with current 256 segment of audio samples
+
+ pAfRd->sampleCount = totNumSampsRd; // write Read AF sample count
+ pAfRd->numPrivateMetadata = prvMdWrtIdx; // write Read AF number of metadata
- pCb->pcmRdIdx += pCb->strFrameLen; // update PCM read index
- if (pCb->pcmRdIdx >= pAfCb->sampleCount)
+ pCb->numPcmSampsPerCh -= totNumSampsRd; // update PCM samples per channel
+
+ if (totNumSampsRd < pCb->strFrameLen)
{
- // update audio frame read index
- pCb->afRdIdx++;
- if (pCb->afRdIdx >= pCb->maxNumAfCb)
+ // Clear remaining Read AF PCM samples
+ for (i = 0; i < pCb->maxAFChanNum; i++)
{
- pCb->afRdIdx = 0;
+ if ((streamMask >> i) & 0x1)
+ {
+ memset(&pAfRd->data.sample[i][pcmWrtIdx], 0, (pCb->strFrameLen-totNumSampsRd));
+ }
}
- // update PCM read index
- pCb->pcmRdIdx = 0;
+ if (pCb->writerActiveFlag == 1)
+ {
+ //
+ // UNDerflow,
+ // read stopped due to insufficient PCM samples in CB to fill Read AF
+ //
- // update number of audio frames in circular buffer
- pCb->numAfCb--;
+ //
+ // Increment underflow count
+ //
+ pCb->errPcmUndCnt++;
+
+ // Mute output on underflow
+ cbReadMuteWithLastAfInfo(pCb, pAfRd);
+
+#if 0 // (***) FL: shows timing of CB underflow
+ // debug
+ {
+ static Uint8 toggleState = 0;
+ if (toggleState == 0)
+ GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_107);
+ else
+ GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_107);
+ toggleState = ~(toggleState);
+ }
+#endif
+
+ #ifdef CB_RW_OP_CAP_PP // debug
+ if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
+ {
+ if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
+ {
+ // log sample count
+ pCb->cb_samples_op[pCb->cb_opCnt] = 0; // due to underflow
+ pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
+ // log idxs
+ pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
+ pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
+ pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
+ pCb->cb_opCnt++;
+ }
+ }
+ #endif
+
+ // Write back circular buffer configuration.
+ Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
+ Cache_wait();
+
+ // Leave the gate
+ GateMP_leave(gateHandle, key);
+
+ return ASP_DECOP_CB_PCM_READ_UNDERFLOW;
+ }
}
- // FL: this update of Last AF is handled above
- //memcpy (&pCb->lastAf, pAfRd, sizeof(PAF_AudioFrame));
+ // Read AF complete, update Last CB AF Info
+ cbUpdateLastAfInfo(pCb, pAfRd);
+#if 0 // (***) FL: shows timing of successful CB read
{
static Uint8 toggleState = 0;
if (toggleState == 0)
GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);
toggleState = ~(toggleState);
}
+#endif
+
+#ifdef CB_RW_OP_CAP_PP // debug
+ if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
+ {
+ if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
+ {
+ // log sample count
+ pCb->cb_samples_op[pCb->cb_opCnt] = pAfRd->sampleCount;
+ pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R;
+ // log idxs
+ pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
+ pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
+ pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
+ pCb->cb_opCnt++;
+ }
+ }
+#endif
}
+#if 0
if (pCb->drainFlag == 1)
{
//
pCb->drainFlag = 0;
}
}
+#endif
// Write back circular buffer configuration.
// NOTE: Probably only a subset of this information needs to be updated.
}
#endif
+#if 0 // FL: unused
// Init last audio frame configuration info
static Void cbInitLastAfInfo(
PAF_AudioFrame *pAfRd // last audio frame stored in CB instance
pAfRd->numPrivateMetadata = 0; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
pAfRd->bsMetadata_offset = 0; /* offset into audio frame for change in bsMetadata_type field */
}
+#endif
// Update last audio frame configuration info
static Void cbUpdateLastAfInfo(
}
// Generate mute AF on circular buffer read using the last AF configuration info
-static Void cbReadMuteWithLastAfInfo (
+static Void cbReadMuteWithLastAfInfo(
PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer control
PAF_AudioFrame *pAfRd // audio frame into which to read
)