]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - pasdk/test_dsp/framework/audioStreamOutDec.c
PASDK-568: added logic and encoder wrapper to handle output buffer wrapping around
[processor-sdk/performance-audio-sr.git] / pasdk / test_dsp / framework / audioStreamOutDec.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 */
35 /*
36  *  ======== audioStreamOutDec.c ========
37  */
39 #include <string.h> // for memset
40 #include <xdc/runtime/Log.h>
41 #include <xdc/std.h>
43 #include "paferr.h"
44 #include "pafsio_ialg.h"
45 #include "pce.h"
46 #include "stdasp.h"
47 #include "asperr.h"
49 #include "aspDecOpCircBuf_master.h"
50 #include "audioStreamProc_common.h"
51 #include "audioStreamOutProc.h"
52 #include "audioStreamOutIo.h"
53 #include "audioStreamOutDec.h"
54 #include "ioConfig.h"    //TODO: remove this header
55 #include "ioPhy.h"
57 #define ENC_Handle PCE_Handle /* works for all: PCE */
59 // debug
60 #include "evmc66x_gpio_dbg.h"
61 #include "dbgCapAf.h"
62 PAF_AST_DecOpCircBufStats gCbStats; // circular buffer stats
64 // debug
65 // Underflow threshold before circular buffer reset and return error to Top-Level FSM
66 #define DEC_OP_CB_RDAF_UND_THR  ( 80 ) // arbitrary setting
67 UInt32 gCbReadAfErr         =0; // read circular buffer error count, not including underflows
68 UInt32 gDecOpCbRdAfUnd      =0; // decoder output circular buffer underflow count
69 UInt32 gMaxDecOpCbRdAfUnd   =0; // max (consecutive) decoder output circular buffer underflow count
70 UInt32 gMasterCbResetCnt    =0; // master circular buffer reset count
73 //   Purpose:   Common Function for processing algorithm chains
74 static Int streamChainFunction(
75     const PAF_ASOT_Params *pP, 
76     const PAF_ASOT_Patchs *pQ, 
77     PAF_ASOT_Config *pAsotCfg, 
78     Int iChainFrameFxns, 
79     Int abortOnError, 
80     Int logArg
81 );
83 //   Purpose:   ASOT Function for Output reset
84 Int asopDecOutProcReset(
85     const PAF_ASOT_Params *pP, 
86     const PAF_ASOT_Patchs *pQ, 
87     PAF_ASOT_Config *pAsotCfg, 
88     Int frame
89 )
90 {
91     PAF_AST_Config *pAstCfg;    // ASIT/ASOT/ASDT shared configuration
92     PAF_AST_IoOut *pOut;        // ASOT IO configuration
93     Int as;                     // Audio Stream Number (1, 2, etc.) */
94     Int zO, zS;
95     Int z;                      // encode counter
96     Int errno;                  // error number
97     Int status;                 // status code
98     
99     status = ASOP_DOP_SOK;
100     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
101     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
102     as = pAstCfg->as;
104     for (z=ENCODE1; z < ENCODEN; z++) 
105     {
106         zO = pP->outputsFromEncodes[z];
107         zS = pP->streamsFromEncodes[z];
108         if (pOut[zO].hIoPhy && pAstCfg->xEnc[z].encodeStatus.mode) 
109         {
110             Int select = pAstCfg->xEnc[z].encodeStatus.select;
111             ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select];
112             ENC_Handle enc = (ENC_Handle )encAlg;
114             TRACE_VERBOSE1("AS%d: PAF_ASOT_outputReset: initializing encode", as+zS);
116             if (encAlg->fxns->algActivate)
117             {
118                 encAlg->fxns->algActivate(encAlg);
119             }
120             
121             if (enc->fxns->reset)
122             {
123                 errno = enc->fxns->reset(enc, NULL, 
124                     &pAstCfg->xEnc[z].encodeControl, 
125                     &pAstCfg->xEnc[z].encodeStatus);
126                 if (errno)
127                 {
128                     status = ASOP_DOP_ERR_RESET_ENCRESET;
129                     return status;
130                 }
131             }
132         }
133     }    
134     
135     return status;
138 //   Purpose:   Reset ASP chain, execute ENC info, and initiate Output
139 Int asopDecOutProcInfo1(
140     const PAF_ASOT_Params *pP, 
141     const PAF_ASOT_Patchs *pQ, 
142     PAF_ASOT_Config *pAsotCfg, 
143     Int frame 
146     PAF_AST_Config *pAstCfg;    // ASIT/ASOT/ASDT shared configuration
147     PAF_AST_IoOut *pOut;        // ASOT IO configuration
148     Int zO, zS; 
149     Int z;                      // decode/encode counter
150     Int errno;                  // error number
151     Int status;                 // status code
152     
153     status = ASOP_DOP_SOK;
154     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
155     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
157     //
158     // Reset ASP chain
159     //
160     TRACE_VERBOSE0("asopDecOutProcInfo1: calling streamChainFunction.");
161     errno = streamChainFunction(pP, pQ, pAsotCfg, PAF_ASP_CHAINFRAMEFXNS_RESET, 1, frame);  // SRC reset is called inside;
162     if (errno)
163     {
164         TRACE_TERSE1("asopDecOutProcInfo1: streamChainFunction returns errno 0x%x ", errno);
165         status = ASOP_DOP_ERR_INFO1_ASPCHAINRESET;
166         return status;
167     }
169     //
170     // Encode Info
171     //
172     TRACE_VERBOSE0("asopDecOutProcInfo1: calling enc->info.");
173     for (z=ENCODE1; z < ENCODEN; z++) 
174     {
175         Int zO = pP->outputsFromEncodes[z];
176         if (pOut[zO].hIoPhy && pAstCfg->xEnc[z].encodeStatus.mode) 
177         {
178             Int select = pAstCfg->xEnc[z].encodeStatus.select;
179             ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select];
180             ENC_Handle enc = (ENC_Handle )encAlg;
181             
182             if (enc->fxns->info)
183             {
184                 errno = enc->fxns->info(enc, NULL,
185                     &pAstCfg->xEnc[z].encodeControl, 
186                     &pAstCfg->xEnc[z].encodeStatus);
187                 if (errno)
188                 {
189                     TRACE_TERSE1("asopDecOutProcInfo1: info returns errno 0x%x ", errno);
190                     status = ASOP_DOP_ERR_INFO1_ENCINFO;
191                     return status;
192                 }
193             }
194         }
195     }
197     //
198     // Initialize Output components
199     //
201     // FL, New IO: Something needed in new IO
202     // FL, New IO: API for multiple Outputs
203     // FL, New IO: SIO calls need to be checked
204     errno = asopSetCheckRateX(pP, pQ, pAsotCfg, 0);
205     if (errno)
206     {
207         TRACE_TERSE1("asopDecOutProcInfo1: info returns errno 0x%x ", errno);
208         status = ASOP_DOP_ERR_INFO1_SETRATEX;
209         return status;
210     }
211     
212     // FL, New IO: API for multiple Outputs
213     // FL, New IO: SIO calls need to be checked
214     errno = asopStartOutput(pP, pQ, pAsotCfg);
215     if (errno)
216     {
217         TRACE_TERSE1("asopDecOutProcInfo1: asopStartOutput returns errno 0x%x ", errno);
218         status = ASOP_DOP_ERR_INFO1_STARTOUTPUT;
219         return status;
220     }    
221     
222     // Find first Output associated with Master Stream
223     zO = OUTPUT1;
224     for (z=ENCODE1; z < ENCODEN; z++)
225     {
226         zS = pP->streamsFromEncodes[z]; // get Stream associated with Encoder
227         if (zS == pAstCfg->masterStr)
228         {
229             // This Encoder is associated with Master Stream.
230             // Note other Encoder can also be associated with Master Stream.
231             zO = pP->outputsFromEncodes[z]; // get Output associated with Encoder
232         }
233     }
234     
235     // Initialize Output buffer configuration
236     errno = asopInitOutBufConfig(&pAstCfg->xOut[zO], &pOut[zO]);
237     if (errno)
238     {
239         TRACE_TERSE1("asopDecOutProcInfo1: asopInitOutBufConfig returns errno 0x%x ", errno);
240         status = ASOP_DOP_ERR_INFO1_STARTOUTPUT;
241         return status;
242     }
243     
244     return status;
245 } //asopDecOutProcInfo1
247 //   Purpose:   Re-initiate Output
248 Int asopDecOutProcInfo2(
249     const PAF_ASOT_Params *pP, 
250     const PAF_ASOT_Patchs *pQ,  
251     PAF_ASOT_Config *pAsotCfg, 
252     Int frame 
255     PAF_AST_Config *pAstCfg;    // ASIT/ASOT/ASDT shared configuration
256     PAF_AST_IoOut  *pOut;       // ASIO IO configuration
257     Int zO, zS;
258     Int z;                      // decode/encode counter
259     Int errno;                  // error number
260     Int status;                 // status code
261     
262     status = ASOP_DOP_SOK;
263     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
264     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
266     // FL, New IO: Something needed in new IO
267     // FL, New IO: API for multiple Outputs
268     // FL, New IO: SIO calls need to be checked
269     errno = asopSetCheckRateX(pP, pQ, pAsotCfg, 0);
270     if (errno)
271     {
272         TRACE_TERSE1("asopDecOutProcInfo2: info returns errno 0x%x ", errno);
273         status = ASOP_DOP_ERR_INFO2_SETRATEX;
274         return status;
275     }
276     
277     // Find first Output associated with Master Stream
278     zO = OUTPUT1;
279     for (z=ENCODE1; z < ENCODEN; z++)
280     {
281         zS = pP->streamsFromEncodes[z]; // get Stream associated with Encoder
282         if (zS == pAstCfg->masterStr)
283         {
284             // This Encoder is associated with Master Stream.
285             // Note other Encoder can also be associated with Master Stream.
286             zO = pP->outputsFromEncodes[z]; // get Output associated with Encoder
287         }
288     }
289     
290     // Start output transfer
291     // FL, New IO: API for single Output
292     asopPhyTransferStart(&pOut[zO]);
293     
294     return status;
297 // Initialize Decoder output processing
298 Int asopDecOutProcInit(
299     const PAF_ASOT_Params *pP,
300     const PAF_ASOT_Patchs *pQ,
301     PAF_ASOT_Config *pAsotCfg, 
302     Int frame 
305     PAF_AST_DecOpCircBufCtl *pCbCtl;    // Decoder output circular buffer control
306     Int z;                              // decode counter
307     Int errno;                          // error number
308     Int status;                         // status code
310     status = ASOP_DOP_SOK;
311     pCbCtl = &pAsotCfg->pAspmCfg->decOpCircBufCtl; // get pointer to circular buffer control
313     for (z=DECODE1; z < DECODEN; z++)
314     {
315         // Initialize decoder output circular buffer for stream reads
316         errno = cbInitStreamRead(pCbCtl, z);
317         if (errno)
318         {
319             TRACE_TERSE1("asopDecOutProcInit:cbInitStreamRead() error=%d", errno);
320             status = ASOP_DOP_ERR_INIT_CBINITREAD;
321             return status;
322         }
323         
324         // Start decoder output circular buffer reads
325         errno = cbReadStart(pCbCtl, z);
326         if (errno)
327         {
328             TRACE_TERSE1("asopDecOutProcInit:cbReadStart() error=%d", errno);
329             status = ASOP_DOP_ERR_INIT_CBREADSTART;
330             return status;
331         }
332         
333         gCbReadAfErr=0;         // reset read circular buffer error count
334         gDecOpCbRdAfUnd=0;      // reset decoder output circular buffer underflow count
335         gMaxDecOpCbRdAfUnd=0;   // reset max decoder output circular buffer underflow count
336         gMasterCbResetCnt=0;    // reset master circular buffer reset count
338         // debug, log circular buffer control variables
339         cbLog(pCbCtl, z, 1, "asopDecOutProcInit:cbReadStart");
340     }
341         
342     return status;
343 } /* asopDecOutProcInit */
345 // Process Decoder output audio data using ASP chain
346 Int asopDecOutProcStream(
347     const PAF_ASOT_Params *pP, 
348     const PAF_ASOT_Patchs *pQ, 
349     PAF_ASOT_Config *pAsotCfg, 
350     Int frame 
353     PAF_AST_Config *pAstCfg;
354     PAF_AST_DecOpCircBufCtl *pCbCtl;    // Decoder output circular buffer control
355     Int z;                              // decode/stream counter
356     PAF_AudioFrame *pAfRd;
357     //PAF_AST_DecOpCircBufStats cbStats;  // circular buffer statistics
358     Int errno;                          // error number
359     Int status;                         // status code
361     status = ASOP_DOP_SOK;
362     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration    
363     pCbCtl = &pAsotCfg->pAspmCfg->decOpCircBufCtl; // get pointer to circular buffer control
364     
365     for (z=DECODE1; z < DECODEN; z++) 
366     {
367         Int zS = pP->streamsFromDecodes[z];
368         
369         //
370         // Read decoder output circular buffer
371         //
372         pAfRd = pAstCfg->xStr[zS].pAudioFrame;
373         //GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);       // debug
374         errno = cbReadAf(pCbCtl, z, pAfRd);
375         //GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);     // debug
376         if ((errno < 0) && 
377             (errno != ASP_DECOP_CB_AF_READ_UNDERFLOW) && 
378             (errno != ASP_DECOP_CB_PCM_READ_UNDERFLOW))
379         {
380             gCbReadAfErr++;
381             TRACE_TERSE1("asopDecOutProcStream:cbReadAf() error=%d", errno);
382             //SW_BREAKPOINT; // debug
383             status = ASOP_DOP_ERR_STREAM_CBREAD;
384             return status;
385         }
387         // Handle underflows
388         if ((errno == ASP_DECOP_CB_AF_READ_UNDERFLOW) ||
389             (errno == ASP_DECOP_CB_PCM_READ_UNDERFLOW))
390         {
391             // FL: Need to check behavior of cbReset() on exit/re-entry into Output processing.
392             gDecOpCbRdAfUnd++; // increment circular buffer underflow count
393             if (gDecOpCbRdAfUnd >= DEC_OP_CB_RDAF_UND_THR) 
394             {
395                 // Underflow count above threshold.
396                 // (1) set max underflow count to threshold
397                 // (2) reset underflow count
398                 // (3) reset circular buffer
399                 
400                 gMaxDecOpCbRdAfUnd = DEC_OP_CB_RDAF_UND_THR; // update max underflow count
401                 gDecOpCbRdAfUnd = 0; // reset underflow count
403                 // Reset circular buffer
404                 cbReset(pCbCtl, z);
405                 gMasterCbResetCnt++; // increment master circular buffer reset count
406                 Log_info0("asopDecOutProcStream:cbReset()");
407             
408                 status = ASOP_DOP_ERR_STREAM_CBREADUNDTHR;
409                 return status;
410             }
411         }
412         else if ((errno == ASP_DECOP_CB_SOK) && (gDecOpCbRdAfUnd > 0))
413         {
414             // No underflow detected.
415             // update max underflow count,
416             // reset underflow count
417             
418             // update max underflow count
419             if (gDecOpCbRdAfUnd > gMaxDecOpCbRdAfUnd)
420             {
421                 gMaxDecOpCbRdAfUnd = gDecOpCbRdAfUnd;
422             }
423             gDecOpCbRdAfUnd = 0; // reset circular buffer underflow count
424         }
425         //Log_info0("asopDecOutProcStream:cbReadAf() complete.");
426         //GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);   // debug
427         Log_info0("asopDecOutProcStream:cbReadAf() complete.");
428         
429 #if 0 // debug
430             // Shows timing of CB read
431             // ADC B8
432             {
433                 static Uint8 toggleState = 0;
434                 if (toggleState == 0)
435                     GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);
436                 else
437                     GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);
438                 toggleState = ~(toggleState);
439             }
440 #endif
442         // debug, get circular buffer statistics
443         //cbGetStats(pCbCtl, z, &cbStats);
444         cbGetStats(pCbCtl, z, &gCbStats);
446         // debug
447         cbLog(pCbCtl, z, 1, "asopDecOutProcStream:cbReadAf()");
448         
449 #if 1 // debug, capture audio frame
450         if (capAfWrite(pAfRd, PAF_LEFT) != CAP_AF_SOK)
451 //      if (capAfWrite(pAfRd, PAF_RIGHT) != CAP_AF_SOK)
452         {
453             Log_info0("asopDecOutProcStream:capAfWrite() error");
454         }
455 #endif
456     }
457             
458     TRACE_VERBOSE0("asopDecOutProcStream: calling streamChainFunction()");
459     errno = streamChainFunction(pP, pQ, pAsotCfg, PAF_ASP_CHAINFRAMEFXNS_APPLY, 1, frame);
460     if (errno)
461     {
462         TRACE_TERSE1("asopDecOutProcStream: streamChainFunction() returns errno 0x%x ", errno);
463         status = ASOP_DOP_ERR_STREAM_ASPCHAINAPPLY;
464         return status;
465     }
467 #if 0 // debug, capture audio frame
468     if (capAfWrite(pAfRd, PAF_LEFT) != CAP_AF_SOK)
469     {
470         Log_info0("asopDecOutProcStream:capAfWrite() error");
471     }
472 #endif
473     
474     return status;
475 } //asopDecodeStream
477 // -----------------------------------------------------------------------------
478 // ASOT Decoding Function - Encode Processing
479 //
480 //   Name:      PAF_ASOT_decodeEncode
481 //   Purpose:   Decoding Function for processing of audio frame data by the
482 //              Encode Algorithm.
483 //   From:      AST Parameter Function -> decodeProcessing
484 //   Uses:      See code.
485 //   States:    x
486 //   Return:    Error number in standard or SIO form (0 on success).
487 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
488 //              * State information as per parent.
489 //
490 Int asopDecOutProcEncode(
491     const PAF_ASOT_Params *pP, 
492     const PAF_ASOT_Patchs *pQ, 
493     PAF_ASOT_Config *pAsotCfg, 
494     Int frame 
497     PAF_AST_Config *pAstCfg;    // ASIT/ASOT/ASDT shared configuration
498     PAF_AST_IoOut  *pOut;       // ASIO IO configuration
499     Int as;                     // Audio Stream Number (1, 2, etc.)
500     Int zX, zE, zS;
501     Int z;                      // encode/output counter
502     Int errno;                  // error number
503     Int status;                 // status code
504     //ioPhyCtl_t ioPhyCtl;
506     status = ASOP_DOP_SOK;
507     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
508     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
509     as = pAstCfg->as;
511     // Await output buffers (but not first time)
512     for (z=OUTPUT1; z < OUTPUTN; z++) 
513     {
514         // determine encoder associated with this output
515         zE = z;
516         for (zX = ENCODE1; zX < ENCODEN; zX++) 
517         {
518             if (pP->outputsFromEncodes[zX] == z) 
519             {
520                 zE = zX;
521                 break;
522             }
523         }
524         zS = pP->streamsFromEncodes[zE];
526         if (pOut[z].hIoPhy)
527         {
528             uint32_t phyXferSizeOld;
530             // update length (e.g. ARC may have changed) - moved out of this function
531 /*            pAstCfg->xOut[z].outBufConfig.lengthofFrame =
532                 pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount;
533 */
534             TRACE_GEN2("asopDecodeEncode: AS%d: processing frame %d -- idle", as+zS, frame);
536 #if 0 // FL, New IO: add similar thing to be figured out
537             // Update framework Phy transfer size
538             phyXferSizeOld = pOut[z].phyXferSize;
539             pOut[z].phyXferSize = pAstCfg->xOut[z].outBufConfig.lengthofFrame * pOut[z].stride * WORD_SIZE_PCM;
540             // Update IO Phy transfer size            
541             ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
542             ioPhyCtl.params.xferFrameSize = pOut[z].phyXferSize;
543             ioPhyControl(pOut[z].hIoPhy, &ioPhyCtl);
544             // Update IO Buff delay to match Phy transfer size
545             if(pOut[z].phyXferSize != phyXferSizeOld) {
546                 ioBuffAdjustDelay(pOut[z].hIoBuff, pOut[z].phyXferSize * (NUM_PRIME_XFERS+1));
547             }
548 /*
549             errno = SIO_reclaim(pAstCfg->xOut[z].hTxSio,(Ptr *) &pAstCfg->xOut[z].pOutBuf, NULL);
550             if (errno < 0)
551             {
552                 SIO_idle(pAstCfg->xOut[z].hTxSio);
553                 TRACE_TERSE2("PAF_ASOT_decodeEncode: AS%d: SIO_reclaim returns error %d", as+zS, -errno);
554                 return -errno; // SIO negates error codes
555             }
556 */
557 #endif
559 #if 0 // debug 
560             // Shows timing of Output Tx SIO reclaim
561             // ADC B8
562             {
563                 static Uint8 toggleState = 0;
564                 if (toggleState == 0)
565                     GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);
566                 else
567                     GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);
568                 toggleState = ~(toggleState);
569             }
570 #endif            
571         }
572         else 
573         {
574             TRACE_VERBOSE2("AS%d: asopDecodeEncode: processing frame %d -- idle <ignored>", as+zS, frame);
575         }
576     }
578     // Encode data
579     for (z=ENCODE1; z < ENCODEN; z++) 
580     {
581 #if 0 // debug, capture audio frame
582         PAF_AudioFrame *pAfRd;
583         pAfRd = pAstCfg->xEnc[z].encodeInStruct.pAudioFrame;
584         if (capAfWrite(pAfRd, PAF_LEFT) != CAP_AF_SOK)
585         {
586             Log_info0("asopDecOutProcEncode:capAfWrite() error");
587         }
588 #endif
589         
590         Int zS = pP->streamsFromEncodes[z];
591         (void)zS; // clear compiler warning in case not used with tracing disabled
592         if (pAstCfg->xEnc[z].encodeStatus.mode) 
593         {
594             Int select = pAstCfg->xEnc[z].encodeStatus.select;
595             ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select];
596             ENC_Handle enc = (ENC_Handle)encAlg;
597             if (select != pAstCfg->xEnc[z].encodeControl.encActive)
598             {
599                 pAstCfg->xEnc[z].encodeControl.encActive = select;
600                 TRACE_TERSE0("asopDecodeEncode: AS%d: changing selected encoder, return error");
601                 return ASOP_DOP_ERR_ENCODE_ENCSELECT;
602             }
603             TRACE_GEN2("asopDecodeEncode: AS%d: processing frame %d -- encode", as+zS, frame);
605             // (MID 1933) temp. workaround for PCE2
606             pAstCfg->xEnc[z].encodeInStruct.pAudioFrame->data.nChannels = PAF_MAXNUMCHAN;
607             //pAstCfg->xEnc[z].encodeInStruct.pAudioFrame->data.nChannels = 2;   //JXTODO: make this correct
609             if (enc->fxns->encode)
610             {
611                 pAstCfg->xEnc[z].encodeOutStruct.bypassFlag =
612                         pP->z_pEncodeStatus[z]->encBypass;
613                 errno = enc->fxns->encode(enc, NULL, 
614                     &pAstCfg->xEnc[z].encodeInStruct, 
615                     &pAstCfg->xEnc[z].encodeOutStruct);
616                 if (errno)
617                 {
618                     if (errno != PCEERR_OUTPUT_POINTERNULL)    // errno = PCEERR_OUTPUT_RESULTRANGE
619                     {
620                         TRACE_TERSE1("asopDecodeEncode: encode returns error %d", errno);
621                         status = ASOP_DOP_ERR_ENCODE_ENC;
622                         return status;
623                     }
624                 }
625             }
626         }
627         else 
628         {
629             TRACE_VERBOSE2("asopDecodeEncode: AS%d: processing frame %d -- encode <ignored>",
630                 as+pP->streamsFromEncodes[z], frame);
631         }
632     }
634     // add debug code to dump output samples to memory
636     // Transmit data
637     for (z=OUTPUT1; z < OUTPUTN; z++) 
638     {
639         // determine stream associated with this output
640         zE = z;
641         for (zX = ENCODE1; zX < ENCODEN; zX++) 
642         {
643             if (pP->outputsFromEncodes[zX] == z) 
644             {
645                 zE = zX;
646                 break;
647             }
648         }
649         zS = pP->streamsFromEncodes[zE];
651 #if 0  // FL, New IO: Something needed in new IO
652         if (pAstCfg->xOut[z].hTxSio) 
653         {
654             TRACE_GEN2("PAF_ASOT_decodeEncode: AS%d: processing frame %d -- output", as+zS, frame);
655             //GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106);       // debug
656             errno = SIO_issue(pAstCfg->xOut[z].hTxSio, 
657                 &pAstCfg->xOut[z].outBufConfig, sizeof (pAstCfg->xOut[z].outBufConfig), 0);
658             //GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106);     // debug
659             if (errno)
660             {
661                 SIO_idle(pAstCfg->xOut[z].hTxSio);
662                 if (errno == 0x105)     // 0x105 == RINGIO_EBUFFULL
663                 {
664                     //statStruct_LogFullRing(STATSTRUCT_AS1_F2);
665                     TRACE_TERSE1("PAF_ASOT_decodeEncode: SIO_idle returned RINGIO_EBUFFULL (0x%x)", errno);
666                 }
667                 if (errno > 0)
668                 {
669                     TRACE_TERSE1("PAF_ASOT_decodeEncode: return error 0x%x line %d", errno);
670                     return (ASPERR_ISSUE + (z << 4));
671                 }
672                 else if (errno < 0)
673                 {
674                     TRACE_TERSE1("PAF_ASOT_decodeEncode: return neg error 0x%x line %d", -errno);
675                     return -errno; // SIO negates error codes
676                 }
677             }
678             if (errno > 0)
679             {
680                 return (ASPERR_ISSUE + (z << 4));
681             }
682             else if (errno < 0)
683             {
684                 return -errno; // SIO negates error codes
685             }
686         }
687         else 
688         {
689             TRACE_GEN2("PAF_ASOT_decodeEncode: AS%d: processing frame %d -- output <ignored>", as+zS, frame);
690         }
691 #endif
692     }
694     return status;
695 } /* asopDecodeEncode */
697 //   Purpose: Check if output processing of current stream is complete
698 Int asopDecOutProcFinalTest(
699     const struct PAF_ASOT_Params *pP, 
700     const struct PAF_ASOT_Patchs *pQ, 
701     struct PAF_ASOT_Config *pAsotCfg, 
702     Int frame
705     PAF_AST_DecOpCircBufCtl *pCbCtl;    // decoder output circular buffer control
706     Int8 drainedFlag;                   // CB drained indicator flag
707     Int zMD;                            // master Dec index
708     Int errno;                          // error number
709     Int status;                         // status code
710     
711     status = ASOP_DOP_SOK;
712     pCbCtl = &pAsotCfg->pAspmCfg->decOpCircBufCtl; // get pointer to circular buffer control
713     zMD = pAsotCfg->pAstCfg->masterDec; // get master Dec index
715     // Check circular buffer drain state
716     errno = cbCheckDrainState(pCbCtl, zMD, &drainedFlag);
717     if (errno)
718     {
719         status = ASOP_DOP_ERR_FINALTEST_CBCHKDRAIN;
720         return status;
721     }
722     else if (drainedFlag == 1) // errno == 0
723     {
724         status = ASOP_DOP_ERR_FINALTEST_CBDRAINED;
725         return status;
726     }
727     
728     return status;
729 }    
731 // -----------------------------------------------------------------------------
732 // ASOT Decoding Function - Stream-Final Processing
733 //
734 //   Name:      PAF_ASOT_decodeComplete
735 //   Purpose:   Decoding Function for terminating the decoding process.
736 //   From:      AST Parameter Function -> decodeProcessing
737 //   Uses:      See code.
738 //   States:    x
739 //   Return:    0.
740 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
741 //              * State information as per parent.
742 //
743 Int asopDecOutProcComplete(
744     const PAF_ASOT_Params *pP, 
745     const PAF_ASOT_Patchs *pQ, 
746     PAF_ASOT_Config *pAsotCfg, 
747     Int frame
750     PAF_AST_Config *pAstCfg;            // ASIT/ASOT/ASDT shared configuration
751     PAF_AST_IoOut  *pOut;               // ASIO IO configuration
752     PAF_AST_DecOpCircBufCtl *pCbCtl;    // Decoder output circular buffer control
753     Int as;                             // Audio Stream Number (1, 2, etc.)
754     Int z;                              // decode/encode counter
755     Int errno;                          // error number
756     Int status;                         // status code
757     
758     status = ASOP_DOP_SOK;
759     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
760     as = pAstCfg->as;
761     (void)as;  // clear compiler warning in case not used with tracing disabled
763     pCbCtl = &pAsotCfg->pAspmCfg->decOpCircBufCtl; // get pointer to circular buffer control
764     
765     for (z=DECODE1; z < DECODEN; z++)
766     {
767         // Stop decoder output circular buffer reads
768         errno = cbReadStop(pCbCtl, z);
769         if (errno)
770         {
771             TRACE_TERSE1("asopDecOutProcComplete:cbReadStop() error=%d", errno);
772             //SW_BREAKPOINT; // debug
773             status = ASOP_DOP_ERR_COMPLETE_CBREADSTOP;
774             return status;
775         }
776         // debug
777         cbLog(pCbCtl, z, 1, "asopDecOutProcComplete:cbReadStop");
778     }
779     
780     streamChainFunction(pP, pQ, pAsotCfg, PAF_ASP_CHAINFRAMEFXNS_FINAL, 0, frame);
782     for (z=ENCODE1; z < ENCODEN; z++) 
783     {
784         Int zO = pP->outputsFromEncodes[z];
785         if (pOut[zO].hIoPhy && pAstCfg->xEnc[z].encodeStatus.mode) 
786         {
787             Int select = pAstCfg->xEnc[z].encodeStatus.select;
788             ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select];
789 #ifdef PAF_ASP_FINAL
790             ENC_Handle enc = (ENC_Handle)encAlg;
791 #endif /* PAF_ASP_FINAL */
792             TRACE_VERBOSE1("asopDecOutProcComplete: AS%d: finalizing encode", as+z);
793 #ifdef PAF_ASP_FINAL
794             if (enc->fxns->final)
795             {
796                 enc->fxns->final(enc, NULL, &pAstCfg->xEnc[z].encodeControl,
797                     &pAstCfg->xEnc[z].encodeStatus);
798             }
799 #endif /* PAF_ASP_FINAL */
800             if (encAlg->fxns->algDeactivate)
801             {
802                 encAlg->fxns->algDeactivate(encAlg);
803             }
804         }
805         else 
806         {
807             TRACE_VERBOSE1("asopDecOutProcComplete: AS%d: finalizing encode <ignored>", as+z);
808         }
809     }
811     // wait for remaining data to be output
812     errno = asopStopOutput(pP, pQ, pAsotCfg);
813     if (errno)
814     {
815         status = ASOP_DOP_ERR_COMPLETE_STOPOUTPUT;
816         return status;
817     }
819     return status;
820 } //asopDecOutProcComplete
822 // -----------------------------------------------------------------------------
823 // ASOT Decoding Function - Encode Command Processing
824 //
825 //   Name:      PAF_ASOT_encodeCommand
826 //   Purpose:   Decoding Function for processing Encode Commands.
827 //   From:      AST Parameter Function -> decodeProcessing
828 //   Uses:      See code.
829 //   States:    x
830 //   Return:    0.
831 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
832 //              * Command execution.
833 //              * SIO control errors.
834 //              * Error number macros.
835 //
836 Int asopDecOutProcEncodeCommand(
837     const PAF_ASOT_Params *pP, 
838     const PAF_ASOT_Patchs *pQ, 
839     PAF_ASOT_Config *pAsotCfg
842     PAF_AST_Config *pAstCfg;
843     Int as;                     // Audio Stream Number (1, 2, etc.)
844     Int zO, zS;
845     Int z;                      // encode counter
846     Int errno = 0;              // error number
847     Int status;                 // status code
849     status = ASOP_DOP_SOK;
850     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
851     as = pAstCfg->as;
853     for (z=ENCODE1; z < ENCODEN; z++) 
854     {
855         zO = pP->outputsFromEncodes[z];
856         zS = pP->streamsFromEncodes[z];
857         if (!(pAstCfg->xEnc[z].encodeStatus.command2 & 0x80)) 
858         {
859             switch (pAstCfg->xEnc[z].encodeStatus.command2) 
860             {
861                 case 0: // command none - process
862                     pAstCfg->xEnc[z].encodeStatus.command2 |= 0x80;
863                     break;
864                 case 1: // mute command
865                     TRACE_VERBOSE2("asopDecOutProcEncodeCommand: AS%d: encode command mute (0x%02x)", as+zS, 1);
866 #if 0 // FL, New IO: Something needed in new IO
867                     if ((pAstCfg->xOut[zO].outBufStatus.audio & 0x0f) != PAF_OB_AUDIO_QUIET
868                         && pAstCfg->xOut[zO].hTxSio
869                         && (errno = SIO_ctrl (pAstCfg->xOut[zO].hTxSio, PAF_SIO_CONTROL_MUTE, 0))) 
870                     {
871                         errno = (errno & 0xff) | ASPERR_MUTE;
872                         /* convert to sensical errno */
873                         TRACE_TERSE1("asopDecOutProcEncodeCommand: AS%d: SIO control failed (mute)", as+zS);
874                         TRACE_TERSE2("asopDecOutProcEncodeCommand: AS%d: errno = 0x%04x <ignored>", as+zS, errno);
875                     }
876                     else 
877                     {
878                         pAstCfg->xOut[zO].outBufStatus.audio |= PAF_OB_AUDIO_MUTED;
879                     }
880 #endif
881                     pAstCfg->xEnc[z].encodeStatus.command2 |= 0x80;
882                     break;
883                 case 2: // unmute command
884                     TRACE_VERBOSE2("asopDecOutProcEncodeCommand: AS%d: encode command unmute (0x%02x)", as+zS, 2);
885 #if 0 // FL, New IO: Something needed in new IO
886                     if ((pAstCfg->xOut[zO].outBufStatus.audio & 0x0f) != PAF_OB_AUDIO_QUIET
887                         && pAstCfg->xOut[zO].hTxSio
888                         && (errno = SIO_ctrl (pAstCfg->xOut[zO].hTxSio, PAF_SIO_CONTROL_UNMUTE, 0))) 
889                     {
890                         errno = (errno & 0xff) | ASPERR_MUTE;
891                         /* convert to sensical errno */
892                         TRACE_TERSE1("asopDecOutProcEncodeCommand: AS%d: SIO control failed (unmute)", as+zS);
893                         TRACE_TERSE2("asopDecOutProcEncodeCommand: AS%d: errno = 0x%04x <ignored>", as+zS, errno);
894                     }
895                     else 
896                     {
897                         pAstCfg->xOut[zO].outBufStatus.audio &= ~PAF_OB_AUDIO_MUTED;
898                     }
899 #endif
900                     pAstCfg->xEnc[z].encodeStatus.command2 |= 0x80;
901                     break;
902                 default: // command unknown - ignore
903                     break;
904             }
905         }
906     }
908     //ERRNO_RPRT (TaskAsop, errno);
910     return status;
911 } //asopDecOutProcEncodeCommand
913 // -----------------------------------------------------------------------------
914 // ASOT Decoding Function Helper - Chain Processing
915 //
916 //   Name:      PAF_ASOT_streamChainFunction
917 //   Purpose:   Common Function for processing algorithm chains.
918 //   From:      AST Parameter Function -> decodeInfo1
919 //              AST Parameter Function -> decodeStream
920 //              AST Parameter Function -> decodeComplete
921 //   Uses:      See code.
922 //   States:    x
923 //   Return:    Error number in standard form (0 on success).
924 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
925 //              * State information as per parent.
926 //
927 static Int streamChainFunction(
928     const PAF_ASOT_Params *pP, 
929     const PAF_ASOT_Patchs *pQ, 
930     PAF_ASOT_Config *pAsotCfg, 
931     Int iChainFrameFxns, 
932     Int abortOnError, 
933     Int logArg
936     PAF_AST_Config *pAstCfg;
937     Int as;                     // Audio Stream Number (1, 2, etc.)
938     Int z;                      // stream counter
939     Int dFlag, eFlag, gear;
940     Int zX;
941     Int zS;
942     Int errno;                  // error number
944     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
945     as = pAstCfg->as;
946     (void)as; // clear compiler warning in case not used with tracing disabled
948     for (zS = STREAM1; zS < STREAMN; zS++)
949     {
950         z = pP->streamOrder[zS];  // Select stream order from streamOrder parameter - MID 788
952         // apply stream
953         //      unless the stream is associated with a decoder and it is not running
954         // or
955         //      unless the stream is associated with an encoder and it is not running
956         // Also gear control only works for streams with an associated decoder
957         // if no such association exists then gear 0 (All) is used
958         dFlag = 1;
959         gear = 0;
960         for (zX = DECODE1; zX < DECODEN; zX++) 
961         {
962             if (pP->streamsFromDecodes[zX] == z) 
963             {
964                 dFlag = pAstCfg->xDec[zX].decodeStatus.mode;
965                 gear = pAstCfg->xDec[zX].decodeStatus.aspGearStatus;
966                 break;
967             }
968         }
969         eFlag = 1;
970         for (zX = ENCODE1; zX < ENCODEN; zX++) 
971         {
972             if (pP->streamsFromEncodes[zX] == z) 
973             {
974                 eFlag = pAstCfg->xEnc[zX].encodeStatus.mode;
975                 break;
976             }
977         }
979         if (dFlag && eFlag) 
980         {
981             PAF_ASP_Chain *chain = pAstCfg->xStr[z].aspChain[gear];
982             PAF_AudioFrame *frame = pAstCfg->xStr[z].pAudioFrame;
983             Int (*func) (PAF_ASP_Chain *, PAF_AudioFrame *) =
984                 chain->fxns->chainFrameFunction[iChainFrameFxns];
986             TRACE_GEN2(iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_RESET
987                        ? "asopStreamChainFunction: AS%d: processing frame %d -- audio stream (reset)"
988                        : iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_APPLY
989                        ? "asopStreamChainFunction: AS%d: processing frame %d -- audio stream (apply)"
990                        : iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_FINAL
991                        ? "asopStreamChainFunction: AS%d: processing frame %d -- audio stream (final)"
992                        : "asopStreamChainFunction: AS%d: processing frame %d -- audio stream (?????)",
993                        as+z, logArg);
994             errno = (*func) (chain, frame);   // ASP chain reset function: SRC is the 1st in the chain and reset
995             TRACE_VERBOSE2("asopStreamChainFunction: AS%d: errno 0x%x.", as+z, errno);
997             if (errno && abortOnError)
998             {
999                 return errno;
1000             }
1001         }
1002         else 
1003         {
1004             TRACE_GEN2(iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_RESET
1005                        ? "asopStreamChainFunction: AS%d: processing frame %d -- audio stream (reset) <ignored>"
1006                        : iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_APPLY
1007                        ? "asopStreamChainFunction: AS%d: processing frame %d -- audio stream (apply) <ignored>"
1008                        : iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_FINAL
1009                        ? "asopStreamChainFunction: AS%d: processing frame %d -- audio stream (final) <ignored>"
1010                        : "asopStreamChainFunction: AS%d: processing frame %d -- audio stream (?????) <ignored>",
1011                        as+z, logArg);
1012         }
1013     }
1015     return 0;
1016 } //asopStreamChainFunction
1019 /* nothing past this point */