📄 omxacaac_mdctinv_s32_s16.c
字号:
/** * * File Name: omxACAAC_MDCTInv_S32_S16.c * OpenMAX DL: v1.0.2 * Revision: 10586 * Date: Wednesday, March 5, 2008 * * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. * * * * Description: * This file contains module for IMDCT for an AAC decoder * */#include <math.h> #include "omxtypes.h" #include "armOMX.h"#include "omxAC.h"#include "armAC.h"#include "armCOMM.h"#include "armACAAC_Tables.h"/** * Function: omxACAAC_MDCTInv_S32_S16 (3.2.3.5.2) * * Description: * This function computes an inverse MDCT to generate 1024 reconstructed * 16-bit signed little-endian PCM samples as output for each channel. In * order to adapt the time/frequency resolution of the filterbank to the * characteristics of the input signal, a block switching tool is also * adopted. For each channel, 1024 time-frequency domain samples are * transformed into the time domain via the IMDCT. After applying the * windowing operation, the first half of the windowed sequence is added to * the second half of the previous block windowed sequence to reconstruct 1024 * output samples for each channel. Output can be interleaved according to * pcmMode. * If pcmMode equals 2, output is in the sequence pDstPcmAudioOut[2*i], * i=0 to 1023, i.e., 1024 output samples are stored in the sequence: * * pDstPcmAudioOut[0], pDstPcmAudioOut[2], * pDstPcmAudioOut[4], ..., pDstPcmAudioOut[2046]. * * If pcmMode equals 1, output is in the sequence: * * pDstPcmAudioOut[i], i=0 to 1023. * * Users must also preallocate an input-output buffer pointed by * pSrcDstOverlapAddBuf for overlap-add operation. Reset this buffer to * zero before first call, then use the output of the current call as the * input of the next call for the same channel. * * Reference: [ISO14496-3], sub-clause 4.6.11 * * Input Arguments: * * pSrcSpectralCoefs - pointer to the input time-frequency domain samples * in Q28.3 format. There are 1024 elements in the buffer pointed * by pSrcSpectralCoefs. * pSrcDstOverlapAddBuf - pointer to the overlap-add buffer which contains * the second half of the previous block windowed sequence in * Q28.3. There are 1024 elements in this buffer. * winSequence - analysis window sequence specifier for the current block; * the following values are allowed: * 0=only_long_sequence/long_window, * 1=long_start_sequence/long_start_window, * 2=eight_short_sequence/short window, * 3=long_stop_sequence/long_stop_window. The function will return * an error if winSequence<0 or winSequence>3. * winShape - analysis window shape specifier for the current block. The * following values are allowed: 0=sine window, 1=Kaiser-Bessel * derived (KBD) window. The function will return an error if this * parameter is not equal to either 0 or 1. * prevWinShape - analysis window shape specifier for the previous block. * The following values are allowed: 0=sine window, 1=Kaiser-Bessel * derived (KBD) window. The function will return an error if this * parameter is not equal to either 0 or 1. * pcmMode - flag that indicates whether the PCM audio output is * interleaved (LRLRLR ) or not: 1 = not interleaved 2 = * interleaved * * Output Arguments: * * pDstPcmAudioOut - Pointer to the output 1024 reconstructed 16-bit signed * little-endian PCM samples in Q15.0, interleaved if needed. * pSrcDstOverlapAddBuf - pointer to the overlap-add buffer which contains * the second half of the current block windowed sequence in Q28.3. * * Return Value: * * OMX_Sts_NoErr - no error * OMX_Sts_BadArgErr - bad arguments * - at least one of the pointers is NULL: * - pSrcSpectralCoefs, * - pSrcDstOverlapAddBuf, or * - pDstPcmAudioOut * - winSequence < 0, or winSequence > 3 * - winShape < 0, or winShape > 1 * - prevWinShape < 0, or prevWinShape > 1 * - pcmMode < 1, or pcmMode > 2 * */OMXResult omxACAAC_MDCTInv_S32_S16( const OMX_S32 *pSrcSpectralCoefs, OMX_S16 *pDstPcmAudioOut, OMX_S32 *pSrcDstOverlapAddBuf, OMX_INT winSequence, OMX_INT winShape, OMX_INT prevWinShape, OMX_INT pcmMode ){ const OMX_F64 *pLeftWinShortPrev = NULL,*pLeftWinShort = NULL,*pLeftWinLongPrev = NULL; const OMX_F64 *pRightWinShort = NULL,*pRightWinLong = NULL; /*To avoid warnings*/ OMX_F64 *pDstCoeff,*pBuffer; OMX_F64 dstCoeff[ARM_AAC_WIN_LONG << 1],buffer[ARM_AAC_WIN_SHORT]; OMX_F64 theta,PiByN,alpha,coeff; OMX_F64 output,cosine,outCoeff0; OMX_INT outCoeff,inCoeff,winNum; /* Argument Check */ armRetArgErrIf( pSrcSpectralCoefs == NULL, OMX_Sts_BadArgErr); armRetArgErrIf( pDstPcmAudioOut == NULL, OMX_Sts_BadArgErr); armRetArgErrIf( pSrcDstOverlapAddBuf == NULL, OMX_Sts_BadArgErr); armRetArgErrIf( (winSequence > 3) || (winSequence < 0) , OMX_Sts_BadArgErr); armRetArgErrIf( (winShape > 1) || (winShape < 0) , OMX_Sts_BadArgErr); armRetArgErrIf( (prevWinShape > 1) || (prevWinShape < 0), OMX_Sts_BadArgErr); armRetArgErrIf( (pcmMode > 2) || (pcmMode < 1) , OMX_Sts_BadArgErr); /* Processing */ /*Windowing pointer assignments*/ switch(prevWinShape) { case 0: /*sine window*/ pLeftWinShortPrev = armACAAC_winShortSine; pLeftWinLongPrev = armACAAC_winLongSine; break; case 1: /*KBD window*/ pLeftWinShortPrev = armACAAC_winShortKBD; pLeftWinLongPrev = armACAAC_winLongKBD; break; } switch(winShape) { case 0: /*sine window*/ pRightWinShort = armACAAC_winShortSine + ARM_AAC_WIN_SHORT - 1; pRightWinLong = armACAAC_winLongSine + ARM_AAC_WIN_LONG - 1; pLeftWinShort = armACAAC_winShortSine; break; case 1: /*KBD window*/ pRightWinShort = armACAAC_winShortKBD + ARM_AAC_WIN_SHORT - 1; pRightWinLong = armACAAC_winLongKBD + ARM_AAC_WIN_LONG - 1; pLeftWinShort = armACAAC_winShortKBD; break; } /*IMDCT*/ pDstCoeff = dstCoeff; pBuffer = buffer; if(winSequence == ARM_AAC_EIGHT_SHORT_SEQUENCE) { /*Short IMDCT*/ outCoeff0 = 64.5; PiByN = armPI/(ARM_AAC_WIN_SHORT << 1); /*Adding the Inital zeros to buffer*/ for(outCoeff = 0; outCoeff < 448 ; outCoeff++) { *pDstCoeff++ = 0; } for(winNum = 0; winNum < OMX_AAC_WIN_MAX ; winNum++) { for(outCoeff = 0 ; outCoeff < (ARM_AAC_WIN_SHORT << 1) ; outCoeff ++) { theta = (2*PiByN)*( (OMX_F64)outCoeff + outCoeff0); output = 0; for(inCoeff = 0; inCoeff < ARM_AAC_WIN_SHORT ; inCoeff ++) { alpha = theta * ( (OMX_F64)inCoeff + .5); cosine = cos(alpha); coeff = pSrcSpectralCoefs[inCoeff]/ (OMX_F64)(1 << ARM_AAC_Q_FACTOR); coeff = cosine * coeff; output = output + coeff; } output = (output/ARM_AAC_WIN_SHORT); /*Windowing operation */ if(outCoeff < ARM_AAC_WIN_SHORT) { /* First Half */ /*Window and store in the buffer*/ if(winNum == 0) { output = pLeftWinShortPrev[outCoeff] * output; } else { output = pLeftWinShort[outCoeff] * output; output = pBuffer[outCoeff] + output; } *pDstCoeff++ = output; } else { /*Second Half*/ output = pRightWinShort[ARM_AAC_WIN_SHORT - outCoeff] * output; pBuffer[outCoeff - ARM_AAC_WIN_SHORT] = output; } } pSrcSpectralCoefs += ARM_AAC_WIN_SHORT; } for(outCoeff = 0 ; outCoeff < ARM_AAC_WIN_SHORT ; outCoeff++) { *pDstCoeff++ = pBuffer[outCoeff]; } /*Adding the terminating zeros to the buffer*/ for(outCoeff = 0; outCoeff < 448 ; outCoeff++) { *pDstCoeff++ = 0; } } else { /*Long IMDCT*/ outCoeff0 = 512.5; PiByN = armPI/(ARM_AAC_WIN_LONG << 1); for(outCoeff = 0 ; outCoeff < (ARM_AAC_WIN_LONG << 1) ; outCoeff ++) { theta = (2*PiByN)*( (OMX_F64)outCoeff + outCoeff0); output = 0; for(inCoeff = 0; inCoeff < ARM_AAC_WIN_LONG ; inCoeff ++) { alpha = theta * ( (OMX_F64)inCoeff + .5); cosine = cos(alpha); coeff = pSrcSpectralCoefs[inCoeff]/ (OMX_F64)(1 << ARM_AAC_Q_FACTOR); coeff = cosine * coeff; output = output + coeff; } pDstCoeff[outCoeff] = (output/ARM_AAC_WIN_LONG); } } pDstCoeff = dstCoeff; /*Windowing*/ switch(winSequence) { case ARM_AAC_ONLY_LONG_SEQUENCE: for(outCoeff = 0 ; outCoeff < ARM_AAC_WIN_LONG ; outCoeff ++) { /*Left Half*/ output = pLeftWinLongPrev[outCoeff] * pDstCoeff[outCoeff] ; pDstCoeff[outCoeff] = output; /*Right Half*/ output = pRightWinLong[-outCoeff] * pDstCoeff[outCoeff + ARM_AAC_WIN_LONG] ; pDstCoeff[outCoeff + ARM_AAC_WIN_LONG] = output; } break; case ARM_AAC_LONG_STOP_SEQUENCE: for(outCoeff = 0 ; outCoeff < 448 ; outCoeff ++) { pDstCoeff[outCoeff] = 0; } for(outCoeff = 448 ; outCoeff < 576 ; outCoeff ++) { output = pLeftWinShortPrev[outCoeff - 448] * pDstCoeff[outCoeff]; pDstCoeff[outCoeff] = output; } for(outCoeff = ARM_AAC_WIN_LONG ; outCoeff < (ARM_AAC_WIN_LONG << 1) ; outCoeff ++) { output = pRightWinLong[ARM_AAC_WIN_LONG - outCoeff] * pDstCoeff[outCoeff]; pDstCoeff[outCoeff] = output; } break; case ARM_AAC_LONG_START_SEQUENCE: for(outCoeff = 0 ; outCoeff < ARM_AAC_WIN_LONG ; outCoeff ++) { output = pLeftWinLongPrev[outCoeff] * pDstCoeff[outCoeff]; pDstCoeff[outCoeff] = output; } for(outCoeff = 1472 ; outCoeff < 1600 ; outCoeff ++) { output = pRightWinShort[1472 - outCoeff] * pDstCoeff[outCoeff]; pDstCoeff[outCoeff] = output; } for(outCoeff = 1600 ; outCoeff < (ARM_AAC_WIN_LONG << 1 ) ; outCoeff ++) { pDstCoeff[outCoeff] = 0; } break; case ARM_AAC_EIGHT_SHORT_SEQUENCE: /*Windowing already done*/ break; } /*Overlap and Add*/ for(outCoeff = 0 ;outCoeff < ARM_AAC_WIN_LONG ; outCoeff++) { output = pDstCoeff[outCoeff] + pSrcDstOverlapAddBuf[outCoeff]/ (OMX_F64)(1 << ARM_AAC_Q_FACTOR); pSrcDstOverlapAddBuf[outCoeff] = armSatRoundFloatToS32( (pDstCoeff[outCoeff + ARM_AAC_WIN_LONG]) * (1 << ARM_AAC_Q_FACTOR) ); /*Rounding*/ pDstPcmAudioOut[pcmMode * outCoeff] = (OMX_S16)armSatRoundFloatToS16(output); } return OMX_Sts_NoErr;}/*End of File*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -