Change root folder name, create pasdk subfolder
[processor-sdk/performance-audio-sr.git] / processor_audio_sdk_1_00_00_00 / pasdk / common / paf_decOpCircBuf.c
1 #include <string.h> // for memset()
2 #include <xdc/std.h>
3 #include <ti/sysbios/hal/Cache.h>
4 #include <xdc/runtime/Log.h>
6 #include "pafdec.h"
7 #include "pafsp.h"
8 #include "paf_decOpCircBuf.h"
10 #define MAX_NUM_AF_PCM      ( 4 )
11 #define MAX_NUM_AF_DDP      ( 2 )
13 #define CB_INIT_RD_LAG      ( 2 )
15 // Initialize circular buffer
16 Int cbInit(
17     Int8 sourceSelect,          // source select (PCM, DDP, etc.)
18     Int16 decOpFrameLen,        // decoder output frame length (PCM samples)
19     Int16 strFrameLen,          // stream frame length (PCM samples)
20     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
21 )
22 {
23     PAF_AudioFrame *pAfCb;
24     PAF_AudioData *pPcmBuf;
25     Int8 *pMetaBuf; //QIN
26     Int8 n;
27     Int8 i;
29     // set input frame length
30     pCb->decOpFrameLen = decOpFrameLen;
31     
32     // set output frame length
33     pCb->strFrameLen = strFrameLen;
34     
35     // initialize circular buffer maximum number of audio frames
36     if (sourceSelect == PAF_SOURCE_PCM)
37     {
38         pCb->maxNumAfCb = MAX_NUM_AF_PCM;
39         pCb->afWrtIdx = CB_INIT_RD_LAG;
40         pCb->afRdIdx = 0;
41         pCb->pcmRdIdx = 0; // 2*256 in behind
42         
43         // initialize audio frames
44         for (n=0; n<pCb->maxNumAfCb; n++)
45         {
46             pAfCb = &pCb->afCb[n];
47             pAfCb->sampleDecode = PAF_SOURCE_PCM;
48             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
49             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
50             pAfCb->sampleCount = decOpFrameLen;
51             pAfCb->channelConfigurationRequest.full = 0;
52             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
53             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
54             pAfCb->channelConfigurationStream.full = 0;
55             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
56             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
57         }
58     }
59     else if (sourceSelect == PAF_SOURCE_DDP)
60     {
61         pCb->maxNumAfCb = MAX_NUM_AF_DDP;
62         pCb->afRdIdx = 0;
63         pCb->afWrtIdx = 0;//1;//QIN - Reduce delay to prevent cb overflow. Need further investigation.
64         pCb->pcmRdIdx = 0;//decOpFrameLen - CB_INIT_RD_LAG*strFrameLen; //QIN - Reduce delay to prevent cb overflow. Need further investigation.
65         
66         // initialize audio frames
67         for (n=0; n<pCb->maxNumAfCb; n++)
68         {
69             pAfCb = &pCb->afCb[n];
70             pAfCb->sampleDecode = PAF_SOURCE_DDP;
71             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
72             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
73             pAfCb->sampleCount = decOpFrameLen;
74             pAfCb->channelConfigurationRequest.full = 0;
75             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
76             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
77             pAfCb->channelConfigurationStream.full = 0;
78             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
79             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
80         }
81     }
82     else
83     {
84         return PAF_DECOP_CB_INIT_INV_SOURCE_SEL;
85     }
87     // initialize circular buffer current number of frames
88     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
89     
90     // initialize audio frame PCM buffers
91     pPcmBuf = pCb->pcmBuf;
92     pMetaBuf = pCb->metaBuf; //QIN
93     for (n=0; n<pCb->maxNumAfCb; n++)
94     {
95         pAfCb = &pCb->afCb[n];
96         pAfCb->data.nChannels = PAF_DECOP_CB_MAX_NUM_PCM_CH;
97         pAfCb->data.nSamples = decOpFrameLen;
98         for (i=0; i<PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
99         {
100             pAfCb->data.sample[i] = pPcmBuf;
101             memset(pAfCb->data.sample[i], decOpFrameLen, 0);
102             pPcmBuf += decOpFrameLen;
103             
104             pAfCb->data.samsiz[i] = 0;
105         }
106         //Initialize metadata buffers //QIN
107         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
108         {
109             pAfCb->pafPrivateMetadata[i].offset = 0; 
110             pAfCb->pafPrivateMetadata[i].size   = 0; 
111             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
112             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
113         }
114     }
115     // update flags
116     pCb->writerActiveFlag = 0;
117     pCb->readerActiveFlag = 0;
118     pCb->emptyFlag = 0;
119     //pCb->cbWriteAfInit = 0;
120     
121     // (***) FL: revisit
122     // Write back circular buffer configuration
123     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
124     // Write back AF circular buffer
125     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
126     // Write back PCM data
127     for (n=0; n<pCb->maxNumAfCb; n++)
128     {
129         pAfCb = &pCb->afCb[n];
130         Cache_wb(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
131         Cache_wb(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
132         for (i=0; i<PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
133         {
134             Cache_wb(pAfCb->data.sample[i], decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
135         }
136         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)     // Write back metadata //QIN
137         {
138             Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
139         }
140     }
141     Cache_wait();
143     return PAF_DECOP_CB_SOK;
146 // Start writes to circular buffer
147 Int cbWriteStart(
148     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
151     PAF_AudioFrame *pAfCb;
152     Int8 n;
153     Int8 i;
155     // (***) FL: revisit
156     // Invalidate circular buffer configuration.
157     // NOTE: Probably only a subset of this information needs to be updated.
158     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
159     Cache_wait();
160     
161     // Invalidate AF circular buffer
162     Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
163     for (n=0; n<pCb->maxNumAfCb; n++)
164     {
165         pAfCb = &pCb->afCb[n];
166         Cache_inv(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
167         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
168         {
169              Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
170         }
171     }
172     Cache_wait();
173             
174     // update flags
175     pCb->writerActiveFlag = 1;
176     pCb->emptyFlag = 0;
177     
178     // (***) FL: revisit
179     // Write back circular buffer configuration
180     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
182     return PAF_DECOP_CB_SOK;
183 };
185 // Stop writes to circular buffer
186 Int cbWriteStop(
187     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
190     // update flags
191     pCb->writerActiveFlag = 0;
192     pCb->emptyFlag = 1;
194     // (***) FL: revisit
195     // Write back circular buffer configuration
196     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
197     
198     return PAF_DECOP_CB_SOK;
201 // Start reads from circular buffer
202 Int cbReadStart(
203     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
206     // update flags
207     pCb->readerActiveFlag = 1;
208     
209     // (***) FL: revisit
210     // Write back circular buffer configuration
211     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
213     return PAF_DECOP_CB_SOK;
216 // Stop reads from circular buffer
217 Int cbReadStop(
218     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
221     // update flags
222     pCb->readerActiveFlag = 0;
223     
224     // (***) FL: revisit
225     // Write back circular buffer configuration
226     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
228     return PAF_DECOP_CB_SOK;
230 // restore read/write flags of the circular buffer. - QIN
231 Int cbReadWriteRestore(
232     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
235     // Invalidate circular buffer configuration.
236     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
237     Cache_wait();
239     // update flags
240     pCb->readerActiveFlag = 1;
241     pCb->writerActiveFlag = 1;
242     
243     // (***) FL: revisit
244     // Write back circular buffer configuration
245     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
247     return PAF_DECOP_CB_SOK;
250 // Read audio frame from circular buffer
251 Int cbReadAf(
252     PAF_DecodeOpCircBuf *pCb,   // decoder output circular buffer
253     PAF_AudioFrame *pAfRd       // audio frame into which to read
256     PAF_AudioFrame *pAfCb;
257     PAF_ChannelMask_HD streamMask;
258     Int8 i;
259     Int16 j;
261     // (***) FL: revisit
262     // Invalidate circular buffer configuration.
263     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
264     Cache_wait();
266     if ((pCb->writerActiveFlag == 1) && (pCb->emptyFlag == 1))
267     {
268         // This shouldn't occur:
269         //  writer is active AND draining circular buffer
270         Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, emptyFlag=%d", pCb->writerActiveFlag, pCb->emptyFlag);
271         return PAF_DECOP_CB_READ_INVSTATE;
272     }
274     if ((pCb->writerActiveFlag == 0) && (pCb->emptyFlag == 0))
275     {
276         //
277         // No active writer, not draining circular buffer.
278         // Skip UNDerflow check, mute output.
279         //
280         
281         pAfRd->sampleDecode = PAF_SOURCE_PCM;
282         PAF_PROCESS_ZERO(pAfRd->sampleProcess);
283         pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
284         pAfRd->sampleCount = pCb->strFrameLen;
285         pAfRd->channelConfigurationRequest.full = 0;
286         pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
287         pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
288         pAfRd->channelConfigurationStream.full = 0;
289         pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
290         pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
291         
292         // compute stream mask
293         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
294         // Clear PCM data
295         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
296         {
297             if ((streamMask >> i) & 0x1)
298             {
299                 memset(pAfRd->data.sample[i], pCb->strFrameLen, 0);
300             }
301             pAfRd->data.samsiz[i] = 0;
302         }
303         
304         return PAF_DECOP_CB_SOK;
305     }
306         
307     if ((pCb->writerActiveFlag == 1))
308     {
309         // check underflow
310         if (pCb->numAfCb <= 0)
311         {
312             return PAF_DECOP_CB_READ_UNDERFLOW;
313         }
314     }
315     
316     if ((pCb->writerActiveFlag == 1) || (pCb->emptyFlag == 1))
317     {
318         //
319         // Writer active or draining remaining frames in circular buffer.
320         // Get next output audio frame.
321         //
322         
323         // get pointer to current audio frame in circular buffer
324         pAfCb = &pCb->afCb[pCb->afRdIdx];
326         // (***) FL: revisit
327         // Invalidate audio frame
328         Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
329         Cache_inv(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
330         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
331         {
332             Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
333             Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, PAF_MAX_PRIVATE_MD_SZ*sizeof(Int8), Cache_Type_ALLD, 0);
334         }
335         Cache_wait();
337         // compute stream mask
338         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
340         // Invalidate PCM data
341         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
342         {
343             if ((streamMask >> i) & 0x1)
344             {
345                 Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], pCb->strFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
346             }
347         }
348         Cache_wait();        
349         
350         // read audio frame information updated by decoder
351         pAfRd->sampleDecode = pAfCb->sampleDecode;
352         PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
353         pAfRd->sampleRate = pAfCb->sampleRate;
354         pAfRd->sampleCount = pCb->strFrameLen;
355         pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
356         pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
357         
358         // read metadata information updated by decoder //QIN
359         pAfRd->bsMetadata_type     = pAfCb->bsMetadata_type;        /* non zero if metadata is attached. */
360         pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
361         pAfRd->numPrivateMetadata  = pAfCb->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
362         pAfRd->bsMetadata_offset   = pAfCb->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
363         
364         // read PCM samples
365         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
366         {
367             if ((streamMask >> i) & 0x1)
368             {
369                 for (j = 0; j < pCb->strFrameLen; j++)
370                 {
371                     pAfRd->data.sample[i][j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
372                 }
374                 pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
375             }
376         }
377         // read metadata //QIN
378         for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++)
379         {
380             //Invalidate metadata data
381               Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
382             Cache_wait();        
383             if ((pAfCb->pafPrivateMetadata[i].offset >= pCb->pcmRdIdx) 
384                  &&(pAfCb->pafPrivateMetadata[i].offset < (pCb->pcmRdIdx + pCb->strFrameLen))
385                  &&(pAfCb->pafPrivateMetadata[i].size))
386             {
387                 //Invalidate metadata data
388                 Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
389                 Cache_wait();        
391                 // the offset is adjusted for segment [pCb->pcmRdIdx, (pCb->pcmRdIdx + pCb->pafFrameLen)]
392                 pAfRd->pafPrivateMetadata[i].offset = 0;//pAfCb->pafPrivateMetadata[i].offset - pCb->pcmRdIdx;
393                 pAfRd->pafPrivateMetadata[i].size   = pAfCb->pafPrivateMetadata[i].size;
394                 memcpy (pAfRd->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size);
395             }
396             else //reset un-used buf
397             {
398                 pAfRd->pafPrivateMetadata[i].offset = 0;
399                 pAfRd->pafPrivateMetadata[i].size   = 0;
400             }
401         }
402         pCb->pcmRdIdx += pCb->strFrameLen; // update PCM read index
403         if (pCb->pcmRdIdx == pCb->decOpFrameLen)
404         {
405             // update audio frame read index
406             pCb->afRdIdx++;
407             if (pCb->afRdIdx >= pCb->maxNumAfCb)
408             {
409                 pCb->afRdIdx = 0;
410             }
411             
412             // update PCM read index
413             pCb->pcmRdIdx = 0;
414             
415             // update number of audio frames in circular buffer
416             pCb->numAfCb--;
417         }
418     }
419     
420     if (pCb->emptyFlag == 1)
421     {
422         //
423         // Writer inactive, but remaining frames in circular buffer.
424         // Update empty flag.
425         //
426         if (pCb->numAfCb <= 0)
427         {
428             pCb->emptyFlag = 0;
429         }
430     }
431     
432     // (***) FL: revisit
433     // Write back circular buffer configuration.
434     // NOTE: Probably only a subset of this information needs to be updated.
435     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
436     Cache_wait();    
437         
438     return PAF_DECOP_CB_SOK;
441 // Write audio frame to circular buffer
442 Int cbWriteAf(
443     PAF_DecodeOpCircBuf *pCb,   // decoder output circular buffer
444     PAF_AudioFrame *pAfWrt      // audio frame from which to write
447     PAF_AudioFrame *pAfCb;
448     PAF_ChannelMask_HD streamMask;
449     Int8 i;
450     Int16 j;
452     // (***) FL: revisit
453     // Invalidate circular buffer configuration.
454     // NOTE: Probably only a subset of this information needs to be updated.
455     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
456     Cache_wait();
457     
458     if (pCb->readerActiveFlag == 1)
459     {
460         //
461         // Normal case, reader active.
462         // If reader not active, don't write to circular buffer or check OVRflow.
464 #if 0        
465         if (pCb->cbWriteAfInit == 0)
466         {
467             // Invalidate AF circular buffer
468             Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
469             for (n=0; n<pCb->maxNumAfCb; n++)
470             {
471                 pAfCb = &pCb->afCb[n];
472                 Cache_inv(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
473             }
474             Cache_wait();
476             pCb->cbWriteAfInit = 1;
477         }
478 #endif        
481         // check overflow
482         //if (pCb->numAfCb >= pCb->maxNumAfCb)
483         //{
484         //    return PAF_DECOP_CB_WRITE_OVERFLOW;
485         //}
486         while (pCb->numAfCb >= pCb->maxNumAfCb); //Qin replace with while loop for debugging
487         // get pointer to current audio frame in circular buffer
488         pAfCb = &pCb->afCb[pCb->afWrtIdx];
489            
490         // write audio frame information updated by decoder
491         pAfCb->sampleDecode = pAfWrt->sampleDecode;
492         PAF_PROCESS_COPY(pAfCb->sampleProcess, pAfWrt->sampleProcess);
493         pAfCb->sampleRate = pAfWrt->sampleRate;
494         pAfCb->sampleCount = pAfWrt->sampleCount;
495         pAfCb->channelConfigurationRequest = pAfWrt->channelConfigurationRequest;
496         pAfCb->channelConfigurationStream = pAfWrt->channelConfigurationStream;
497         // write metadata information updated by decoder//QIN
498         pAfCb->bsMetadata_type     = pAfWrt->bsMetadata_type;        /* non zero if metadata is attached. */
499         pAfCb->pafBsMetadataUpdate = pAfWrt->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
500         pAfCb->numPrivateMetadata  = pAfWrt->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
501         pAfCb->bsMetadata_offset   = pAfWrt->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
502         // write PCM samples
503         streamMask = pAfWrt->fxns->channelMask(pAfWrt, pAfCb->channelConfigurationStream);
504         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
505         {
506             if ((streamMask >> i) & 0x1)
507             {
508                 for (j = 0; j < pCb->decOpFrameLen; j++)
509                 {
510                     pAfCb->data.sample[i][j] = pAfWrt->data.sample[i][j];
511                 }            
512                 
513                 pAfCb->data.samsiz[i] = pAfWrt->data.samsiz[i];
514             }
515         }
516         
517         //Write metadata to circular buffer //QIN
518         for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++)
519         {
520             if (pAfWrt->pafPrivateMetadata[i].size )
521             {
522                 pAfCb->pafPrivateMetadata[i].offset = pAfWrt->pafPrivateMetadata[i].offset; 
523                 pAfCb->pafPrivateMetadata[i].size   = pAfWrt->pafPrivateMetadata[i].size; 
524                 memcpy (pAfCb->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].size); 
525             }
526             else 
527             {
528                 pAfCb->pafPrivateMetadata[i].offset = 0; 
529                 pAfCb->pafPrivateMetadata[i].size   = 0; 
530             }
531         }
532         // update audio frame write index
533         pCb->afWrtIdx++;
534         if (pCb->afWrtIdx >= pCb->maxNumAfCb)
535         {
536             pCb->afWrtIdx = 0;
537         }
538         
539         // update number of audio frames in circular buffer
540         pCb->numAfCb++;
542         // (***) FL: revisit
543         // Write back circular buffer configuration
544         Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
545         // write back audio frame
546         Cache_wb(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
547         Cache_wb(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
548         // write back PCM data
549         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
550         {
551             if ((streamMask >> i) & 0x1)
552             {
553                 Cache_wb(pAfCb->data.sample[i], pCb->decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
554             }
555         }
557         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
558         {
559             Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
560             Cache_wb(pAfCb->pafPrivateMetadata[i].pMdBuf, PAF_MAX_PRIVATE_MD_SZ*sizeof(Int8), Cache_Type_ALLD, 0);
561         }
562         Cache_wait();
563     }  
564     
565     return PAF_DECOP_CB_SOK;
568 // Get next audio frame to write in circular buffer
569 Int cbGetNextWriteAf(
570     PAF_DecodeOpCircBuf *pCb, // decoder output circular buffer
571     PAF_AudioFrame **ppAfWrt  // audio frame next to be written
574     // get pointer to current audio frame in circular buffer
575     *ppAfWrt = &pCb->afCb[pCb->afWrtIdx];
576     
577     // update audio frame write index
578     pCb->afWrtIdx++;
579     if (pCb->afWrtIdx > pCb->maxNumAfCb)
580     {
581         pCb->afWrtIdx = 0;
582     }    
583     
584     return PAF_DECOP_CB_SOK;
587 // Output log of circular buffer control variables (debug)
588 Int cbLog(
589     PAF_DecodeOpCircBuf *pCb,
590     Int8 fullLog
593     Log_info4("afRdIdx=%d, pcmRdIdx=%d, afWrtIdx=%d, numAfCb=%d", pCb->afRdIdx, pCb->pcmRdIdx, 
594         pCb->afWrtIdx, 
595         pCb->numAfCb);
596     if (fullLog)
597     {
598         Log_info1("maxNumAfCb=%d", pCb->maxNumAfCb);  
599         Log_info2("decOpFrameLen=%d, strFrameLen=%d", pCb->decOpFrameLen, pCb->strFrameLen);
600         //Log_info1("cbWriteInit=%d", pCb->cbWriteAfInit);
601     }
602     
603     return 0;