]> 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
2281dd25765b175fd71d70960299b5a515dc2566
[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 // Init last audio frame configuration info 
51 static Void cbInitLastAfInfo(
52     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer control
53     PAF_AudioFrame *pAfInit     // audio frame used for init
54 );
57 #if 0 // FL: moved to common
58 // Initialize circular buffer control
59 Int cbCtlInit(
60     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
61     PAF_AST_DecOpCircBuf **pXDecOpCb    // address of decoder output circular buffer base pointer
62 )
63 {
64     GateMP_Handle gateHandle;
65     Int status;
66     
67     do {
68         status = GateMP_open(ASP_DECODE_CB_GATE_NAME, &gateHandle);
69     } while (status == GateMP_E_NOTFOUND);
70     if (status == GateMP_S_SUCCESS)
71     {
72         pCbCtl->gateHandle = gateHandle;
73     }
74     else
75     {
76         pCbCtl->gateHandle = NULL;
77         return ASP_DECOP_CB_CTL_INIT_INV_GATE;
78     }
79     
80     pCbCtl->numCb = numCb;          // init number of circular buffers
81     pCbCtl->pXDecOpCb = pXDecOpCb;  // init base address of circular buffers
82     
83     return ASP_DECOP_CB_SOK;
84 }
85 #endif
87 // debug
88 //Int8 gCbInitDecWriteCnt=0;
89 //Int8 gCbInitDecWriteThdCnt=0;
91 /// Initialize circular buffer for Decoder writes
92 Int cbInitDecWrite(
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     Int8 resetRwFlags,                  // whether to reset reader, writer, and drain flags
98     PAF_AudioFrame *pDecInitAf          // pointer to Dec output audio frame used for CB initialization
99 )
101     IArg key;
102     GateMP_Handle gateHandle;
103     PAF_AST_DecOpCircBuf *pCb;
104     PAF_AudioFrame *pAfCb;
105     PAF_AudioData *pPcmBuf;
106     UInt8 *pMetaBuf;
107     Int8 n;
108     Int8 i;
110     //gCbInitDecWriteCnt++; // debug
111     
112     // Get gate handle
113     gateHandle = pCbCtl->gateHandle;
114     // Enter gate
115     key = GateMP_enter(gateHandle);
117     // Get circular buffer base pointer
118     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
119     
120     // Invalidate circular buffer configuration
121     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
122     Cache_wait();
124     //Log_info1("cbInitDecWrite:afCb=0x%04x", (IArg)pCb->afCb); // debug
126     // Set source select
127     pCb->sourceSel = sourceSelect;
129     // Set input frame length
130     pCb->decOpFrameLen = decOpFrameLen;
131     
132     //pCb->afInitialLag = 0;  // default No lag
133     //pCb->afLagIdx = 0;
134     // Initialize CB primed flag
135     pCb->primedFlag = 0;
136     // Initialize delta samples
137     pCb->deltaSamps = 0;
138     
139     // Initialize circular buffer:
140     //  - maximum number of AFs
141     //  - target nominal delay
142     //  - AF write, read indices
143     //  - maximum AF channel and sample counts
144     //  - maximum number of PCM samples per channel
145     if (sourceSelect == PAF_SOURCE_PCM)
146     {
147         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_PCM;
148         
149         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_PCM;
150         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kPCM;
151         
152         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_PCM;
153         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_PCM;
154         
155         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH;
156         pCb->maxAFSampCount = DEF_DEC_OP_FRAME_LEN; 
158         pCb->maxNumPcmSampsPerCh = (Int32)(pCb->pcmBufEnd - pCb->pcmBuf)/pCb->maxAFChanNum;
159     }
160     else if (sourceSelect == PAF_SOURCE_AAC)
161     {
162         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_AAC;
164         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_PCM;
165         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_AAC;
167         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_AAC;
168         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_AAC;
170         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_AAC;
171         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kAAC;
173         pCb->maxNumPcmSampsPerCh = (Int32)(pCb->pcmBufEnd - pCb->pcmBuf)/pCb->maxAFChanNum;
174     }
175     else if ((sourceSelect == PAF_SOURCE_DDP) || (sourceSelect == PAF_SOURCE_AC3))
176     {
177         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_DDP;
178         
179         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_DDP;
180         pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_DDP;
181         
182         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_DDP;
183         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_DDP;
184         
185         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_DDP;
186         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kDDP;
188         pCb->maxNumPcmSampsPerCh = (Int32)(pCb->pcmBufEnd - pCb->pcmBuf)/pCb->maxAFChanNum;
189     }
190     else if (sourceSelect == PAF_SOURCE_THD)
191     {
192         //gCbInitSourceSelThdCnt++; //debug
193         
194         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD;
195         
196         //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_THD;
197         // FL: (***) set nominal delay per sampling rate -- need to review these settings
198         switch (pDecInitAf->sampleRate)
199         {
200             case PAF_SAMPLERATE_44100HZ:
201             case PAF_SAMPLERATE_48000HZ:
202                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD;
203                 break;
204             case PAF_SAMPLERATE_88200HZ:
205             case PAF_SAMPLERATE_96000HZ:
206                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_96kTHD;
207                 break;
208             case PAF_SAMPLERATE_176400HZ:
209             case PAF_SAMPLERATE_192000HZ:
210                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_192kTHD;
211                 break;
212             default:
213                 pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD;
214                 break;
215         }
216         
217         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_THD;
218         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_THD;
219         
220         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_MAT;
221         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kMAT;        
223         pCb->maxNumPcmSampsPerCh = (Int32)(pCb->pcmBufEnd - pCb->pcmBuf)/pCb->maxAFChanNum;
224     }
225         else if ((sourceSelect == PAF_SOURCE_DTS)   ||
226                  (sourceSelect == PAF_SOURCE_DTSHD) ||
227                  (sourceSelect == PAF_SOURCE_DTS12) ||
228                  (sourceSelect == PAF_SOURCE_DTS13) ||
229                  (sourceSelect == PAF_SOURCE_DTS14) ||
230                  (sourceSelect == PAF_SOURCE_DTS16) ||
231                  (sourceSelect == PAF_SOURCE_DTSALL)
232                 )
233     {
234         pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_DTS;
235         pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_DTS;
236         pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_DTS;
237         pCb->pcmRdIdx = 0;
238         pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_DTS;
239         pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kDTS;
241         // initialize audio frames
242         for (n=0; n<pCb->maxNumAfCb; n++)
243         {
244             pAfCb = &pCb->afCb[n];
245             pAfCb->sampleDecode = sourceSelect;
246             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
247             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
248             pAfCb->sampleCount = decOpFrameLen;
249             pAfCb->channelConfigurationRequest.full = 0;
250             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
251             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
252             pAfCb->channelConfigurationStream.full = 0;
253             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
254             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
256             // write metadata information updated by decoder
257             pAfCb->bsMetadata_type     = PAF_bsMetadata_DTS_X;          /* Audio data from DTSX decoder. */
258             pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
259             pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
260             pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
261         }
262     }
263     else
264     {
265         //
266         // Currently unsupported source select
267         //
268         
269         SW_BREAKPOINT; // debug
270         
271         // Leave the gate
272         GateMP_leave(gateHandle, key);
274         return ASP_DECOP_CB_INIT_INV_SOURCE_SEL;
275     }
277     // Initialize circular buffer:
278     //  - PCM read index
279     //  - Private metadata read index
280     //  - number of PCM samples in CB
281     pCb->pcmRdIdx = 0;
282     pCb->prvMdRdIdx = 0;
283     pCb->numPcmSampsPerCh = 0;
285     // Initialize audio frames
286     for (n = 0; n < pCb->maxNumAfCb; n++)
287     {
288         pAfCb = &pCb->afCb[n]; // get pointer to CB AF
289         
290         // Dec init AF sample count not correct for CB AFs.
291         // Dec Op frame length is computed in framework based on selected source.
292         pAfCb->sampleCount = decOpFrameLen;
294         // initialize CB AF using Dec init AF
295         pAfCb->sampleDecode = pDecInitAf->sampleDecode;
296         PAF_PROCESS_COPY(pAfCb->sampleProcess, pDecInitAf->sampleProcess);
297         pAfCb->sampleRate = pDecInitAf->sampleRate;
298         pAfCb->channelConfigurationRequest.full = pDecInitAf->channelConfigurationRequest.full;
299         pAfCb->channelConfigurationStream.full = pDecInitAf->channelConfigurationStream.full;
300         
301         // initialize metadata information updated by decoder
302         pAfCb->bsMetadata_type     = PAF_bsMetadata_none;           /* non zero if metadata is attached. */
303         pAfCb->pafBsMetadataUpdate = 0;                             /* indicates whether bit-stream metadata update */
304         pAfCb->numPrivateMetadata  = 0;                             /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
305         pAfCb->bsMetadata_offset   = 0;                             /* offset into audio frame for change in bsMetadata_type field */
306     }
307     
308     // Initialize circular buffer current number of frames
309     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
310     
311     // Initialize audio frame PCM buffers
312     pPcmBuf = pCb->pcmBuf;
313     pMetaBuf = pCb->metaBuf;
314     for (n=0; n<pCb->maxNumAfCb; n++)
315     {
316         pAfCb = &pCb->afCb[n]; // get pointer to CB AF
317         
318         pAfCb->data.nChannels = pCb->maxAFChanNum;
319         pAfCb->data.nSamples = decOpFrameLen;
320         for (i=0; i<pCb->maxAFChanNum; i++)
321         {
322             pAfCb->data.sample[i] = pPcmBuf;
323             memset(pAfCb->data.sample[i], 0, pCb->maxAFSampCount);
324             pPcmBuf += pCb->maxAFSampCount;
325             
326             pAfCb->data.samsiz[i] = 0;
327         }
328         
329         // Initialize metadata buffers
330         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
331         {
332             pAfCb->pafPrivateMetadata[i].offset = 0; 
333             pAfCb->pafPrivateMetadata[i].size   = 0; 
334             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
335             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
336         }
337     }
338     
339     // Initialize last audio frame configuration info
340     cbInitLastAfInfo(pCb, pDecInitAf);
341     
342     // Reset read/write flags
343     if (resetRwFlags != 0)
344     {
345         pCb->writerActiveFlag = 0;
346         pCb->readerActiveFlag = 0;
347         pCb->drainFlag = 0;
348     }
349     
350     // Reset stats
351     pCb->readAfWriterInactiveCnt = 0;
352     pCb->readAfNdCnt = 0;
353     pCb->wrtAfReaderInactiveCnt = 0;
354     pCb->wrtAfZeroSampsCnt = 0;
355     pCb->errAfUndCnt = 0;
356     pCb->errAfOvrCnt = 0;
357     pCb->errPcmUndCnt = 0;
358     pCb->errPcmOvrCnt = 0;
359     
360     // Write back circular buffer configuration
361     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
362     // Write back AF circular buffer
363     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
364     // Write back PCM data
365     for (n=0; n<pCb->maxNumAfCb; n++)
366     {
367         pAfCb = &pCb->afCb[n];
368         Cache_wb(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
369         Cache_wb(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
370         for (i=0; i<pCb->maxAFChanNum; i++)
371         {
372             Cache_wb(pAfCb->data.sample[i], pCb->maxAFSampCount*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
373         }
374     }
375     Cache_wait();
377     // Leave the gate
378     GateMP_leave(gateHandle, key);
379     
380     return ASP_DECOP_CB_SOK;
383 //Int8 gCbWriteStartCnt=0; // debug
385 // Start writes to circular buffer
386 Int cbWriteStart(
387     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
388     Int8 cbIdx                          // decoder output circular buffer index
391     IArg key;
392     GateMP_Handle gateHandle;
393     PAF_AST_DecOpCircBuf *pCb;
394     PAF_AudioFrame *pAfCb;
395     Int8 n;
396     //Int8 i;
398     //gCbWriteStartCnt++; // debug
399     
400     // Get gate handle
401     gateHandle = pCbCtl->gateHandle;
402     // Enter gate
403     key = GateMP_enter(gateHandle);
405     // Get circular buffer base pointer
406     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
408     // Invalidate circular buffer configuration.
409     // NOTE: Probably only a subset of this information needs to be updated.
410     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
411     Cache_wait();
412     
413     //Log_info1("cbWriteStart:afCb=0x%04x", (IArg)pCb->afCb); // debug
414     
415     // Invalidate AF circular buffer
416     Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
417     for (n=0; n<pCb->maxNumAfCb; n++)
418     {
419         pAfCb = &pCb->afCb[n];
420         Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
421     }
422     Cache_wait();
423             
424     // update flags
425     pCb->writerActiveFlag = 1;
426     pCb->drainFlag = 0;
427     //pCb->afLagIdx = 0;
428     
429     // Write back circular buffer configuration
430     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
431     Cache_wait();
433     // Leave the gate
434     GateMP_leave(gateHandle, key);
436     return ASP_DECOP_CB_SOK;
437 };
439 // Stop writes to circular buffer
440 Int cbWriteStop(
441     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
442     Int8 cbIdx                          // decoder output circular buffer index
445     IArg key;
446     GateMP_Handle gateHandle;
447     PAF_AST_DecOpCircBuf *pCb;
449     // Get gate handle
450     gateHandle = pCbCtl->gateHandle;
451     // Enter gate
452     key = GateMP_enter(gateHandle);
454     // Get circular buffer base pointer
455     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
457     // Invalidate circular buffer configuration
458     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
459     Cache_wait();
461     //Log_info1("cbWriteStop:afCb=0x%04x", (IArg)pCb->afCb);  // debug
462     
463     // update flags
464     pCb->writerActiveFlag = 0;
465     pCb->drainFlag = 1;
467     // Write back circular buffer configuration
468     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
469     Cache_wait();
470     
471     // Leave the gate
472     GateMP_leave(gateHandle, key);
474     return ASP_DECOP_CB_SOK;
477 // debug
478 //Int16 gSampleCountBuf[10];
479 //Int16 gCalcDeltaSampsBuf[10];
480 //Int8 gPrimedFlagCnt=0;
482 // (***) FL: revisit
483 // Write audio frame to circular buffer
484 Int cbWriteAf(
485     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
486     Int8 cbIdx,                         // decoder output circular buffer index
487     PAF_AudioFrame *pAfWrt              // audio frame from which to write
490     IArg key;
491     GateMP_Handle gateHandle;
492     PAF_AST_DecOpCircBuf *pCb;
493     PAF_AudioFrame *pAfCb;
494     PAF_ChannelMask_HD streamMask;
495     Int8 i;
496     Int16 j;
497     PAF_AudioData *pPcmBuf; 
498     UInt8 *pMetaBuf; 
499     //int nextWrtIdx;
500     //PAF_AudioFrame *pAfCbNextAf; 
501     PAF_AudioFrame *pAfCbRd;
502     PAF_AudioData *pPcmBufRd, *pPcmBufWrt;
503     Int8 pcmOvr;
504     
505     // Get gate handle
506     gateHandle = pCbCtl->gateHandle;
507     // Enter gate
508     key = GateMP_enter(gateHandle);
510     //Log_info2("cbWriteAf:gate enter, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug
512     // Get circular buffer base pointer
513     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
514     //Log_info1("cbWriteAf:pCb=0x%04x", (IArg)pCb); // debug
516     // Invalidate circular buffer configuration.
517     // NOTE: Probably only a subset of this information needs to be updated.
518     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
519     Cache_wait();
521     //Log_info1("cbWriteAf:afCb=0x%04x", (IArg)pCb->afCb); // debug
522     //Log_info2("cbWriteAf:pCb->readerActiveFlag=%d, pCb->writerActiveFlag=%d", (IArg)pCb->readerActiveFlag, (IArg)pCb->writerActiveFlag); // debug
524     //if (pCb->readerActiveFlag == 1)
525     //{
526     //    //
527     //    // Normal case, reader active.
528     //    //
529         
530         if (pAfWrt->sampleCount != 0)
531         {
532             //Log_info2("cbWriteAf:pCb->numAfCb=%d, pCb->maxNumAfCb=%d", (IArg)pCb->readerActiveFlag, (IArg)pCb->maxNumAfCb); // debug
534             // check AF overflow
535             if (pCb->numAfCb >= pCb->maxNumAfCb)
536             {
537                 pCb->errAfOvrCnt++;
539                 //SW_BREAKPOINT;
540                 Log_info1("cbWriteAf: ERROR: AF CB overflow, numAfCb=%d", pCb->numAfCb);
542                 // Write back circular buffer configuration
543                 Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
544                 Cache_wait();
546                 // Leave the gate
547                 GateMP_leave(gateHandle, key);
549                 //Log_info2("cbWriteAf:gate leave, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug
551                 return ASP_DECOP_CB_AF_WRITE_OVERFLOW;
552             }
553             
554             // FL: this won't reliably detect overflow because of PCM buffer write address wrap
555             // check PCM overflow
556             //if ((pCb->numPcmSampsPerCh + pAfWrt->sampleCount) > pCb->maxNumPcmSampsPerCh)
557             //{
558             //    pCb->errPcmOvrCnt++;
559             //
560             //    Log_info3("cbWriteAf: ERROR: PCM CB overflow, sampleCount=%d, numPcmSampsPerCh=%d, maxNumPcmSampsPerCh=%d",
561             //        pCb->numPcmSampsPerCh, pAfWrt->sampleCount, pCb->maxNumPcmSampsPerCh);
562             //
563             //    // Write back circular buffer configuration
564             //    Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
565             //    Cache_wait();
566             //
567             //    // Leave the gate
568             //    GateMP_leave(gateHandle, key);
569             //
570             //    return ASP_DECOP_CB_PCM_WRITE_OVERFLOW;
571             //}
573             // get CB AF write info
574             pAfCb = &pCb->afCb[pCb->afWrtIdx];                      // get CB AF to be written
575             pPcmBufWrt = pAfCb->data.sample[0];                     // get current location in PCM buffer to be written
576             // (***) FL: currently no metadata buffer overflow detection
577             pMetaBuf = pAfCb->pafPrivateMetadata[0].pMdBuf;         // get current location in MD buffer to be written
578             
579             // get CB AF read info
580             pAfCbRd = &pCb->afCb[pCb->afRdIdx];                     // get CB AF being read
581             //pPcmBufRd = pAfCbRd->data.sample[0];                    // FL: starting location of PCM samples for AF being read
582             pPcmBufRd = pAfCbRd->data.sample[0] + pCb->pcmRdIdx;    // FL: current location of PCM samples for AF being read
583             
584             // Check PCM buffer overflow
585             pPcmBuf = pPcmBufWrt;
586             pcmOvr = 0;
587             for (i = 0; i < pCb->maxAFChanNum; i++)
588             {
589                 //
590                 // Writes of PCM to PCM CB use CC stream, but this isn't considered here.
591                 // For each channel which *can* be written, check the current reader location won't be overwritten.
592                 // The current reader location is the earliest channel which *could have been* written for that CB AF.
593                 //
594                 if ((pPcmBuf + pAfWrt->sampleCount) >= pCb->pcmBufEnd)
595                 {
596                     // this write will wrap
597                     
598                     // check OVR before wrap
599                     if ((pPcmBuf < pPcmBufRd) && 
600                         ((pPcmBuf + pAfWrt->sampleCount) >= pPcmBufRd))
601                     {
602                         pCb->errPcmOvrCnt++;
603                         pcmOvr = 1;
604                     }
605                     
606                     if (pcmOvr == 0)
607                     {
608                         // wrap pointer
609                         pPcmBuf = pCb->pcmBuf;   
610                         // check OVR after wrap
611                         if ((pPcmBuf < pPcmBufRd) && 
612                             ((pPcmBuf + pAfWrt->sampleCount) >= pPcmBufRd))
613                         {
614                             pCb->errPcmOvrCnt++;
615                             pcmOvr = 1;
616                         }                                                                
617                     }
618                 }
619                 else if ((pPcmBuf < pPcmBufRd) && 
620                     ((pPcmBuf + pAfWrt->sampleCount) >= pPcmBufRd))
621                 {
622                     // this write won't wrap
623                     
624                     pCb->errPcmOvrCnt++;
625                     pcmOvr = 1;
626                 }
627                 else
628                 {
629                     // update pointer
630                     pPcmBuf += pAfWrt->sampleCount;                                        
631                 }
632                 
633                 if (pcmOvr == 1)
634                 {
635                     Log_info2("cbWriteAf: ERROR: PCM CB overflow, sampleCount=%d, numPcmSampsPerCh=%d", 
636                          pAfWrt->sampleCount, pCb->numPcmSampsPerCh);
637             
638                     //SW_BREAKPOINT; // debug
639                     
640                     // Write back circular buffer configuration
641                     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
642                     Cache_wait();
643             
644                     // Leave the gate
645                     GateMP_leave(gateHandle, key);
646             
647                     return ASP_DECOP_CB_PCM_WRITE_OVERFLOW;
648                 }
649             }
650             
651             // (***) FL: !!! REVISIT!!! 
652             //           Allocating memory for max # channels (e.g. 32 for THD).
653             //           GROSS over allocation for THD 192 kHz, 6ch max.
654             // configure AF sample pointers
655             pPcmBuf = pPcmBufWrt;
656             for (i = 0; i < pCb->maxAFChanNum; i++)
657             {
658                 // check PCM buffer wrap
659                 if ((pPcmBuf + pAfWrt->sampleCount) >= pCb->pcmBufEnd)
660                 {
661                     pPcmBuf = pCb->pcmBuf;
662                 }
663                 
664                 pAfCb->data.sample[i] = pPcmBuf;                
665                 pPcmBuf += pAfWrt->sampleCount;
666                 pAfCb->data.samsiz[i] = 0;
667             }
668             Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); // FL: this is write back and invalidate??
669             Cache_wait();
671             // FL: brute force reset of all metadata in CB AF?
672             for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
673             {
674                 pAfCb->pafPrivateMetadata[i].offset = 0;
675                 pAfCb->pafPrivateMetadata[i].size   = 0;
676                 pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
677                 pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
678             }
680 #if 0 // FL: unused
681             nextWrtIdx = 0;
682             if ((pCb->afWrtIdx + 1) >= pCb->maxNumAfCb)
683             {
684                 //Log_info0("cbWriteAf: AF Wrap around **** ");
685                 // next audio frame will be audio frame 0
686                 nextWrtIdx = 0;
687             }
688             else
689             {
690                 // next audio frame will be current audio frame + 1
691                 nextWrtIdx = pCb->afWrtIdx + 1;
692             }
693             
694             pAfCbNextAf = &pCb->afCb[nextWrtIdx]; // +1 or last AF if overflow
695             pAfCbNextAf->data.sample[0] = &pAfCb->data.sample[pCb->maxAFChanNum - 1][pAfWrt->sampleCount]; // pAfCb->data.sample[15] + (pAfCb->sampleCount * sizeof(PAF_AudioData));
696 #endif
697             
698             // write audio frame information updated by decoder
699             pAfCb->sampleDecode = pAfWrt->sampleDecode;
700             PAF_PROCESS_COPY(pAfCb->sampleProcess, pAfWrt->sampleProcess);
701             pAfCb->sampleRate = pAfWrt->sampleRate;
702             pAfCb->sampleCount = pAfWrt->sampleCount;
703             pAfCb->channelConfigurationRequest = pAfWrt->channelConfigurationRequest;
704             pAfCb->channelConfigurationStream = pAfWrt->channelConfigurationStream;
705             // write metadata information updated by decoder
706             pAfCb->bsMetadata_type     = pAfWrt->bsMetadata_type;        /* non zero if metadata is attached. */
707             pAfCb->pafBsMetadataUpdate = pAfWrt->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
708             pAfCb->numPrivateMetadata  = pAfWrt->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
709             pAfCb->bsMetadata_offset   = pAfWrt->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
710             
711 #ifdef DTS_BUILD
712         pAfCb->mode = pAfWrt->mode;                                       /* mode is used in DTSX to pass info to PARMA */
713         pAfCb->numChansUsedForMetadata = pAfWrt->numChansUsedForMetadata; /* if metadata is used in DTSX*/
714         pAfCb->pafBsFixedData = pAfWrt->pafBsFixedData;                   /* if true, do not convert float to fixed in DTSX metadata transfer */
715         pAfCb->root = pAfWrt->root;                                       /* used for channel MASK in DTSX . BAD IDEA, need fix */
716         pAfCb->resetCount = pAfWrt->resetCount;                           /* used for communication between DTSX and PARMA */
717 #endif          
718             // write PCM samples
719             streamMask = pAfWrt->fxns->channelMask(pAfWrt, pAfCb->channelConfigurationStream);
720             for (i = 0; i < pCb->maxAFChanNum; i++)
721             {
722 #ifndef DTS_BUILD
723             if ((streamMask >> i) & 0x1)
724 #endif
725             { //DTSX needs up to 16 channels to transfer metadata.
726                     for (j = 0; j < pAfWrt->sampleCount; j++)
727                     {
728                         pAfCb->data.sample[i][j] = pAfWrt->data.sample[i][j];
729                     }
731                     pAfCb->data.samsiz[i] = pAfWrt->data.samsiz[i];
732                 }
733             }
734             
735             // Update PCM samples per channel
736             pCb->numPcmSampsPerCh += pAfWrt->sampleCount;
737             
738             #ifdef CB_RW_OP_CAP_PP // debug
739             if (pCb->cb_opCnt < CB_OP_COUNT_MAX)
740             {
741                 if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL))
742                 {
743                     // log sample count
744                     pCb->cb_samples_op[pCb->cb_opCnt] = pAfWrt->sampleCount;
745                     pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_W;
746                     // log idxs
747                     pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx;
748                     pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx;
749                     pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance
750                     pCb->cb_opCnt++;
751                 }
752             }
753             #endif
755             // prepare metadata buffer pointers according to the metadata and buffer sizes
756             for (i = 0; i < pAfWrt->numPrivateMetadata; i++)
757             {
758                 UInt8 *nextMdBuf;
759                 if (i == 0)
760                 {
761                     nextMdBuf = (pAfCb->pafPrivateMetadata[0].pMdBuf + pAfWrt->pafPrivateMetadata[0].size);                    
762                 }
763                 else
764                 {
765                     nextMdBuf = (pAfCb->pafPrivateMetadata[i-1].pMdBuf + pAfWrt->pafPrivateMetadata[i-1].size);                    
766                 }
767                 if (nextMdBuf >= pCb->metaBufEnd) // metadata buffer overflow
768                 {
769                     pAfCb->pafPrivateMetadata[i].pMdBuf = pCb->metaBuf;
770                 }
771                 else if (i != 0)
772                 {
773                     pAfCb->pafPrivateMetadata[i].pMdBuf = nextMdBuf;
774                 }
775                 Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, sizeof(UInt8 *), Cache_Type_ALLD, 0);
776             }
778             // Write metadata to circular buffer
779             for (i = 0; i < pAfWrt->numPrivateMetadata; i++) // only copy numPrivateMetadata
780             {
781                 pAfCb->pafPrivateMetadata[i].offset = pAfWrt->pafPrivateMetadata[i].offset;
782                 pAfCb->pafPrivateMetadata[i].size   = pAfWrt->pafPrivateMetadata[i].size;
783                 memcpy(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].size);
784             }
786             Cache_inv(pAfCb->pafPrivateMetadata, pAfWrt->numPrivateMetadata*sizeof(PAF_PrivateMetadata *), Cache_Type_ALLD, 0); // FL: this is write back and invalidate??
787             Cache_wait();
788             for (i = 0; i < pAfCb->numPrivateMetadata; i++) // only write back numPrivateMetadata
789             {
790                 //Log_info4("cbWriteAf: AF: %d nummd: %d offset: %d size: %d ", pCb->afWrtIdx, pAfCb->numPrivateMetadata, pAfCb->pafPrivateMetadata[i].offset,  pAfCb->pafPrivateMetadata[i].size);
791                 Cache_wb(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
792             }
793             // update audio frame write index
794             pCb->afWrtIdx++;
795             if (pCb->afWrtIdx >= pCb->maxNumAfCb)
796             {
797                 pCb->afWrtIdx = 0;
798             }
800             pCb->afCb[pCb->afWrtIdx].data.sample[0] = &pAfCb->data.sample[pCb->maxAFChanNum - 1][pAfWrt->sampleCount];
801             if (pAfWrt->numPrivateMetadata > 0)
802             {
803                 pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf = pAfCb->pafPrivateMetadata[pAfWrt->numPrivateMetadata - 1].pMdBuf + pAfWrt->pafPrivateMetadata[pAfWrt->numPrivateMetadata - 1].size;
804             }
805             else
806             {
807                 pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf = pAfCb->pafPrivateMetadata[0].pMdBuf;
808                 Cache_wb(pCb->afCb , ASP_DECOP_CB_MAX_NUM_PCM_FRAMES*sizeof(PAF_AudioFrame *), Cache_Type_ALLD, 0);
809                 Cache_wait();
810             }
811             Cache_inv(pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf, sizeof(UInt8 *), Cache_Type_ALLD, 0);
812             Cache_wait();
813             // update number of audio frames in circular buffer
814             pCb->numAfCb++;
815             
816             // Update CB Lag index 
817             //if (pCb->afLagIdx < pCb->afInitialLag)
818             //{
819             //    pCb->afLagIdx += 1;
820             //}
821             
822             // Update CB primed flag.
823             // Calculate number of delta samples before allowing CB read.
824             if (pCb->primedFlag == 0)
825             {
826                 pCb->primedFlag = 1;
827                 
828                 // THD has variable number of AUs per frame. 
829                 // Some frames can be quite large (e.g. 96 AUs), and delta samples calculation small or even negative.
830                 // In this case, there won't be any reader hold off, and no nominal delay in the CB.
831                 pCb->deltaSamps = pCb->targetNDSamps;
832                 
833                 // debug
834                 //gSampleCountBuf[gPrimedFlagCnt] = pAfWrt->sampleCount;
835                 //gCalcDeltaSampsBuf[gPrimedFlagCnt] = pCb->deltaSamps;
836                 //if (gPrimedFlagCnt < 10)
837                 //    gPrimedFlagCnt++;
838             }
840             // Update delta samples using number of write audio frame samples.
841             if (pCb->deltaSamps > 0)
842             {
843                 pCb->deltaSamps = pCb->deltaSamps - pAfWrt->sampleCount;
844             }
845             
846             // Write back circular buffer configuration
847             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
848             // write back audio frame
849             Cache_wb(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
850             Cache_wb(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
851             Cache_wb(pAfCb->pafPrivateMetadata, pAfWrt->numPrivateMetadata*sizeof(PAF_PrivateMetadata *), Cache_Type_ALLD, 0);
852             Cache_wait();
853             // write back PCM data
854             for (i = 0; i < pCb->maxAFChanNum; i++)
855             {
856 #ifndef DTS_BUILD
857             if ((streamMask >> i) & 0x1)
858 #endif
859             {//DTSX needs up to 16 channels to transfer metadata.
860                     Cache_wb(pAfCb->data.sample[i], pAfWrt->sampleCount * sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
861                 }
862             }
863             Cache_wait();
865 #if 0 // (***) FL: shows timing of CB write
866             // debug
867             {
868                 static Uint8 toggleState = 0;
869                if (toggleState == 0)
870                    GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_99);
871                else
872                    GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_99);
873                toggleState = ~(toggleState);
874             }
875 #endif
877             Log_info3("wrote %d samples into AF %d sourceSel: %d", pAfCb->sampleCount, pCb->afWrtIdx, pCb->sourceSel);
878             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);
879         }
880         else
881         {
882             //
883             // Skip write in case of 0 sample count
884             //
885             
886             // writing audio frame w/ zero samples
887             // update stat
888             pCb->wrtAfZeroSampsCnt++;
890             // Write back circular buffer configuration
891             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
892             Cache_wait();
893         }
894     //}
895     //else if (pCb->readerActiveFlag == 0)
896     if (pCb->readerActiveFlag == 0)
897     {
898         //
899         // Reader inactive, don't write to circular buffer or check OVRflow.
900         //
901         
902         // writing AF w/ inactive reader
903         // update stat
904         pCb->wrtAfReaderInactiveCnt++;
906         // Write back circular buffer configuration
907         Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
908         Cache_wait();
909     }
911     // Leave the gate
912     GateMP_leave(gateHandle, key);
914     //Log_info2("cbWriteAf:gate leave, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug
916     return ASP_DECOP_CB_SOK;
919 #if 0
920 // Get next audio frame to write in circular buffer
921 Int cbGetNextWriteAf(
922     PAF_AST_DecOpCircBufCtl *pCbCtl,    // decoder output circular buffer control
923     Int8 cbIdx,                         // decoder output circular buffer index
924     PAF_AudioFrame **ppAfWrt            // audio frame next to be written
927     IArg key;
928     GateMP_Handle gateHandle;
929     PAF_AST_DecOpCircBuf *pCb;
931     // Get gate handle
932     gateHandle = pCbCtl->gateHandle;
933     // Enter gate
934     key = GateMP_enter(gateHandle);
936     // Get circular buffer base pointer
937     pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]);
939     // get pointer to current audio frame in circular buffer
940     *ppAfWrt = &pCb->afCb[pCb->afWrtIdx];
941     
942     // update audio frame write index
943     pCb->afWrtIdx++;
944     if (pCb->afWrtIdx > pCb->maxNumAfCb)
945     {
946         pCb->afWrtIdx = 0;
947     }    
948     
949     // Leave the gate
950     GateMP_leave(gateHandle, key);
952     return ASP_DECOP_CB_SOK;
954 #endif
956 // Init last audio frame configuration info 
957 static Void cbInitLastAfInfo(
958     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer control
959     PAF_AudioFrame *pAfInit     // audio frame used for init
962     memset(&pCb->lastAf, 0, sizeof(PAF_AudioFrame));
963     
964     pCb->lastAf.sampleDecode = pAfInit->sampleDecode;
965     pCb->lastAf.sampleRate = pAfInit->sampleRate;
966     pCb->lastAf.channelConfigurationRequest.full = pAfInit->channelConfigurationRequest.full;
967     pCb->lastAf.channelConfigurationStream.full = pAfInit->channelConfigurationStream.full;