12e80a665fb4990b78e60bd9dcde855e7c3d1197
[processor-sdk/performance-audio-sr.git] / processor_audio_sdk_1_00_00_00 / pasdk / common / paf_decOpCircBuf.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>
41 #include "common.h"
42 #include "pafdec.h"
43 #include "pafsp.h"
44 #include "paf_decOpCircBuf.h"
46 #define MAX_NUM_AF_PCM      ( 4 )
47 #define MAX_NUM_AF_DDP      ( 2 )
49 #define CB_INIT_RD_LAG      ( 2 )
51 // Initialize circular buffer
52 Int cbInit(
53     Int8 sourceSelect,          // source select (PCM, DDP, etc.)
54     Int16 decOpFrameLen,        // decoder output frame length (PCM samples)
55     Int16 strFrameLen,          // stream frame length (PCM samples)
56     PAF_DecodeOpCircBuf *pCb,   // decoder output circular buffer
57     Int8 resetRwFlags           // whether to reset reader, writer, and empty flags
58 )
59 {
60     PAF_AudioFrame *pAfCb;
61     PAF_AudioData *pPcmBuf;
62     Int8 *pMetaBuf; //QIN
63     Int8 n;
64     Int8 i;
66     // set input frame length
67     pCb->decOpFrameLen = decOpFrameLen;
68     
69     // set output frame length
70     pCb->strFrameLen = strFrameLen;
71     
72     // initialize circular buffer maximum number of audio frames
73     if (sourceSelect == PAF_SOURCE_PCM)
74     {
75         pCb->maxNumAfCb = MAX_NUM_AF_PCM;
76         pCb->afWrtIdx = CB_INIT_RD_LAG;
77         pCb->afRdIdx = 0;
78         pCb->pcmRdIdx = 0; // 2*256 in behind
79         
80         // initialize audio frames
81         for (n=0; n<pCb->maxNumAfCb; n++)
82         {
83             pAfCb = &pCb->afCb[n];
84             pAfCb->sampleDecode = PAF_SOURCE_PCM;
85             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
86             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
87             pAfCb->sampleCount = decOpFrameLen;
88             pAfCb->channelConfigurationRequest.full = 0;
89             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
90             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
91             pAfCb->channelConfigurationStream.full = 0;
92             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
93             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
94         }
95     }
96     else if (sourceSelect == PAF_SOURCE_DDP)
97     {
98         pCb->maxNumAfCb = MAX_NUM_AF_DDP;
99         pCb->afRdIdx = 0;
100         pCb->pcmRdIdx = decOpFrameLen - CB_INIT_RD_LAG*strFrameLen;
101         pCb->afWrtIdx = 1;
102         
103         // initialize audio frames
104         for (n=0; n<pCb->maxNumAfCb; n++)
105         {
106             pAfCb = &pCb->afCb[n];
107             pAfCb->sampleDecode = PAF_SOURCE_DDP;
108             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
109             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
110             pAfCb->sampleCount = decOpFrameLen;
111             pAfCb->channelConfigurationRequest.full = 0;
112             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
113             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
114             pAfCb->channelConfigurationStream.full = 0;
115             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
116             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
117         }
118     }
119     else
120     {
121         return PAF_DECOP_CB_INIT_INV_SOURCE_SEL;
122     }
124     // initialize circular buffer current number of frames
125     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
126     
127     // initialize audio frame PCM buffers
128     pPcmBuf = pCb->pcmBuf;
129     pMetaBuf = pCb->metaBuf; //QIN
130     for (n=0; n<pCb->maxNumAfCb; n++)
131     {
132         pAfCb = &pCb->afCb[n];
133         pAfCb->data.nChannels = PAF_DECOP_CB_MAX_NUM_PCM_CH;
134         pAfCb->data.nSamples = decOpFrameLen;
135         for (i=0; i<PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
136         {
137             pAfCb->data.sample[i] = pPcmBuf;
138             memset(pAfCb->data.sample[i], decOpFrameLen, 0);
139             pPcmBuf += decOpFrameLen;
140             
141             pAfCb->data.samsiz[i] = 0;
142         }
143         //Initialize metadata buffers //QIN
144         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
145         {
146             pAfCb->pafPrivateMetadata[i].offset = 0; 
147             pAfCb->pafPrivateMetadata[i].size   = 0; 
148             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
149             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
150         }
151     }
152     
153     // reset read/write flags
154     if (resetRwFlags)
155     {
156         pCb->writerActiveFlag = 0;
157         pCb->readerActiveFlag = 0;
158         pCb->emptyFlag = 0;
159     }
160     // reset error counts
161     pCb->errUndCnt = 0;
162     pCb->errOvrCnt = 0;
163     
164     // (***) FL: revisit
165     // Write back circular buffer configuration
166     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
167     // Write back AF circular buffer
168     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
169     // Write back PCM data
170     for (n=0; n<pCb->maxNumAfCb; n++)
171     {
172         pAfCb = &pCb->afCb[n];
173         Cache_wb(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
174         Cache_wb(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
175         for (i=0; i<PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
176         {
177             Cache_wb(pAfCb->data.sample[i], decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
178         }
179         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)     // Write back metadata //QIN
180         {
181             Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
182         }
183     }
184     Cache_wait();
186     return PAF_DECOP_CB_SOK;
189 // Start writes to circular buffer
190 Int cbWriteStart(
191     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
194     PAF_AudioFrame *pAfCb;
195     Int8 n;
196     Int8 i;
198     // (***) FL: revisit
199     // Invalidate circular buffer configuration.
200     // NOTE: Probably only a subset of this information needs to be updated.
201     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
202     Cache_wait();
203     
204     // Invalidate AF circular buffer
205     Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
206     for (n=0; n<pCb->maxNumAfCb; n++)
207     {
208         pAfCb = &pCb->afCb[n];
209         Cache_inv(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
210         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
211         {
212              Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
213         }
214     }
215     Cache_wait();
216             
217     // update flags
218     pCb->writerActiveFlag = 1;
219     pCb->emptyFlag = 0;
220     
221     // (***) FL: revisit
222     // Write back circular buffer configuration
223     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
224     Cache_wait();
226     return PAF_DECOP_CB_SOK;
227 };
229 // Stop writes to circular buffer
230 Int cbWriteStop(
231     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
234     // Invalidate circular buffer configuration
235     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
236     Cache_wait();
237     
238     // update flags
239     pCb->writerActiveFlag = 0;
240     pCb->emptyFlag = 1;
242     // (***) FL: revisit
243     // Write back circular buffer configuration
244     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
245     Cache_wait();
246     
247     return PAF_DECOP_CB_SOK;
250 // Start reads from circular buffer
251 Int cbReadStart(
252     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
255     // Invalidate circular buffer configuration
256     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
257     Cache_wait();
258     
259     // update flags
260     pCb->readerActiveFlag = 1;
261     
262     // (***) FL: revisit
263     // Write back circular buffer configuration
264     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
265     Cache_wait();
267     return PAF_DECOP_CB_SOK;
270 // Stop reads from circular buffer
271 Int cbReadStop(
272     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
275     // Invalidate circular buffer configuration
276     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
277     Cache_wait();
278     
279     // update flags
280     pCb->readerActiveFlag = 0;
281     
282     // (***) FL: revisit
283     // Write back circular buffer configuration
284     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
285     Cache_wait();
287     return PAF_DECOP_CB_SOK;
290 // Read audio frame from circular buffer
291 Int cbReadAf(
292     PAF_DecodeOpCircBuf *pCb,   // decoder output circular buffer
293     PAF_AudioFrame *pAfRd       // audio frame into which to read
296     PAF_AudioFrame *pAfCb;
297     PAF_ChannelMask_HD streamMask;
298     Int8 i;
299     Int16 j;
301     // (***) FL: revisit
302     // Invalidate circular buffer configuration.
303     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
304     Cache_wait();
306     if ((pCb->writerActiveFlag == 1) && (pCb->emptyFlag == 1))
307     {
308         // This shouldn't occur:
309         //  writer is active AND draining circular buffer
310         Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, emptyFlag=%d", pCb->writerActiveFlag, pCb->emptyFlag);
311         SW_BREAKPOINT; // FL: debug
312         return PAF_DECOP_CB_READ_INVSTATE;
313     }
315     if ((pCb->writerActiveFlag == 0) && (pCb->emptyFlag == 0))
316     {
317         //
318         // No active writer, not draining circular buffer.
319         // Skip UNDerflow check, mute output.
320         //
321         pAfRd->sampleDecode = PAF_SOURCE_PCM;
322         PAF_PROCESS_ZERO(pAfRd->sampleProcess);
323         pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
324         pAfRd->sampleCount = pCb->strFrameLen;
325         pAfRd->channelConfigurationRequest.full = 0;
326         pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
327         pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
328         pAfRd->channelConfigurationStream.full = 0;
329         pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
330         pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
331         
332         // compute stream mask
333         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
334         // Clear PCM data
335         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
336         {
337             if ((streamMask >> i) & 0x1)
338             {
339                 memset(pAfRd->data.sample[i], pCb->strFrameLen, 0);
340             }
341             pAfRd->data.samsiz[i] = 0;
342         }
343         
344         return PAF_DECOP_CB_SOK;
345     }
346         
347     if ((pCb->writerActiveFlag == 1))
348     {
349         // check underflow
350         if (pCb->numAfCb <= 0)
351         {
352             pCb->errUndCnt++;
353             //SW_BREAKPOINT; // FL: debug
354             Log_info1("cbReadAf: ERROR: underflow, numAfCb=%d", pCb->numAfCb);
355             return PAF_DECOP_CB_READ_UNDERFLOW;
356         }
357     }
358     
359     if ((pCb->writerActiveFlag == 1) || (pCb->emptyFlag == 1))
360     {
361         //
362         // Writer active or draining remaining frames in circular buffer.
363         // Get next output audio frame.
364         //
365         
366         // get pointer to current audio frame in circular buffer
367         pAfCb = &pCb->afCb[pCb->afRdIdx];
369         // (***) FL: revisit
370         // Invalidate audio frame
371         Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
372         Cache_inv(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
373         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
374         {
375             Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
376             Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, PAF_MAX_PRIVATE_MD_SZ*sizeof(Int8), Cache_Type_ALLD, 0);
377         }
378         Cache_wait();
380         // compute stream mask
381         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
383         // Invalidate PCM data
384         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
385         {
386             if ((streamMask >> i) & 0x1)
387             {
388                 Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], pCb->strFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
389             }
390         }
391         Cache_wait();        
392         
393         // read audio frame information updated by decoder
394         pAfRd->sampleDecode = pAfCb->sampleDecode;
395         PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
396         pAfRd->sampleRate = pAfCb->sampleRate;
397         pAfRd->sampleCount = pCb->strFrameLen;
398         pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
399         pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
400         
401         // read metadata information updated by decoder //QIN
402         pAfRd->bsMetadata_type     = pAfCb->bsMetadata_type;        /* non zero if metadata is attached. */
403         pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
404         pAfRd->numPrivateMetadata  = pAfCb->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
405         pAfRd->bsMetadata_offset   = pAfCb->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
406         
407         // read PCM samples
408         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
409         {
410             if ((streamMask >> i) & 0x1)
411             {
412                 for (j = 0; j < pCb->strFrameLen; j++)
413                 {
414                     pAfRd->data.sample[i][j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
415                 }
417                 pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
418             }
419         }
420         // read metadata //QIN
421         for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++)
422         {
423             //Invalidate metadata data
424             Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
425             Cache_wait();        
426             if ((pAfCb->pafPrivateMetadata[i].offset >= pCb->pcmRdIdx) 
427                  &&(pAfCb->pafPrivateMetadata[i].offset < (pCb->pcmRdIdx + pCb->strFrameLen))
428                  &&(pAfCb->pafPrivateMetadata[i].size))
429             {
430                 //Invalidate metadata data
431                 Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
432                 Cache_wait();        
434                 // the offset is adjusted for segment [pCb->pcmRdIdx, (pCb->pcmRdIdx + pCb->pafFrameLen)]
435                 pAfRd->pafPrivateMetadata[i].offset = 0;//pAfCb->pafPrivateMetadata[i].offset - pCb->pcmRdIdx;
436                 pAfRd->pafPrivateMetadata[i].size   = pAfCb->pafPrivateMetadata[i].size;
437                 memcpy (pAfRd->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size);
438             }
439             else //reset un-used buf
440             {
441                 pAfRd->pafPrivateMetadata[i].offset = 0;
442                 pAfRd->pafPrivateMetadata[i].size   = 0;
443             }
444         }
445         pCb->pcmRdIdx += pCb->strFrameLen; // update PCM read index
446         if (pCb->pcmRdIdx == pCb->decOpFrameLen)
447         {
448             // update audio frame read index
449             pCb->afRdIdx++;
450             if (pCb->afRdIdx >= pCb->maxNumAfCb)
451             {
452                 pCb->afRdIdx = 0;
453             }
454             
455             // update PCM read index
456             pCb->pcmRdIdx = 0;
457             
458             // update number of audio frames in circular buffer
459             pCb->numAfCb--;
460         }
461     }
462     
463     if (pCb->emptyFlag == 1)
464     {
465         //
466         // Writer inactive, but remaining frames in circular buffer.
467         // Update empty flag.
468         //
469         if (pCb->numAfCb <= 0)
470         {
471             pCb->emptyFlag = 0;
472         }
473     }
474     
475     // (***) FL: revisit
476     // Write back circular buffer configuration.
477     // NOTE: Probably only a subset of this information needs to be updated.
478     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
479     Cache_wait();    
480         
481     return PAF_DECOP_CB_SOK;
484 // Write audio frame to circular buffer
485 Int cbWriteAf(
486     PAF_DecodeOpCircBuf *pCb,   // decoder output circular buffer
487     PAF_AudioFrame *pAfWrt      // audio frame from which to write
490     PAF_AudioFrame *pAfCb;
491     PAF_ChannelMask_HD streamMask;
492     Int8 i;
493     Int16 j;
495     // (***) FL: revisit
496     // Invalidate circular buffer configuration.
497     // NOTE: Probably only a subset of this information needs to be updated.
498     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
499     Cache_wait();
500     
501     if (pCb->readerActiveFlag == 1)
502     {
503         //
504         // Normal case, reader active.
505         // If reader not active, don't write to circular buffer or check OVRflow.
507 #if 0        
508         if (pCb->cbWriteAfInit == 0)
509         {
510             // Invalidate AF circular buffer
511             Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
512             for (n=0; n<pCb->maxNumAfCb; n++)
513             {
514                 pAfCb = &pCb->afCb[n];
515                 Cache_inv(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
516             }
517             Cache_wait();
519             pCb->cbWriteAfInit = 1;
520         }
521 #endif        
523         // check overflow
524         if (pCb->numAfCb >= pCb->maxNumAfCb)
525         {
526             pCb->errOvrCnt++;
527             //SW_BREAKPOINT;
528             Log_info1("cbWriteAf: ERROR: overflow, numAfCb=%d", pCb->numAfCb);
529             return PAF_DECOP_CB_WRITE_OVERFLOW;
530         }
531         //while (pCb->numAfCb >= pCb->maxNumAfCb); //Qin replace with while loop for debugging
532         // get pointer to current audio frame in circular buffer
533         pAfCb = &pCb->afCb[pCb->afWrtIdx];
534            
535         // write audio frame information updated by decoder
536         pAfCb->sampleDecode = pAfWrt->sampleDecode;
537         PAF_PROCESS_COPY(pAfCb->sampleProcess, pAfWrt->sampleProcess);
538         pAfCb->sampleRate = pAfWrt->sampleRate;
539         pAfCb->sampleCount = pAfWrt->sampleCount;
540         pAfCb->channelConfigurationRequest = pAfWrt->channelConfigurationRequest;
541         pAfCb->channelConfigurationStream = pAfWrt->channelConfigurationStream;
542         // write metadata information updated by decoder//QIN
543         pAfCb->bsMetadata_type     = pAfWrt->bsMetadata_type;        /* non zero if metadata is attached. */
544         pAfCb->pafBsMetadataUpdate = pAfWrt->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
545         pAfCb->numPrivateMetadata  = pAfWrt->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
546         pAfCb->bsMetadata_offset   = pAfWrt->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
547         // write PCM samples
548         streamMask = pAfWrt->fxns->channelMask(pAfWrt, pAfCb->channelConfigurationStream);
549         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
550         {
551             if ((streamMask >> i) & 0x1)
552             {
553                 for (j = 0; j < pCb->decOpFrameLen; j++)
554                 {
555                     pAfCb->data.sample[i][j] = pAfWrt->data.sample[i][j];
556                 }            
557                 
558                 pAfCb->data.samsiz[i] = pAfWrt->data.samsiz[i];
559             }
560         }
561         
562         //Write metadata to circular buffer //QIN
563         for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++)
564         {
565             if (pAfWrt->pafPrivateMetadata[i].size)
566             {
567                 pAfCb->pafPrivateMetadata[i].offset = pAfWrt->pafPrivateMetadata[i].offset; 
568                 pAfCb->pafPrivateMetadata[i].size   = pAfWrt->pafPrivateMetadata[i].size; 
569                 memcpy (pAfCb->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].size); 
570             }
571             else 
572             {
573                 pAfCb->pafPrivateMetadata[i].offset = 0; 
574                 pAfCb->pafPrivateMetadata[i].size   = 0; 
575             }
576         }
577         // update audio frame write index
578         pCb->afWrtIdx++;
579         if (pCb->afWrtIdx >= pCb->maxNumAfCb)
580         {
581             pCb->afWrtIdx = 0;
582         }
583         
584         // update number of audio frames in circular buffer
585         pCb->numAfCb++;
587         // (***) FL: revisit
588         // Write back circular buffer configuration
589         Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
590         // write back audio frame
591         Cache_wb(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
592         Cache_wb(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
593         // write back PCM data
594         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
595         {
596             if ((streamMask >> i) & 0x1)
597             {
598                 Cache_wb(pAfCb->data.sample[i], pCb->decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
599             }
600         }
601         // write back private metadata
602         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
603         {
604             Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
605             Cache_wb(pAfCb->pafPrivateMetadata[i].pMdBuf, PAF_MAX_PRIVATE_MD_SZ*sizeof(Int8), Cache_Type_ALLD, 0);
606         }
607         Cache_wait();
608     }  
609     
610     return PAF_DECOP_CB_SOK;
613 // Get next audio frame to write in circular buffer
614 Int cbGetNextWriteAf(
615     PAF_DecodeOpCircBuf *pCb, // decoder output circular buffer
616     PAF_AudioFrame **ppAfWrt  // audio frame next to be written
619     // get pointer to current audio frame in circular buffer
620     *ppAfWrt = &pCb->afCb[pCb->afWrtIdx];
621     
622     // update audio frame write index
623     pCb->afWrtIdx++;
624     if (pCb->afWrtIdx > pCb->maxNumAfCb)
625     {
626         pCb->afWrtIdx = 0;
627     }    
628     
629     return PAF_DECOP_CB_SOK;
632 // Output log of circular buffer control variables (debug)
633 Int cbLog(
634     PAF_DecodeOpCircBuf *pCb,
635     Int8 fullLog, 
636     char *locInfo
639     Log_info1("CB: %s", (IArg)locInfo);
640     Log_info3("CB: readerActiveFlag=%d, writerActiveFlag=%d, emptyFlag=%d", pCb->readerActiveFlag, pCb->writerActiveFlag, pCb->emptyFlag);
641     Log_info4("CB: afRdIdx=%d, pcmRdIdx=%d, afWrtIdx=%d, numAfCb=%d", pCb->afRdIdx, pCb->pcmRdIdx, 
642         pCb->afWrtIdx, 
643         pCb->numAfCb);
644     if (fullLog)
645     {
646         Log_info1("CB: maxNumAfCb=%d", pCb->maxNumAfCb);  
647         Log_info2("CB: decOpFrameLen=%d, strFrameLen=%d", pCb->decOpFrameLen, pCb->strFrameLen);
648         //Log_info1("cbWriteInit=%d", pCb->cbWriteAfInit);
649     }
650     
651     return 0;