/* Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/ All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include // for memset() #include #include #include #include #include #include "common.h" #include "paftyp.h" #include "pafdec.h" #include "aspDecOpCircBuf_master.h" #define DEF_SOURCE_SEL ( PAF_SOURCE_PCM ) // default source select #define DEF_DEC_OP_FRAME_LEN ( 256 ) // default decoder output frame length #define DEF_STR_FRAME_LEN ( 256 ) // default stream frame length #define MAX_NUM_AF_PCM ( 4 ) #define CB_INIT_RD_LAG_PCM ( 2 ) // 0...3 #define MAX_NUM_AF_DDP ( 2 ) #define CB_INIT_RD_LAG_DDP ( 4 ) // 0...5 // Generate mute AF on circular buffer read static Void cbReadAfMute( PAF_AudioFrame *pAfRd, // audio frame into which to read Int16 strFrameLen // stream frame length (output transaction size) ); // Initialize circular buffer control Int cbCtlInit( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control PAF_AST_DecOpCircBuf **pXDecOpCb // address of decoder output circular buffer base pointer ) { GateMP_Params gateParams; GateMP_Handle gateHandle; GateMP_Params_init(&gateParams); gateParams.localProtect = GateMP_LocalProtect_THREAD; gateParams.remoteProtect = GateMP_RemoteProtect_SYSTEM; gateParams.name = ASP_DECODE_CB_GATE_NAME; gateParams.regionId = ASP_DECODE_CB_GATE_REGION_ID; gateHandle = GateMP_create(&gateParams); if (gateHandle != NULL) { pCbCtl->gateHandle = gateHandle; } else { pCbCtl->gateHandle = NULL; return ASP_DECOP_CB_CTL_INIT_INV_GATE; } pCbCtl->pXDecOpCb = pXDecOpCb; return ASP_DECOP_CB_SOK; } // Initialize circular buffer Int cbInit( PAF_AST_DecOpCircBuf *pCb ) { PAF_AudioFrame *pAfCb; PAF_AudioData *pPcmBuf; UInt8 *pMetaBuf; Int8 n; Int8 i; // set source select pCb->sourceSel = DEF_SOURCE_SEL; // set input frame length pCb->decOpFrameLen = DEF_DEC_OP_FRAME_LEN; // set output frame length pCb->strFrameLen = DEF_STR_FRAME_LEN; // initialize circular buffer maximum number of audio frames pCb->maxNumAfCb = MAX_NUM_AF_PCM; pCb->afWrtIdx = CB_INIT_RD_LAG_PCM; pCb->afRdIdx = 0; pCb->pcmRdIdx = 0; // 2*256 in behind // initialize audio frames for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->sampleDecode = PAF_SOURCE_PCM; PAF_PROCESS_ZERO(pAfCb->sampleProcess); pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ; pAfCb->sampleCount = DEF_DEC_OP_FRAME_LEN; pAfCb->channelConfigurationRequest.full = 0; pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE; pAfCb->channelConfigurationStream.full = 0; pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE; } // initialize circular buffer current number of frames pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx; // initialize audio frame PCM buffers pPcmBuf = pCb->pcmBuf; pMetaBuf = pCb->metaBuf; //QIN for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->data.nChannels = ASP_DECOP_CB_MAX_NUM_PCM_CH; pAfCb->data.nSamples = DEF_DEC_OP_FRAME_LEN; for (i=0; idata.sample[i] = pPcmBuf; memset(pAfCb->data.sample[i], DEF_DEC_OP_FRAME_LEN, 0); pPcmBuf += DEF_DEC_OP_FRAME_LEN; pAfCb->data.samsiz[i] = 0; } // Initialize metadata buffers //QIN for (i=0; ipafPrivateMetadata[i].offset = 0; pAfCb->pafPrivateMetadata[i].size = 0; pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf; pMetaBuf += PAF_MAX_PRIVATE_MD_SZ; } } // reset read/write flags pCb->writerActiveFlag = 0; pCb->readerActiveFlag = 0; pCb->emptyFlag = 0; // reset error counts pCb->errUndCnt = 0; pCb->errOvrCnt = 0; // (***) FL: revisit // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); // Write back AF circular buffer Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0); // Write back PCM data for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; Cache_wb(pAfCb->data.samsiz, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0); Cache_wb(pAfCb->data.sample, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); for (i=0; idata.sample[i], DEF_DEC_OP_FRAME_LEN*sizeof(PAF_AudioData), Cache_Type_ALLD, 0); } // FL: unnecessary since part of AF //for (i=0; ipafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); //} } Cache_wait(); return ASP_DECOP_CB_SOK; } // Initialize circular buffer based on selected source Int cbInitSourceSel( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 cbIdx, // decoder output circular buffer index Int8 sourceSelect, // source select (PCM, DDP, etc.) Int16 decOpFrameLen, // decoder output frame length (PCM samples) Int16 strFrameLen, // stream frame length (PCM samples) Int8 resetRwFlags // whether to reset reader, writer, and empty flags ) { IArg key; GateMP_Handle gateHandle; PAF_AST_DecOpCircBuf *pCb; PAF_AudioFrame *pAfCb; PAF_AudioData *pPcmBuf; UInt8 *pMetaBuf; //QIN Int8 n; Int8 i; // 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(); //Log_info1("cbInitSourceSel:afCb=0x%04x", (IArg)pCb->afCb); // FL: debug // set source select pCb->sourceSel = sourceSelect; // set input frame length pCb->decOpFrameLen = decOpFrameLen; // set output frame length pCb->strFrameLen = strFrameLen; // initialize circular buffer maximum number of audio frames if (sourceSelect == PAF_SOURCE_PCM) { pCb->maxNumAfCb = MAX_NUM_AF_PCM; pCb->afWrtIdx = CB_INIT_RD_LAG_PCM; pCb->afRdIdx = 0; pCb->pcmRdIdx = 0; // 2*256 in behind // initialize audio frames for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->sampleDecode = PAF_SOURCE_PCM; PAF_PROCESS_ZERO(pAfCb->sampleProcess); pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ; pAfCb->sampleCount = decOpFrameLen; pAfCb->channelConfigurationRequest.full = 0; pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE; pAfCb->channelConfigurationStream.full = 0; pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE; } } else if (sourceSelect == PAF_SOURCE_DDP) { pCb->maxNumAfCb = MAX_NUM_AF_DDP; pCb->afWrtIdx = 1; pCb->afRdIdx = 0; pCb->pcmRdIdx = decOpFrameLen - CB_INIT_RD_LAG_DDP*strFrameLen; // 4*256 behind // initialize audio frames for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->sampleDecode = PAF_SOURCE_DDP; PAF_PROCESS_ZERO(pAfCb->sampleProcess); pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ; pAfCb->sampleCount = decOpFrameLen; pAfCb->channelConfigurationRequest.full = 0; pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE; pAfCb->channelConfigurationStream.full = 0; pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE; } } else { // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_INIT_INV_SOURCE_SEL; } // initialize circular buffer current number of frames pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx; // initialize audio frame PCM buffers pPcmBuf = pCb->pcmBuf; pMetaBuf = pCb->metaBuf; //QIN for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->data.nChannels = ASP_DECOP_CB_MAX_NUM_PCM_CH; pAfCb->data.nSamples = decOpFrameLen; for (i=0; idata.sample[i] = pPcmBuf; memset(pAfCb->data.sample[i], decOpFrameLen, 0); pPcmBuf += decOpFrameLen; pAfCb->data.samsiz[i] = 0; } // Initialize metadata buffers //QIN for (i=0; ipafPrivateMetadata[i].offset = 0; pAfCb->pafPrivateMetadata[i].size = 0; pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf; pMetaBuf += PAF_MAX_PRIVATE_MD_SZ; } } // reset read/write flags if (resetRwFlags) { pCb->writerActiveFlag = 0; pCb->readerActiveFlag = 0; pCb->emptyFlag = 0; } // reset error counts pCb->errUndCnt = 0; pCb->errOvrCnt = 0; // (***) FL: revisit // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); // Write back AF circular buffer Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0); // Write back PCM data for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; Cache_wb(pAfCb->data.samsiz, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0); Cache_wb(pAfCb->data.sample, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); for (i=0; idata.sample[i], decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0); } // FL: unnecessary since part of AF //for (i=0; ipafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); //} } Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; } // Start reads from circular buffer Int cbReadStart( 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(); //Log_info1("cbReadStart:afCb=0x%04x", (IArg)pCb->afCb); // FL: debug // update flags pCb->readerActiveFlag = 1; // (***) FL: revisit // 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; } // Stop reads from circular buffer Int cbReadStop( 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(); //Log_info1("cbReadStop:afCb=0x%04x", (IArg)pCb->afCb); // FL: debug // update flags pCb->readerActiveFlag = 0; // (***) FL: revisit // 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; } // Read audio frame from circular buffer Int cbReadAf( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 cbIdx, // decoder output circular buffer index PAF_AudioFrame *pAfRd // audio frame into which to read ) { IArg key; GateMP_Handle gateHandle; PAF_AST_DecOpCircBuf *pCb; PAF_AudioFrame *pAfCb; PAF_ChannelMask_HD streamMask; Int8 i; Int16 j; // Get gate handle gateHandle = pCbCtl->gateHandle; // Enter gate key = GateMP_enter(gateHandle); // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]); // (***) FL: revisit // Invalidate circular buffer configuration. Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); //Log_info1("cbReadAf:afCb=0x%04x", (IArg)pCb->afCb); // FL: debug if ((pCb->writerActiveFlag == 1) && (pCb->emptyFlag == 1)) { // This shouldn't occur: // writer is active AND draining circular buffer //Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, emptyFlag=%d", pCb->writerActiveFlag, pCb->emptyFlag); // FL: debug SW_BREAKPOINT; // FL: debug // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_READ_INVSTATE; } if ((pCb->writerActiveFlag == 0) && (pCb->emptyFlag == 0)) { // // No active writer, not draining circular buffer. // Skip UNDerflow check, mute output. // cbReadAfMute(pAfRd, pCb->strFrameLen); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; } // (writerActiveFlag,emptyFlag)=(1,0) and (0,1) are left // Here we are checking (1,0) state here if ((pCb->writerActiveFlag == 1)) { // check underflow if (pCb->numAfCb <= 0) { // // Increment underflow count. // Mute output on underflow. // pCb->errUndCnt++; cbReadAfMute(pAfRd, pCb->strFrameLen); //SW_BREAKPOINT; // FL: debug // 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_READ_UNDERFLOW; } } if ((pCb->writerActiveFlag == 1) || (pCb->emptyFlag == 1)) { // // Writer active or draining remaining frames in circular buffer. // Get next output audio frame. // // get pointer to current audio frame in circular buffer pAfCb = &pCb->afCb[pCb->afRdIdx]; // (***) FL: revisit // Invalidate audio frame Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0); Cache_inv(pAfCb->data.samsiz, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0); for (i=0; inumPrivateMetadata; i++) //QIN // FL: only invalidate numPrivateMetadata { //Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); // FL: unnecessary since part of AF Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // FL: only update metadata package size } Cache_wait(); // compute stream mask streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream); // Invalidate PCM data for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; 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 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 //QIN pAfRd->bsMetadata_type = pAfCb->bsMetadata_type; /* non zero if 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 */ // read PCM samples for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; 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]; } } // read metadata //QIN for (i = 0; i < pAfCb->numPrivateMetadata; i++) // FL: only read numPrivateMetadata { // FL: this is done above ////Invalidate metadata data //Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); //Cache_wait(); if ((pAfCb->pafPrivateMetadata[i].offset >= pCb->pcmRdIdx) &&(pAfCb->pafPrivateMetadata[i].offset < (pCb->pcmRdIdx + pCb->strFrameLen)) &&(pAfCb->pafPrivateMetadata[i].size)) { // FL: this is done above ////Invalidate metadata data //Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); //Cache_wait(); // the offset is adjusted for segment [pCb->pcmRdIdx, (pCb->pcmRdIdx + pCb->pafFrameLen)] pAfRd->pafPrivateMetadata[i].offset = 0; //pAfCb->pafPrivateMetadata[i].offset - pCb->pcmRdIdx; pAfRd->pafPrivateMetadata[i].size = pAfCb->pafPrivateMetadata[i].size; memcpy(pAfRd->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size); } else //reset un-used buf { pAfRd->pafPrivateMetadata[i].offset = 0; pAfRd->pafPrivateMetadata[i].size = 0; } } pCb->pcmRdIdx += pCb->strFrameLen; // update PCM read index if (pCb->pcmRdIdx == pCb->decOpFrameLen) { // update audio frame read index pCb->afRdIdx++; if (pCb->afRdIdx >= pCb->maxNumAfCb) { pCb->afRdIdx = 0; } // update PCM read index pCb->pcmRdIdx = 0; // update number of audio frames in circular buffer pCb->numAfCb--; } } if (pCb->emptyFlag == 1) { // // Writer inactive, but remaining frames in circular buffer. // Update empty flag. // if (pCb->numAfCb <= 0) { pCb->emptyFlag = 0; } } // (***) FL: revisit // Write back circular buffer configuration. // NOTE: Probably only a subset of this information needs to be updated. 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; } // Generate mute AF on circular buffer read static Void cbReadAfMute( PAF_AudioFrame *pAfRd, // audio frame into which to read Int16 strFrameLen // stream frame length (output transaction size) ) { PAF_ChannelMask_HD streamMask; Int8 i; pAfRd->sampleDecode = PAF_SOURCE_PCM; PAF_PROCESS_ZERO(pAfRd->sampleProcess); pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ; pAfRd->sampleCount = strFrameLen; pAfRd->channelConfigurationRequest.full = 0; pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4; pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE; pAfRd->channelConfigurationStream.full = 0; pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4; pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE; // compute stream mask streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream); // Clear PCM data for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++) { if ((streamMask >> i) & 0x1) { memset(pAfRd->data.sample[i], strFrameLen, 0); } pAfRd->data.samsiz[i] = 0; } }