/* Copyright (c) 2017, Texas Instruments Incorporated - http://www.ti.com/ All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* * ======== audioStreamOutProc.c ======== */ #include // for memset #include #include #include #include #include #include "paferr.h" #include #include #include #include #include #include #include "asperr.h" #include "common.h" #include "aspMsg_common.h" #include "aspMsg_master.h" #include "aspDecOpCircBuf_master.h" #include "audioStreamProc_common.h" #include "audioStreamOutProc.h" #define TRACE_TIME(a) // // Audio Stream Definitions // // // Audio Stream Processing Definitions // #define aspLinkInit pQ->i_aspLinkInit // // Encoder Definitions // #define encLinkInit pQ->i_encLinkInit // // Output Definitions // #define outLinkInit pP->i_outLinkInit /* ---------------------------------------------------------------- */ /* Parameter macro definitions end here. */ /* ---------------------------------------------------------------- */ // // Standardized Definitions // #define ENC_Handle PCE_Handle /* works for all: PCE */ #define __TASK_NAME__ "TaskAsop" /* FL: Check if at least one output selected */ static Int checkOutSel( const PAF_ASOT_Params *pP, PAF_ASOT_Config *pC, Int *pOutSel ); /* FL: Check if at least one output sio changed */ static Int checkOutSio( const PAF_ASOT_Params *pP, PAF_ASOT_Config *pC, Int *pOutSioUpdate ); LINNO_DEFN(TaskAsop); /* Line number macros */ ERRNO_DEFN(TaskAsop); /* Error number macros */ // ASOT configuration #pragma DATA_SECTION(gPAF_ASOT_config, ".globalSectionPafAsotConfig") PAF_ASOT_Config gPAF_ASOT_config = { NULL, // acp &gPAF_ASPM_config, // pAspmCfg &gPAF_AST_config // pAstCfg }; // Underflow threshold before circular buffer reset and return error to Top-Level FSM #define DEC_OP_CB_RDAF_UND_THR ( 80 ) // FL: arbitrary setting UInt32 gCbReadAfErr =0; // read circular buffer error count, not including underflows UInt32 gDecOpCbRdAfUnd =0; // decoder output circular buffer underflow count UInt32 gMaxDecOpCbRdAfUnd =0; // max (consecutive) decoder output circular buffer underflow count // Global debug counters */ UInt32 gTaskAsopCnt=0; // debug UInt32 gAsopInitCnt =0; UInt32 gAsopStreamCnt =0; UInt32 gAsopEncodeCnt =0; UInt32 gAsopFinalCnt =0; UInt32 gAsopQuitCnt =0; // FL: (***) debug #include "evmc66x_gpio_dbg.h" /* * ======== taskAsopFxn ======== * Audio Stream Output Processing task function */ Void taskAsopFxn( // Int betaPrimeValue, // FL: revisit const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ ) { PAF_ASOT_Config *pC; /* Local configuration pointer */ PAF_AST_Config *pAstCfg; /* Common (shared) configuration pointer */ Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* input/encode/stream/decode/output counter */ Int i; /* phase */ Int errno; /* error number */ Int zMS; Int loopCount = 0; // used to stop trace to see startup behavior. Log_info0("Enter taskAsopFxn()"); // // Audio Framework Parameters & Patch (*pP, *pQ) // if (!pP) { TRACE_TERSE0("TaskAsop: No Parameters defined. Exiting."); LINNO_RPRT(TaskAsop, -1); return; } if (!pQ) { TRACE_TERSE0("TaskAsip: No Patchs defined. Exiting."); LINNO_RPRT(TaskAsop, -1); return; } // // Audio Framework Configuration (*pC): // pC = &gPAF_ASOT_config; pAstCfg = pC->pAstCfg; /* Obtain Audio Stream Number (1, 2, etc.) */ as = pAstCfg->as; TRACE_TERSE1("TaskAsop: Started with AS%d.", as); // // Initialize message log trace and line number reporting // for (z=STREAM1; z < STREAMN; z++) { TRACE_TERSE1("TaskAsop: AS%d: initiated", as+z); } LINNO_RPRT(TaskAsop, -1); // // Determine stream index // zMS = pAstCfg->masterStr; // Initialize as per parametrized phases: // // In standard form these are: // - Malloc: Memory Allocation // - Config: Configuration Initialization // - AcpAlg: ACP Algorithm Initialization and Local Attachment // - Common: Common Memory Initialization // - AlgKey: Dec/Enc chain to Array Initialization // - Device: I/O Device Initialization // - Unused: (available) // - Unused: (available) // LINNO_RPRT(TaskAsop, -2); for (i=0; i < lengthof(pP->fxns->initPhase); i++) { Int linno; if (pP->fxns->initPhase[i]) { if (linno = pP->fxns->initPhase[i](pP, pQ, pC)) { LINNO_RPRT(TaskAsop, linno); return; } } else { TRACE_TERSE1("TaskAsop: AS%d: initialization phase - null", as+zMS); } TRACE_TERSE2("TaskAsop: AS%d: initialization phase - %d completed", as+zMS, i); LINNO_RPRT(TaskAsop, -i-3); } // // End of Initialization -- display memory usage report. // if (pP->fxns->memStatusPrint) { pP->fxns->memStatusPrint(HEAP_INTERNAL, HEAP_INTERNAL1, HEAP_EXTERNAL, HEAP_INTERNAL1_SHM); } // // Main processing loop // for (z=STREAM1; z < STREAMN; z++) { TRACE_VERBOSE1("TaskAsip: AS%d: running", as+z); } errno = 0; for (;;) { Int outSel; loopCount++; TRACE_GEN2("TaskAsop (begin Main loop %d) (errno 0x%x)", loopCount, errno); // any error forces idling of output if (errno) { for (z=OUTPUT1; z < OUTPUTN; z++) { if (pAstCfg->xOut[z].hTxSio) { SIO_idle(pAstCfg->xOut[z].hTxSio); } } TRACE_TERSE1("TaskAsop: Trace stopped at loop %d.", loopCount); ERRNO_RPRT(TaskAsop, errno); } TRACE_VERBOSE1("TaskAsop: AS%d: ... sleeping ...", as+zMS); Task_sleep(1); TRACE_GEN1("TaskAsop: AS%d: Output device selection ...", as+zMS); if (errno = pP->fxns->selectDevices(pP, pQ, pC)) { TRACE_TERSE2("TaskAsop: AS%d: selectDevices returned errno = 0x%04x", as+zMS, errno); continue; } // if no output selected skip any remaining processing if (errno = checkOutSel(pP, pC, &outSel)) { TRACE_TERSE2("TaskAsop: AS%d: checkOutSel returned errno = 0x%04x", as+zMS, errno); continue; } else if (!outSel) { TRACE_VERBOSE1("TaskAsop: AS%d: No output selected...", as+zMS); continue; } TRACE_VERBOSE0("TaskAsop: calling outputProcessing."); errno = pP->fxns->decodeProcessing(pP, pQ, pC, -1); if (errno) { TRACE_TERSE1("TaskAsop: outputProcessing returns 0x%x, continue", errno); } else { TRACE_VERBOSE0("TaskAsop: outputProcessing complete with no error."); } } // End of main processing loop for (;;) Log_info0("Exit taskAsopFxn()"); } // ----------------------------------------------------------------------------- // AST Initialization Function - Memory Allocation // // Name: PAF_ASOT_initPhaseMalloc // Purpose: Audio Stream Output Task Function for initialization of data pointers // by allocation of memory. // From: audioStream1Task or equivalent // Uses: See code. // States: x // Return: 0 on success. // Source code line number on MEM_calloc failure. // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // * Memory allocation errors. // Int PAF_ASOT_initPhaseMalloc ( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int zMS; Error_Block eb; //Int i; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; zMS = pAstCfg->masterStr; TRACE_TERSE1("PAF_ASOT_initPhaseMalloc: AS%d: initialization phase - memory allocation", as+zMS); // Initialize error block Error_init(&eb); /* Stream memory */ if (!(pAstCfg->xStr = Memory_calloc((IHeap_Handle)HEAP_INTERNAL, STREAMN * sizeof (*pAstCfg->xStr), 4, &eb))) { TRACE_TERSE1("PAF_ASOT_initPhaseMalloc: AS%d: Memory_calloc failed", as+zMS); SW_BREAKPOINT; return __LINE__; } TRACE_TERSE3("PAF_ASOT_initPhaseMalloc. (pAstCfg->xStr) %d bytes from space %d at 0x%x.", STREAMN * sizeof (*pAstCfg->xStr), HEAP_ID_INTERNAL, (IArg)pAstCfg->xStr); { Int z; /* stream counter */ PAF_AudioFrame *fBuf; if (!(fBuf = (PAF_AudioFrame *)Memory_calloc((IHeap_Handle)HEAP_INTERNAL, STREAMS * sizeof (*fBuf), 4, &eb))) { TRACE_TERSE1("PAF_ASOT_initPhaseMalloc: AS%d: Memory_calloc failed", as+zMS); SW_BREAKPOINT; return __LINE__; } TRACE_TERSE3("PAF_ASOT_initPhaseMalloc. (fBuf) %d bytes from space %d at 0x%x.", STREAMS * sizeof (*fBuf), HEAP_ID_INTERNAL, (IArg)fBuf); for (z=STREAM1; z < STREAMN; z++) { pAstCfg->xStr[z].pAudioFrame = &fBuf[z-STREAM1]; TRACE_TERSE2("pAstCfg->xStr[%d].pAudioFrame = 0x%x", z, (IArg)pAstCfg->xStr[z].pAudioFrame); } } /* Encode memory */ if (!(pAstCfg->xEnc = Memory_calloc((IHeap_Handle)HEAP_INTERNAL, ENCODEN * sizeof (*pAstCfg->xEnc), 4, &eb))) { TRACE_TERSE1("PAF_ASOT_initPhaseMalloc: AS%d: Memory_calloc failed", as+zMS); SW_BREAKPOINT; return __LINE__; } TRACE_TERSE3("PAF_ASOT_initPhaseMalloc. (pAstCfg->xEnc) %d bytes from space %d at 0x%x.", ENCODEN * sizeof (*pAstCfg->xEnc), HEAP_ID_INTERNAL, (IArg)pAstCfg->xEnc); /* Output memory */ if (!(pAstCfg->xOut = Memory_calloc((IHeap_Handle)HEAP_INTERNAL, OUTPUTN * sizeof (*pAstCfg->xOut), 4, &eb))) { TRACE_TERSE1("PAF_ASOT_initPhaseMalloc: AS%d: Memory_calloc failed", as+zMS); SW_BREAKPOINT; return __LINE__; } TRACE_TERSE3("PAF_ASOT_initPhaseMalloc. (pAstCfg->xOut) %d bytes from space %d at 0x%x.", OUTPUTN * sizeof (*pAstCfg->xOut), HEAP_ID_INTERNAL, (IArg)pAstCfg->xOut); TRACE_TERSE1("PAF_ASOT_initPhaseMalloc: AS%d: initialization phase - memory allocation complete.", as+zMS); return 0; } //PAF_ASOT_initPhaseMalloc // ----------------------------------------------------------------------------- // ASOT Initialization Function - Memory Initialization from Configuration // // Name: PAF_ASOT_initPhaseConfig // Purpose: Audio Stream Output Task Function for initialization of data values // from parameters. // From: audioStream1Task or equivalent // Uses: See code. // States: x // Return: 0 on success. // Other as per initFrame0 and initFrame1. // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // Int PAF_ASOT_initPhaseConfig( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* input/encode/stream/decode/output counter */ Int zMS; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; zMS = pAstCfg->masterStr; TRACE_TERSE1("PAF_ASOT_initPhaseConfig: AS%d: initialization phase - configuration", as+zMS); // // Unspecified elements have been initialized to zero during alloc // for (z=STREAM1; z < STREAMN; z++) { Int linno; if (linno = pP->fxns->initFrame0(pP, pQ, pC, z)) { return linno; } if (linno = pP->fxns->initFrame1(pP, pQ, pC, z, -1)) { return linno; } } for (z=ENCODE1; z < ENCODEN; z++) { Int zO = pP->outputsFromEncodes[z]; Int zS = pP->streamsFromEncodes[z]; pAstCfg->xEnc[z].encodeControl.size = sizeof(pAstCfg->xEnc[z].encodeControl); pAstCfg->xEnc[z].encodeControl.pAudioFrame = pAstCfg->xStr[zS].pAudioFrame; pAstCfg->xEnc[z].encodeControl.pVolumeStatus = &pAstCfg->xEnc[z].volumeStatus; pAstCfg->xEnc[z].encodeControl.pOutBufConfig = &pAstCfg->xOut[zO].outBufConfig; pAstCfg->xEnc[z].encodeStatus = *pP->z_pEncodeStatus[z]; pAstCfg->xEnc[z].encodeControl.encActive = pAstCfg->xEnc[z].encodeStatus.select; pAstCfg->xEnc[z].volumeStatus = *pP->pVolumeStatus; pAstCfg->xEnc[z].encodeInStruct.pAudioFrame = pAstCfg->xStr[zS].pAudioFrame; } for (z=OUTPUT1; z < OUTPUTN; z++) { pAstCfg->xOut[z].outBufStatus = *pP->pOutBufStatus; } TRACE_TERSE1("PAF_ASOT_initPhaseConfig: AS%d: initialization phase - configuration complete.", as+zMS); return 0; } //PAF_ASOT_initPhaseConfig // ----------------------------------------------------------------------------- // ASOT Initialization Function - ACP Algorithm Instantiation // // Name: PAF_ASOT_initPhaseAcpAlg // Purpose: Audio Stream Input Task Function for initialization of ACP by // instantiation of the algorithm. // From: audioStream1Task or equivalent // Uses: See code. // States: x // Return: 0 on success. // Source code line number on ACP Algorithm creation failure. // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // * Memory allocation errors. // Int PAF_ASOT_initPhaseAcpAlg( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* input/encode/stream/decode/output counter */ Int betaPrimeOffset; ACP_Handle acp; Int zMS; Int zS, zX; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; zMS = pAstCfg->masterStr; TRACE_TERSE1("PAF_ASOT_initPhaseAcpAlg: AS%d: initialization phase - ACP Algorithm", as+zMS); ACP_MDS_init(); if (!(acp = (ACP_Handle )ACP_MDS_create(NULL))) { TRACE_TERSE1("PAF_ASOT_initPhaseAcpAlg: AS%d: ACP algorithm instance creation failed", as+zMS); return __LINE__; } pC->acp = acp; ((ALG_Handle)acp)->fxns->algControl((ALG_Handle) acp, ACP_GETBETAPRIMEOFFSET, (IALG_Status *)&betaPrimeOffset); for (z=ENCODE1; z < ENCODEN; z++) { zS = pP->streamsFromEncodes[z]; acp->fxns->attach(acp, ACP_SERIES_STD, STD_BETA_ENCODE + betaPrimeOffset * (as-1+zS), (IALG_Status *)&pAstCfg->xEnc[z].encodeStatus); acp->fxns->attach(acp, ACP_SERIES_STD, STD_BETA_VOLUME + betaPrimeOffset * (as-1+zS), (IALG_Status *)&pAstCfg->xEnc[z].volumeStatus); /* Ignore errors, not reported. */ } for (z=OUTPUT1; z < OUTPUTN; z++) { zS = z; for (zX = ENCODE1; zX < ENCODEN; zX++) { if (pP->outputsFromEncodes[zX] == z) { zS = pP->streamsFromEncodes[zX]; break; } } acp->fxns->attach(acp, ACP_SERIES_STD, STD_BETA_OB + betaPrimeOffset * (as-1+zS), (IALG_Status *)&pAstCfg->xOut[z].outBufStatus); /* Ignore errors, not reported. */ } TRACE_TERSE1("PAF_ASOT_initPhaseAcpAlg: AS%d: initialization phase - ACP Algorithm complete.", as+zMS); return 0; } //PAF_ASOT_initPhaseAcpAlg // ----------------------------------------------------------------------------- // ASOT Initialization Function - Common Memory // // Name: PAF_ASOT_initPhaseCommon // Purpose: Audio Stream Output Task Function for allocation of common memory. // From: audioStream1Task or equivalent // Uses: See code. // States: x // Return: 0 on success. // Source code line number on PAF_ALG_alloc failure. // Source code line number on PAF_ALG_mallocMemory failure. // Source code line number on Decode Chain initialization failure. // Source code line number on ASP Chain initialization failure. // Source code line number on Encode Chain initialization failure. // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // * Memory allocation errors. // Int PAF_ASOT_initPhaseCommon( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* stream counter */ Int g; /* gear */ ACP_Handle acp; PAF_IALG_Config pafAlgConfig; IALG_MemRec common[3][PAF_IALG_COMMON_MEMN+1]; acp = pC->acp; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; TRACE_TERSE0("PAF_ASOT_initPhaseCommon: initialization phase - Common Memory"); // // Determine memory needs and instantiate algorithms across audio streams // TRACE_TERSE0("PAF_ASOT_initPhaseCommon: calling PAF_ALG_setup."); PAF_ALG_setup(&pafAlgConfig, HEAP_ID_INTERNAL, HEAP_INTERNAL, HEAP_ID_INTERNAL1, HEAP_INTERNAL1, HEAP_ID_EXTERNAL, HEAP_EXTERNAL, HEAP_ID_INTERNAL1_SHM, HEAP_INTERNAL1_SHM, HEAP_ID_EXTERNAL_SHM, HEAP_EXTERNAL_SHM, HEAP_ID_EXTERNAL_NONCACHED_SHM, HEAP_EXTERNAL_NONCACHED_SHM, HEAP_CLEAR); if (pP->fxns->headerPrint) { pP->fxns->headerPrint(); } for (z = STREAM1; z < STREAMN; z++) { //Int zD, zE, zX; Int zE, zX; TRACE_TERSE1("PAF_ASOT_initPhaseCommon: AS%d: initialization phase - Common Memory", as+z); // // Determine common memory needs for: // (1) ASP Algorithms // (2) Encode Algorithms // (3) Logical Output drivers // PAF_ALG_init(common[z], lengthof(common[z]), COMMONSPACE); zE = -1; for (zX = ENCODE1; zX < ENCODEN; zX++) { if (pP->streamsFromEncodes[zX] == z) { zE = zX; break; } } TRACE_TERSE1("Calling PAF_ALG_ALLOC for stream common[%d].", z); if (PAF_ALG_ALLOC(aspLinkInit[z-STREAM1][0], common[z])) { TRACE_TERSE1("PAF_ASOT_initPhaseCommon: AS%d: PAF_ALG_alloc failed", as+z); TRACE_TERSE2("Failed to alloc %d bytes from space %d ", common[z]->size, common[z]->space); SW_BREAKPOINT; return __LINE__; } TRACE_TERSE3("alloced %d bytes from space %d at 0x%x", common[z]->size, common[z]->space, (IArg)common[z]->base); if (pP->fxns->allocPrint) { pP->fxns->allocPrint((const PAF_ALG_AllocInit *)(aspLinkInit[z-STREAM1][0]), sizeof (*(aspLinkInit[z-STREAM1][0])), &pafAlgConfig); } if (zE >= 0) { TRACE_TERSE1("PAF_ASOT_initPhaseCommon: calling PAF_ALG_ALLOC/ for encoder common[%d].", z); if (PAF_ALG_ALLOC(encLinkInit[zE-ENCODE1], common[z])) { TRACE_TERSE1("PAF_ASOT_initPhaseCommon: AS%d: PAF_ALG_alloc failed", as+z); SW_BREAKPOINT; return __LINE__; } TRACE_TERSE3("alloced %d bytes from space %d at 0x%x", common[z]->size, common[z]->space, (IArg)common[z]->base); if (pP->fxns->allocPrint) { pP->fxns->allocPrint((const PAF_ALG_AllocInit *)(encLinkInit[z-ENCODE1]), sizeof (*(encLinkInit[z-ENCODE1])), &pafAlgConfig); } } // // Determine common memory needs of Logical IO drivers // if (OUTPUT1 <= z && z < OUTPUTN) { TRACE_TERSE1("PAF_ASOT_initPhaseCommon: calling PAF_ALG_ALLOC outLinkInit common[%d].", z); if (PAF_ALG_ALLOC(outLinkInit[z-OUTPUT1], common[z])) { TRACE_TERSE1("PAF_ASOT_initPhaseMalloc: AS%d: PAF_ALG_alloc failed", as+z); TRACE_TERSE2("Failed to alloc %d bytes from space %d", common[z]->size, (IArg)common[z]->space); SW_BREAKPOINT; return __LINE__; } TRACE_TERSE3("alloced %d bytes from space %d at 0x%x", common[z]->size, common[z]->space, (IArg)common[z]->base); if (pP->fxns->allocPrint) { pP->fxns->allocPrint((const PAF_ALG_AllocInit *)(outLinkInit[z-INPUT1]), sizeof (*(outLinkInit[z-INPUT1])), &pafAlgConfig); } } } { // Changes made to share scratch between zones // Assume maximum 3 zones and scratch common memory is at offset 0; int max=0; for (z=STREAM1; zsize, common[z]->space, (IArg)common[z]->base); // share zone0 scratch with all zones common[z][0].base = common[0][0].base; if (pP->fxns->commonPrint) { pP->fxns->commonPrint(common[z], &pafAlgConfig); } zE = -1; for (zX = ENCODE1; zX < ENCODEN; zX++) { if (pP->streamsFromEncodes[zX] == z) { zE = zX; break; } } pAstCfg->xStr[z].aspChain[0] = NULL; for (g=0; g < GEARS; g++) { PAF_ASP_Chain *chain; TRACE_TERSE0("PAF_ASOT_initPhaseCommon: calling PAF_ASP_chainInit for ASPs."); chain = PAF_ASP_chainInit(&pAstCfg->xStr[z].aspChainData[g], pP->pChainFxns, HEAP_INTERNAL, as+z, acp, &trace, aspLinkInit[z-STREAM1][g], pAstCfg->xStr[z].aspChain[0], common[z], &pafAlgConfig); if (!chain) { TRACE_TERSE2("AS%d: ASP chain %d initialization failed", as+z, g); return __LINE__; } else { pAstCfg->xStr[z].aspChain[g] = chain; } } if (zE >= 0) { PAF_ASP_Chain *chain; TRACE_TERSE0("PAF_ASOT_initPhaseCommon: calling PAF_ASP_chainInit for encode."); chain = PAF_ASP_chainInit(&pAstCfg->xEnc[zE].encChainData, pP->pChainFxns, HEAP_INTERNAL, as+z, acp, &trace, encLinkInit[zE-ENCODE1], NULL, common[z], &pafAlgConfig); if (!chain) { TRACE_TERSE1("AS%d: Encode chain initialization failed", as+z); return __LINE__; } } // // Allocate non-common memories for Logical IO drivers // Since these structures are used at run-time we allocate from external memory if (OUTPUT1 <= z && z < OUTPUTN) { PAF_ASP_Chain *chain; TRACE_TERSE2("PAF_ASOT_initPhaseMalloc: AS%d: non-common output chain init for %d", as+z, z); chain = PAF_ASP_chainInit (&pAstCfg->xOut[z].outChainData, pP->pChainFxns, HEAP_EXTERNAL, as+z, acp, &trace, outLinkInit[z-OUTPUT1], NULL, common[z], &pafAlgConfig); if (!chain) { TRACE_TERSE1("AS%d: Output chain initialization failed", as+z); return __LINE__; } } } TRACE_TERSE1("AS%d: PAF_ASOT_initPhaseCommon: Returning complete.", as+z); return 0; } //PAF_ASOT_initPhaseCommon // ----------------------------------------------------------------------------- // ASOT Initialization Function - Algorithm Keys // // Name: PAF_ASOT_initPhaseAlgKey // Purpose: Audio Stream Output Task Function for initialization of data values // from parameters for Algorithm Keys. // From: audioStream1Task or equivalent // Uses: See code. // States: x // Return: 0. // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // // ............................................................................. Int PAF_ASOT_initPhaseAlgKey( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* decode/encode counter */ Int s; /* key number */ PAF_ASP_Link *that; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; (void)as; // clear compiler warning in case not used with tracing disabled TRACE_VERBOSE1("PAF_ASOT_initPhaseAlgKey: AS%d: initialization phase - Algorithm Keys", as); for (z=ENCODE1; z < ENCODEN; z++) { for (s=0; s < pP->pEncAlgKey->length; s++) { if ((pP->pEncAlgKey->code[s].full != 0) && (that = PAF_ASP_chainFind(&pAstCfg->xEnc[z].encChainData, pP->pEncAlgKey->code[s]))) { pAstCfg->xEnc[z].encAlg[s] = (ALG_Handle )that->alg; } /* Cast in interface, for now --Kurt */ else { pAstCfg->xEnc[z].encAlg[s] = NULL; } } } return 0; } //PAF_ASOT_initPhaseAlgKey // ----------------------------------------------------------------------------- // ASOT Initialization Function - I/O Devices // // Name: PAF_ASOT_initPhaseDevice // Purpose: Audio Stream Output Task Function for initialization of I/O Devices. // From: audioStream1Task or equivalent // Uses: See code. // States: x // Return: 0 on success. // Source code line number on device allocation failure. // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // * Memory allocation errors. // Int PAF_ASOT_initPhaseDevice( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* input/output counter */ PAF_SIO_IALG_Obj *pObj; PAF_SIO_IALG_Config *pAlgConfig; PAF_IALG_Config pafAlgConfig; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; (void)as; // clear compiler warning in case not used with tracing disabled TRACE_TERSE1("PAF_ASOT_initPhaseDevice: AS%d: initialization phase - I/O Devices", as); if(pP->fxns->bufMemPrint) { PAF_ALG_setup (&pafAlgConfig, HEAP_ID_INTERNAL, HEAP_INTERNAL, HEAP_ID_INTERNAL1, HEAP_INTERNAL1, HEAP_ID_EXTERNAL, HEAP_EXTERNAL, HEAP_ID_INTERNAL1_SHM, HEAP_INTERNAL1_SHM, HEAP_ID_EXTERNAL_SHM, HEAP_EXTERNAL_SHM, HEAP_ID_EXTERNAL_NONCACHED_SHM, HEAP_EXTERNAL_NONCACHED_SHM, HEAP_CLEAR); TRACE_TERSE2("PAF_ASOT_initPhaseDevice: AS%d: calling PAF_ALG_setup with clear at %d.", as, HEAP_CLEAR); } for (z=OUTPUT1; z < OUTPUTN; z++) { PAF_OutBufConfig *pConfig = &pAstCfg->xOut[z].outBufConfig; pObj = (PAF_SIO_IALG_Obj *)pAstCfg->xOut[z].outChainData.head->alg; pAlgConfig = &pObj->config; pAstCfg->xOut[z].hTxSio = NULL; pConfig->base.pVoid = pAlgConfig->pMemRec[0].base; pConfig->pntr.pVoid = pAlgConfig->pMemRec[0].base; pConfig->head.pVoid = pAlgConfig->pMemRec[0].base; pConfig->allocation = pAlgConfig->pMemRec[0].size; pConfig->sizeofElement = 3; pConfig->precision = 24; if(pP->fxns->bufMemPrint) { pP->fxns->bufMemPrint(z,pAlgConfig->pMemRec[0].size,PAF_ALG_memSpaceToHeapId(&pafAlgConfig,pAlgConfig->pMemRec[0].space),1); } } TRACE_TERSE1("PAF_ASOT_initPhaseDevice: AS%d: initialization phase - I/O Devices complete.", as); return 0; } //PAF_ASOT_initPhaseDevice // ----------------------------------------------------------------------------- // ASOT Initialization Function Helper - Initialization of Audio Frame // // Name: PAF_ASOT_initFrame0 // Purpose: Audio Stream Output Task Function for initialization of the Audio // Frame(s) by memory allocation and loading of data pointers // and values. // From: AST Parameter Function -> decodeInfo // Uses: See code. // States: x // Return: 0 on success. // Source code line number on MEM_calloc failure. // Source code line number on unsupported option. // Trace: Message Log "trace" in Debug Project Configuration reports: // * Memory allocation errors. // * Unsupported option errors. // // MID 314 extern const char AFChanPtrMap[PAF_MAXNUMCHAN+1][PAF_MAXNUMCHAN]; extern PAF_ChannelConfigurationMaskTable PAF_ASP_stdCCMT_patch; Int PAF_ASOT_initFrame0( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, Int z ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int ch; //Int aLen; Int aLen_int=0,aLen_ext=0; Int aSize = sizeof(PAF_AudioData); Int aAlign = aSize < sizeof (int) ? sizeof (int) : aSize; Int maxFrameLength = pP->maxFramelength; Int zX; PAF_AudioData *aBuf_int=NULL; PAF_AudioData *aBuf_ext=NULL; XDAS_UInt8 *metadataBuf; char i; Error_Block eb; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; // Initialize error block Error_init(&eb); // Compute maximum framelength (needed for ARC support) maxFrameLength += PA_MODULO - maxFrameLength % PA_MODULO; //aLen = numchan[z] * maxFrameLength; for (i=0; i < numchan[z]; i++) { if (pP->pAudioFrameBufStatus->space[i] == IALG_SARAM) { aLen_int += maxFrameLength; } else { aLen_ext += maxFrameLength; } } // // Initialize audio frame elements directly // pAstCfg->xStr[z].pAudioFrame->fxns = pP->pAudioFrameFunctions; pAstCfg->xStr[z].pAudioFrame->data.nChannels = PAF_MAXNUMCHAN; /// /// pAstCfg->xStr[z].pAudioFrame->data.nChannels = PAF_MAXNUMCHAN_AF; pAstCfg->xStr[z].pAudioFrame->data.nSamples = FRAMELENGTH; pAstCfg->xStr[z].pAudioFrame->data.sample = pAstCfg->xStr[z].audioFrameChannelPointers; pAstCfg->xStr[z].pAudioFrame->data.samsiz = pAstCfg->xStr[z].audioFrameChannelSizes; pAstCfg->xStr[z].pAudioFrame->pChannelConfigurationMaskTable = &PAF_ASP_stdCCMT; // // Allocate memory for and initialize pointers to audio data buffers // // The NUMCHANMASK is used to identify the channels for which data // buffers can be allocated. Using this mask and switch statement // rather than some other construct allows efficient code generation, // providing just the code necessary (with significant savings). // if (pP->fxns->bufMemPrint) { pP->fxns->bufMemPrint(z, aLen_int*aSize, HEAP_ID_FRMBUF, 2); pP->fxns->bufMemPrint(z, aLen_ext*aSize, HEAP_ID_EXTERNAL, 2); } TRACE_TERSE1("PAF_ASOT_initFrame0: AS%d: Memory_calloc for audio buffers", as+z); if (aLen_int*aSize!=0) // check size != 0, otherwise malloc throws fatal error { if (!(aBuf_int = (PAF_AudioData *)Memory_calloc((IHeap_Handle)HEAP_FRMBUF, (aLen_int+(maxFrameLength-FRAMELENGTH))*aSize, aAlign, &eb))) //Qin: Add start offset { TRACE_TERSE1("PAF_ASOT_initFrame0: AS%d: Memory_calloc failed", as+z); TRACE_TERSE2(" maxFrameLength: %d. aLen_int*aSize: %d", maxFrameLength, (aLen_int+(maxFrameLength-FRAMELENGTH))*aSize); SW_BREAKPOINT; return __LINE__; } } if (aLen_ext*aSize!=0) { if (!(aBuf_ext = (PAF_AudioData *)Memory_calloc((IHeap_Handle)HEAP_EXTERNAL, (aLen_ext+(maxFrameLength-FRAMELENGTH))*aSize, aAlign, &eb)))//Qin: Add start offset { TRACE_TERSE1("PAF_ASOT_initFrame0: AS%d: Memory_calloc failed", as+z); TRACE_TERSE2(" maxFrameLength: %d. aLen_ext*aSize: %d", maxFrameLength, (aLen_ext+(maxFrameLength-FRAMELENGTH))*aSize); SW_BREAKPOINT; return __LINE__; } } TRACE_TERSE3(" maxFrameLength: %d. aLen_int*aSize: %d. aBuf_int: 0x%x", maxFrameLength, (aLen_int+(maxFrameLength-FRAMELENGTH))*aSize, (IArg)aBuf_int); TRACE_TERSE3(" maxFrameLength: %d. aLen_ext*aSize: %d. aBuf_ext: 0x%x", maxFrameLength, (aLen_ext+(maxFrameLength-FRAMELENGTH))*aSize, (IArg)aBuf_ext); TRACE_TERSE1("PAF_ASOT_initFrame0: AS%d: Memory_calloc for metadata buffers", as+z); if (!(metadataBuf = (XDAS_UInt8 *)Memory_calloc((IHeap_Handle)HEAP_MDBUF, pP->pMetadataBufStatus->bufSize*pP->pMetadataBufStatus->NumBuf, pP->pMetadataBufStatus->alignment, &eb))) { TRACE_TERSE1("PAF_ASOT_initFrame0: AS%d: Memory_calloc failed", as+z); TRACE_TERSE1(" bufSize*NumBuf: %d", pP->pMetadataBufStatus->bufSize*pP->pMetadataBufStatus->NumBuf); SW_BREAKPOINT; return __LINE__; } { Int i; #pragma UNROLL(1) for (i=0; i < PAF_MAXNUMCHAN_AF; i++) { pAstCfg->xStr[z].audioFrameChannelPointers[i] = NULL; } } // MID 314 if((numchan[z] > PAF_MAXNUMCHAN) || (numchan[z] < 1)) { TRACE_TERSE1("PAF_ASOT_initFrame0: AS%d: unsupported option", as+z); return __LINE__; } else { Int j = 0; Int k = 0; TRACE_TERSE1("PAF_ASOT_initFrame0: AFChanPtrMap[%d][i]", numchan[z]); for(i=0;ipAudioFrameBufStatus->space[i] == IALG_SARAM) { pAstCfg->xStr[z].audioFrameChannelPointers[chan] = aBuf_int + maxFrameLength*(j+1) - FRAMELENGTH; j++; } else { pAstCfg->xStr[z].audioFrameChannelPointers[chan] = aBuf_ext + maxFrameLength*(k+1) - FRAMELENGTH; k++; } TRACE_TERSE3("PAF_ASOT_initFrame0: chan = %d = AFChanPtrMap[%d][%d].", chan, numchan[z], i); TRACE_TERSE2("PAF_ASOT_initFrame0: audioFrameChannelPointers[%d]: 0x%x", chan, (IArg)pAstCfg->xStr[z].audioFrameChannelPointers[chan]); } } } for (ch=PAF_LEFT; ch < PAF_MAXNUMCHAN_AF; ch++) { if (pAstCfg->xStr[z].audioFrameChannelPointers[ch]) { pAstCfg->xStr[z].origAudioFrameChannelPointers[ch] = pAstCfg->xStr[z].audioFrameChannelPointers[ch]; } } // // Initialize meta data elements // pAstCfg->xStr[z].pAudioFrame->pafBsMetadataUpdate = XDAS_FALSE; pAstCfg->xStr[z].pAudioFrame->numPrivateMetadata = 0; pAstCfg->xStr[z].pAudioFrame->bsMetadata_offset = 0; pAstCfg->xStr[z].pAudioFrame->bsMetadata_type = PAF_bsMetadata_channelData; pAstCfg->xStr[z].pAudioFrame->privateMetadataBufSize = pP->pMetadataBufStatus->bufSize; for(i=0;ipMetadataBufStatus->NumBuf;i++) { pAstCfg->xStr[z].pAudioFrame->pafPrivateMetadata[i].offset = 0; pAstCfg->xStr[z].pAudioFrame->pafPrivateMetadata[i].size = 0; pAstCfg->xStr[z].pAudioFrame->pafPrivateMetadata[i].pMdBuf = metadataBuf + pP->pMetadataBufStatus->bufSize*i; } // // Initialize decoder elements directly // for (zX = DECODE1; zX < DECODEN; zX++) { if (pP->streamsFromDecodes[zX] == z) { #ifdef NOAUDIOSHARE pAstCfg->xDec[zX].decodeInStruct.audioShare.nSamples = 0; pAstCfg->xDec[zX].decodeInStruct.audioShare.sample = NULL; #else /* NOAUDIOSHARE */ pAstCfg->xDec[zX].decodeInStruct.audioShare.nSamples = aLen_int; pAstCfg->xDec[zX].decodeInStruct.audioShare.sample = aBuf_int; #endif /* NOAUDIOSHARE */ } } return 0; } //PAF_ASOT_initFrame0 // ----------------------------------------------------------------------------- // ASOT Initialization Function Helper - Reinitialization of Audio Frame // AST Decoding Function - Reinitialization of Audio Frame // // Name: PAF_ASOT_initFrame1 // Purpose: Audio Stream Task Function for initialization or reinitiali- // zation of the Audio Frame(s) by loading of data values of a // time-varying nature. // From: audioStream1Task or equivalent // AST Parameter Function -> decodeInfo // AST Parameter Function -> decodeDecode // Uses: See code. // States: x // Return: 0. // Trace: None. // Int PAF_ASOT_initFrame1( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, Int z, Int apply ) { PAF_AST_Config *pAstCfg; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration // // Reinitialize audio frame elements: // // Channel Configurations during sys init = Unknown // " " during info or decode = None // // Sample Rate / Count during sys init, info or decode = Unknown / 0 // if (apply < 0) { pAstCfg->xStr[z].pAudioFrame->channelConfigurationRequest.legacy = PAF_CC_UNKNOWN; pAstCfg->xStr[z].pAudioFrame->channelConfigurationStream.legacy = PAF_CC_UNKNOWN; } else { pAstCfg->xStr[z].pAudioFrame->channelConfigurationRequest.legacy = PAF_CC_NONE; pAstCfg->xStr[z].pAudioFrame->channelConfigurationStream.legacy = PAF_CC_NONE; } if (apply < 1) { pAstCfg->xStr[z].pAudioFrame->sampleRate = PAF_SAMPLERATE_UNKNOWN; pAstCfg->xStr[z].pAudioFrame->sampleCount = 0; } return 0; } //PAF_ASOT_initFrame1 // ----------------------------------------------------------------------------- // ASOT Selection Function - Output Device Selection // // Name: PAF_ASOT_selectDevices // Purpose: Audio Stream Output Task Function for selecting the devices used // for output. // From: audioStream1Task or equivalent // Uses: See code. // States: x // Return: Error number in standard form (0 on success). // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // Int PAF_ASOT_selectDevices( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* input/output counter */ Int errno = 0; /* error number */ Int errme; /* error number, local */ Int device; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; (void)as; // clear compiler warning in case not used with tracing disabled // Select output devices for (z=OUTPUT1; z < OUTPUTN; z++) { if ((device = pAstCfg->xOut[z].outBufStatus.sioSelect) >= 0) { TRACE_VERBOSE2("PAF_ASOT_selectDevices: AS%d: output device %d selecting ...", as+z, device); /* check for valid index into device array */ if (device >= pQ->devout->n) { device = 0; /* treat as device None */ } errme = pP->fxns->deviceSelect(&pAstCfg->xOut[z].hTxSio, SIO_OUTPUT, HEAP_ID_OUTBUF, (Ptr)pQ->devout->x[device]); if (errme) { TRACE_VERBOSE2("PAF_ASOT_selectDevices: errme 0x%x, errno 0x%x", errme, errno); if (!errno) { errno = ASPERR_DEVOUT + errme; } pAstCfg->xOut[z].outBufStatus.sioSelect = 0x80; } else { Int zE; pAstCfg->xOut[z].outBufStatus.sioSelect = device | 0x80; // register outBufStatus and encodeStatus pointers with output devices // This enables proper IEC encapsulation. if (pAstCfg->xOut[z].hTxSio) { // set max # of output buffers (use override if necessary) if (pAstCfg->xOut[z].outBufStatus.maxNumBufOverride == 0) { SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_MAX_NUMBUF, (Arg)pP->poutNumBufMap[z]->maxNumBuf); } else { SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_MAX_NUMBUF, (Arg)pAstCfg->xOut[z].outBufStatus.maxNumBufOverride); } // register PAF_SIO_IALG object address SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_IALGADDR, (Arg)pAstCfg->xOut[z].outChainData.head->alg); SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_BUFSTATUSADDR, (Arg)&pAstCfg->xOut[z].outBufStatus); for (zE=ENCODE1; zE < ENCODEN; zE++) { if (pP->outputsFromEncodes[zE] == z) { SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_ENCSTATUSADDR, (Arg)&pAstCfg->xEnc[zE].encodeStatus); break; } } } } } // if device selected and valid then enable stat tracking if // required and start clocking if ((pAstCfg->xOut[z].outBufStatus.sioSelect < 0) && (pAstCfg->xOut[z].hTxSio)) { TRACE_VERBOSE0("PAF_ASOT_selectDevices: start SIO clocks"); errme = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_OUTPUT_START_CLOCKS, 0); if (errme) { TRACE_VERBOSE2("PAF_ASOT_selectDevices: errme 0x%x, errno 0x%x", errme, errno); SIO_idle(pAstCfg->xOut[z].hTxSio); if (!errno) { errno = ASPERR_DEVOUT + errme; } } } } return errno; } //PAF_ASOT_selectDevices // ----------------------------------------------------------------------------- // ASOT Processing Function - Decode Processing // // Name: PAF_ASOT_decodeProcessing // Purpose: Audio Stream Output Task Function for processing audio data. // Int PAF_ASOT_decodeProcessing( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, Int sourceSelect ) { PAF_AST_Config *pAstCfg; Int z; /* decode counter */ Int errno; /* error number */ Int getVal; enum { INIT, STREAM, ENCODE, FINAL, QUIT } state; state = INIT; errno = 0; /* error number */ Int frame; // (***) FL: formerly -- decoder input frame count Int block; // decoder output block count / input frame Int outSioUpdate; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration for (;;) { // FL: Check if any change in output SIO, e.g. from Output shortcut. // Changes will break FSM and allow Output reconfiguration. if (errno = checkOutSio(pP, pC, &outSioUpdate)) { TRACE_TERSE1("PAF_ASOT_decodeProcessing: checkOutSio returned errno = 0x%04x", errno); break; } else if (outSioUpdate) { TRACE_VERBOSE0("PAF_ASOT_decodeProcessing: Change in Output SIO selection"); state = QUIT; } // Process commands (encode) if (getVal = pP->fxns->encodeCommand(pP, pQ, pC)) { /* ignore */; } // Process state (decode) switch (state) { case INIT: // initial state gAsopInitCnt++; Log_info0("TaskAsop: state=INIT"); // Reset audio frame pointers to original values // (may be needed if error occurred). for (z=STREAM1; z < STREAMN; z++) { Int ch; for (ch=PAF_LEFT; ch < PAF_MAXNUMCHAN_AF; ch++) { if (pAstCfg->xStr[z].audioFrameChannelPointers[ch]) { pAstCfg->xStr[z].audioFrameChannelPointers[ch] = pAstCfg->xStr[z].origAudioFrameChannelPointers[ch]; } } } // Reset audio frame meta data elements { Int i; for (z=STREAM1; z < STREAMN; z++) { pAstCfg->xStr[z].pAudioFrame->pafBsMetadataUpdate = XDAS_FALSE; pAstCfg->xStr[z].pAudioFrame->numPrivateMetadata = 0; pAstCfg->xStr[z].pAudioFrame->bsMetadata_offset = 0; pAstCfg->xStr[z].pAudioFrame->bsMetadata_type = PAF_bsMetadata_channelData; for (i=0; ipMetadataBufStatus->NumBuf; i++) { pAstCfg->xStr[z].pAudioFrame->pafPrivateMetadata[i].offset = 0; pAstCfg->xStr[z].pAudioFrame->pafPrivateMetadata[i].size = 0; } } } if (errno = pP->fxns->decodeInit(pP, pQ, pC, sourceSelect)) { TRACE_VERBOSE1("PAF_ASOT_decodeProcessing: INIT, errno 0x%x. break after decodeInit", errno); break; } // (***) FL: setup output (ASP chain reset, ENC reset, setCheckRateX, start output) // Contained in INFO1 in combined FSM. // Establish secondary timing if (errno = pP->fxns->decodeInfo1(pP, pQ, pC, frame, block)) { TRACE_VERBOSE1("PAF_ASOT_decodeProcessing: INIT, errno 0x%x. break after decodeInfo1", errno); break; } frame = 0; block = 0; TRACE_VERBOSE0("PAF_ASOT_decodeProcessing: state: INIT->STREAM"); state = STREAM; continue; case STREAM: // stream state gAsopStreamCnt++; Log_info0("TaskAsop: state=STREAM"); if (errno = pP->fxns->decodeStream(pP, pQ, pC, frame, block)) { TRACE_TERSE1("PAF_ASOT_decodeProcessing: state: STREAM. decodeStream err 0x%x", errno); break; } TRACE_VERBOSE0("PAF_ASOT_decodeProcessing: state: STREAM->ENCODE"); state = ENCODE; continue; case ENCODE: // encode state gAsopEncodeCnt++; Log_info0("TaskAsop: state=ENCODE"); if (errno = pP->fxns->decodeEncode(pP, pQ, pC, frame, block)) { TRACE_TERSE1("PAF_ASOT_decodeProcessing: state: ENCODE. decodeEncode err 0x%x", errno); break; } // (***) FL: do we need this? // AF pointers come from CB read, any resets occur in Decoder AF. // Reset audio frame pointers to original values // (may have been adjusted by ARC or the like). for (z=STREAM1; z < STREAMN; z++) { Int ch; for (ch=PAF_LEFT; ch < PAF_MAXNUMCHAN_AF; ch++) { if (pAstCfg->xStr[z].audioFrameChannelPointers[ch]) { pAstCfg->xStr[z].audioFrameChannelPointers[ch] = pAstCfg->xStr[z].origAudioFrameChannelPointers[ch]; } } } // // (***) FL: update output (setCheckRateX) // Contained in INFO2 in combined FSM. if (errno = pP->fxns->decodeInfo2(pP, pQ, pC, frame, block)) { TRACE_TERSE1("PAF_ASOT_decodeProcessing: ENCODE break on decodeInfo2. errno 0x%x", errno); break; } block++; TRACE_VERBOSE0("PAF_ASOT_decodeProcessing: state: ENCODE->FINAL"); state = FINAL; continue; case FINAL: gAsopFinalCnt++; Log_info0("TaskAsop: state=FINAL"); // // (***) FL: this needs to be fixed. // (1) Only require selected Output to be in this FSM // => Dec Status checks aren't valid, // will probably always exit FSM if only Output running // (2) Checking Dec Status info asych to input events (maybe ok) // #if 0 // Check for final frame, and if indicated: // - Update audio flag to cause output buffer flush rather than // the default truncate in "complete" processing. // - Exit state machine to "complete" processing. if (pP->fxns->decodeFinalTest(pP, pQ, pC, frame, block)) { for (z=OUTPUT1; z < OUTPUTN; z++) { if ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_SOUND) { TRACE_VERBOSE0("PAF_ASOT_outputProcessing: state: FINAL: SOUND -> QUIET"); pAstCfg->xOut[z].outBufStatus.audio++; // SOUND -> QUIET } } break; } #endif TRACE_VERBOSE0("PAF_ASOT_decodeProcessing: state: FINAL->STREAM"); state = STREAM; continue; case QUIT: gAsopQuitCnt++; Log_info0("TaskAsop: state=QUIT"); TRACE_VERBOSE0("PAF_ASOT_decodeProcessing: state: QUIT"); errno = ASPERR_QUIT; break; default: // unknown state // Unknown: // - Set error number registers. // - Exit state machine to "complete" processing. TRACE_TERSE1("PAF_ASOT_decodeProcessing: state: unknown, 0x%x", state); errno = ASPERR_UNKNOWNSTATE; break; } // End of switch (state). TRACE_VERBOSE0("PAF_ASOT_decodeProcessing: Calling decode complete"); if (pP->fxns->decodeComplete(pP, pQ, pC, NULL, frame, block)) { /* ignored? */; } return errno; } // End of for (;;) return errno; } // ----------------------------------------------------------------------------- // ASOT Decoding Function - Encode Command Processing // // Name: PAF_ASOT_encodeCommand // Purpose: Decoding Function for processing Encode Commands. // From: AST Parameter Function -> decodeProcessing // Uses: See code. // States: x // Return: 0. // Trace: Message Log "trace" in Debug Project Configuration reports: // * Command execution. // * SIO control errors. // * Error number macros. // Int PAF_ASOT_encodeCommand( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* encode counter */ Int errno = 0; /* error number */ Int zO, zS; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; for (z=ENCODE1; z < ENCODEN; z++) { zO = pP->outputsFromEncodes[z]; zS = pP->streamsFromEncodes[z]; if (! (pAstCfg->xEnc[z].encodeStatus.command2 & 0x80)) { switch (pAstCfg->xEnc[z].encodeStatus.command2) { case 0: // command none - process pAstCfg->xEnc[z].encodeStatus.command2 |= 0x80; break; case 1: // mute command TRACE_VERBOSE2("AS%d: PAF_ASOT_encodeCommand: encode command mute (0x%02x)", as+zS, 1); if ((pAstCfg->xOut[zO].outBufStatus.audio & 0x0f) != PAF_OB_AUDIO_QUIET && pAstCfg->xOut[zO].hTxSio && (errno = SIO_ctrl (pAstCfg->xOut[zO].hTxSio, PAF_SIO_CONTROL_MUTE, 0))) { errno = (errno & 0xff) | ASPERR_MUTE; /* convert to sensical errno */ TRACE_TERSE1("AS%d: PAF_ASOT_encodeCommand: SIO control failed (mute)", as+zS); TRACE_TERSE2("AS%d: PAF_ASOT_encodeCommand: errno = 0x%04x ", as+zS, errno); } else { pAstCfg->xOut[zO].outBufStatus.audio |= PAF_OB_AUDIO_MUTED; } pAstCfg->xEnc[z].encodeStatus.command2 |= 0x80; break; case 2: // unmute command TRACE_VERBOSE2("AS%d: PAF_ASOT_encodeCommand: encode command unmute (0x%02x)", as+zS, 2); if ((pAstCfg->xOut[zO].outBufStatus.audio & 0x0f) != PAF_OB_AUDIO_QUIET && pAstCfg->xOut[zO].hTxSio && (errno = SIO_ctrl (pAstCfg->xOut[zO].hTxSio, PAF_SIO_CONTROL_UNMUTE, 0))) { errno = (errno & 0xff) | ASPERR_MUTE; /* convert to sensical errno */ TRACE_TERSE1("AS%d: PAF_ASOT_encodeCommand: SIO control failed (unmute)", as+zS); TRACE_TERSE2("AS%d: PAF_ASOT_encodeCommand: errno = 0x%04x ", as+zS, errno); } else { pAstCfg->xOut[zO].outBufStatus.audio &= ~PAF_OB_AUDIO_MUTED; } pAstCfg->xEnc[z].encodeStatus.command2 |= 0x80; break; default: // command unknown - ignore break; } } } ERRNO_RPRT (TaskAsop, errno); return 0; } //PAF_ASOT_encodeCommand // Purpose: Decoding Function for reinitializing the decoding process. Int PAF_ASOT_decodeInit( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, Int sourceSelect ) { PAF_AST_Config *pAstCfg; PAF_AST_DecOpCircBufCtl *pCbCtl; /* Decoder output circular buffer control */ Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* decode/encode counter */ Int errno; /* error number */ Int zO, zS; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; pCbCtl = &pC->pAspmCfg->decOpCircBufCtl; // get pointer to circular buffer control for (z=DECODE1; z < DECODEN; z++) { // Start decoder output circular buffer reads errno = cbReadStart(pCbCtl, z); if (errno) { TRACE_TERSE1("PAF_ASOT_decodeInit:cbReadStart() error=%d", errno); SW_BREAKPOINT; // FL: debug return errno; } gCbReadAfErr=0; // reset read circular buffer error count gDecOpCbRdAfUnd=0; // reset decoder output circular buffer underflow count gMaxDecOpCbRdAfUnd=0; // reset max decoder output circular buffer underflow count // FL: debug cbLog(pCbCtl, z, 1, "PAF_ASOT_decodeInit:cbReadStart"); } // TODO: move this to start of this function so that it doesn't affect IO timing for (z=ENCODE1; z < ENCODEN; z++) { zO = pP->outputsFromEncodes[z]; zS = pP->streamsFromEncodes[z]; if (pAstCfg->xOut[zO].hTxSio && pAstCfg->xEnc[z].encodeStatus.mode) { Int select = pAstCfg->xEnc[z].encodeStatus.select; ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select]; ENC_Handle enc = (ENC_Handle )encAlg; TRACE_VERBOSE1("AS%d: PAF_ASOT_decodeInit: initializing encode", as+zS); if (encAlg->fxns->algActivate) { encAlg->fxns->algActivate (encAlg); } if (enc->fxns->reset && (errno = enc->fxns->reset(enc, NULL, &pAstCfg->xEnc[z].encodeControl, &pAstCfg->xEnc[z].encodeStatus))) { return errno; } } } return 0; } // ----------------------------------------------------------------------------- // ASOT Decoding Function - Info Processing, Initial // // Name: PAF_ASOT_decodeInfo1 // Purpose: Decoding Function for processing information in a manner that // is unique to initial frames of input data. // From: AST Parameter Function -> decodeProcessing // Uses: See code. // States: x // Return: Error number in standard or SIO form (0 on success). // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // Int PAF_ASOT_decodeInfo1( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, Int frame, Int block ) { PAF_AST_Config *pAstCfg; Int z; /* decode/encode counter */ Int errno; /* error number */ pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration // run the chain of ASP's on the stream. TRACE_VERBOSE0("PAF_ASOT_decodeInfo1: calling streamChainFunction."); if (errno = pP->fxns->streamChainFunction(pP, pQ, pC, PAF_ASP_CHAINFRAMEFXNS_RESET, 1, frame)) { TRACE_TERSE1("PAF_ASOT_decodeInfo1: streamChainFunction returns errno 0x%x ", errno); return errno; } TRACE_VERBOSE0("PAF_ASOT_decodeInfo1: calling enc->info."); for (z=ENCODE1; z < ENCODEN; z++) { Int zO = pP->outputsFromEncodes[z]; if (pAstCfg->xOut[zO].hTxSio && pAstCfg->xEnc[z].encodeStatus.mode) { Int select = pAstCfg->xEnc[z].encodeStatus.select; ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select]; ENC_Handle enc = (ENC_Handle )encAlg; if (enc->fxns->info && (errno = enc->fxns->info(enc, NULL, &pAstCfg->xEnc[z].encodeControl, &pAstCfg->xEnc[z].encodeStatus))) { TRACE_TERSE1("PAF_ASOT_decodeInfo1: info returns errno 0x%x ", errno); return errno; } } } if (errno = pP->fxns->setCheckRateX(pP, pQ, pC, 0)) { // ignore if rateX has changed since we haven't, but are about to, // start the output. If we didn't ignore this case then the state machine // would restart unnecessarily, e.g. in the case of SRC, resulting in // added latency. if (errno != ASPERR_INFO_RATECHANGE) { TRACE_TERSE1("PAF_ASOT_decodeInfo1: setCheckRateX returns errno 0x%x, not RATECHANGE", errno); return errno; } else { TRACE_TERSE0("PAF_ASOT_decodeInfo1: RATECHANGE returns RATECHANGE, ignoring"); } } if (errno = pP->fxns->startOutput(pP, pQ, pC)) { if (errno == 0x105) { TRACE_TERSE1("PAF_ASOT_decodeInfo1: startOutput returns RING BUFFER FULL (0x%x)", errno); } else { TRACE_TERSE1("PAF_ASOT_decodeInfo1: startOutput returns errno 0x%x", errno); } return errno; } return 0; } // ----------------------------------------------------------------------------- // ASOT Decoding Function - Info Processing, Subsequent // // Name: PAF_ASOT_decodeInfo2 // Purpose: Decoding Function for processing information in a manner that // is unique to frames of input data other than the initial one. // From: AST Parameter Function -> decodeProcessing // Uses: See code. // States: x // Return: Error number in standard form (0 on success). // Trace: None. // Int PAF_ASOT_decodeInfo2( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, Int frame, Int block ) { //PAF_AST_Config *pAstCfg; Int errno; //pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration errno = pP->fxns->setCheckRateX (pP, pQ, pC, 1); TRACE_VERBOSE1("PAF_ASOT_decodeInfo2: return 0x%x", errno); return errno; } //PAF_ASOT_decodeInfo2 // ----------------------------------------------------------------------------- // ASOT Decoding Function - Stream Processing // // Name: PAF_ASOT_decodeStream // Purpose: Decoding Function for processing of audio frame data by the // ASP Algorithms. // From: AST Parameter Function -> decodeProcessing // Uses: See code. // States: x // Return: Error number in standard form (0 on success). // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent/child. // Int PAF_ASOT_decodeStream( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, Int frame, Int block ) { PAF_AST_Config *pAstCfg; PAF_AST_DecOpCircBufCtl *pCbCtl; /* Decoder output circular buffer control */ Int z; /* decode/stream counter */ PAF_AudioFrame *pAfRd; Int cbErrno; Int errno; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration pCbCtl = &pC->pAspmCfg->decOpCircBufCtl; // get pointer to circular buffer control for (z=DECODE1; z < DECODEN; z++) { Int zS = pP->streamsFromDecodes[z]; // // Read decoder output circular buffer // pAfRd = pAstCfg->xStr[zS].pAudioFrame; GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106); cbErrno = cbReadAf(pCbCtl, z, pAfRd); if ((cbErrno < 0) && (cbErrno != ASP_DECOP_CB_READ_UNDERFLOW)) { gCbReadAfErr++; TRACE_TERSE1("PAF_ASOT_decodeStream:cbReadAf() error=%d", cbErrno); //SW_BREAKPOINT; // FL: debug return cbErrno; } // Handle underflows if (cbErrno == ASP_DECOP_CB_READ_UNDERFLOW) { // FL: some number of underflows alway occur on start of stream when ASOT only depends on configured Output. // DDP: ~2 underflows // MAT-THD: ~16 underflows // Need to check behavior of cbReset(). // Need to check behavior on exit/re-entry into Output processing. gDecOpCbRdAfUnd++; // increment circular buffer underflow count if (gDecOpCbRdAfUnd >= DEC_OP_CB_RDAF_UND_THR) { // Underflow count above threshold. // (1) set max underflow count to threshold // (2) reset underflow count // (3) reset circular buffer gMaxDecOpCbRdAfUnd = DEC_OP_CB_RDAF_UND_THR; // update max underflow count gDecOpCbRdAfUnd = 0; // reset underflow count // Reset circular buffer cbReset(pCbCtl, z); Log_info0("PAF_ASOT_decodeStream:cbReset"); return cbErrno; } } else if ((cbErrno == ASP_DECOP_CB_SOK) && (gDecOpCbRdAfUnd > 0)) { // No underflow detected. // update max underflow count, // reset underflow count // update max underflow count if (gDecOpCbRdAfUnd > gMaxDecOpCbRdAfUnd) { gMaxDecOpCbRdAfUnd = gDecOpCbRdAfUnd; } gDecOpCbRdAfUnd = 0; // reset circular buffer underflow count } //Log_info0("PAF_ASOT_decodeStream:cbReadAf() complete."); GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106); Log_info0("PAF_ASOT_decodeStream:cbReadAf() complete."); #if 0 // (***) FL: shows timing of CB read // (***) debug // B8 { static Uint8 toggleState = 0; if (toggleState == 0) GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106); else GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106); toggleState = ~(toggleState); } #endif // FL: debug cbLog(pCbCtl, z, 1, "PAF_ASOT_decodeStream:cbReadAf"); //if (capAfWrite(pAfRd, 0) != CAP_AF_SOK) //{ // Log_info0("capAfWrite() error"); //} } TRACE_VERBOSE0("PAF_ASOT_outputStream: calling streamChainFunction."); errno = pP->fxns->streamChainFunction(pP, pQ, pC, PAF_ASP_CHAINFRAMEFXNS_APPLY, 1, block); if (errno) { TRACE_TERSE1("PAF_ASOT_outputStream: streamChainFunction returns errno 0x%x ", errno); return errno; } return 0; } //PAF_ASOT_decodeStream // ----------------------------------------------------------------------------- // ASOT Decoding Function - Encode Processing // // Name: PAF_ASOT_decodeEncode // Purpose: Decoding Function for processing of audio frame data by the // Encode Algorithm. // From: AST Parameter Function -> decodeProcessing // Uses: See code. // States: x // Return: Error number in standard or SIO form (0 on success). // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // Int PAF_ASOT_decodeEncode( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, Int frame, Int block ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* encode/output counter */ Int errno; /* error number */ Int zX, zE, zS; UInt32 curTime; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; // Await output buffers (but not first time) for (z=OUTPUT1; z < OUTPUTN; z++) { // determine encoder associated with this output zE = z; for (zX = ENCODE1; zX < ENCODEN; zX++) { if (pP->outputsFromEncodes[zX] == z) { zE = zX; break; } } zS = pP->streamsFromEncodes[zE]; if (pAstCfg->xOut[z].hTxSio) { // update length (e.g. ARC may have changed) pAstCfg->xOut[z].outBufConfig.lengthofFrame = pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount; TRACE_GEN2("PAF_ASOT_decodeEncode: AS%d: processing block %d -- idle", as+zS, block); errno = SIO_reclaim(pAstCfg->xOut[z].hTxSio,(Ptr *) &pAstCfg->xOut[z].pOutBuf, NULL); if (errno < 0) { SIO_idle(pAstCfg->xOut[z].hTxSio); TRACE_TERSE2("PAF_ASOT_decodeEncode: AS%d: SIO_reclaim returns error %d", as+zS, -errno); return -errno; // SIO negates error codes } // TODO: use pC->xOut[z].pOutBuf in following ->encode call #if 0 // (***) FL: shows timing of Input Rx SIO reclaim after decoding has started (autodet complete) // (***) debug // B8 { static Uint8 toggleState = 0; if (toggleState == 0) GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106); else GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106); toggleState = ~(toggleState); } #endif // // Simulate Tx SIO_reclaim() pend // //Semaphore_pend(semaphoreTxAudio, BIOS_WAIT_FOREVER); gTaskAsopCnt++; curTime = Clock_getTicks(); //System_printf("System time in TaskAsipFxn Tx audio = %lu\n", (ULong)curTime); //Log_info1("outputEncode():Tx SIO reclaim(), system time = %u", curTime); } else { TRACE_VERBOSE2("AS%d: PAF_ASOT_decodeEncode: processing block %d -- idle ", as+zS, block); } } // Encode data for (z=ENCODE1; z < ENCODEN; z++) { Int zO = pP->outputsFromEncodes[z]; Int zS = pP->streamsFromEncodes[z]; (void)zS; // clear compiler warning in case not used with tracing disabled if (pAstCfg->xOut[zO].hTxSio && pAstCfg->xEnc[z].encodeStatus.mode) { Int select = pAstCfg->xEnc[z].encodeStatus.select; ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select]; ENC_Handle enc = (ENC_Handle )encAlg; if (select != pAstCfg->xEnc[z].encodeControl.encActive) { pAstCfg->xEnc[z].encodeControl.encActive = select; TRACE_TERSE0("PAF_ASOT_decodeEncode: return error"); return (-1); } TRACE_GEN2("AS%d: PAF_ASOT_decodeEncode: processing block %d -- encode", as+zS, block); // (MID 1933) temp. workaround for PCE2 pAstCfg->xEnc[z].encodeInStruct.pAudioFrame->data.nChannels = PAF_MAXNUMCHAN; /* #if (CURRENT_TRACE_MASK & TRACE_MASK_DATA) { PAF_AudioFrame *pAudioFrame = pC->xEnc[z].encodeInStruct.pAudioFrame; int *wp; wp = (int*)pAudioFrame->data.sample[0]; TRACE_DATA((&TR_MOD, "as1-f2: AS%d PAF_ASOT_outputEncode: encoding from ch 0 0x%x. line %d", z, wp, __LINE__)); TRACE_DATA((&TR_MOD, "as1-f2: [0]: 0x%x, [16]: 0x%x, [99]: 0x%x (ch0)", wp[0], wp[16], wp[99])); wp = (int*)pAudioFrame->data.sample[1]; TRACE_DATA((&TR_MOD, "as1-f2: PAF_ASOT_outputEncode: encoding from ch 1 0x%x. line %d", wp, __LINE__)); TRACE_DATA((&TR_MOD, "as1-f2: [0]: 0x%x, [16]: 0x%x, [99]: 0x%x (ch1)", wp[0], wp[16], wp[99])); wp = (int*)pAudioFrame->data.sample[2]; TRACE_DATA((&TR_MOD, "as1-f2: PAF_ASOT_outputEncode: encoding from ch 2 0x%x. line %d", wp, __LINE__)); TRACE_DATA((&TR_MOD, "as1-f2: [0]: 0x%x, [16]: 0x%x, [99]: 0x%x (ch2)", wp[0], wp[16], wp[99])); } #endif */ if (enc->fxns->encode) { pAstCfg->xEnc[z].encodeOutStruct.bypassFlag = pP->z_pEncodeStatus[z]->encBypass; if (errno = enc->fxns->encode(enc, NULL, &pAstCfg->xEnc[z].encodeInStruct, &pAstCfg->xEnc[z].encodeOutStruct)) { if (errno != PCEERR_OUTPUT_POINTERNULL) { TRACE_TERSE1("PAF_ASOT_decodeEncode: return error %d line %d", errno); return errno; } } /* #if (CURRENT_TRACE_MASK & TRACE_MASK_DATA) else { int *wp = (int*)pC->xOut[z].pOutBuf->pntr.pVoid; TRACE_DATA((&TR_MOD, "as1-f2: PAF_ASOT_outputEncode: encoded to 0x%x. line %d", wp, __LINE__)); TRACE_DATA((&TR_MOD, "as1-f2: [0]: 0x%x, [16]: 0x%x, [99]: 0x%x", wp[0], wp[16], wp[99])); } #endif */ } } else { TRACE_VERBOSE2("PAF_ASOT_decodeEncode: AS%d: processing block %d -- encode ", as+pP->streamsFromEncodes[z], block); } } // Transmit data for (z=OUTPUT1; z < OUTPUTN; z++) { // determine encoder associated with this output zE = z; for (zX = ENCODE1; zX < ENCODEN; zX++) { if (pP->outputsFromEncodes[zX] == z) { zE = zX; break; } } zS = pP->streamsFromEncodes[zE]; if (pAstCfg->xOut[z].hTxSio) { TRACE_GEN2("PAF_ASOT_decodeEncode: AS%d: processing block %d -- output", as+zS, block); errno = SIO_issue(pAstCfg->xOut[z].hTxSio, &pAstCfg->xOut[z].outBufConfig, sizeof (pAstCfg->xOut[z].outBufConfig), 0); if (errno) { SIO_idle(pAstCfg->xOut[z].hTxSio); if (errno == 0x105) // 0x105 == RINGIO_EBUFFULL { // statStruct_LogFullRing(STATSTRUCT_AS1_F2); TRACE_TERSE1("PAF_ASOT_decodeEncode: SIO_idle returned RINGIO_EBUFFULL (0x%x)", errno); } if (errno > 0) { TRACE_TERSE1("PAF_ASOT_decodeEncode: return error 0x%x line %d", errno); return (ASPERR_ISSUE + (z << 4)); } else if (errno < 0) { TRACE_TERSE1("PAF_ASOT_decodeEncode: return neg error 0x%x line %d", -errno); return -errno; // SIO negates error codes } } if (errno > 0) { return (ASPERR_ISSUE + (z << 4)); } else if (errno < 0) { return -errno; // SIO negates error codes } } else { TRACE_GEN2("PAF_ASOT_decodeEncode: AS%d: processing block %d -- output ", as+zS, block); } } return 0; } //PAF_ASOT_decodeEncode // ----------------------------------------------------------------------------- // ASOT Decoding Function - Stream-Final Processing // // Name: PAF_ASOT_decodeComplete // Purpose: Decoding Function for terminating the decoding process. // From: AST Parameter Function -> decodeProcessing // Uses: See code. // States: x // Return: 0. // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // Int PAF_ASOT_decodeComplete( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, ALG_Handle decAlg[], Int frame, Int block ) { PAF_AST_Config *pAstCfg; PAF_AST_DecOpCircBufCtl *pCbCtl; /* Decoder output circular buffer control */ Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* decode/encode counter */ Int errno; /* error number */ pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; (void)as; // clear compiler warning in case not used with tracing disabled pCbCtl = &pC->pAspmCfg->decOpCircBufCtl; // get pointer to circular buffer control for (z=DECODE1; z < DECODEN; z++) { // Stop decoder output circular buffer reads errno = cbReadStop(pCbCtl, z); if (errno) { TRACE_TERSE1("PAF_ASOT_decodeComplete:cbReadStop() error=%d", errno); SW_BREAKPOINT; // FL: debug return errno; } // FL: debug cbLog(pCbCtl, z, 1, "PAF_ASOT_decodeComplete:cbReadStop"); } pP->fxns->streamChainFunction(pP, pQ, pC, PAF_ASP_CHAINFRAMEFXNS_FINAL, 0, frame); for (z=ENCODE1; z < ENCODEN; z++) { Int zO = pP->outputsFromEncodes[z]; if (pAstCfg->xOut[zO].hTxSio && pAstCfg->xEnc[z].encodeStatus.mode) { Int select = pAstCfg->xEnc[z].encodeStatus.select; ALG_Handle encAlg = pAstCfg->xEnc[z].encAlg[select]; #ifdef PAF_ASP_FINAL ENC_Handle enc = (ENC_Handle)encAlg; #endif /* PAF_ASP_FINAL */ TRACE_VERBOSE1("PAF_ASOT_decodeComplete: AS%d: finalizing encode", as+z); #ifdef PAF_ASP_FINAL if (enc->fxns->final) enc->fxns->final(enc, NULL, &pAstCfg->xEnc[z].encodeControl, &pAstCfg->xEnc[z].encodeStatus); #endif /* PAF_ASP_FINAL */ if (encAlg->fxns->algDeactivate) { encAlg->fxns->algDeactivate(encAlg); } } else { TRACE_VERBOSE1("PAF_ASOT_decodeComplete: AS%d: finalizing encode ", as+z); } } // wait for remaining data to be output pP->fxns->stopOutput(pP, pQ, pC); return 0; } //PAF_ASOT_decodeComplete // ----------------------------------------------------------------------------- // ASOT Decoding Function Helper - SIO Driver Start // // Name: PAF_ASOT_startOutput // Purpose: Decoding Function for initiating output. // From: AST Parameter Function -> decodeInfo1 // Uses: See code. // States: x // Return: Error number in standard or SIO form (0 on success). // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // * SIO control errors. // #define DEC_OUTNUMBUF_MAP(X) \ pP->poutNumBufMap[z]->map[(X) >= pP->poutNumBufMap[z]->length ? 0 : (X)] Int PAF_ASOT_startOutput( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* output counter */ Int errno,nbufs; /* error number */ Int zE, zS, zX; Int zMD; PAF_SIO_IALG_Obj *pObj; PAF_SIO_IALG_Config *pAlgConfig; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; zMD = pAstCfg->masterDec; for (z=OUTPUT1; z < OUTPUTN; z++) { if (pAstCfg->xOut[z].hTxSio) { // determine associated encoder and stream zE = z; zS = z; for (zX = ENCODE1; zX < ENCODEN; zX++) { if (pP->outputsFromEncodes[zX] == z) { zE = zX; zS = pP->streamsFromEncodes[zE]; break; } } // Set sample count so that DOB knows how much data to send pAstCfg->xOut[z].outBufConfig.lengthofFrame = pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount; if (pAstCfg->xOut[z].outBufStatus.markerMode == PAF_OB_MARKER_ENABLED) { pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg; pAlgConfig = &pObj->config; memset(pAstCfg->xOut[z].outBufConfig.base.pVoid, 0xAA, pAlgConfig->pMemRec[0].size); } // The index to DEC_OUTNUMBUF_MAP will always come from the primary/master // decoder. How should we handle the sourceProgram for multiple decoders? // Override as needed nbufs = DEC_OUTNUMBUF_MAP(pAstCfg->xDec[zMD].decodeStatus.sourceProgram); if (pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram] > 0) { nbufs = pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram]; } SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_NUMBUF, nbufs); if (errno = SIO_issue(pAstCfg->xOut[z].hTxSio, &pAstCfg->xOut[z].outBufConfig, sizeof(pAstCfg->xOut[z].outBufConfig), 0)) { SIO_idle(pAstCfg->xOut[z].hTxSio); TRACE_TERSE2("PAF_ASOT_startOutput: AS%d: SIO_issue failed (0x%x)", as+zS, errno); return errno; } if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) && (errno = SIO_ctrl (pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_UNMUTE, 0))) { errno = (errno & 0xff) | ASPERR_MUTE; /* convert to sensical errno */ TRACE_TERSE2("as1-f2: PAF_ASOT_startOutput: AS%d: SIO control failed (unmute) 0x%x", as+zS, errno); return (errno); } else { pAstCfg->xOut[z].outBufStatus.audio = (pAstCfg->xOut[z].outBufStatus.audio & 0xf0) | PAF_OB_AUDIO_SOUND; } TRACE_VERBOSE1("PAF_ASOT_startOutput: AS%d: output started", as+zS); } } return 0; } //PAF_ASOT_startOutput // ----------------------------------------------------------------------------- // ASOT Decoding Function Helper - SIO Driver Stop // // Name: PAF_ASOT_stopOutput // Purpose: Decoding Function for terminating output. // From: AST Parameter Function -> decodeProcessing // AST Parameter Function -> decodeComplete // Uses: See code. // States: x // Return: Error number in standard or SIO form (0 on success). // Trace: Message Log "trace" in Debug Project Configuration reports: // * SIO control errors. // Int PAF_ASOT_stopOutput( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* output counter */ Int errno = 0, getVal; Int zS, zX; PAF_SIO_IALG_Obj *pObj; PAF_SIO_IALG_Config *pAlgConfig; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; (void)as; // clear compiler warning in case not used with tracing disabled for (z=OUTPUT1; z < OUTPUTN; z++) { if (pAstCfg->xOut[z].hTxSio) { // determine associated encoder and stream zS = z; (void)zS; for (zX = ENCODE1; zX < ENCODEN; zX++) { if (pP->outputsFromEncodes[zX] == z) { zS = pP->streamsFromEncodes[zX]; break; } } // Mute output before audio data termination in the usual case, // where such termination is due to decode error or user command. // Identification of this as the usual case is provided by the // "decode processing" state machine. if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) && ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_SOUND) && (getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_MUTE, 0))) { if (!errno) { errno = (getVal & 0xff) | ASPERR_MUTE; /* convert to sensical errno */ } TRACE_VERBOSE1("PAF_ASOT_stopOutput: AS%d: SIO control failed (mute)", as+zS); } TRACE_TIME((&TIME_MOD, "... + %d = %d (stopOutput -- begin PAF_SIO_CONTROL_IDLE)", dtime(), TSK_time())); // Terminate audio data output, truncating (ignore) or flushing // (play out) final samples as per (1) control register set by // the user and (2) the type of audio data termination: #if 0 // This form is not used because driver support for truncating // data is not supported for internal clocks, although it is // for external clocks. getVal = SIO_ctrl(pC->xOut[z].hTxSio, PAF_SIO_CONTROL_IDLE, pC->xOut[z].outBufStatus.flush & (pC->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH ? 1 : 0); /* UNTESTED */ #else // This form should be used when driver support for truncating // data is supported for both internal and external clocks. getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_IDLE, pAstCfg->xOut[z].outBufStatus.flush ? 1 : (pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH ? 1 : 0); /* TESTED */ #endif TRACE_TIME((&TIME_MOD, "... + %d = %d (stopOutput -- after PAF_SIO_CONTROL_IDLE)", dtime(), TSK_time())); if (!errno) { errno = getVal; } // Mute output after audio data termination in a special case, // where such termination is due to processing of a final frame // or user command. Identification of this as a special case is // provided by the "decode processing" state machine. if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) && ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH) && (getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_MUTE, 0))) { if (!errno) { errno = (getVal & 0xff) | ASPERR_MUTE; /* convert to sensical errno */ } TRACE_VERBOSE1("as1-f2: PAF_ASOT_stopOutput: AS%d: SIO control failed (mute)", as+zS); } pAstCfg->xOut[z].outBufStatus.audio &= ~0x0f; // zero output buffers pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg; pAlgConfig = &pObj->config; memset (pAstCfg->xOut[z].outBufConfig.base.pVoid, 0, pAlgConfig->pMemRec[0].size); } //pAstCfg->xOut[z].hTxSio }//OUTPUT return errno; } //PAF_ASOT_stopOutput // ----------------------------------------------------------------------------- // ASOT Decoding Function Helper - SIO Driver Change // // Name: PAF_ASOT_setCheckRateX // Purpose: Decoding Function for reinitiating output. // From: AST Parameter Function -> decodeInfo1 // AST Parameter Function -> decodeInfo2 // Uses: See code. // States: x // Return: Error number in standard form (0 on success). // Trace: None. // /* 0: set, 1: check, unused for now. --Kurt */ Int PAF_ASOT_setCheckRateX( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, Int check ) { PAF_AST_Config *pAstCfg; float rateX; PAF_SampleRateHz rateO /* std */, rateI /* inv */; Int z; /* output counter */ Int zx; /* output re-counter */ Int getVal; int inputRate, inputCount, outputRate, outputCount; Int zMD; Int zMI; Int zMS; Int zE, zX; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration zMD = pAstCfg->masterDec; zMS = pAstCfg->masterStr; zMI = pP->zone.master; inputRate = pAstCfg->xInp[zMI].inpBufStatus.sampleRateStatus; inputCount = pAstCfg->xDec[zMD].decodeStatus.frameLength; rateI = pAstCfg->xStr[zMS].pAudioFrame->fxns->sampleRateHz (pAstCfg->xStr[zMS].pAudioFrame, inputRate, PAF_SAMPLERATEHZ_INV); for (z=OUTPUT1; z < OUTPUTN; z++) { if (pAstCfg->xOut[z].hTxSio && (pAstCfg->xOut[z].outBufStatus.clock & 0x01)) { // determine associated encoder zE = z; for (zX = ENCODE1; zX < ENCODEN; zX++) { if (pP->outputsFromEncodes[zX] == z) { zE = zX; break; } } outputRate = pAstCfg->xEnc[zE].encodeStatus.sampleRate; outputCount = pAstCfg->xEnc[zE].encodeStatus.frameLength; rateO = pAstCfg->xStr[zMS].pAudioFrame->fxns->sampleRateHz (pAstCfg->xStr[zMS].pAudioFrame, outputRate, PAF_SAMPLERATEHZ_STD); if (rateI > 0 && rateO > 0) rateX = rateO /* std */ * rateI /* inv */; else if (inputCount != 0) rateX = (float )outputCount / inputCount; else return ( ASPERR_INFO_RATERATIO ); getVal = SIO_ctrl (pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_RATEX, (Arg) &rateX); if (getVal == DOBERR_RATECHANGE) { for (zx=OUTPUT1; zx < OUTPUTN; zx++) if (pAstCfg->xOut[zx].hTxSio) SIO_idle (pAstCfg->xOut[zx].hTxSio); // this forces an exit from the calling state machine which will // eventually call startOutput which calls setCheckRateX for all outputs // and so it is ok, in the presence of a rate change on any output, to // exit this loop /function early. return ASPERR_INFO_RATECHANGE; } else if( getVal != SYS_OK ) return ((getVal & 0xff) | ASPERR_RATE_CHECK); } } return 0; } //PAF_ASOT_setCheckRateX // ----------------------------------------------------------------------------- // ASOT Decoding Function Helper - Chain Processing // // Name: PAF_ASOT_streamChainFunction // Purpose: Common Function for processing algorithm chains. // From: AST Parameter Function -> decodeInfo1 // AST Parameter Function -> decodeStream // AST Parameter Function -> decodeComplete // Uses: See code. // States: x // Return: Error number in standard form (0 on success). // Trace: Message Log "trace" in Debug Project Configuration reports: // * State information as per parent. // Int PAF_ASOT_streamChainFunction( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pC, Int iChainFrameFxns, Int abortOnError, Int logArg ) { PAF_AST_Config *pAstCfg; Int as; /* Audio Stream Number (1, 2, etc.) */ Int z; /* stream counter */ Int errno; /* error number */ Int dFlag, eFlag, gear; Int zX; Int zS; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration as = pAstCfg->as; (void)as; // clear compiler warning in case not used with tracing disabled for (zS = STREAM1; zS < STREAMN; zS++) { z = pP->streamOrder[zS]; // Select stream order from streamOrder parameter - MID 788 // apply stream // unless the stream is associated with a decoder and it is not running // or // unless the stream is associated with an encoder and it is not running // Also gear control only works for streams with an associated decoder // if no such association exists then gear 0 (All) is used dFlag = 1; gear = 0; for (zX = DECODE1; zX < DECODEN; zX++) { if (pP->streamsFromDecodes[zX] == z) { dFlag = pAstCfg->xDec[zX].decodeStatus.mode; gear = pAstCfg->xDec[zX].decodeStatus.aspGearStatus; break; } } eFlag = 1; for (zX = ENCODE1; zX < ENCODEN; zX++) { if (pP->streamsFromEncodes[zX] == z) { eFlag = pAstCfg->xEnc[zX].encodeStatus.mode; break; } } if (dFlag && eFlag) { PAF_ASP_Chain *chain = pAstCfg->xStr[z].aspChain[gear]; PAF_AudioFrame *frame = pAstCfg->xStr[z].pAudioFrame; Int (*func) (PAF_ASP_Chain *, PAF_AudioFrame *) = chain->fxns->chainFrameFunction[iChainFrameFxns]; TRACE_GEN2(iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_RESET ? "PAF_ASOT_streamChainFunction: AS%d: processing frame %d -- audio stream (reset)" : iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_APPLY ? "PAF_ASOT_streamChainFunction: AS%d: processing block %d -- audio stream (apply)" : iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_FINAL ? "PAF_ASOT_streamChainFunction: AS%d: processing frame %d -- audio stream (final)" : "PAF_ASOT_streamChainFunction: AS%d: processing frame %d -- audio stream (?????)", as+z, logArg); errno = (*func) (chain, frame); TRACE_VERBOSE2("PAF_ASOT_streamChainFunction: AS%d: errno 0x%x.", as+z, errno); if (errno && abortOnError) return errno; } else { TRACE_GEN2(iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_RESET ? "PAF_ASOT_streamChainFunction: AS%d: processing frame %d -- audio stream (reset) " : iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_APPLY ? "PAF_ASOT_streamChainFunction: AS%d: processing block %d -- audio stream (apply) " : iChainFrameFxns == PAF_ASP_CHAINFRAMEFXNS_FINAL ? "PAF_ASOT_streamChainFunction: AS%d: processing frame %d -- audio stream (final) " : "PAF_ASOT_streamChainFunction: AS%d: processing frame %d -- audio stream (?????) ", as+z, logArg); } /* { void dp_tracePAF_Data(float *lBuf, float *rBuf, int count); PAF_AudioFrameData *afd; float ** afPtr; afd = &(pC->xStr->pAudioFrame->data); afPtr = (float**)afd->sample; dp_tracePAF_Data(afPtr[4], afPtr[5], 256); } */ } return 0; } //PAF_ASOT_streamChainFunction /* FL: Check if at least one output selected */ static Int checkOutSel( const PAF_ASOT_Params *pP, PAF_ASOT_Config *pC, Int *pOutSel ) { PAF_AST_Config *pAstCfg; Int outSel; Int z; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration outSel = 0; for (z=OUTPUT1; z < OUTPUTN; z++) { if (pAstCfg->xOut[z].hTxSio) { outSel = 1; break; } } *pOutSel = outSel; return 0; } /* FL: Check if at least one output sio changed */ static Int checkOutSio( const PAF_ASOT_Params *pP, PAF_ASOT_Config *pC, Int *pOutSioUpdate ) { PAF_AST_Config *pAstCfg; Int outSioUpdate; Int z; pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration outSioUpdate = 0; for (z=OUTPUT1; z < OUTPUTN; z++) { if (pAstCfg->xOut[z].outBufStatus.sioSelect >= 0) { outSioUpdate = 1; break; } } *pOutSioUpdate = outSioUpdate; return 0; }