summaryrefslogtreecommitdiff
path: root/audio_codec/libraac/tns.c (plain)
blob: d3f430ef5ecd1c2f419ba7c288e186ca06f7ed2e
1/* ***** BEGIN LICENSE BLOCK *****
2 * Source last modified: $Id: tns.c,v 1.2 2005/05/24 16:01:55 albertofloyd Exp $
3 *
4 * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved.
5 *
6 * The contents of this file, and the files included with this file,
7 * are subject to the current version of the RealNetworks Public
8 * Source License (the "RPSL") available at
9 * http://www.helixcommunity.org/content/rpsl unless you have licensed
10 * the file under the current version of the RealNetworks Community
11 * Source License (the "RCSL") available at
12 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
13 * will apply. You may also obtain the license terms directly from
14 * RealNetworks. You may not use this file except in compliance with
15 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
16 * to this file, the RCSL. Please see the applicable RPSL or RCSL for
17 * the rights, obligations and limitations governing use of the
18 * contents of the file.
19 *
20 * This file is part of the Helix DNA Technology. RealNetworks is the
21 * developer of the Original Code and owns the copyrights in the
22 * portions it created.
23 *
24 * This file, and the files included with this file, is distributed
25 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
26 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
27 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
28 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
29 * ENJOYMENT OR NON-INFRINGEMENT.
30 *
31 * Technology Compatibility Kit Test Suite(s) Location:
32 * http://www.helixcommunity.org/content/tck
33 *
34 * Contributor(s):
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/**************************************************************************************
39 * Fixed-point HE-AAC decoder
40 * Jon Recker (jrecker@real.com)
41 * February 2005
42 *
43 * tns.c - apply TNS to spectrum
44 **************************************************************************************/
45
46#include "coder.h"
47#include "assembly.h"
48
49#define FBITS_LPC_COEFS 20
50
51/* inverse quantization tables for TNS filter coefficients, format = Q31
52 * see bottom of file for table generation
53 * negative (vs. spec) since we use MADD for filter kernel
54 */
55static const int invQuant3[16] = {
56 0x00000000, 0xc8767f65, 0x9becf22c, 0x83358feb, 0x83358feb, 0x9becf22c, 0xc8767f65, 0x00000000,
57 0x2bc750e9, 0x5246dd49, 0x6ed9eba1, 0x7e0e2e32, 0x7e0e2e32, 0x6ed9eba1, 0x5246dd49, 0x2bc750e9,
58};
59
60static const int invQuant4[16] = {
61 0x00000000, 0xe5632654, 0xcbf00dbe, 0xb4c373ee, 0xa0e0a15f, 0x9126145f, 0x8643c7b3, 0x80b381ac,
62 0x7f7437ad, 0x7b1d1a49, 0x7294b5f2, 0x66256db2, 0x563ba8aa, 0x4362210e, 0x2e3d2abb, 0x17851aad,
63};
64
65/**************************************************************************************
66 * Function: DecodeLPCCoefs
67 *
68 * Description: decode LPC coefficients for TNS
69 *
70 * Inputs: order of TNS filter
71 * resolution of coefficients (3 or 4 bits)
72 * coefficients unpacked from bitstream
73 * scratch buffer (b) of size >= order
74 *
75 * Outputs: LPC coefficients in Q(FBITS_LPC_COEFS), in 'a'
76 *
77 * Return: none
78 *
79 * Notes: assumes no guard bits in input transform coefficients
80 * a[i] = Q(FBITS_LPC_COEFS), don't store a0 = 1.0
81 * (so a[0] = first delay tap, etc.)
82 * max abs(a[i]) < log2(order), so for max order = 20 a[i] < 4.4
83 * (up to 3 bits of gain) so a[i] has at least 31 - FBITS_LPC_COEFS - 3
84 * guard bits
85 * to ensure no intermediate overflow in all-pole filter, set
86 * FBITS_LPC_COEFS such that number of guard bits >= log2(max order)
87 **************************************************************************************/
88static void DecodeLPCCoefs(int order, int res, signed char *filtCoef, int *a, int *b)
89{
90 int i, m, t;
91 const int *invQuantTab;
92
93 if (res == 3) {
94 invQuantTab = invQuant3;
95 } else if (res == 4) {
96 invQuantTab = invQuant4;
97 } else {
98 return;
99 }
100
101 for (m = 0; m < order; m++) {
102 t = invQuantTab[filtCoef[m] & 0x0f]; /* t = Q31 */
103 for (i = 0; i < m; i++) {
104 b[i] = a[i] - (MULSHIFT32(t, a[m - i - 1]) << 1);
105 }
106 for (i = 0; i < m; i++) {
107 a[i] = b[i];
108 }
109 a[m] = t >> (31 - FBITS_LPC_COEFS);
110 }
111}
112
113/**************************************************************************************
114 * Function: FilterRegion
115 *
116 * Description: apply LPC filter to one region of coefficients
117 *
118 * Inputs: number of transform coefficients in this region
119 * direction flag (forward = 1, backward = -1)
120 * order of filter
121 * 'size' transform coefficients
122 * 'order' LPC coefficients in Q(FBITS_LPC_COEFS)
123 * scratch buffer for history (must be >= order samples long)
124 *
125 * Outputs: filtered transform coefficients
126 *
127 * Return: guard bit mask (OR of abs value of all filtered transform coefs)
128 *
129 * Notes: assumes no guard bits in input transform coefficients
130 * gains 0 int bits
131 * history buffer does not need to be preserved between regions
132 **************************************************************************************/
133static int FilterRegion(int size, int dir, int order, int *audioCoef, int *a, int *hist)
134{
135 int i, j, y, hi32, inc, gbMask;
136 U64 sum64;
137
138 /* init history to 0 every time */
139 for (i = 0; i < order; i++) {
140 hist[i] = 0;
141 }
142
143 sum64.w64 = 0; /* avoid warning */
144 gbMask = 0;
145 inc = (dir ? -1 : 1);
146 do {
147 /* sum64 = a0*y[n] = 1.0*y[n] */
148 y = *audioCoef;
149 sum64.r.hi32 = y >> (32 - FBITS_LPC_COEFS);
150 sum64.r.lo32 = y << FBITS_LPC_COEFS;
151
152 /* sum64 += (a1*y[n-1] + a2*y[n-2] + ... + a[order-1]*y[n-(order-1)]) */
153 for (j = order - 1; j > 0; j--) {
154 sum64.w64 = MADD64(sum64.w64, hist[j], a[j]);
155 hist[j] = hist[j - 1];
156 }
157 sum64.w64 = MADD64(sum64.w64, hist[0], a[0]);
158 y = (sum64.r.hi32 << (32 - FBITS_LPC_COEFS)) | (sum64.r.lo32 >> FBITS_LPC_COEFS);
159
160 /* clip output (rare) */
161 hi32 = sum64.r.hi32;
162 if ((hi32 >> 31) != (hi32 >> (FBITS_LPC_COEFS - 1))) {
163 y = (hi32 >> 31) ^ 0x7fffffff;
164 }
165
166 hist[0] = y;
167 *audioCoef = y;
168 audioCoef += inc;
169 gbMask |= FASTABS(y);
170 } while (--size);
171
172 return gbMask;
173}
174
175/**************************************************************************************
176 * Function: TNSFilter
177 *
178 * Description: apply temporal noise shaping, if enabled
179 *
180 * Inputs: valid AACDecInfo struct
181 * index of current channel
182 *
183 * Outputs: updated transform coefficients
184 * updated minimum guard bit count for this channel
185 *
186 * Return: 0 if successful, -1 if error
187 **************************************************************************************/
188int TNSFilter(AACDecInfo *aacDecInfo, int ch)
189{
190 int win, winLen, nWindows, nSFB, filt, bottom, top, order, maxOrder, dir;
191 int start, end, size, tnsMaxBand, numFilt, gbMask;
192 int *audioCoef;
193 unsigned char *filtLength, *filtOrder, *filtRes, *filtDir;
194 signed char *filtCoef;
195 const unsigned char *tnsMaxBandTab;
196 const short *sfbTab;
197 ICSInfo *icsInfo;
198 TNSInfo *ti;
199 PSInfoBase *psi;
200
201 /* validate pointers */
202 if (!aacDecInfo || !aacDecInfo->psInfoBase) {
203 return -1;
204 }
205 psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
206 icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
207 ti = &psi->tnsInfo[ch];
208
209 if (!ti->tnsDataPresent) {
210 return 0;
211 }
212
213 if (icsInfo->winSequence == 2) {
214 nWindows = NWINDOWS_SHORT;
215 winLen = NSAMPS_SHORT;
216 nSFB = sfBandTotalShort[psi->sampRateIdx];
217 maxOrder = tnsMaxOrderShort[aacDecInfo->profile];
218 sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
219 tnsMaxBandTab = tnsMaxBandsShort + tnsMaxBandsShortOffset[aacDecInfo->profile];
220 tnsMaxBand = tnsMaxBandTab[psi->sampRateIdx];
221 } else {
222 nWindows = NWINDOWS_LONG;
223 winLen = NSAMPS_LONG;
224 nSFB = sfBandTotalLong[psi->sampRateIdx];
225 maxOrder = tnsMaxOrderLong[aacDecInfo->profile];
226 sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
227 tnsMaxBandTab = tnsMaxBandsLong + tnsMaxBandsLongOffset[aacDecInfo->profile];
228 tnsMaxBand = tnsMaxBandTab[psi->sampRateIdx];
229 }
230
231 if (tnsMaxBand > icsInfo->maxSFB) {
232 tnsMaxBand = icsInfo->maxSFB;
233 }
234
235 filtRes = ti->coefRes;
236 filtLength = ti->length;
237 filtOrder = ti->order;
238 filtDir = ti->dir;
239 filtCoef = ti->coef;
240
241 gbMask = 0;
242 audioCoef = psi->coef[ch];
243 for (win = 0; win < nWindows; win++) {
244 bottom = nSFB;
245 numFilt = ti->numFilt[win];
246 for (filt = 0; filt < numFilt; filt++) {
247 top = bottom;
248 bottom = top - *filtLength++;
249 bottom = MAX(bottom, 0);
250 order = *filtOrder++;
251 order = MIN(order, maxOrder);
252
253 if (order) {
254 start = sfbTab[MIN(bottom, tnsMaxBand)];
255 end = sfbTab[MIN(top, tnsMaxBand)];
256 size = end - start;
257 if (size > 0) {
258 dir = *filtDir++;
259 if (dir) {
260 start = end - 1;
261 }
262
263 DecodeLPCCoefs(order, filtRes[win], filtCoef, psi->tnsLPCBuf, psi->tnsWorkBuf);
264 gbMask |= FilterRegion(size, dir, order, audioCoef + start, psi->tnsLPCBuf, psi->tnsWorkBuf);
265 }
266 filtCoef += order;
267 }
268 }
269 audioCoef += winLen;
270 }
271
272 /* update guard bit count if necessary */
273 size = CLZ(gbMask) - 1;
274 if (psi->gbCurrent[ch] > size) {
275 psi->gbCurrent[ch] = size;
276 }
277
278 return 0;
279}
280
281/* Code to generate invQuantXXX[] tables
282 * {
283 * int res, i, t;
284 * double powScale, iqfac, iqfac_m, d;
285 *
286 * powScale = pow(2.0, 31) * -1.0; / ** make coefficients negative for using MADD in kernel ** /
287 * for (res = 3; res <= 4; res++) {
288 * iqfac = ( ((1 << (res-1)) - 0.5) * (2.0 / M_PI) );
289 * iqfac_m = ( ((1 << (res-1)) + 0.5) * (2.0 / M_PI) );
290 * printf("static const int invQuant%d[16] = {\n", res);
291 * for (i = 0; i < 16; i++) {
292 * / ** extend bottom 4 bits into signed, 2's complement number ** /
293 * t = (i << 28) >> 28;
294 *
295 * if (t >= 0) d = sin(t / iqfac);
296 * else d = sin(t / iqfac_m);
297 *
298 * d *= powScale;
299 * printf("0x%08x, ", (int)(d > 0 ? d + 0.5 : d - 0.5));
300 * if ((i & 0x07) == 0x07)
301 * printf("\n");
302 * }
303 * printf("};\n\n");
304 * }
305 * }
306 */
307
308