/* 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. * */ // // Framework support function (implementation) // #include // #include #include #include #include #include #include #include //#include #include #include #include "as0.h" #include "inpbuf.h" #include #include #include "outbuf.h" #include /* ASPERR_*OUT_* */ #include //#include "pafhjt.h" #include "common.h" #include "paf_heapMgr.h" #include "aspMsg_common.h" #include "aspMsg_master.h" #include "audioStreamProc_common.h" #define PAF_DEVICE_VERSION (PAF_DEVICE & 0xffff) #if PAF_DEVICE_VERSION == 0xE000 #define _DEBUG // This is to enable log_printfs #endif /* PAF_DEVICE_VERSION */ #include // allows you to set a different trace module in pa.cfg #define TR_MOD trace // Allow a developer to selectively enable tracing. // For release, set mask to 1 to make it easier to catch any errors. #define CURRENT_TRACE_MASK 1 // terse only #define TRACE_MASK_TERSE 1 // only flag errors #define TRACE_MASK_GENERAL 2 // log a half dozen lines per loop #define TRACE_MASK_VERBOSE 4 // trace full operation #if (CURRENT_TRACE_MASK & TRACE_MASK_TERSE) #define TRACE_TERSE(a) LOG_printf a #else #define TRACE_TERSE(a) #endif #if (CURRENT_TRACE_MASK & TRACE_MASK_GENERAL) #define TRACE_GEN(a) LOG_printf a #else #define TRACE_GEN(a) #endif #if (CURRENT_TRACE_MASK & TRACE_MASK_VERBOSE) #define TRACE_VERBOSE(a) LOG_printf a #else #define TRACE_VERBOSE(a) #endif // // Audio Stream Task / Decode Processing - Device Allocation Function // // Name: PAF_DEC_deviceAllocate // Purpose: Decode Function for "device allocation" to // (1) allocate buffer memory, and // (2) initialize a Buffer Configuration, including pointers // to that buffer memory. // From: AST Parameter Function -> deviceAllocate // Uses: None. // States: None. // Return: 0 on success. // 1 on MEM_calloc failure. // Trace: None. // Int PAF_DEC_deviceAllocate( SIO_Handle *pHandle, int mode, int heapID, int bufSize, Ptr pBufCfg ) { Ptr pBuf; Error_Block eb; *pHandle = NULL; // Initialize error block Error_init(&eb); //#ifdef _TMS320C6X //#warn Changed back to MEM_calloc until Mantis ID 81 resolved -- mwatson //#endif // if (! (pBuf = (Ptr )MEM_alloc (heapID, bufSize, 128))) //if (! (pBuf = (Ptr )MEM_calloc (heapID, bufSize, 128))) if (!(pBuf = (Ptr )Memory_calloc((IHeap_Handle)pafHeapMgr_readHeapHandle(heapID), bufSize, 128, &eb))) return (SYS_EALLOC); if( mode == SIO_OUTPUT ) { PAF_OutBufConfig *pConfig = (PAF_OutBufConfig *)pBufCfg; pConfig->base.pVoid = pBuf; pConfig->pntr.pVoid = pBuf; pConfig->head.pVoid = pBuf; pConfig->allocation = bufSize; pConfig->precision = 24; } else { PAF_InpBufConfig *pConfig = (PAF_InpBufConfig *)pBufCfg; pConfig->base.pVoid = pBuf; pConfig->pntr.pVoid = pBuf; pConfig->head.pVoid = pBuf; pConfig->allocation = bufSize; pConfig->precision = 16; } return SYS_OK; } /* PAF_DEC_deviceAllocate */ // // Audio Stream Task / Decode Processing - Device Selection Function // // Name: PAF_DEC_deviceSelect // Purpose: Decode Function for "device selection" which // (1) "closes" any open device on that handle, and // (2) "opens" a new device on that handle if not None. // From: AST Parameter Function -> deviceSelect // Uses: See code. // States: None. // Return: 0 on success. // 1 on error in device create. // 2 on error in device open. // 3 on error in device close. // 4 on error in device idle. // Trace: None. // Int PAF_DEC_deviceSelect( SIO_Handle *pHandle, int mode, int heapID, Ptr pParams ) { // Device must be idled, closed, and freed to select new: if (*pHandle) { if (SIO_idle (*pHandle)) return ASPERR_DEVINP_IDLE-ASPERR_DEVINP; if (SIO_ctrl (*pHandle, PAF_SIO_CONTROL_CLOSE, 0)) return ASPERR_DEVINP_CLOSE-ASPERR_DEVINP; PAF_SIO_free (*pHandle, mode ); /* For consistency, should return integer. --Kurt */ } // Select new device: if (! pParams) { /* input/output device None */ *pHandle = NULL; } else if (! (*pHandle = PAF_SIO_recreate (pParams, mode, &trace, heapID))) return ASPERR_DEVINP_CREATE-ASPERR_DEVINP; else if (SIO_ctrl (*pHandle, PAF_SIO_CONTROL_OPEN, (Arg) pParams)) return ASPERR_DEVINP_OPEN-ASPERR_DEVINP; return 0; } /* PAF_DEC_deviceSelect */ // // Audio Stream Task / Decode Processing - Frame Length Computation Function // // Name: PAF_DEC_computeFrameLength // Purpose: Compute frame length to be generated by a decode algorithm, // including effects of the "buffer ratio" which is used to // indicate possible subsequent up-sampling by 2 or 4 (-2 or // -4) or down-sampling by 2 or 4 (2 or 4). // From: AST Parameter Function -> computeFrameLength // Uses: See code. // States: None. // Return: Frame length. // Trace: None. // #include #if 0 /* commenting IP component header file inclusion */ #include #include #include #define DEC_MINSAMGEN PCM_MINSAMGEN #if DEC_MINSAMGEN != AC3_MINSAMGEN #error internal error #elif DEC_MINSAMGEN != DTS_MINSAMGEN #error internal error #elif DEC_MINSAMGEN != AAC_MINSAMGEN #error internal error #endif /* DEC_MINSAMGEN */ #define DEC_MAXSAMGEN PCM_MAXSAMGEN #if DEC_MAXSAMGEN != AC3_MAXSAMGEN #error internal error #elif DEC_MAXSAMGEN != DTS_MAXSAMGEN #error internal error #elif defined (AAC_SUPPORT) && DEC_MAXSAMGEN != AAC_MAXSAMGEN #error internal error #endif /* DEC_MAXSAMGEN */ #else #define DEC_MINSAMGEN PCM_MINSAMGEN #define DEC_MAXSAMGEN PCM_MAXSAMGEN #endif // FL: change alg handle to decIdx, index is w.r.t. dec zones //Int //PAF_DEC_computeFrameLength( // ALG_Handle alg, // Int frameLength, // Int bufferRatio //) Int PAF_DEC_computeFrameLength( Int decIdx, Int frameLength, Int bufferRatio ) { Int m, n, o, p; // Messaging Int argIdx; char decMsgBuf[ASP_MSG_BUF_LEN]; // FL: dec control message to slave argIdx = 0; // set decIdx *(Int *)&decMsgBuf[argIdx] = decIdx; argIdx += sizeof(Int); // set decCtrlCmd *(IALG_Cmd *)&decMsgBuf[argIdx] = DEC_MINSAMGEN; if(AspMsgSend(ASP_SLAVE_DEC_CONTROL, ASP_MASTER_DEC_CONTROL_DONE, decMsgBuf, decMsgBuf) != ASP_MSG_NO_ERR) { SW_BREAKPOINT; return -1; // temporary } else { argIdx = 0; // get decCtrlRet m = *(Int *)&decMsgBuf[argIdx]; TRACE_TERSE1("decCtrlRet (m)=%d", m); } #if 0 // FL: decoder control call, slave m = alg->fxns->algControl(alg, DEC_MINSAMGEN, NULL); #endif // FL: dec control message to slave argIdx = 0; // set decIdx *(Int *)&decMsgBuf[argIdx] = decIdx; argIdx += sizeof(Int); // set decCtrlCmd *(IALG_Cmd *)&decMsgBuf[argIdx] = DEC_MAXSAMGEN; if(AspMsgSend(ASP_SLAVE_DEC_CONTROL, ASP_MASTER_DEC_CONTROL_DONE, decMsgBuf, decMsgBuf) != ASP_MSG_NO_ERR) { SW_BREAKPOINT; return -1; // temporary } else { argIdx = 0; // get decCtrlRet n = *(Int *)&decMsgBuf[argIdx]; TRACE_TERSE1("decCtrlRet (n)=%d", n); } #if 0 // FL: decoder control call, slave n = alg->fxns->algControl(alg, DEC_MAXSAMGEN, NULL); #endif if (m != n) { o = n < frameLength ? n : frameLength; o = o / m * m; if (bufferRatio > 0) { if (bufferRatio == 4 && (p = o / 4) > m && p % 8 == 0) return p; else if (bufferRatio == 4 && (p = o / 2) > m && p % 8 == 0) return p; else if (bufferRatio == 2 && (p = o / 2) > m && p % 8 == 0) return p; } else if (bufferRatio < 0) { if (bufferRatio == -4 && (p = o * 4) > m && p % 8 == 0) return p; else if (bufferRatio == -4 && (p = o * 2) > m && p % 8 == 0) return p; else if (bufferRatio == -2 && (p = o * 2) > m && p % 8 == 0) return p; } if (o % 8 == 0) return o; } return m; } /* PAF_DEC_computeFrameLength */ // // Audio Stream Task / Decode Processing - Input Status Update // // Name: PAF_DEC_updateInputStatus // Purpose: Decode Function for maintaining Input Status. // From: AST Parameter Function -> updateInputStatus // Uses: See code. // States: None. // Return: 0 on success. // Other on SIO Control failure (using SIO error numbers). // Trace: None. // Int PAF_DEC_updateInputStatus( SIO_Handle hSio, PAF_InpBufStatus *pStatus, PAF_InpBufConfig *pConfig) { Int errno; PAF_SIO_InputStatus inputStatus; // initialize all values to unknown so that device specific // driver layer need only fill in those entries that it is aware of. // This allows extensibility of the structure without requiring users // to re-code. inputStatus.lock = 0; inputStatus.sampleRateData = PAF_SAMPLERATE_UNKNOWN; inputStatus.sampleRateMeasured = PAF_SAMPLERATE_UNKNOWN; inputStatus.nonaudio = PAF_IEC_AUDIOMODE_UNKNOWN; inputStatus.emphasis = PAF_IEC_PREEMPHASIS_UNKNOWN; errno = SIO_ctrl (hSio, (Uns)PAF_SIO_CONTROL_GET_INPUT_STATUS, (Arg) &inputStatus); if (errno) return errno; pStatus->sampleRateData = inputStatus.sampleRateData; pStatus->sampleRateMeasured = inputStatus.sampleRateMeasured; pStatus->nonaudio = inputStatus.nonaudio; pStatus->emphasisData = inputStatus.emphasis; // if MSB of override clear then use as reported lock // if = 0x80 then use default [0x81] // if = 0x81 then use measured (from device) // others not defined or implemented if ((pStatus->lockOverride & (XDAS_Int8)0x80) == 0) pStatus->lock = pStatus->lockOverride; else if (pStatus->lockOverride == (XDAS_Int8)0x80) pStatus->lock = inputStatus.lock; else if (pStatus->lockOverride == (XDAS_Int8)0x81) pStatus->lock = inputStatus.lock; // if MSB of override clear then use it as sample rate for system, // if = 0x80 then use default [0x82] // if = 0x81 then use data // if = 0x82 then use measured // others not defined or implemented if ((pStatus->sampleRateOverride & (XDAS_Int8)0x80) == 0) pStatus->sampleRateStatus = pStatus->sampleRateOverride; else if (pStatus->sampleRateOverride == (XDAS_Int8)0x80) pStatus->sampleRateStatus = pStatus->sampleRateMeasured; else if (pStatus->sampleRateOverride == (XDAS_Int8)0x81) pStatus->sampleRateStatus = pStatus->sampleRateData; else if (pStatus->sampleRateOverride == (XDAS_Int8)0x82) pStatus->sampleRateStatus = pStatus->sampleRateMeasured; // Update emphasis status: if ((pStatus->emphasisOverride & (XDAS_Int8)0x80) == 0) { if (pStatus->emphasisData == PAF_IEC_PREEMPHASIS_YES) pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_YES; else pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_NO; } else if (pStatus->emphasisOverride == (XDAS_Int8 )(0x80+PAF_IEC_PREEMPHASIS_YES)) pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_YES; else /* IBEmphasisOverrideNo or other */ pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_NO; // Update precision control pConfig->precision = pStatus->precisionInput = pStatus->precisionOverride < 0 ? pStatus->precisionDefault : pStatus->precisionOverride > 0 ? pStatus->precisionOverride : pStatus->precisionDetect > 0 ? pStatus->precisionDetect : pStatus->precisionDefault; return 0; } /* PAF_DEC_updateInputStatus */ // ---------------------------------------------------------------------------- #ifndef HSE // ............................................................................ // // Audio Stream Task / Asynchronous Rate Conversion (ARC) - Control // // Name: PAF_ARC_controlRate // Purpose: Control ARC conversion rate // From: AST Parameter Function -> controlRate // Uses: See code. // States: None. // Return: 0 on success. // Other on SIO Control failure (using SIO error numbers). // Trace: None. // #include /* ldexp() */ #include #include Int PAF_ARC_controlRate( SIO_Handle hRxSio, SIO_Handle hTxSio, ACP_Handle acp, double arcRatio) // KR032013 { Int errno; if (hRxSio && hTxSio) { PAF_SIO_Stats *pRxStats, *pTxStats; //extern double arcRatio; // output / input rate // KR032013 XDAS_UInt32 inputsPerOutputQ24 = (XDAS_UInt32) ldexp( arcRatio, 24); static const ACP_Unit readARCOutputsRemainingQ24_s[] = { readARCOutputsRemainingQ24 }, wroteARCInputsPerOutputQ24_s[] = { wroteARCInputsPerOutputQ24 }; ACP_Unit y4[4]; if (errno = SIO_ctrl (hRxSio, PAF_SIO_CONTROL_GET_STATS, (Arg) &pRxStats)) { TRACE_TERSE ((&TR_MOD, "ARC: Error retrieving Rx xfer stats" " (0x%04x)", errno)); return errno; } if (errno = SIO_ctrl (hTxSio, PAF_SIO_CONTROL_GET_STATS, (Arg) &pTxStats)) { TRACE_TERSE ((&TR_MOD, "ARC: Error retrieving Tx xfer stats" " (0x%04x)", errno)); return errno; } y4[0] = wroteARCInputsPerOutputQ24_s[0]; y4[1] = wroteARCInputsPerOutputQ24_s[1]; y4[2] = (MdInt) inputsPerOutputQ24; y4[3] = (MdInt)(inputsPerOutputQ24 >> 16); if (errno = acp->fxns->apply (acp, y4, NULL)) { TRACE_TERSE ((&TR_MOD, "ARC: Error sending ARC rate ratio" " (0x%04x)", errno)); return errno; } if (errno = acp->fxns->apply (acp, readARCOutputsRemainingQ24_s, y4)) { TRACE_TERSE ((&TR_MOD, "ARC: Error retrieving ARC timing" " (0x%04x)", errno)); return errno; } { static XDAS_UInt32 outputsRemainingQ24[2]; const double arcDiff = pRxStats->dpll.v - (pTxStats->dpll.v + ldexp( outputsRemainingQ24[1], -24) * pTxStats->dpll.dv); outputsRemainingQ24[1] = outputsRemainingQ24[0]; outputsRemainingQ24[0] = ((XDAS_UInt32) y4[3] << 16) + y4[2]; TRACE_GEN ((&TR_MOD, "time dif %d.%08d", (int) arcDiff, (int) (1.e8 * (arcDiff - (int) arcDiff)))); } } return 0; } // ............................................................................ #else Int PAF_ARC_controlRate( SIO_Handle hRxSio, SIO_Handle hTxSio, ACP_Handle acp, double arcRatio) // KR032013 { return 1; } #endif //HSE // ---------------------------------------------------------------------------- // // Audio Stream Task / Pass Processing - Buffer Copy // // Name: PAF_BUF_copy // Purpose: Decode Function for copying the data in the input buffer // to the output buffer. // From: AST Parameter Function -> copy // Uses: None. // States: None. // Return: 0 on success. // 0x80000000 for errors in required arguments. // Trace: None. // #define min(a, b) (((a) < (b)) ? (a) : (b)) #include #include /* DO NOT REMOVE THIS CODE_SECTION. --Kurt */ #pragma CODE_SECTION(PAF_BUF_copy,".text:_PAF_BUF_copy") Int PAF_BUF_copy( Uns inpChan, PAF_InpBufConfig *pInpCfg, Uns outChan, PAF_OutBufConfig *pOutCfg) { Int i; Int *pInBuf, *pOutBuf; Int numSamples; #ifndef __TI_EABI__ asm (" .clink"); #endif if( (pInpCfg == NULL) || (pOutCfg == NULL) ) return ASPERR_UNSPECIFIED; if( (inpChan > pInpCfg->stride) || (outChan > pOutCfg->stride) ) return ASPERR_UNSPECIFIED; //for now assume =32bit words if( (pInpCfg->sizeofElement != 4) || (pInpCfg->sizeofElement != pOutCfg->sizeofElement) ) return ASPERR_UNSPECIFIED; pInBuf = pInpCfg->pntr.pLgInt; pOutBuf = pOutCfg->pntr.pLgInt; numSamples = min(pInpCfg->frameLength, pOutCfg->lengthofFrame); pInBuf += inpChan; pOutBuf += outChan; for( i=0; i < numSamples; i++ ) { *pOutBuf = *pInBuf; pInBuf += pInpCfg->stride; pOutBuf += pOutCfg->stride; } return 0; } /* PAF_BUF_copy */ // EOF