545 files changed, 230976 insertions, 0 deletions
diff --git a/audio_codec/libraac/tns.c b/audio_codec/libraac/tns.c new file mode 100644 index 0000000..d3f430e --- a/dev/null +++ b/audio_codec/libraac/tns.c @@ -0,0 +1,307 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Source last modified: $Id: tns.c,v 1.2 2005/05/24 16:01:55 albertofloyd Exp $ + * + * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, + * are subject to the current version of the RealNetworks Public + * Source License (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the current version of the RealNetworks Community + * Source License (the "RCSL") available at + * http://www.helixcommunity.org/content/rcsl, in which case the RCSL + * will apply. You may also obtain the license terms directly from + * RealNetworks. You may not use this file except in compliance with + * the RPSL or, if you have a valid RCSL with RealNetworks applicable + * to this file, the RCSL. Please see the applicable RPSL or RCSL for + * the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the + * portions it created. + * + * This file, and the files included with this file, is distributed + * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS + * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET + * ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point HE-AAC decoder + * Jon Recker (jrecker@real.com) + * February 2005 + * + * tns.c - apply TNS to spectrum + **************************************************************************************/ + +#include "coder.h" +#include "assembly.h" + +#define FBITS_LPC_COEFS 20 + +/* inverse quantization tables for TNS filter coefficients, format = Q31 + * see bottom of file for table generation + * negative (vs. spec) since we use MADD for filter kernel + */ +static const int invQuant3[16] = { + 0x00000000, 0xc8767f65, 0x9becf22c, 0x83358feb, 0x83358feb, 0x9becf22c, 0xc8767f65, 0x00000000, + 0x2bc750e9, 0x5246dd49, 0x6ed9eba1, 0x7e0e2e32, 0x7e0e2e32, 0x6ed9eba1, 0x5246dd49, 0x2bc750e9, +}; + +static const int invQuant4[16] = { + 0x00000000, 0xe5632654, 0xcbf00dbe, 0xb4c373ee, 0xa0e0a15f, 0x9126145f, 0x8643c7b3, 0x80b381ac, + 0x7f7437ad, 0x7b1d1a49, 0x7294b5f2, 0x66256db2, 0x563ba8aa, 0x4362210e, 0x2e3d2abb, 0x17851aad, +}; + +/************************************************************************************** + * Function: DecodeLPCCoefs + * + * Description: decode LPC coefficients for TNS + * + * Inputs: order of TNS filter + * resolution of coefficients (3 or 4 bits) + * coefficients unpacked from bitstream + * scratch buffer (b) of size >= order + * + * Outputs: LPC coefficients in Q(FBITS_LPC_COEFS), in 'a' + * + * Return: none + * + * Notes: assumes no guard bits in input transform coefficients + * a[i] = Q(FBITS_LPC_COEFS), don't store a0 = 1.0 + * (so a[0] = first delay tap, etc.) + * max abs(a[i]) < log2(order), so for max order = 20 a[i] < 4.4 + * (up to 3 bits of gain) so a[i] has at least 31 - FBITS_LPC_COEFS - 3 + * guard bits + * to ensure no intermediate overflow in all-pole filter, set + * FBITS_LPC_COEFS such that number of guard bits >= log2(max order) + **************************************************************************************/ +static void DecodeLPCCoefs(int order, int res, signed char *filtCoef, int *a, int *b) +{ + int i, m, t; + const int *invQuantTab; + + if (res == 3) { + invQuantTab = invQuant3; + } else if (res == 4) { + invQuantTab = invQuant4; + } else { + return; + } + + for (m = 0; m < order; m++) { + t = invQuantTab[filtCoef[m] & 0x0f]; /* t = Q31 */ + for (i = 0; i < m; i++) { + b[i] = a[i] - (MULSHIFT32(t, a[m - i - 1]) << 1); + } + for (i = 0; i < m; i++) { + a[i] = b[i]; + } + a[m] = t >> (31 - FBITS_LPC_COEFS); + } +} + +/************************************************************************************** + * Function: FilterRegion + * + * Description: apply LPC filter to one region of coefficients + * + * Inputs: number of transform coefficients in this region + * direction flag (forward = 1, backward = -1) + * order of filter + * 'size' transform coefficients + * 'order' LPC coefficients in Q(FBITS_LPC_COEFS) + * scratch buffer for history (must be >= order samples long) + * + * Outputs: filtered transform coefficients + * + * Return: guard bit mask (OR of abs value of all filtered transform coefs) + * + * Notes: assumes no guard bits in input transform coefficients + * gains 0 int bits + * history buffer does not need to be preserved between regions + **************************************************************************************/ +static int FilterRegion(int size, int dir, int order, int *audioCoef, int *a, int *hist) +{ + int i, j, y, hi32, inc, gbMask; + U64 sum64; + + /* init history to 0 every time */ + for (i = 0; i < order; i++) { + hist[i] = 0; + } + + sum64.w64 = 0; /* avoid warning */ + gbMask = 0; + inc = (dir ? -1 : 1); + do { + /* sum64 = a0*y[n] = 1.0*y[n] */ + y = *audioCoef; + sum64.r.hi32 = y >> (32 - FBITS_LPC_COEFS); + sum64.r.lo32 = y << FBITS_LPC_COEFS; + + /* sum64 += (a1*y[n-1] + a2*y[n-2] + ... + a[order-1]*y[n-(order-1)]) */ + for (j = order - 1; j > 0; j--) { + sum64.w64 = MADD64(sum64.w64, hist[j], a[j]); + hist[j] = hist[j - 1]; + } + sum64.w64 = MADD64(sum64.w64, hist[0], a[0]); + y = (sum64.r.hi32 << (32 - FBITS_LPC_COEFS)) | (sum64.r.lo32 >> FBITS_LPC_COEFS); + + /* clip output (rare) */ + hi32 = sum64.r.hi32; + if ((hi32 >> 31) != (hi32 >> (FBITS_LPC_COEFS - 1))) { + y = (hi32 >> 31) ^ 0x7fffffff; + } + + hist[0] = y; + *audioCoef = y; + audioCoef += inc; + gbMask |= FASTABS(y); + } while (--size); + + return gbMask; +} + +/************************************************************************************** + * Function: TNSFilter + * + * Description: apply temporal noise shaping, if enabled + * + * Inputs: valid AACDecInfo struct + * index of current channel + * + * Outputs: updated transform coefficients + * updated minimum guard bit count for this channel + * + * Return: 0 if successful, -1 if error + **************************************************************************************/ +int TNSFilter(AACDecInfo *aacDecInfo, int ch) +{ + int win, winLen, nWindows, nSFB, filt, bottom, top, order, maxOrder, dir; + int start, end, size, tnsMaxBand, numFilt, gbMask; + int *audioCoef; + unsigned char *filtLength, *filtOrder, *filtRes, *filtDir; + signed char *filtCoef; + const unsigned char *tnsMaxBandTab; + const short *sfbTab; + ICSInfo *icsInfo; + TNSInfo *ti; + PSInfoBase *psi; + + /* validate pointers */ + if (!aacDecInfo || !aacDecInfo->psInfoBase) { + return -1; + } + psi = (PSInfoBase *)(aacDecInfo->psInfoBase); + icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]); + ti = &psi->tnsInfo[ch]; + + if (!ti->tnsDataPresent) { + return 0; + } + + if (icsInfo->winSequence == 2) { + nWindows = NWINDOWS_SHORT; + winLen = NSAMPS_SHORT; + nSFB = sfBandTotalShort[psi->sampRateIdx]; + maxOrder = tnsMaxOrderShort[aacDecInfo->profile]; + sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx]; + tnsMaxBandTab = tnsMaxBandsShort + tnsMaxBandsShortOffset[aacDecInfo->profile]; + tnsMaxBand = tnsMaxBandTab[psi->sampRateIdx]; + } else { + nWindows = NWINDOWS_LONG; + winLen = NSAMPS_LONG; + nSFB = sfBandTotalLong[psi->sampRateIdx]; + maxOrder = tnsMaxOrderLong[aacDecInfo->profile]; + sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx]; + tnsMaxBandTab = tnsMaxBandsLong + tnsMaxBandsLongOffset[aacDecInfo->profile]; + tnsMaxBand = tnsMaxBandTab[psi->sampRateIdx]; + } + + if (tnsMaxBand > icsInfo->maxSFB) { + tnsMaxBand = icsInfo->maxSFB; + } + + filtRes = ti->coefRes; + filtLength = ti->length; + filtOrder = ti->order; + filtDir = ti->dir; + filtCoef = ti->coef; + + gbMask = 0; + audioCoef = psi->coef[ch]; + for (win = 0; win < nWindows; win++) { + bottom = nSFB; + numFilt = ti->numFilt[win]; + for (filt = 0; filt < numFilt; filt++) { + top = bottom; + bottom = top - *filtLength++; + bottom = MAX(bottom, 0); + order = *filtOrder++; + order = MIN(order, maxOrder); + + if (order) { + start = sfbTab[MIN(bottom, tnsMaxBand)]; + end = sfbTab[MIN(top, tnsMaxBand)]; + size = end - start; + if (size > 0) { + dir = *filtDir++; + if (dir) { + start = end - 1; + } + + DecodeLPCCoefs(order, filtRes[win], filtCoef, psi->tnsLPCBuf, psi->tnsWorkBuf); + gbMask |= FilterRegion(size, dir, order, audioCoef + start, psi->tnsLPCBuf, psi->tnsWorkBuf); + } + filtCoef += order; + } + } + audioCoef += winLen; + } + + /* update guard bit count if necessary */ + size = CLZ(gbMask) - 1; + if (psi->gbCurrent[ch] > size) { + psi->gbCurrent[ch] = size; + } + + return 0; +} + +/* Code to generate invQuantXXX[] tables + * { + * int res, i, t; + * double powScale, iqfac, iqfac_m, d; + * + * powScale = pow(2.0, 31) * -1.0; / ** make coefficients negative for using MADD in kernel ** / + * for (res = 3; res <= 4; res++) { + * iqfac = ( ((1 << (res-1)) - 0.5) * (2.0 / M_PI) ); + * iqfac_m = ( ((1 << (res-1)) + 0.5) * (2.0 / M_PI) ); + * printf("static const int invQuant%d[16] = {\n", res); + * for (i = 0; i < 16; i++) { + * / ** extend bottom 4 bits into signed, 2's complement number ** / + * t = (i << 28) >> 28; + * + * if (t >= 0) d = sin(t / iqfac); + * else d = sin(t / iqfac_m); + * + * d *= powScale; + * printf("0x%08x, ", (int)(d > 0 ? d + 0.5 : d - 0.5)); + * if ((i & 0x07) == 0x07) + * printf("\n"); + * } + * printf("};\n\n"); + * } + * } + */ + |