/proc/self/cwd/libfaad/sbr_hfgen.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding |
3 | | ** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com |
4 | | ** |
5 | | ** This program is free software; you can redistribute it and/or modify |
6 | | ** it under the terms of the GNU General Public License as published by |
7 | | ** the Free Software Foundation; either version 2 of the License, or |
8 | | ** (at your option) any later version. |
9 | | ** |
10 | | ** This program is distributed in the hope that it will be useful, |
11 | | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | ** GNU General Public License for more details. |
14 | | ** |
15 | | ** You should have received a copy of the GNU General Public License |
16 | | ** along with this program; if not, write to the Free Software |
17 | | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
18 | | ** |
19 | | ** Any non-GPL usage of this software or parts of this software is strictly |
20 | | ** forbidden. |
21 | | ** |
22 | | ** The "appropriate copyright message" mentioned in section 2c of the GPLv2 |
23 | | ** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" |
24 | | ** |
25 | | ** Commercial non-GPL licensing of this software is possible. |
26 | | ** For more info contact Nero AG through Mpeg4AAClicense@nero.com. |
27 | | ** |
28 | | ** $Id: sbr_hfgen.c,v 1.26 2007/11/01 12:33:35 menno Exp $ |
29 | | **/ |
30 | | |
31 | | /* High Frequency generation */ |
32 | | |
33 | | #include "common.h" |
34 | | #include "structs.h" |
35 | | |
36 | | #ifdef SBR_DEC |
37 | | |
38 | | #include "sbr_syntax.h" |
39 | | #include "sbr_hfgen.h" |
40 | | #include "sbr_fbt.h" |
41 | | |
42 | | /* static function declarations */ |
43 | | #ifdef SBR_LOW_POWER |
44 | | static void calc_prediction_coef_lp(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], |
45 | | complex_t *alpha_0, complex_t *alpha_1, real_t *rxx); |
46 | | static void calc_aliasing_degree(sbr_info *sbr, real_t *rxx, real_t *deg); |
47 | | #else |
48 | | static void calc_prediction_coef(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], |
49 | | complex_t *alpha_0, complex_t *alpha_1, uint8_t k); |
50 | | #endif |
51 | | static void calc_chirp_factors(sbr_info *sbr, uint8_t ch); |
52 | | static void patch_construction(sbr_info *sbr); |
53 | | |
54 | | |
55 | | void hf_generation(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], |
56 | | qmf_t Xhigh[MAX_NTSRHFG][64] |
57 | | #ifdef SBR_LOW_POWER |
58 | | ,real_t *deg |
59 | | #endif |
60 | | ,uint8_t ch) |
61 | 7.51k | { |
62 | 7.51k | uint8_t l, i, x; |
63 | 7.51k | ALIGN complex_t alpha_0[64], alpha_1[64]; |
64 | | #ifdef SBR_LOW_POWER |
65 | | ALIGN real_t rxx[64]; |
66 | | #endif |
67 | | |
68 | 7.51k | uint8_t offset = sbr->tHFAdj; |
69 | 7.51k | uint8_t first = sbr->t_E[ch][0]; |
70 | 7.51k | uint8_t last = sbr->t_E[ch][sbr->L_E[ch]]; |
71 | | |
72 | 7.51k | calc_chirp_factors(sbr, ch); |
73 | | |
74 | | #ifdef SBR_LOW_POWER |
75 | | memset(deg, 0, 64*sizeof(real_t)); |
76 | | #endif |
77 | | |
78 | 7.51k | if ((ch == 0) && (sbr->Reset)) |
79 | 6.06k | patch_construction(sbr); |
80 | | |
81 | | /* calculate the prediction coefficients */ |
82 | | #ifdef SBR_LOW_POWER |
83 | | calc_prediction_coef_lp(sbr, Xlow, alpha_0, alpha_1, rxx); |
84 | | calc_aliasing_degree(sbr, rxx, deg); |
85 | | #endif |
86 | | |
87 | | /* actual HF generation */ |
88 | 20.0k | for (i = 0; i < sbr->noPatches; i++) |
89 | 12.5k | { |
90 | 90.9k | for (x = 0; x < sbr->patchNoSubbands[i]; x++) |
91 | 78.4k | { |
92 | 78.4k | real_t a0_r, a0_i, a1_r, a1_i; |
93 | 78.4k | real_t bw, bw2; |
94 | 78.4k | uint8_t q, p, k, g; |
95 | | |
96 | | /* find the low and high band for patching */ |
97 | 78.4k | k = sbr->kx + x; |
98 | 141k | for (q = 0; q < i; q++) |
99 | 62.5k | { |
100 | 62.5k | k += sbr->patchNoSubbands[q]; |
101 | 62.5k | } |
102 | 78.4k | p = sbr->patchStartSubband[i] + x; |
103 | | |
104 | | #ifdef SBR_LOW_POWER |
105 | | if (x != 0 /*x < sbr->patchNoSubbands[i]-1*/) |
106 | | deg[k] = deg[p]; |
107 | | else |
108 | | deg[k] = 0; |
109 | | #endif |
110 | | |
111 | 78.4k | g = sbr->table_map_k_to_g[k]; |
112 | | |
113 | 78.4k | bw = sbr->bwArray[ch][g]; |
114 | 78.4k | bw2 = MUL_C(bw, bw); |
115 | | |
116 | | /* do the patching */ |
117 | | /* with or without filtering */ |
118 | 78.4k | if (bw2 > 0) |
119 | 37.1k | { |
120 | 37.1k | real_t temp1_r, temp2_r, temp3_r; |
121 | 37.1k | #ifndef SBR_LOW_POWER |
122 | 37.1k | real_t temp1_i, temp2_i, temp3_i; |
123 | 37.1k | calc_prediction_coef(sbr, Xlow, alpha_0, alpha_1, p); |
124 | 37.1k | #endif |
125 | | |
126 | 37.1k | a0_r = MUL_C(RE(alpha_0[p]), bw); |
127 | 37.1k | a1_r = MUL_C(RE(alpha_1[p]), bw2); |
128 | 37.1k | #ifndef SBR_LOW_POWER |
129 | 37.1k | a0_i = MUL_C(IM(alpha_0[p]), bw); |
130 | 37.1k | a1_i = MUL_C(IM(alpha_1[p]), bw2); |
131 | 37.1k | #endif |
132 | | |
133 | 37.1k | temp2_r = QMF_RE(Xlow[first - 2 + offset][p]); |
134 | 37.1k | temp3_r = QMF_RE(Xlow[first - 1 + offset][p]); |
135 | 37.1k | #ifndef SBR_LOW_POWER |
136 | 37.1k | temp2_i = QMF_IM(Xlow[first - 2 + offset][p]); |
137 | 37.1k | temp3_i = QMF_IM(Xlow[first - 1 + offset][p]); |
138 | 37.1k | #endif |
139 | 1.19M | for (l = first; l < last; l++) |
140 | 1.16M | { |
141 | 1.16M | temp1_r = temp2_r; |
142 | 1.16M | temp2_r = temp3_r; |
143 | 1.16M | temp3_r = QMF_RE(Xlow[l + offset][p]); |
144 | 1.16M | #ifndef SBR_LOW_POWER |
145 | 1.16M | temp1_i = temp2_i; |
146 | 1.16M | temp2_i = temp3_i; |
147 | 1.16M | temp3_i = QMF_IM(Xlow[l + offset][p]); |
148 | 1.16M | #endif |
149 | | |
150 | | #ifdef SBR_LOW_POWER |
151 | | QMF_RE(Xhigh[l + offset][k]) = |
152 | | temp3_r |
153 | | +(MUL_R(a0_r, temp2_r) + |
154 | | MUL_R(a1_r, temp1_r)); |
155 | | #else |
156 | 1.16M | QMF_RE(Xhigh[l + offset][k]) = |
157 | 1.16M | temp3_r |
158 | 1.16M | +(MUL_R(a0_r, temp2_r) - |
159 | 1.16M | MUL_R(a0_i, temp2_i) + |
160 | 1.16M | MUL_R(a1_r, temp1_r) - |
161 | 1.16M | MUL_R(a1_i, temp1_i)); |
162 | 1.16M | QMF_IM(Xhigh[l + offset][k]) = |
163 | 1.16M | temp3_i |
164 | 1.16M | +(MUL_R(a0_i, temp2_r) + |
165 | 1.16M | MUL_R(a0_r, temp2_i) + |
166 | 1.16M | MUL_R(a1_i, temp1_r) + |
167 | 1.16M | MUL_R(a1_r, temp1_i)); |
168 | 1.16M | #endif |
169 | 1.16M | } |
170 | 41.3k | } else { |
171 | 1.31M | for (l = first; l < last; l++) |
172 | 1.27M | { |
173 | 1.27M | QMF_RE(Xhigh[l + offset][k]) = QMF_RE(Xlow[l + offset][p]); |
174 | 1.27M | #ifndef SBR_LOW_POWER |
175 | 1.27M | QMF_IM(Xhigh[l + offset][k]) = QMF_IM(Xlow[l + offset][p]); |
176 | 1.27M | #endif |
177 | 1.27M | } |
178 | 41.3k | } |
179 | 78.4k | } |
180 | 12.5k | } |
181 | | |
182 | 7.51k | if (sbr->Reset) |
183 | 7.32k | { |
184 | 7.32k | limiter_frequency_table(sbr); |
185 | 7.32k | } |
186 | 7.51k | } |
187 | | |
188 | | typedef struct |
189 | | { |
190 | | complex_t r01; |
191 | | complex_t r02; |
192 | | complex_t r11; |
193 | | complex_t r12; |
194 | | complex_t r22; |
195 | | real_t det; |
196 | | } acorr_coef; |
197 | | |
198 | | #ifdef SBR_LOW_POWER |
199 | | static void auto_correlation(sbr_info *sbr, acorr_coef *ac, |
200 | | qmf_t buffer[MAX_NTSRHFG][64], |
201 | | uint8_t bd, uint8_t len) |
202 | | { |
203 | | real_t r01 = 0, r02 = 0, r11 = 0; |
204 | | int8_t j; |
205 | | uint8_t offset = sbr->tHFAdj; |
206 | | #ifdef FIXED_POINT |
207 | | const real_t rel = FRAC_CONST(0.999999); // 1 / (1 + 1e-6f); |
208 | | uint32_t maxi = 0; |
209 | | uint32_t pow2, exp; |
210 | | #else |
211 | | const real_t rel = 1 / (1 + 1e-6f); |
212 | | #endif |
213 | | |
214 | | |
215 | | #ifdef FIXED_POINT |
216 | | mask = 0; |
217 | | |
218 | | for (j = (offset-2); j < (len + offset); j++) |
219 | | { |
220 | | real_t x; |
221 | | x = QMF_RE(buffer[j][bd])>>REAL_BITS; |
222 | | mask |= x ^ (x >> 31); |
223 | | } |
224 | | |
225 | | exp = wl_min_lzc(mask); |
226 | | |
227 | | /* improves accuracy */ |
228 | | if (exp > 0) |
229 | | exp -= 1; |
230 | | |
231 | | for (j = offset; j < len + offset; j++) |
232 | | { |
233 | | real_t buf_j = ((QMF_RE(buffer[j][bd])+(1<<(exp-1)))>>exp); |
234 | | real_t buf_j_1 = ((QMF_RE(buffer[j-1][bd])+(1<<(exp-1)))>>exp); |
235 | | real_t buf_j_2 = ((QMF_RE(buffer[j-2][bd])+(1<<(exp-1)))>>exp); |
236 | | |
237 | | /* normalisation with rounding */ |
238 | | r01 += MUL_R(buf_j, buf_j_1); |
239 | | r02 += MUL_R(buf_j, buf_j_2); |
240 | | r11 += MUL_R(buf_j_1, buf_j_1); |
241 | | } |
242 | | RE(ac->r12) = r01 - |
243 | | MUL_R(((QMF_RE(buffer[len+offset-1][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[len+offset-2][bd])+(1<<(exp-1)))>>exp)) + |
244 | | MUL_R(((QMF_RE(buffer[offset-1][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[offset-2][bd])+(1<<(exp-1)))>>exp)); |
245 | | RE(ac->r22) = r11 - |
246 | | MUL_R(((QMF_RE(buffer[len+offset-2][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[len+offset-2][bd])+(1<<(exp-1)))>>exp)) + |
247 | | MUL_R(((QMF_RE(buffer[offset-2][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[offset-2][bd])+(1<<(exp-1)))>>exp)); |
248 | | #else |
249 | | for (j = offset; j < len + offset; j++) |
250 | | { |
251 | | r01 += QMF_RE(buffer[j][bd]) * QMF_RE(buffer[j-1][bd]); |
252 | | r02 += QMF_RE(buffer[j][bd]) * QMF_RE(buffer[j-2][bd]); |
253 | | r11 += QMF_RE(buffer[j-1][bd]) * QMF_RE(buffer[j-1][bd]); |
254 | | } |
255 | | RE(ac->r12) = r01 - |
256 | | QMF_RE(buffer[len+offset-1][bd]) * QMF_RE(buffer[len+offset-2][bd]) + |
257 | | QMF_RE(buffer[offset-1][bd]) * QMF_RE(buffer[offset-2][bd]); |
258 | | RE(ac->r22) = r11 - |
259 | | QMF_RE(buffer[len+offset-2][bd]) * QMF_RE(buffer[len+offset-2][bd]) + |
260 | | QMF_RE(buffer[offset-2][bd]) * QMF_RE(buffer[offset-2][bd]); |
261 | | #endif |
262 | | RE(ac->r01) = r01; |
263 | | RE(ac->r02) = r02; |
264 | | RE(ac->r11) = r11; |
265 | | |
266 | | ac->det = MUL_R(RE(ac->r11), RE(ac->r22)) - MUL_F(MUL_R(RE(ac->r12), RE(ac->r12)), rel); |
267 | | } |
268 | | #else |
269 | | static void auto_correlation(sbr_info *sbr, acorr_coef *ac, qmf_t buffer[MAX_NTSRHFG][64], |
270 | | uint8_t bd, uint8_t len) |
271 | 37.1k | { |
272 | 37.1k | real_t r01r = 0, r01i = 0, r02r = 0, r02i = 0, r11r = 0; |
273 | 37.1k | real_t temp1_r, temp1_i, temp2_r, temp2_i, temp3_r, temp3_i, temp4_r, temp4_i, temp5_r, temp5_i; |
274 | | #ifdef FIXED_POINT |
275 | | const real_t rel = FRAC_CONST(0.999999); // 1 / (1 + 1e-6f); |
276 | | uint32_t mask, exp; |
277 | | real_t half; |
278 | | #else |
279 | 37.1k | const real_t rel = 1 / (1 + 1e-6f); |
280 | 37.1k | #endif |
281 | 37.1k | int8_t j; |
282 | 37.1k | uint8_t offset = sbr->tHFAdj; |
283 | | |
284 | | #ifdef FIXED_POINT |
285 | | mask = 0; |
286 | | |
287 | | for (j = (offset-2); j < (len + offset); j++) |
288 | | { |
289 | | real_t x; |
290 | | x = QMF_RE(buffer[j][bd])>>REAL_BITS; |
291 | | mask |= x ^ (x >> 31); |
292 | | x = QMF_IM(buffer[j][bd])>>REAL_BITS; |
293 | | mask |= x ^ (x >> 31); |
294 | | } |
295 | | |
296 | | exp = wl_min_lzc(mask); |
297 | | |
298 | | /* All-zero input. */ |
299 | | if (exp == 0) { |
300 | | RE(ac->r01) = 0; |
301 | | IM(ac->r01) = 0; |
302 | | RE(ac->r02) = 0; |
303 | | IM(ac->r02) = 0; |
304 | | RE(ac->r11) = 0; |
305 | | // IM(ac->r11) = 0; // unused |
306 | | RE(ac->r12) = 0; |
307 | | IM(ac->r12) = 0; |
308 | | RE(ac->r22) = 0; |
309 | | // IM(ac->r22) = 0; // unused |
310 | | ac->det = 0; |
311 | | return; |
312 | | } |
313 | | /* Otherwise exp > 0. */ |
314 | | /* improves accuracy */ |
315 | | exp -= 1; |
316 | | /* Now exp is 0..31 */ |
317 | | half = (1 << exp) >> 1; |
318 | | |
319 | | temp2_r = (QMF_RE(buffer[offset-2][bd]) + half) >> exp; |
320 | | temp2_i = (QMF_IM(buffer[offset-2][bd]) + half) >> exp; |
321 | | temp3_r = (QMF_RE(buffer[offset-1][bd]) + half) >> exp; |
322 | | temp3_i = (QMF_IM(buffer[offset-1][bd]) + half) >> exp; |
323 | | // Save these because they are needed after loop |
324 | | temp4_r = temp2_r; |
325 | | temp4_i = temp2_i; |
326 | | temp5_r = temp3_r; |
327 | | temp5_i = temp3_i; |
328 | | |
329 | | for (j = offset; j < len + offset; j++) |
330 | | { |
331 | | temp1_r = temp2_r; // temp1_r = (QMF_RE(buffer[offset-2][bd] + (1<<(exp-1))) >> exp; |
332 | | temp1_i = temp2_i; // temp1_i = (QMF_IM(buffer[offset-2][bd] + (1<<(exp-1))) >> exp; |
333 | | temp2_r = temp3_r; // temp2_r = (QMF_RE(buffer[offset-1][bd] + (1<<(exp-1))) >> exp; |
334 | | temp2_i = temp3_i; // temp2_i = (QMF_IM(buffer[offset-1][bd] + (1<<(exp-1))) >> exp; |
335 | | temp3_r = (QMF_RE(buffer[j][bd]) + half) >> exp; |
336 | | temp3_i = (QMF_IM(buffer[j][bd]) + half) >> exp; |
337 | | r01r += MUL_R(temp3_r, temp2_r) + MUL_R(temp3_i, temp2_i); |
338 | | r01i += MUL_R(temp3_i, temp2_r) - MUL_R(temp3_r, temp2_i); |
339 | | r02r += MUL_R(temp3_r, temp1_r) + MUL_R(temp3_i, temp1_i); |
340 | | r02i += MUL_R(temp3_i, temp1_r) - MUL_R(temp3_r, temp1_i); |
341 | | r11r += MUL_R(temp2_r, temp2_r) + MUL_R(temp2_i, temp2_i); |
342 | | } |
343 | | |
344 | | // These are actual values in temporary variable at this point |
345 | | // temp1_r = (QMF_RE(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp; |
346 | | // temp1_i = (QMF_IM(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp; |
347 | | // temp2_r = (QMF_RE(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp; |
348 | | // temp2_i = (QMF_IM(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp; |
349 | | // temp3_r = (QMF_RE(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp; |
350 | | // temp3_i = (QMF_IM(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp; |
351 | | // temp4_r = (QMF_RE(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp; |
352 | | // temp4_i = (QMF_IM(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp; |
353 | | // temp5_r = (QMF_RE(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp; |
354 | | // temp5_i = (QMF_IM(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp; |
355 | | |
356 | | RE(ac->r12) = r01r - |
357 | | (MUL_R(temp3_r, temp2_r) + MUL_R(temp3_i, temp2_i)) + |
358 | | (MUL_R(temp5_r, temp4_r) + MUL_R(temp5_i, temp4_i)); |
359 | | IM(ac->r12) = r01i - |
360 | | (MUL_R(temp3_i, temp2_r) - MUL_R(temp3_r, temp2_i)) + |
361 | | (MUL_R(temp5_i, temp4_r) - MUL_R(temp5_r, temp4_i)); |
362 | | RE(ac->r22) = r11r - |
363 | | (MUL_R(temp2_r, temp2_r) + MUL_R(temp2_i, temp2_i)) + |
364 | | (MUL_R(temp4_r, temp4_r) + MUL_R(temp4_i, temp4_i)); |
365 | | |
366 | | #else |
367 | | |
368 | 37.1k | temp2_r = QMF_RE(buffer[offset-2][bd]); |
369 | 37.1k | temp2_i = QMF_IM(buffer[offset-2][bd]); |
370 | 37.1k | temp3_r = QMF_RE(buffer[offset-1][bd]); |
371 | 37.1k | temp3_i = QMF_IM(buffer[offset-1][bd]); |
372 | | // Save these because they are needed after loop |
373 | 37.1k | temp4_r = temp2_r; |
374 | 37.1k | temp4_i = temp2_i; |
375 | 37.1k | temp5_r = temp3_r; |
376 | 37.1k | temp5_i = temp3_i; |
377 | | |
378 | 1.44M | for (j = offset; j < len + offset; j++) |
379 | 1.40M | { |
380 | 1.40M | temp1_r = temp2_r; // temp1_r = QMF_RE(buffer[j-2][bd]; |
381 | 1.40M | temp1_i = temp2_i; // temp1_i = QMF_IM(buffer[j-2][bd]; |
382 | 1.40M | temp2_r = temp3_r; // temp2_r = QMF_RE(buffer[j-1][bd]; |
383 | 1.40M | temp2_i = temp3_i; // temp2_i = QMF_IM(buffer[j-1][bd]; |
384 | 1.40M | temp3_r = QMF_RE(buffer[j][bd]); |
385 | 1.40M | temp3_i = QMF_IM(buffer[j][bd]); |
386 | 1.40M | r01r += temp3_r * temp2_r + temp3_i * temp2_i; |
387 | 1.40M | r01i += temp3_i * temp2_r - temp3_r * temp2_i; |
388 | 1.40M | r02r += temp3_r * temp1_r + temp3_i * temp1_i; |
389 | 1.40M | r02i += temp3_i * temp1_r - temp3_r * temp1_i; |
390 | 1.40M | r11r += temp2_r * temp2_r + temp2_i * temp2_i; |
391 | 1.40M | } |
392 | | |
393 | | // These are actual values in temporary variable at this point |
394 | | // temp1_r = QMF_RE(buffer[len+offset-1-2][bd]; |
395 | | // temp1_i = QMF_IM(buffer[len+offset-1-2][bd]; |
396 | | // temp2_r = QMF_RE(buffer[len+offset-1-1][bd]; |
397 | | // temp2_i = QMF_IM(buffer[len+offset-1-1][bd]; |
398 | | // temp3_r = QMF_RE(buffer[len+offset-1][bd]); |
399 | | // temp3_i = QMF_IM(buffer[len+offset-1][bd]); |
400 | | // temp4_r = QMF_RE(buffer[offset-2][bd]); |
401 | | // temp4_i = QMF_IM(buffer[offset-2][bd]); |
402 | | // temp5_r = QMF_RE(buffer[offset-1][bd]); |
403 | | // temp5_i = QMF_IM(buffer[offset-1][bd]); |
404 | | |
405 | 37.1k | RE(ac->r12) = r01r - |
406 | 37.1k | (temp3_r * temp2_r + temp3_i * temp2_i) + |
407 | 37.1k | (temp5_r * temp4_r + temp5_i * temp4_i); |
408 | 37.1k | IM(ac->r12) = r01i - |
409 | 37.1k | (temp3_i * temp2_r - temp3_r * temp2_i) + |
410 | 37.1k | (temp5_i * temp4_r - temp5_r * temp4_i); |
411 | 37.1k | RE(ac->r22) = r11r - |
412 | 37.1k | (temp2_r * temp2_r + temp2_i * temp2_i) + |
413 | 37.1k | (temp4_r * temp4_r + temp4_i * temp4_i); |
414 | | |
415 | 37.1k | #endif |
416 | | |
417 | 37.1k | RE(ac->r01) = r01r; |
418 | 37.1k | IM(ac->r01) = r01i; |
419 | 37.1k | RE(ac->r02) = r02r; |
420 | 37.1k | IM(ac->r02) = r02i; |
421 | 37.1k | RE(ac->r11) = r11r; |
422 | | |
423 | 37.1k | ac->det = MUL_R(RE(ac->r11), RE(ac->r22)) - MUL_F(rel, (MUL_R(RE(ac->r12), RE(ac->r12)) + MUL_R(IM(ac->r12), IM(ac->r12)))); |
424 | 37.1k | } |
425 | | #endif |
426 | | |
427 | | /* calculate linear prediction coefficients using the covariance method */ |
428 | | #ifndef SBR_LOW_POWER |
429 | | static void calc_prediction_coef(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], |
430 | | complex_t *alpha_0, complex_t *alpha_1, uint8_t k) |
431 | 37.1k | { |
432 | 37.1k | real_t tmp; |
433 | 37.1k | acorr_coef ac; |
434 | | |
435 | 37.1k | auto_correlation(sbr, &ac, Xlow, k, sbr->numTimeSlotsRate + 6); |
436 | | |
437 | 37.1k | if (ac.det == 0) |
438 | 36.4k | { |
439 | 36.4k | RE(alpha_1[k]) = 0; |
440 | 36.4k | IM(alpha_1[k]) = 0; |
441 | 36.4k | } else { |
442 | | #ifdef FIXED_POINT |
443 | | tmp = (MUL_R(RE(ac.r01), RE(ac.r12)) - MUL_R(IM(ac.r01), IM(ac.r12)) - MUL_R(RE(ac.r02), RE(ac.r11))); |
444 | | RE(alpha_1[k]) = DIV_R(tmp, ac.det); |
445 | | tmp = (MUL_R(IM(ac.r01), RE(ac.r12)) + MUL_R(RE(ac.r01), IM(ac.r12)) - MUL_R(IM(ac.r02), RE(ac.r11))); |
446 | | IM(alpha_1[k]) = DIV_R(tmp, ac.det); |
447 | | #else |
448 | 676 | tmp = REAL_CONST(1.0) / ac.det; |
449 | 676 | RE(alpha_1[k]) = (MUL_R(RE(ac.r01), RE(ac.r12)) - MUL_R(IM(ac.r01), IM(ac.r12)) - MUL_R(RE(ac.r02), RE(ac.r11))) * tmp; |
450 | 676 | IM(alpha_1[k]) = (MUL_R(IM(ac.r01), RE(ac.r12)) + MUL_R(RE(ac.r01), IM(ac.r12)) - MUL_R(IM(ac.r02), RE(ac.r11))) * tmp; |
451 | 676 | #endif |
452 | 676 | } |
453 | | |
454 | 37.1k | if (RE(ac.r11) == 0) |
455 | 35.3k | { |
456 | 35.3k | RE(alpha_0[k]) = 0; |
457 | 35.3k | IM(alpha_0[k]) = 0; |
458 | 35.3k | } else { |
459 | | #ifdef FIXED_POINT |
460 | | tmp = -(RE(ac.r01) + MUL_R(RE(alpha_1[k]), RE(ac.r12)) + MUL_R(IM(alpha_1[k]), IM(ac.r12))); |
461 | | RE(alpha_0[k]) = DIV_R(tmp, RE(ac.r11)); |
462 | | tmp = -(IM(ac.r01) + MUL_R(IM(alpha_1[k]), RE(ac.r12)) - MUL_R(RE(alpha_1[k]), IM(ac.r12))); |
463 | | IM(alpha_0[k]) = DIV_R(tmp, RE(ac.r11)); |
464 | | #else |
465 | 1.84k | tmp = 1.0f / RE(ac.r11); |
466 | 1.84k | RE(alpha_0[k]) = -(RE(ac.r01) + MUL_R(RE(alpha_1[k]), RE(ac.r12)) + MUL_R(IM(alpha_1[k]), IM(ac.r12))) * tmp; |
467 | 1.84k | IM(alpha_0[k]) = -(IM(ac.r01) + MUL_R(IM(alpha_1[k]), RE(ac.r12)) - MUL_R(RE(alpha_1[k]), IM(ac.r12))) * tmp; |
468 | 1.84k | #endif |
469 | 1.84k | } |
470 | | |
471 | | /* Sanity check; important: use "yes" check to filter-out NaN values. */ |
472 | 37.1k | if ((MUL_R(RE(alpha_0[k]),RE(alpha_0[k])) + MUL_R(IM(alpha_0[k]),IM(alpha_0[k])) <= REAL_CONST(16)) && |
473 | 37.1k | (MUL_R(RE(alpha_1[k]),RE(alpha_1[k])) + MUL_R(IM(alpha_1[k]),IM(alpha_1[k])) <= REAL_CONST(16))) |
474 | 36.6k | return; |
475 | | /* Fallback */ |
476 | 518 | RE(alpha_0[k]) = 0; |
477 | 518 | IM(alpha_0[k]) = 0; |
478 | 518 | RE(alpha_1[k]) = 0; |
479 | 518 | IM(alpha_1[k]) = 0; |
480 | 518 | } |
481 | | #else |
482 | | static void calc_prediction_coef_lp(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], |
483 | | complex_t *alpha_0, complex_t *alpha_1, real_t *rxx) |
484 | | { |
485 | | uint8_t k; |
486 | | real_t tmp; |
487 | | acorr_coef ac; |
488 | | |
489 | | for (k = 1; k < sbr->f_master[0]; k++) |
490 | | { |
491 | | auto_correlation(sbr, &ac, Xlow, k, sbr->numTimeSlotsRate + 6); |
492 | | |
493 | | if (ac.det == 0) |
494 | | { |
495 | | RE(alpha_0[k]) = 0; |
496 | | RE(alpha_1[k]) = 0; |
497 | | } else { |
498 | | tmp = MUL_R(RE(ac.r01), RE(ac.r22)) - MUL_R(RE(ac.r12), RE(ac.r02)); |
499 | | RE(alpha_0[k]) = DIV_R(tmp, (-ac.det)); |
500 | | |
501 | | tmp = MUL_R(RE(ac.r01), RE(ac.r12)) - MUL_R(RE(ac.r02), RE(ac.r11)); |
502 | | RE(alpha_1[k]) = DIV_R(tmp, ac.det); |
503 | | } |
504 | | |
505 | | if ((RE(alpha_0[k]) >= REAL_CONST(4)) || (RE(alpha_1[k]) >= REAL_CONST(4))) |
506 | | { |
507 | | RE(alpha_0[k]) = REAL_CONST(0); |
508 | | RE(alpha_1[k]) = REAL_CONST(0); |
509 | | } |
510 | | |
511 | | /* reflection coefficient */ |
512 | | if (RE(ac.r11) == 0) |
513 | | { |
514 | | rxx[k] = COEF_CONST(0.0); |
515 | | } else { |
516 | | rxx[k] = DIV_C(RE(ac.r01), RE(ac.r11)); |
517 | | rxx[k] = -rxx[k]; |
518 | | if (rxx[k] > COEF_CONST(1.0)) rxx[k] = COEF_CONST(1.0); |
519 | | if (rxx[k] < COEF_CONST(-1.0)) rxx[k] = COEF_CONST(-1.0); |
520 | | } |
521 | | } |
522 | | } |
523 | | |
524 | | static void calc_aliasing_degree(sbr_info *sbr, real_t *rxx, real_t *deg) |
525 | | { |
526 | | uint8_t k; |
527 | | |
528 | | rxx[0] = COEF_CONST(0.0); |
529 | | deg[1] = COEF_CONST(0.0); |
530 | | |
531 | | for (k = 2; k < sbr->k0; k++) |
532 | | { |
533 | | deg[k] = 0.0; |
534 | | |
535 | | if ((k % 2 == 0) && (rxx[k] < COEF_CONST(0.0))) |
536 | | { |
537 | | if (rxx[k-1] < 0.0) |
538 | | { |
539 | | deg[k] = COEF_CONST(1.0); |
540 | | |
541 | | if (rxx[k-2] > COEF_CONST(0.0)) |
542 | | { |
543 | | deg[k-1] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]); |
544 | | } |
545 | | } else if (rxx[k-2] > COEF_CONST(0.0)) { |
546 | | deg[k] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]); |
547 | | } |
548 | | } |
549 | | |
550 | | if ((k % 2 == 1) && (rxx[k] > COEF_CONST(0.0))) |
551 | | { |
552 | | if (rxx[k-1] > COEF_CONST(0.0)) |
553 | | { |
554 | | deg[k] = COEF_CONST(1.0); |
555 | | |
556 | | if (rxx[k-2] < COEF_CONST(0.0)) |
557 | | { |
558 | | deg[k-1] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]); |
559 | | } |
560 | | } else if (rxx[k-2] < COEF_CONST(0.0)) { |
561 | | deg[k] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]); |
562 | | } |
563 | | } |
564 | | } |
565 | | } |
566 | | #endif |
567 | | |
568 | | /* FIXED POINT: bwArray = COEF */ |
569 | | static real_t mapNewBw(uint8_t invf_mode, uint8_t invf_mode_prev) |
570 | 11.6k | { |
571 | 11.6k | switch (invf_mode) |
572 | 11.6k | { |
573 | 1.65k | case 1: /* LOW */ |
574 | 1.65k | if (invf_mode_prev == 0) /* NONE */ |
575 | 1.35k | return COEF_CONST(0.6); |
576 | 308 | else |
577 | 308 | return COEF_CONST(0.75); |
578 | | |
579 | 1.52k | case 2: /* MID */ |
580 | 1.52k | return COEF_CONST(0.9); |
581 | | |
582 | 2.53k | case 3: /* HIGH */ |
583 | 2.53k | return COEF_CONST(0.98); |
584 | | |
585 | 5.92k | default: /* NONE */ |
586 | 5.92k | if (invf_mode_prev == 1) /* LOW */ |
587 | 72 | return COEF_CONST(0.6); |
588 | 5.85k | else |
589 | 5.85k | return COEF_CONST(0.0); |
590 | 11.6k | } |
591 | 11.6k | } |
592 | | |
593 | | /* FIXED POINT: bwArray = COEF */ |
594 | | static void calc_chirp_factors(sbr_info *sbr, uint8_t ch) |
595 | 7.51k | { |
596 | 7.51k | uint8_t i; |
597 | | |
598 | 19.1k | for (i = 0; i < sbr->N_Q; i++) |
599 | 11.6k | { |
600 | 11.6k | sbr->bwArray[ch][i] = mapNewBw(sbr->bs_invf_mode[ch][i], sbr->bs_invf_mode_prev[ch][i]); |
601 | | |
602 | 11.6k | if (sbr->bwArray[ch][i] < sbr->bwArray_prev[ch][i]) |
603 | 207 | sbr->bwArray[ch][i] = MUL_F(sbr->bwArray[ch][i], FRAC_CONST(0.75)) + MUL_F(sbr->bwArray_prev[ch][i], FRAC_CONST(0.25)); |
604 | 11.4k | else |
605 | 11.4k | sbr->bwArray[ch][i] = MUL_F(sbr->bwArray[ch][i], FRAC_CONST(0.90625)) + MUL_F(sbr->bwArray_prev[ch][i], FRAC_CONST(0.09375)); |
606 | | |
607 | 11.6k | if (sbr->bwArray[ch][i] < COEF_CONST(0.015625)) |
608 | 5.68k | sbr->bwArray[ch][i] = COEF_CONST(0.0); |
609 | | |
610 | 11.6k | if (sbr->bwArray[ch][i] >= COEF_CONST(0.99609375)) |
611 | 0 | sbr->bwArray[ch][i] = COEF_CONST(0.99609375); |
612 | | |
613 | 11.6k | sbr->bwArray_prev[ch][i] = sbr->bwArray[ch][i]; |
614 | 11.6k | sbr->bs_invf_mode_prev[ch][i] = sbr->bs_invf_mode[ch][i]; |
615 | 11.6k | } |
616 | 7.51k | } |
617 | | |
618 | | static void patch_construction(sbr_info *sbr) |
619 | 6.06k | { |
620 | 6.06k | uint8_t i, k; |
621 | 6.06k | uint8_t odd, sb; |
622 | 6.06k | uint8_t msb = sbr->k0; |
623 | 6.06k | uint8_t usb = sbr->kx; |
624 | 6.06k | uint8_t goalSbTab[] = { 21, 23, 32, 43, 46, 64, 85, 93, 128, 0, 0, 0 }; |
625 | | /* (uint8_t)(2.048e6/sbr->sample_rate + 0.5); */ |
626 | 6.06k | uint8_t goalSb = goalSbTab[get_sr_index(sbr->sample_rate)]; |
627 | | |
628 | 6.06k | sbr->noPatches = 0; |
629 | | |
630 | 6.06k | if (goalSb < (sbr->kx + sbr->M)) |
631 | 3.63k | { |
632 | 27.0k | for (i = 0, k = 0; sbr->f_master[i] < goalSb; i++) |
633 | 23.4k | k = i+1; |
634 | 3.63k | } else { |
635 | 2.43k | k = sbr->N_master; |
636 | 2.43k | } |
637 | | |
638 | 6.06k | if (sbr->N_master == 0) |
639 | 0 | { |
640 | 0 | sbr->noPatches = 0; |
641 | 0 | sbr->patchNoSubbands[0] = 0; |
642 | 0 | sbr->patchStartSubband[0] = 0; |
643 | |
|
644 | 0 | return; |
645 | 0 | } |
646 | | |
647 | 6.06k | do |
648 | 13.7k | { |
649 | 13.7k | uint8_t j = k + 1; |
650 | | |
651 | 13.7k | do |
652 | 34.5k | { |
653 | 34.5k | j--; |
654 | | |
655 | 34.5k | sb = sbr->f_master[j]; |
656 | 34.5k | odd = (sb - 2 + sbr->k0) % 2; |
657 | 34.5k | } while (sb > (sbr->k0 - 1 + msb - odd)); |
658 | | |
659 | 13.7k | sbr->patchNoSubbands[sbr->noPatches] = max(sb - usb, 0); |
660 | 13.7k | sbr->patchStartSubband[sbr->noPatches] = sbr->k0 - odd - |
661 | 13.7k | sbr->patchNoSubbands[sbr->noPatches]; |
662 | | |
663 | 13.7k | if (sbr->patchNoSubbands[sbr->noPatches] > 0) |
664 | 10.9k | { |
665 | 10.9k | usb = sb; |
666 | 10.9k | msb = sb; |
667 | 10.9k | sbr->noPatches++; |
668 | 10.9k | } else { |
669 | 2.82k | msb = sbr->kx; |
670 | 2.82k | } |
671 | | |
672 | 13.7k | if (sbr->f_master[k] - sb < 3) |
673 | 10.2k | k = sbr->N_master; |
674 | 13.7k | } while (sb != (sbr->kx + sbr->M)); |
675 | | |
676 | 6.06k | if ((sbr->patchNoSubbands[sbr->noPatches-1] < 3) && (sbr->noPatches > 1)) |
677 | 760 | { |
678 | 760 | sbr->noPatches--; |
679 | 760 | } |
680 | | |
681 | 6.06k | sbr->noPatches = min(sbr->noPatches, 5); |
682 | 6.06k | } |
683 | | |
684 | | #endif |