📄 omxacmp3_synthpqmf_s32_s16.c
字号:
/** * * File Name: omxACMP3_SynthPQMF_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 function is used to do synthesis PQMF filtering */#include <math.h>#include "omxtypes.h"#include "armOMX.h"#include "omxAC.h"#include "armCOMM_Bitstream.h"#include "armCOMM.h"#include "armACMP3_Tables.h"#include "armACMP3_CommonTables.h"#include "armAC.h"#define ARM_MP3_VBUFFER_SZ_MASK (0x1ff)/** * Function: omxACMP3_SynthPQMF_S32_S16 (3.1.3.4.2) * * Description: * Stage 2 of the hybrid synthesis filter bank; a critically-sampled * 32-channel PQMF synthesis bank that generates 32 time-domain output samples * for each 32-sample input block of IMDCT outputs. For each input block, the * PQMF generates an output sequence of 16-bit signed little-endian PCM * samples in the vector pointed to by pDstAudioOut. If mode equals 2, the * left and right channel output samples are interleaved (i.e., LRLRLR), such * that the left channel data is organized as follows: pDstAudioOut [2*i], i=0 * to 31. If mode equals 1, then the left and right channel outputs are not * interleaved. A workspace buffer of size 512 x Number of Channels must be * preallocated (pVBuffer). This buffer is referenced by the pointer pVBuffer, * and its elements should be initialized to zero prior to the first call. * During subsequent calls, the pVBuffer input for the current call should * contain the pVbuffer output generated by the previous call. The state * variable pVPosition should be initialized to zero and preserved between * calls. The values contained in pVBuffer or pVPosition should be modified * only during decoder reset, and the reset values should always be zero. * Reference [ISO13818-3], sub-clause 2.5.3.3.2 * * Input Arguments: * * pSrcY - pointer to the block of 32 IMDCT sub-band input samples, in * Q7.24 format * pVBuffer - pointer to the input workspace buffer containing Q7.24 data. * The elements of this buffer should be initialized to zero during * decoder reset. During decoder operation, the values contained in * this buffer should be modified only by the PQMF function. * pVPosition - pointer to the internal workspace index; should be * initialized to zero during decoder reset. During decoder * operation, the value of this index should be preserved between * PQMF calls and should be modified only by the function. * mode - flag that indicates whether or not the PCM audio output channels * should be interleaved 1 - not interleaved 2 - interleaved * * Output Arguments: * * pDstAudioOut - pointer to a block of 32 reconstructed PCM output samples * in 16-bit signed Q0.15 format (little-endian); left and right * channels are interleaved according to the mode flag. This should * be aligned on a 4-byte boundary * pVBuffer - pointer to the updated internal workspace buffer containing * Q7.24 data; see usage notes under input argument discussion * pVPosition - pointer to the updated internal workspace index; see usage * notes under input argument discussion * * Return Value: * * OMX_Sts_NoErr - No errors * OMX_Sts_BadArgErr - bad arguments detected; one or more of the * following conditions is true: mode<1 or mode>2 * - *pVPosition is outside the range [0, 15] at least one of the * following pointers is NULL: pSrcY, pDstAudioOut, pVBuffer, * and/or pVPosition. * */OMXResult omxACMP3_SynthPQMF_S32_S16( OMX_S32 *pSrcY, OMX_S16 *pDstAudioOut, OMX_S32 *pVBuffer, OMX_INT *pVPosition, OMX_INT mode){ OMX_F64 acc, Angle; OMX_F64 VPrime [ARM_MP3_VBUFFER_SZ], Src [ARM_MP3_PQMF_SZ]; OMX_F64 U [ARM_MP3_VBUFFER_SZ]; OMX_S32 i, j, k, J; /* Arguments check */ armRetArgErrIf(pSrcY == NULL, OMX_Sts_BadArgErr) armRetArgErrIf(pDstAudioOut == NULL, OMX_Sts_BadArgErr) armRetArgErrIf(pVBuffer == NULL, OMX_Sts_BadArgErr) armRetArgErrIf(pVPosition == NULL, OMX_Sts_BadArgErr) armRetArgErrIf(mode < 1, OMX_Sts_BadArgErr) armRetArgErrIf(mode > 2, OMX_Sts_BadArgErr) /* Validate Arguments */ armRetArgErrIf(*pVPosition < 0, OMX_Sts_BadArgErr) armRetArgErrIf(*pVPosition > 15, OMX_Sts_BadArgErr) /* Get input */ for (i = 0; i < ARM_MP3_PQMF_SZ; i++) { /* Convert Q7.24 to float */ Src [i] = ((OMX_F64)pSrcY [i]) / (1 << 24); } for (i = 0; i < ARM_MP3_VBUFFER_SZ; i++) { /* Convert Q7.24 to float */ VPrime[i] = ((OMX_F64)pVBuffer [i]) / (1 << 24); } /* * Following equation given in MP3 standard (ISO/IEC 11172-3) is modified * to use a 32 point DCT and symmetry. * * 31 * V[j*64+i] = sum N[i][k] * S[k] * k=0 * for 0 =< i =< 63, 0 =< j =< 15 * where N[i][k] = cos((16+i)*(2k+1)*PI/64) * S[k] = 32 sub-band samples * * The implementation uses 32 point DCT followed by copy as given below. * This change is needed because OMX Spec uses a circular V buffer of size * 512, and pointer to the current update position. 32 DCT outputs for the * current position will be stored after the function call. * 31 * V' [j*32+i] = sum S[k] * cos(i*(2k + 1)*PI/64) * k=0 * where 0 =< k =< 31, 0 =< i =< 31, 0 =< j =< 15 * * V[j*64+i+0] = V'[j*32+i+16] * V[j*64+i+17] = -V'[j*32+31-i] * V[j*64+i+32] = -V'[j*32+16-i] * V[j*64+i+48] = -V'[j*32+i] * V[j*64+16] = 0 * where 0 =< i =< 15, 0 =< j =< 15 */ /* * Variables used for implementing: * * V -> ISO defined buffer of size 1024, each call will update 64 values * VPrime -> V'. Contains 32 point DCT values. V can be obtained from V'. * pVBuffer -> Same as VPrime, but with data type of function API, instead of float. * pVPointer-> Index to VPrime buffer for updating. Implements circular buffer. * U -> ISO defined array of 512, created as from VPrime, to be multiplied by DWindow * */ /* * Indices used for implementing: * * i -> 32 point DCT output index, 0=<i=<32 * k -> ISO defined, 32 samples of one sub-band are indexed using k. 0=<k=<32 * j -> Sub-band index, VPrime contains 16 sub-bands */ /* calculate 32pt DCT of Vi */ j = *pVPosition; for (i = 0; i < ARM_MP3_PQMF_SZ; i++) { Angle = (PI / 64.0) * i; acc = 0.0; for (k = 0; k < ARM_MP3_PQMF_SZ; k++) { acc += cos (Angle * (2.0 * k + 1.0)) * Src [k]; } VPrime [(ARM_MP3_PQMF_SZ * j) + i] = acc; pVBuffer[(ARM_MP3_PQMF_SZ * j) + i] = armSatRoundFloatToS32 (acc * (1 << 24)); } /* update pVPosition */ k = ARM_MP3_PQMF_SZ * *pVPosition; *pVPosition -= 1; if (*pVPosition < 0) { *pVPosition = 15; } /* * ISO defines calculation for U[512] as, * * U[j*64+i] = V[j*128+i] * U[j*64+32+i] = V[j*128+96+i] * for 0 =< i =< 31, 0 =< j =< 7 * * Where V is ISO defined arry of size [16*64] (64 elements per DCT32+Add Matrixing operation) * This calculation of U[512] is implemented using V' of size [16*32] (32 elements DCT32 elements) * */ /* Copy 64 element at a time to fill U of size [512] */ for (j = 0; j < 8; j++) { for (i = 0; i < 16; i++) { /* Copy first 32 elements */ /* Make U values from DCT32 values stored in V' buffer using equation * Relationship of U, V & V' * U [j*64+i] = V[j*128+i+0] = V'[k+i+16] * U [j*64+i+17] = V[j*128+i+17] = -V'[k+31-i] * Where 0 =< i =< 15, 0 =< j =< 7, 0 =< k-VPosition =< 15 */ U [j * 64 + i] = VPrime [k + i + 16]; U [j * 64 + i + 17] = -VPrime [k + 31 - i]; } /* k wraps at the v-buffer boundary */ k = (k + ARM_MP3_PQMF_SZ) & ARM_MP3_VBUFFER_SZ_MASK; for (i = 0; i < 16; i++) { /* Copy next 32 elements */ /* Make U values from DCT32 values stored in V using equation * Relationship of U, V & V' * U [j*64+i+32] = V[j*128+96+i] = V'[k+16-i] * U [j*64+i+48] = V[j*128+96+i+17] = -V'[k+32+i] * Where 0 =< i =< 15, 0 =< j =< 7,, 0 =< k-VPosition-1 =< 15 */ U [j * 64 + i + 32] = -VPrime [k + 16 - i]; U [j * 64 + i + 48] = -VPrime [k + i]; } U [j * 64 + 16] = 0; /* k wraps at the v-buffer boundary */ k = (k + ARM_MP3_PQMF_SZ) & ARM_MP3_VBUFFER_SZ_MASK; } for (i = 0; i < ARM_MP3_PQMF_SZ; i++) { acc = 0.0; for (J = 0; J < 16; J++) { /* i+32*J */ k = i + J * ARM_MP3_PQMF_SZ; acc += U [k] * armACMP3_DWindow [k]; } /* Convert float to Q16.15 */ pDstAudioOut [i * mode] = armSatRoundFloatToS16 (acc * (1 << 15)); } return OMX_Sts_NoErr;}/***************************************************************************** * END OF FILE *****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -