Add GateMP for Decoder Output Circular Buffer
[processor-sdk/performance-audio-sr.git] / processor_audio_sdk_1_00_00_00 / pasdk / test_dsp / framework / aspDecOpCircBuf_master.c
2 /*
3 Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
4 All rights reserved.
6 * Redistribution and use in source and binary forms, with or without 
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 #include <string.h> // for memset()
37 #include <xdc/std.h>
38 #include <ti/sysbios/hal/Cache.h>
39 #include <xdc/runtime/Log.h>
40 #include <ti/ipc/GateMP.h>
42 #include "common.h"
43 #include "paftyp.h"
44 #include "pafdec.h"
45 #include "aspDecOpCircBuf_master.h"
47 #define MAX_NUM_AF_PCM      ( 4 )
48 #define CB_INIT_RD_LAG_PCM  ( 2 ) // 0...3
50 #define MAX_NUM_AF_DDP      ( 2 )
51 #define CB_INIT_RD_LAG_DDP  ( 4 ) // 0...5
53 // Generate mute AF on circular buffer read
54 static Void cbReadAfMute(
55     PAF_AudioFrame *pAfRd,      // audio frame into which to read
56     Int16 strFrameLen           // stream frame length (output transaction size)
57 );
60 // Initialize circular buffer control
61 Int cbCtlInit(
62     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
63     PAF_AST_DecOpCircBuf *xDecOpCb      // decoder output circular buffer base pointer
64 )
65 {
66     GateMP_Params gateParams;
67     GateMP_Handle gateHandle;
68     
69     GateMP_Params_init(&gateParams);
70     gateParams.localProtect = GateMP_LocalProtect_THREAD;
71     gateParams.remoteProtect = GateMP_RemoteProtect_SYSTEM;
72     gateParams.name = ASP_DECODE_CB_GATE_NAME;
73     gateParams.regionId = ASP_DECODE_CB_GATE_REGION_ID;
74     gateHandle = GateMP_create(&gateParams);
75     if (gateHandle != NULL)
76     {
77         pCbCtl->gateHandle = gateHandle;
78     }
79     else
80     {
81         pCbCtl->gateHandle = NULL;
82         return ASP_DECOP_CB_CTL_INIT_INV_GATE;
83     }
84     
85     pCbCtl->xDecOpCb = xDecOpCb;
86     
87     return ASP_DECOP_CB_SOK;
88     
89 }
91 // Initialize circular buffer
92 Int cbInit(
93     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
94     Int8 cbIdx,                         // decoder output circular buffer index
95     Int8 sourceSelect,                  // source select (PCM, DDP, etc.)
96     Int16 decOpFrameLen,                // decoder output frame length (PCM samples)
97     Int16 strFrameLen,                  // stream frame length (PCM samples)
98     Int8 resetRwFlags                   // whether to reset reader, writer, and empty flags
99 )
101     IArg key;
102     GateMP_Handle gateHandle;
103     PAF_AST_DecOpCircBuf *pCb;
104     PAF_AudioFrame *pAfCb;
105     PAF_AudioData *pPcmBuf;
106     UInt8 *pMetaBuf; //QIN
107     Int8 n;
108     Int8 i;
110     // Get gate handle
111     gateHandle = pCbCtl->gateHandle;
112     // Enter gate
113     key = GateMP_enter(gateHandle);
115     // Get circular buffer base pointer
116     pCb = &pCbCtl->xDecOpCb[cbIdx];
117     
118     // set input frame length
119     pCb->decOpFrameLen = decOpFrameLen;
120     
121     // set output frame length
122     pCb->strFrameLen = strFrameLen;
123     
124     // initialize circular buffer maximum number of audio frames
125     if (sourceSelect == PAF_SOURCE_PCM)
126     {
127         pCb->maxNumAfCb = MAX_NUM_AF_PCM;
128         pCb->afWrtIdx = CB_INIT_RD_LAG_PCM;
129         pCb->afRdIdx = 0;
130         pCb->pcmRdIdx = 0; // 2*256 in behind
131         
132         // initialize audio frames
133         for (n=0; n<pCb->maxNumAfCb; n++)
134         {
135             pAfCb = &pCb->afCb[n];
136             pAfCb->sampleDecode = PAF_SOURCE_PCM;
137             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
138             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
139             pAfCb->sampleCount = decOpFrameLen;
140             pAfCb->channelConfigurationRequest.full = 0;
141             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
142             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
143             pAfCb->channelConfigurationStream.full = 0;
144             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
145             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
146         }
147     }
148     else if (sourceSelect == PAF_SOURCE_DDP)
149     {
150         pCb->maxNumAfCb = MAX_NUM_AF_DDP;
151         pCb->afWrtIdx = 1;
152         pCb->afRdIdx = 0;
153         pCb->pcmRdIdx = decOpFrameLen - CB_INIT_RD_LAG_DDP*strFrameLen; // 4*256 behind
154         
155         // initialize audio frames
156         for (n=0; n<pCb->maxNumAfCb; n++)
157         {
158             pAfCb = &pCb->afCb[n];
159             pAfCb->sampleDecode = PAF_SOURCE_DDP;
160             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
161             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
162             pAfCb->sampleCount = decOpFrameLen;
163             pAfCb->channelConfigurationRequest.full = 0;
164             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
165             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
166             pAfCb->channelConfigurationStream.full = 0;
167             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
168             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
169         }
170     }
171     else
172     {
173         // Leave the gate
174         GateMP_leave(gateHandle, key);
176         return ASP_DECOP_CB_INIT_INV_SOURCE_SEL;
177     }
179     // initialize circular buffer current number of frames
180     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
181     
182     // initialize audio frame PCM buffers
183     pPcmBuf = pCb->pcmBuf;
184     pMetaBuf = pCb->metaBuf; //QIN
185     for (n=0; n<pCb->maxNumAfCb; n++)
186     {
187         pAfCb = &pCb->afCb[n];
188         pAfCb->data.nChannels = ASP_DECOP_CB_MAX_NUM_PCM_CH;
189         pAfCb->data.nSamples = decOpFrameLen;
190         for (i=0; i<ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
191         {
192             pAfCb->data.sample[i] = pPcmBuf;
193             memset(pAfCb->data.sample[i], decOpFrameLen, 0);
194             pPcmBuf += decOpFrameLen;
195             
196             pAfCb->data.samsiz[i] = 0;
197         }
198         
199         // Initialize metadata buffers //QIN
200         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
201         {
202             pAfCb->pafPrivateMetadata[i].offset = 0; 
203             pAfCb->pafPrivateMetadata[i].size   = 0; 
204             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
205             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
206         }
207     }
208     
209     // reset read/write flags
210     if (resetRwFlags)
211     {
212         pCb->writerActiveFlag = 0;
213         pCb->readerActiveFlag = 0;
214         pCb->emptyFlag = 0;
215     }
216     // reset error counts
217     pCb->errUndCnt = 0;
218     pCb->errOvrCnt = 0;
219     
220     // (***) FL: revisit
221     // Write back circular buffer configuration
222     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
223     // Write back AF circular buffer
224     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
225     // Write back PCM data
226     for (n=0; n<pCb->maxNumAfCb; n++)
227     {
228         pAfCb = &pCb->afCb[n];
229         Cache_wb(pAfCb->data.samsiz, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
230         Cache_wb(pAfCb->data.sample, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
231         for (i=0; i<ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
232         {
233             Cache_wb(pAfCb->data.sample[i], decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
234         }
235         // FL: unnecessary since part of AF
236         //for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)     // Write back metadata //QIN
237         //{
238         //    Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
239         //}
240     }
241     Cache_wait();
243     // Leave the gate
244     GateMP_leave(gateHandle, key);
245     
246     return ASP_DECOP_CB_SOK;
249 // Start reads from circular buffer
250 Int cbReadStart(
251     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
252     Int8 cbIdx                          // decoder output circular buffer index
255     IArg key;
256     GateMP_Handle gateHandle;
257     PAF_AST_DecOpCircBuf *pCb;
259     // Get gate handle
260     gateHandle = pCbCtl->gateHandle;
261     // Enter gate
262     key = GateMP_enter(gateHandle);
264     // Get circular buffer base pointer
265     pCb = &pCbCtl->xDecOpCb[cbIdx];
266     
267     // Invalidate circular buffer configuration
268     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
269     Cache_wait();
270     
271     // update flags
272     pCb->readerActiveFlag = 1;
273     
274     // (***) FL: revisit
275     // Write back circular buffer configuration
276     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
277     Cache_wait();
279     // Leave the gate
280     GateMP_leave(gateHandle, key);
282     return ASP_DECOP_CB_SOK;
285 // Stop reads from circular buffer
286 Int cbReadStop(
287     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
288     Int8 cbIdx                          // decoder output circular buffer index
291     IArg key;
292     GateMP_Handle gateHandle;
293     PAF_AST_DecOpCircBuf *pCb;
295     // Get gate handle
296     gateHandle = pCbCtl->gateHandle;
297     // Enter gate
298     key = GateMP_enter(gateHandle);
300     // Get circular buffer base pointer
301     pCb = &pCbCtl->xDecOpCb[cbIdx];
303     // Invalidate circular buffer configuration
304     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
305     Cache_wait();
306     
307     // update flags
308     pCb->readerActiveFlag = 0;
309     
310     // (***) FL: revisit
311     // Write back circular buffer configuration
312     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
313     Cache_wait();
315     // Leave the gate
316     GateMP_leave(gateHandle, key);
318     return ASP_DECOP_CB_SOK;
321 // Read audio frame from circular buffer
322 Int cbReadAf(
323     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
324     Int8 cbIdx,                         // decoder output circular buffer index
325     PAF_AudioFrame *pAfRd               // audio frame into which to read
328     IArg key;
329     GateMP_Handle gateHandle;
330     PAF_AST_DecOpCircBuf *pCb;
331     PAF_AudioFrame *pAfCb;
332     PAF_ChannelMask_HD streamMask;
333     Int8 i;
334     Int16 j;
336     // Get gate handle
337     gateHandle = pCbCtl->gateHandle;
338     // Enter gate
339     key = GateMP_enter(gateHandle);
341     // Get circular buffer base pointer
342     pCb = &pCbCtl->xDecOpCb[cbIdx];
344     // (***) FL: revisit
345     // Invalidate circular buffer configuration.
346     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
347     Cache_wait();
349     if ((pCb->writerActiveFlag == 1) && (pCb->emptyFlag == 1))
350     {
351         // This shouldn't occur:
352         //  writer is active AND draining circular buffer
353         Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, emptyFlag=%d", pCb->writerActiveFlag, pCb->emptyFlag);
354         SW_BREAKPOINT; // FL: debug
355         
356         // Leave the gate
357         GateMP_leave(gateHandle, key);
358         
359         return ASP_DECOP_CB_READ_INVSTATE;
360     }
362     if ((pCb->writerActiveFlag == 0) && (pCb->emptyFlag == 0))
363     {
364         //
365         // No active writer, not draining circular buffer.
366         // Skip UNDerflow check, mute output.
367         //
368         cbReadAfMute(pAfRd, pCb->strFrameLen);
369         
370         // Leave the gate
371         GateMP_leave(gateHandle, key);
373         return ASP_DECOP_CB_SOK;
374     }
375         
376     if ((pCb->writerActiveFlag == 1))
377     {
378         // check underflow
379         if (pCb->numAfCb <= 0)
380         {
381             // 
382             // Increment underflow count.
383             // Mute output on underflow.
384             //
385             pCb->errUndCnt++;
386             cbReadAfMute(pAfRd, pCb->strFrameLen);
387             //SW_BREAKPOINT; // FL: debug
388             
389             // Write back circular buffer configuration.
390             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
391             Cache_wait();    
392             
393             // Leave the gate
394             GateMP_leave(gateHandle, key);
395             
396             return ASP_DECOP_CB_READ_UNDERFLOW;
397         }
398     }
399     
400     if ((pCb->writerActiveFlag == 1) || (pCb->emptyFlag == 1))
401     {
402         //
403         // Writer active or draining remaining frames in circular buffer.
404         // Get next output audio frame.
405         //
406         
407         // get pointer to current audio frame in circular buffer
408         pAfCb = &pCb->afCb[pCb->afRdIdx];
410         // (***) FL: revisit
411         // Invalidate audio frame
412         Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
413         Cache_inv(pAfCb->data.samsiz, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
414         for (i=0; i<pAfCb->numPrivateMetadata; i++) //QIN // FL: only invalidate numPrivateMetadata
415         {
416             //Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); // FL: unnecessary since part of AF
417             Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // FL: only update metadata package size
418         }
419         Cache_wait();
421         // compute stream mask
422         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
424         // Invalidate PCM data
425         for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
426         {
427             if ((streamMask >> i) & 0x1)
428             {
429                 Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], pCb->strFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
430             }
431         }
432         Cache_wait();        
433         
434         // read audio frame information updated by decoder
435         pAfRd->sampleDecode = pAfCb->sampleDecode;
436         PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
437         pAfRd->sampleRate = pAfCb->sampleRate;
438         pAfRd->sampleCount = pCb->strFrameLen;
439         pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
440         pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
441         
442         // read metadata information updated by decoder //QIN
443         pAfRd->bsMetadata_type     = pAfCb->bsMetadata_type;        /* non zero if metadata is attached. */
444         pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
445         pAfRd->numPrivateMetadata  = pAfCb->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
446         pAfRd->bsMetadata_offset   = pAfCb->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
447         
448         // read PCM samples
449         for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
450         {
451             if ((streamMask >> i) & 0x1)
452             {
453                 for (j = 0; j < pCb->strFrameLen; j++)
454                 {
455                     pAfRd->data.sample[i][j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
456                 }
458                 pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
459             }
460         }
461         // read metadata //QIN
462         for (i = 0; i < pAfCb->numPrivateMetadata; i++) // FL: only read numPrivateMetadata
463         {
464             // FL: this is done above
465             ////Invalidate metadata data
466             //Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
467             //Cache_wait();        
468             
469             if ((pAfCb->pafPrivateMetadata[i].offset >= pCb->pcmRdIdx) 
470                  &&(pAfCb->pafPrivateMetadata[i].offset < (pCb->pcmRdIdx + pCb->strFrameLen))
471                  &&(pAfCb->pafPrivateMetadata[i].size))
472             {
473                 // FL: this is done above
474                 ////Invalidate metadata data
475                 //Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
476                 //Cache_wait();        
477         
478                 // the offset is adjusted for segment [pCb->pcmRdIdx, (pCb->pcmRdIdx + pCb->pafFrameLen)]
479                 pAfRd->pafPrivateMetadata[i].offset = 0; //pAfCb->pafPrivateMetadata[i].offset - pCb->pcmRdIdx;
480                 pAfRd->pafPrivateMetadata[i].size   = pAfCb->pafPrivateMetadata[i].size;
481                 memcpy(pAfRd->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size);
482             }
483             else //reset un-used buf
484             {
485                 pAfRd->pafPrivateMetadata[i].offset = 0;
486                 pAfRd->pafPrivateMetadata[i].size   = 0;
487             }
488         }
489         
490         pCb->pcmRdIdx += pCb->strFrameLen; // update PCM read index
491         if (pCb->pcmRdIdx == pCb->decOpFrameLen)
492         {
493             // update audio frame read index
494             pCb->afRdIdx++;
495             if (pCb->afRdIdx >= pCb->maxNumAfCb)
496             {
497                 pCb->afRdIdx = 0;
498             }
499             
500             // update PCM read index
501             pCb->pcmRdIdx = 0;
502             
503             // update number of audio frames in circular buffer
504             pCb->numAfCb--;
505         }
506     }
507     
508     if (pCb->emptyFlag == 1)
509     {
510         //
511         // Writer inactive, but remaining frames in circular buffer.
512         // Update empty flag.
513         //
514         if (pCb->numAfCb <= 0)
515         {
516             pCb->emptyFlag = 0;
517         }
518     }
519     
520     // (***) FL: revisit
521     // Write back circular buffer configuration.
522     // NOTE: Probably only a subset of this information needs to be updated.
523     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
524     Cache_wait();    
525         
526     // Leave the gate
527     GateMP_leave(gateHandle, key);
529     return ASP_DECOP_CB_SOK;
532 // Generate mute AF on circular buffer read
533 static Void cbReadAfMute(
534     PAF_AudioFrame *pAfRd,      // audio frame into which to read
535     Int16 strFrameLen           // stream frame length (output transaction size)
538     PAF_ChannelMask_HD streamMask;
539     Int8 i;
540     
541     pAfRd->sampleDecode = PAF_SOURCE_PCM;
542     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
543     pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
544     pAfRd->sampleCount = strFrameLen;
545     pAfRd->channelConfigurationRequest.full = 0;
546     pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
547     pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
548     pAfRd->channelConfigurationStream.full = 0;
549     pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
550     pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
551     
552     // compute stream mask
553     streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
554     // Clear PCM data
555     for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++)
556     {
557         if ((streamMask >> i) & 0x1)
558         {
559             memset(pAfRd->data.sample[i], strFrameLen, 0);
560         }
561         pAfRd->data.samsiz[i] = 0;
562     }