mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-10 21:47:04 +03:00
big merge
This commit is contained in:
300
components/spotify/cspot/bell/libhelix-aac/tns.c
Normal file
300
components/spotify/cspot/bell/libhelix-aac/tns.c
Normal file
@@ -0,0 +1,300 @@
|
||||
/* ***** 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
|
||||
|
||||
//fb
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wnarrowing"
|
||||
|
||||
/* 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] PROGMEM = {
|
||||
0x00000000, 0xc8767f65, 0x9becf22c, 0x83358feb, 0x83358feb, 0x9becf22c, 0xc8767f65, 0x00000000,
|
||||
0x2bc750e9, 0x5246dd49, 0x6ed9eba1, 0x7e0e2e32, 0x7e0e2e32, 0x6ed9eba1, 0x5246dd49, 0x2bc750e9,
|
||||
};
|
||||
|
||||
static const int invQuant4[16] PROGMEM = {
|
||||
0x00000000, 0xe5632654, 0xcbf00dbe, 0xb4c373ee, 0xa0e0a15f, 0x9126145f, 0x8643c7b3, 0x80b381ac,
|
||||
0x7f7437ad, 0x7b1d1a49, 0x7294b5f2, 0x66256db2, 0x563ba8aa, 0x4362210e, 0x2e3d2abb, 0x17851aad,
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
/**************************************************************************************
|
||||
* 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*/ int *tnsMaxBandTab;
|
||||
const /*short*/ int *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");
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user