]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - pasdk/test_arm/framework/aspDecOpCircBuf_slave.c
PASDK-218:Add default THD CB nominal delay setting
[processor-sdk/performance-audio-sr.git] / pasdk / test_arm / framework / aspDecOpCircBuf_slave.c
2 /*
3 Copyright (c) 2017, 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 <xdc/runtime/Log.h>
39 #include <ti/sysbios/hal/Cache.h>
40 #include <ti/uia/events/UIAEvt.h>
42 #include "common.h"
43 #include "paftyp.h"
44 //#include "pafdec.h"
45 //#include "pafsp.h"
46 #include "aspDecOpCircBuf_slave.h"
48 #include "evmc66x_gpio_dbg.h" // Debug
50 #if 0 // FL: moved to common
51 // Initialize circular buffer control
52 Int cbCtlInit(
53     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
54     PAF_AST_DecOpCircBuf **pXDecOpCb    // address of decoder output circular buffer base pointer
55 )
56 {
57     GateMP_Handle gateHandle;
58     Int status;
59     
60     do {
61         status = GateMP_open(ASP_DECODE_CB_GATE_NAME, &gateHandle);
62     } while (status == GateMP_E_NOTFOUND);
63     if (status == GateMP_S_SUCCESS)
64     {
65         pCbCtl->gateHandle = gateHandle;
66     }
67     else
68     {
69         pCbCtl->gateHandle = NULL;
70         return ASP_DECOP_CB_CTL_INIT_INV_GATE;
71     }
72     
73     pCbCtl->numCb = numCb;          // init number of circular buffers
74     pCbCtl->pXDecOpCb = pXDecOpCb;  // init base address of circular buffers
75     
76     return ASP_DECOP_CB_SOK;
77 }
78 #endif
80 // debug
81 //Int8 gCbInitSourceSelCnt=0;
82 //Int8 gCbInitSourceSelThdCnt=0;
84 // Initialize circular buffer based on selected source
85 Int cbInitSourceSel(
86     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
87     Int8 cbIdx,                         // decoder output circular buffer index
88     Int8 sourceSelect,                  // source select (PCM, DDP, etc.)
89     Int16 decOpFrameLen,                // decoder output frame length (PCM samples)
90     Int16 strFrameLen,                  // stream frame length (PCM samples)
91     Int8 resetRwFlags,                  // whether to reset reader, writer, and drain flags
92     PAF_AudioFrame *pDecInfo1Af         // pointer to Dec Info1 audio frame
93 )
94 {
95     IArg key;
96     GateMP_Handle gateHandle;
97     PAF_AST_DecOpCircBuf *pCb;
98     PAF_AudioFrame *pAfCb;
99     PAF_AudioData *pPcmBuf;
100     UInt8 *pMetaBuf;
101     Int8 n;
102     Int8 i;
104     //gCbInitSourceSelCnt++; // debug
105     
106     // Get gate handle
107     gateHandle = pCbCtl->gateHandle;
108     // Enter gate
109     key = GateMP_enter(gateHandle);
111     // Get circular buffer base pointer
112     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
113     
114     // Invalidate circular buffer configuration
115     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
116     Cache_wait();
118     //Log_info1("cbInitSourceSel:afCb=0x%04x", (IArg)pCb->afCb); // debug
120     // Set source select
121     pCb->sourceSel = sourceSelect;
123     // Set input frame length
124     pCb->decOpFrameLen = decOpFrameLen;
125     
126     // Set output frame length
127     pCb->strFrameLen = strFrameLen;
129     //pCb->afInitialLag = 0;  // default No lag
130     //pCb->afLagIdx = 0;
131     // Initialize CB primed flag
132     pCb->primedFlag = 0;
133     // Initialize delta samples
134     pCb->deltaSamps = 0;
135     
136     // Initialize circular buffer:
137     //  - maximum number of AFs
138     //  - target nominal delay
139     //  - AF write, read indices
140     //  - maximum AF channel and sample counts
141     if (sourceSelect == PAF_SOURCE_PCM)
142     {
143         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_PCM;
144         
145         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_PCM;
146         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kPCM;
147         
148         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_PCM;
149         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_PCM;
150         pCb->pcmRdIdx = 0;
151         
152         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH;
153         pCb->maxAFSampCount = DEF_DEC_OP_FRAME_LEN;        
154     }
155     else if ((sourceSelect == PAF_SOURCE_DDP) || (sourceSelect == PAF_SOURCE_AC3))
156     {
157         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_DDP;
158         
159         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_DDP;
160         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_DDP;
161         
162         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_DDP;
163         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_DDP;
164         pCb->pcmRdIdx = 0;
165         
166         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_DDP;
167         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kDDP;
168     }
169     else if (sourceSelect == PAF_SOURCE_THD)
170     {
171         //gCbInitSourceSelThdCnt++; //debug
172         
173         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD;
174         
175         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_THD;
176         // FL: (***) set nominal delay per sampling rate -- need to review these settings
177         switch (pDecInfo1Af->sampleRate)
178         {
179             case PAF_SAMPLERATE_44100HZ:
180             case PAF_SAMPLERATE_48000HZ:
181                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD;
182                 break;
183             case PAF_SAMPLERATE_88200HZ:
184             case PAF_SAMPLERATE_96000HZ:
185                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_96kTHD;
186                 break;
187             case PAF_SAMPLERATE_176400HZ:
188             case PAF_SAMPLERATE_192000HZ:
189                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_192kTHD;
190                 break;
191             default:
192                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD;
193                 break;
194         }
195         
196         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_THD;
197         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_THD;
198         pCb->pcmRdIdx = 0;
199         
200         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_MAT;
201         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kMAT;        
202     }
203     else
204     {
205         //
206         // Currently unsupported source select
207         //
208         
209         SW_BREAKPOINT; // debug
210         
211         // Leave the gate
212         GateMP_leave(gateHandle, key);
214         return ASP_DECOP_CB_INIT_INV_SOURCE_SEL;
215     }
216     
217     // Initialize audio frames
218     for (n = 0; n < pCb->maxNumAfCb; n++)
219     {
220         pAfCb = &pCb->afCb[n]; // get pointer to CB AF
221         
222         // Dec Info1 AF sample count not correct for CB AFs
223         pAfCb->sampleCount = decOpFrameLen;
225         // initialize CB AF using Dec Info1 AF
226         pAfCb->sampleDecode = pDecInfo1Af->sampleDecode;
227         PAF_PROCESS_COPY(pAfCb->sampleProcess, pDecInfo1Af->sampleProcess);
228         pAfCb->sampleRate = pDecInfo1Af->sampleRate;
229         pAfCb->channelConfigurationRequest.full = pDecInfo1Af->channelConfigurationRequest.full;
230         pAfCb->channelConfigurationStream.full = pDecInfo1Af->channelConfigurationStream.full;
231         
232         // initialize metadata information updated by decoder
233         pAfCb->bsMetadata_type     = PAF_bsMetadata_none;           /* non zero if metadata is attached. */
234         pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
235         pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
236         pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
237     }
238     
239     // Initialize circular buffer current number of frames
240     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
241     
242     // Initialize audio frame PCM buffers
243     pPcmBuf = pCb->pcmBuf;
244     pMetaBuf = pCb->metaBuf;
245     for (n=0; n<pCb->maxNumAfCb; n++)
246     {
247         pAfCb = &pCb->afCb[n]; // get pointer to CB AF
248         
249         pAfCb->data.nChannels = pCb->maxAFChanNum;
250         pAfCb->data.nSamples = decOpFrameLen;
251         for (i=0; i<pCb->maxAFChanNum; i++)
252         {
253             pAfCb->data.sample[i] = pPcmBuf;
254             memset(pAfCb->data.sample[i], 0, pCb->maxAFSampCount);
255             pPcmBuf += pCb->maxAFSampCount;
256             
257             pAfCb->data.samsiz[i] = 0;
258         }
259         
260         // Initialize metadata buffers
261         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
262         {
263             pAfCb->pafPrivateMetadata[i].offset = 0; 
264             pAfCb->pafPrivateMetadata[i].size   = 0; 
265             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
266             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
267         }
268     }
269     
270     // Reset read/write flags
271     if (resetRwFlags != 0)
272     {
273         pCb->writerActiveFlag = 0;
274         pCb->readerActiveFlag = 0;
275         pCb->drainFlag = 0;
276     }
277     
278     // Reset stats
279     pCb->readAfWriterInactiveCnt = 0;
280     pCb->wrtAfReaderInactiveCnt = 0;
281     pCb->wrtAfZeroSampsCnt = 0;
282     pCb->errUndCnt = 0;
283     pCb->errOvrCnt = 0;
284     
285     // Write back circular buffer configuration
286     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
287     // Write back AF circular buffer
288     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
289     // Write back PCM data
290     for (n=0; n<pCb->maxNumAfCb; n++)
291     {
292         pAfCb = &pCb->afCb[n];
293         Cache_wb(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
294         Cache_wb(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
295         for (i=0; i<pCb->maxAFChanNum; i++)
296         {
297             Cache_wb(pAfCb->data.sample[i], pCb->maxAFSampCount*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
298         }
299     }
300     Cache_wait();
302     // Leave the gate
303     GateMP_leave(gateHandle, key);
304     
305     return ASP_DECOP_CB_SOK;
308 //Int8 gCbWriteStartCnt=0; // debug
310 // Start writes to circular buffer
311 Int cbWriteStart(
312     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
313     Int8 cbIdx                          // decoder output circular buffer index
316     IArg key;
317     GateMP_Handle gateHandle;
318     PAF_AST_DecOpCircBuf *pCb;
319     PAF_AudioFrame *pAfCb;
320     Int8 n;
321     //Int8 i;
323     //gCbWriteStartCnt++; // debug
324     
325     // Get gate handle
326     gateHandle = pCbCtl->gateHandle;
327     // Enter gate
328     key = GateMP_enter(gateHandle);
330     // Get circular buffer base pointer
331     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
333     // Invalidate circular buffer configuration.
334     // NOTE: Probably only a subset of this information needs to be updated.
335     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
336     Cache_wait();
337     
338     //Log_info1("cbWriteStart:afCb=0x%04x", (IArg)pCb->afCb); // debug
339     
340     // Invalidate AF circular buffer
341     Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
342     for (n=0; n<pCb->maxNumAfCb; n++)
343     {
344         pAfCb = &pCb->afCb[n];
345         Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
346     }
347     Cache_wait();
348             
349     // update flags
350     pCb->writerActiveFlag = 1;
351     pCb->drainFlag = 0;
352     //pCb->afLagIdx = 0;
353     
354     // Write back circular buffer configuration
355     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
356     Cache_wait();
358     // Leave the gate
359     GateMP_leave(gateHandle, key);
361     return ASP_DECOP_CB_SOK;
362 };
364 // Stop writes to circular buffer
365 Int cbWriteStop(
366     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
367     Int8 cbIdx                          // decoder output circular buffer index
370     IArg key;
371     GateMP_Handle gateHandle;
372     PAF_AST_DecOpCircBuf *pCb;
374     // Get gate handle
375     gateHandle = pCbCtl->gateHandle;
376     // Enter gate
377     key = GateMP_enter(gateHandle);
379     // Get circular buffer base pointer
380     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
382     // Invalidate circular buffer configuration
383     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
384     Cache_wait();
386     //Log_info1("cbWriteStop:afCb=0x%04x", (IArg)pCb->afCb);  // debug
387     
388     // update flags
389     pCb->writerActiveFlag = 0;
390     pCb->drainFlag = 1;
392     // Write back circular buffer configuration
393     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
394     Cache_wait();
395     
396     // Leave the gate
397     GateMP_leave(gateHandle, key);
399     return ASP_DECOP_CB_SOK;
402 // debug
403 //Int16 gSampleCountBuf[10];
404 //Int16 gCalcDeltaSampsBuf[10];
405 //Int8 gPrimedFlagCnt=0;
407 // (***) FL: revisit
408 // Write audio frame to circular buffer
409 Int cbWriteAf(
410     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
411     Int8 cbIdx,                         // decoder output circular buffer index
412     PAF_AudioFrame *pAfWrt              // audio frame from which to write
415     IArg key;
416     GateMP_Handle gateHandle;
417     PAF_AST_DecOpCircBuf *pCb;
418     PAF_AudioFrame *pAfCb;
419     PAF_ChannelMask_HD streamMask;
420     Int8 i;
421     Int16 j;
422     PAF_AudioData *pPcmBuf;UInt8 *pMetaBuf; int nextWrtIdx;PAF_AudioFrame *pAfCbNextAf; 
424     // Get gate handle
425     gateHandle = pCbCtl->gateHandle;
426     // Enter gate
427     key = GateMP_enter(gateHandle);
429     //Log_info2("cbWriteAf:gate enter, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug
431     // Get circular buffer base pointer
432     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
433     //Log_info1("cbWriteAf:pCb=0x%04x", (IArg)pCb); // debug
435     // Invalidate circular buffer configuration.
436     // NOTE: Probably only a subset of this information needs to be updated.
437     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
438     Cache_wait();
440     //Log_info1("cbWriteAf:afCb=0x%04x", (IArg)pCb->afCb); // debug
441     //Log_info2("cbWriteAf:pCb->readerActiveFlag=%d, pCb->writerActiveFlag=%d", (IArg)pCb->readerActiveFlag, (IArg)pCb->writerActiveFlag); // debug
443     //if (pCb->readerActiveFlag == 1)
444     //{
445     //    //
446     //    // Normal case, reader active.
447     //    //
448         
449         if (pAfWrt->sampleCount != 0)
450         {
451             //Log_info2("cbWriteAf:pCb->numAfCb=%d, pCb->maxNumAfCb=%d", (IArg)pCb->readerActiveFlag, (IArg)pCb->maxNumAfCb); // debug
453             // check overflow
454             //while (pCb->numAfCb >= pCb->maxNumAfCb); // debug
455             if (pCb->numAfCb >= pCb->maxNumAfCb)
456             {
457                 pCb->errOvrCnt++;
459                 //SW_BREAKPOINT;
460                 Log_info1("cbWriteAf: ERROR: overflow, numAfCb=%d", pCb->numAfCb);
462                 // Write back circular buffer configuration
463                 Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
464                 Cache_wait();
466                 // Leave the gate
467                 GateMP_leave(gateHandle, key);
469                 //Log_info2("cbWriteAf:gate leave, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug
471                 return ASP_DECOP_CB_WRITE_OVERFLOW;
472             }
474             pAfCb = &pCb->afCb[pCb->afWrtIdx];
475             pPcmBuf = pAfCb->data.sample[0];
476             pMetaBuf = pAfCb->pafPrivateMetadata[0].pMdBuf;
477             if((pPcmBuf + (pAfWrt->sampleCount * pCb->maxAFChanNum )) > (pCb->pcmBufEnd))
478             {
479                 pPcmBuf = pCb->pcmBuf;
480             }
482             for (i=0; i<pCb->maxAFChanNum; i++)
483             {
484                 pAfCb->data.sample[i] = pPcmBuf;
485                 pPcmBuf += pAfWrt->sampleCount;
486                 pAfCb->data.samsiz[i] = 0;
487             }
488             Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); // FL: this is write back and invalidate??
489             Cache_wait();
491             //for (i=0; i<pCb->maxAFChanNum; i++){
492             //}
493             for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
494             {
495                 pAfCb->pafPrivateMetadata[i].offset = 0;
496                 pAfCb->pafPrivateMetadata[i].size   = 0;
497                 pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
498                 pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
499             }
501             nextWrtIdx = 0;
502             if ((pCb->afWrtIdx +1) >= pCb->maxNumAfCb)
503             {
504                 //Log_info0("cbWriteAf: AF Wrap around **** ");
505                 // next audio frame will be audio frame 0
506                 nextWrtIdx = 0;
507             }
508             else
509             {
510                 // next audio frame will be current audio frame + 1
511                 nextWrtIdx = pCb->afWrtIdx + 1;
512             }
514             pAfCbNextAf = &pCb->afCb[nextWrtIdx]; // +1 or last AF if overflow
515             pAfCbNextAf->data.sample[0] = &pAfCb->data.sample[pCb->maxAFChanNum - 1][pAfWrt->sampleCount];// pAfCb->data.sample[15] + (pAfCb->sampleCount * sizeof(PAF_AudioData));
517             // write audio frame information updated by decoder
518             pAfCb->sampleDecode = pAfWrt->sampleDecode;
519             PAF_PROCESS_COPY(pAfCb->sampleProcess, pAfWrt->sampleProcess);
520             pAfCb->sampleRate = pAfWrt->sampleRate;
521             pAfCb->sampleCount = pAfWrt->sampleCount;
522             pAfCb->channelConfigurationRequest = pAfWrt->channelConfigurationRequest;
523             pAfCb->channelConfigurationStream = pAfWrt->channelConfigurationStream;
524             // write metadata information updated by decoder
525             pAfCb->bsMetadata_type     = pAfWrt->bsMetadata_type;        /* non zero if metadata is attached. */
526             pAfCb->pafBsMetadataUpdate = pAfWrt->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
527             pAfCb->numPrivateMetadata  = pAfWrt->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
528             pAfCb->bsMetadata_offset   = pAfWrt->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
529             // write PCM samples
530             streamMask = pAfWrt->fxns->channelMask(pAfWrt, pAfCb->channelConfigurationStream);
531             for (i = 0; i < pCb->maxAFChanNum; i++)
532             {
533                 if ((streamMask >> i) & 0x1)
534                 {
535                     for (j = 0; j < pAfWrt->sampleCount; j++)
536                     {
537                         pAfCb->data.sample[i][j] = pAfWrt->data.sample[i][j];
538                     }
540                     pAfCb->data.samsiz[i] = pAfWrt->data.samsiz[i];
541                 }
542             }
544             #ifdef CB_RW_OP_CAP_PP // debug
545             if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
546             {
547                 if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
548                 {
549                     // log sample count
550                     pCb->cb_samples_op[pCb->cb_opCnt] = pAfWrt->sampleCount;
551                     pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_W;
552                     // log idxs
553                     pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
554                     pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
555                     pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
556                     pCb->cb_opCnt++;
557                 }
558             }
559             #endif
561             // prepare metadata buffer pointers according to the metadata and buffer sizes
562             for (i=0; i < pAfWrt->numPrivateMetadata; i++)
563             {
564                 UInt8 *nextMdBuf;
565                 if(i == 0)
566                     nextMdBuf = (pAfCb->pafPrivateMetadata[0].pMdBuf + pAfWrt->pafPrivateMetadata[0].size);
567                 else
568                     nextMdBuf = (pAfCb->pafPrivateMetadata[i-1].pMdBuf + pAfWrt->pafPrivateMetadata[i-1].size);
569                 if(nextMdBuf >= pCb->metaBufEnd) // metadata buffer overflow
570                 {
571                     pAfCb->pafPrivateMetadata[i].pMdBuf = pCb->metaBuf;
572                 }
573                 else if(i != 0)
574                 {
575                     pAfCb->pafPrivateMetadata[i].pMdBuf = nextMdBuf;
576                 }
577                 Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, sizeof(UInt8 *), Cache_Type_ALLD, 0);
578             }
580             // Write metadata to circular buffer
581             for (i = 0; i < pAfWrt->numPrivateMetadata; i++) // only copy numPrivateMetadata
582             {
583                 pAfCb->pafPrivateMetadata[i].offset = pAfWrt->pafPrivateMetadata[i].offset;
584                 pAfCb->pafPrivateMetadata[i].size   = pAfWrt->pafPrivateMetadata[i].size;
585                 memcpy(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].size);
586             }
588             Cache_inv(pAfCb->pafPrivateMetadata, pAfWrt->numPrivateMetadata*sizeof(PAF_PrivateMetadata *), Cache_Type_ALLD, 0); // FL: this is write back and invalidate??
589             Cache_wait();
590             for (i=0; i<pAfCb->numPrivateMetadata; i++) // only write back numPrivateMetadata
591             {
592                 //Log_info4("cbWriteAf: AF: %d nummd: %d offset: %d size: %d ", pCb->afWrtIdx, pAfCb->numPrivateMetadata, pAfCb->pafPrivateMetadata[i].offset,  pAfCb->pafPrivateMetadata[i].size);
593                 Cache_wb(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
594             }
595             // update audio frame write index
596             pCb->afWrtIdx++;
597             if (pCb->afWrtIdx >= pCb->maxNumAfCb)
598             {
599                 pCb->afWrtIdx = 0;
600             }
602             pCb->afCb[pCb->afWrtIdx].data.sample[0] = &pAfCb->data.sample[pCb->maxAFChanNum - 1][pAfWrt->sampleCount];
603             if(pAfWrt->numPrivateMetadata > 0)
604             {
605                 pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf = pAfCb->pafPrivateMetadata[pAfWrt->numPrivateMetadata - 1].pMdBuf + pAfWrt->pafPrivateMetadata[pAfWrt->numPrivateMetadata - 1].size;
606             }
607             else
608             {
609                 pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf = pAfCb->pafPrivateMetadata[0].pMdBuf;
610                 Cache_wb(pCb->afCb , ASP_DECOP_CB_MAX_NUM_PCM_FRAMES*sizeof(PAF_AudioFrame *), Cache_Type_ALLD, 0);
611                 Cache_wait();
612             }
613             Cache_inv(pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf, sizeof(UInt8 *), Cache_Type_ALLD, 0);
614             Cache_wait();
615             // update number of audio frames in circular buffer
616             pCb->numAfCb++;
617             
618             // Update CB Lag index 
619             //if (pCb->afLagIdx < pCb->afInitialLag)
620             //{
621             //    pCb->afLagIdx += 1;
622             //}
623             
624             // Update CB primed flag
625             // calculate number of delta samples before 
626             if (pCb->primedFlag == 0)
627             {
628                 pCb->primedFlag = 1;
629                 
630                 // Calculate number of output frames to block reader.
631                 // This is sample count reader waits before allowed to actually read samples from the CB.
632                 pCb->deltaSamps = (pCb->targetNDSamps - pAfWrt->sampleCount + (pCb->strFrameLen-1)) / pCb->strFrameLen * pCb->strFrameLen;
633                 
634                 // debug
635                 //gSampleCountBuf[gPrimedFlagCnt] = pAfWrt->sampleCount;
636                 //gCalcDeltaSampsBuf[gPrimedFlagCnt] = pCb->deltaSamps;
637                 //if (gPrimedFlagCnt < 10)
638                 //    gPrimedFlagCnt++;
639             }
641             // Write back circular buffer configuration
642             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
643             // write back audio frame
644             Cache_wb(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
645             Cache_wb(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
646             Cache_wb(pAfCb->pafPrivateMetadata, pAfWrt->numPrivateMetadata*sizeof(PAF_PrivateMetadata *), Cache_Type_ALLD, 0);
647             Cache_wait();
648             // write back PCM data
649             for (i = 0; i < pCb->maxAFChanNum; i++)
650             {
651                 if ((streamMask >> i) & 0x1)
652                 {
653                     Cache_wb(pAfCb->data.sample[i], pAfWrt->sampleCount * sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
654                 }
655             }
656             Cache_wait();
658             {
659                 static Uint8 toggleState = 0;
660                if (toggleState == 0)
661                    GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_99);
662                else
663                    GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_99);
664                toggleState = ~(toggleState);
665             }
666             Log_info3("wrote %d samples into AF %d sourceSel: %d", pAfCb->sampleCount, pCb->afWrtIdx, pCb->sourceSel);
667             Log_info4("CBWMETA num=%d  size=%d  offset=%d chrequest=0x%04x", pAfCb->numPrivateMetadata, pAfCb->pafPrivateMetadata[0].size, pAfCb->pafPrivateMetadata[0].offset, pAfCb->channelConfigurationRequest.full);
668         }
669         else
670         {
671             //
672             // Skip write in case of 0 sample count
673             //
674             
675             // writing audio frame w/ zero samples
676             // update stat
677             pCb->wrtAfZeroSampsCnt++;
679             // Write back circular buffer configuration
680             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
681             Cache_wait();
682         }
683     //}
684     //else if (pCb->readerActiveFlag == 0)
685     if (pCb->readerActiveFlag == 0)
686     {
687         //
688         // Reader inactive, don't write to circular buffer or check OVRflow.
689         //
690         
691         // writing AF w/ inactive reader
692         // update stat
693         pCb->wrtAfReaderInactiveCnt++;
695         // Write back circular buffer configuration
696         Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
697         Cache_wait();
698     }
700     // Leave the gate
701     GateMP_leave(gateHandle, key);
703     //Log_info2("cbWriteAf:gate leave, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug
705     return ASP_DECOP_CB_SOK;
708 #if 0
709 // Get next audio frame to write in circular buffer
710 Int cbGetNextWriteAf(
711     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
712     Int8 cbIdx,                         // decoder output circular buffer index
713     PAF_AudioFrame **ppAfWrt            // audio frame next to be written
716     IArg key;
717     GateMP_Handle gateHandle;
718     PAF_AST_DecOpCircBuf *pCb;
720     // Get gate handle
721     gateHandle = pCbCtl->gateHandle;
722     // Enter gate
723     key = GateMP_enter(gateHandle);
725     // Get circular buffer base pointer
726     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
728     // get pointer to current audio frame in circular buffer
729     *ppAfWrt = &pCb->afCb[pCb->afWrtIdx];
730     
731     // update audio frame write index
732     pCb->afWrtIdx++;
733     if (pCb->afWrtIdx > pCb->maxNumAfCb)
734     {
735         pCb->afWrtIdx = 0;
736     }    
737     
738     // Leave the gate
739     GateMP_leave(gateHandle, key);
741     return ASP_DECOP_CB_SOK;
743 #endif