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 | */ |
55 | static const int invQuant3[16] = { |
56 | 0x00000000, 0xc8767f65, 0x9becf22c, 0x83358feb, 0x83358feb, 0x9becf22c, 0xc8767f65, 0x00000000, |
57 | 0x2bc750e9, 0x5246dd49, 0x6ed9eba1, 0x7e0e2e32, 0x7e0e2e32, 0x6ed9eba1, 0x5246dd49, 0x2bc750e9, |
58 | }; |
59 | |
60 | static 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 | **************************************************************************************/ |
88 | static 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 | **************************************************************************************/ |
133 | static 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 | **************************************************************************************/ |
188 | int 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 |