blob: 493243942f00a4396dabb6c06a86dfa7fa3a96f4
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 | { |
62 | uint8_t l, i, x; |
63 | ALIGN complex_t alpha_0[64], alpha_1[64]; |
64 | #ifdef SBR_LOW_POWER |
65 | ALIGN real_t rxx[64]; |
66 | #endif |
67 | |
68 | uint8_t offset = sbr->tHFAdj; |
69 | uint8_t first = sbr->t_E[ch][0]; |
70 | uint8_t last = sbr->t_E[ch][sbr->L_E[ch]]; |
71 | |
72 | calc_chirp_factors(sbr, ch); |
73 | |
74 | #ifdef SBR_LOW_POWER |
75 | memset(deg, 0, 64 * sizeof(real_t)); |
76 | #endif |
77 | |
78 | if ((ch == 0) && (sbr->Reset)) { |
79 | patch_construction(sbr); |
80 | } |
81 | |
82 | /* calculate the prediction coefficients */ |
83 | #ifdef SBR_LOW_POWER |
84 | calc_prediction_coef_lp(sbr, Xlow, alpha_0, alpha_1, rxx); |
85 | calc_aliasing_degree(sbr, rxx, deg); |
86 | #endif |
87 | |
88 | /* actual HF generation */ |
89 | for (i = 0; i < sbr->noPatches; i++) { |
90 | for (x = 0; x < sbr->patchNoSubbands[i]; x++) { |
91 | real_t a0_r, a0_i, a1_r, a1_i; |
92 | real_t bw, bw2; |
93 | uint8_t q, p, k, g; |
94 | |
95 | /* find the low and high band for patching */ |
96 | k = sbr->kx + x; |
97 | for (q = 0; q < i; q++) { |
98 | k += sbr->patchNoSubbands[q]; |
99 | } |
100 | p = sbr->patchStartSubband[i] + x; |
101 | |
102 | #ifdef SBR_LOW_POWER |
103 | if (x != 0 /*x < sbr->patchNoSubbands[i]-1*/) { |
104 | deg[k] = deg[p]; |
105 | } else { |
106 | deg[k] = 0; |
107 | } |
108 | #endif |
109 | |
110 | g = sbr->table_map_k_to_g[k]; |
111 | |
112 | bw = sbr->bwArray[ch][g]; |
113 | bw2 = MUL_C(bw, bw); |
114 | |
115 | /* do the patching */ |
116 | /* with or without filtering */ |
117 | if (bw2 > 0) { |
118 | real_t temp1_r, temp2_r, temp3_r; |
119 | #ifndef SBR_LOW_POWER |
120 | real_t temp1_i, temp2_i, temp3_i; |
121 | calc_prediction_coef(sbr, Xlow, alpha_0, alpha_1, p); |
122 | #endif |
123 | |
124 | a0_r = MUL_C(RE(alpha_0[p]), bw); |
125 | a1_r = MUL_C(RE(alpha_1[p]), bw2); |
126 | #ifndef SBR_LOW_POWER |
127 | a0_i = MUL_C(IM(alpha_0[p]), bw); |
128 | a1_i = MUL_C(IM(alpha_1[p]), bw2); |
129 | #endif |
130 | |
131 | temp2_r = QMF_RE(Xlow[first - 2 + offset][p]); |
132 | temp3_r = QMF_RE(Xlow[first - 1 + offset][p]); |
133 | #ifndef SBR_LOW_POWER |
134 | temp2_i = QMF_IM(Xlow[first - 2 + offset][p]); |
135 | temp3_i = QMF_IM(Xlow[first - 1 + offset][p]); |
136 | #endif |
137 | for (l = first; l < last; l++) { |
138 | temp1_r = temp2_r; |
139 | temp2_r = temp3_r; |
140 | temp3_r = QMF_RE(Xlow[l + offset][p]); |
141 | #ifndef SBR_LOW_POWER |
142 | temp1_i = temp2_i; |
143 | temp2_i = temp3_i; |
144 | temp3_i = QMF_IM(Xlow[l + offset][p]); |
145 | #endif |
146 | |
147 | #ifdef SBR_LOW_POWER |
148 | QMF_RE(Xhigh[l + offset][k]) = |
149 | temp3_r |
150 | + (MUL_R(a0_r, temp2_r) + |
151 | MUL_R(a1_r, temp1_r)); |
152 | #else |
153 | QMF_RE(Xhigh[l + offset][k]) = |
154 | temp3_r |
155 | + (MUL_R(a0_r, temp2_r) - |
156 | MUL_R(a0_i, temp2_i) + |
157 | MUL_R(a1_r, temp1_r) - |
158 | MUL_R(a1_i, temp1_i)); |
159 | QMF_IM(Xhigh[l + offset][k]) = |
160 | temp3_i |
161 | + (MUL_R(a0_i, temp2_r) + |
162 | MUL_R(a0_r, temp2_i) + |
163 | MUL_R(a1_i, temp1_r) + |
164 | MUL_R(a1_r, temp1_i)); |
165 | #endif |
166 | } |
167 | } else { |
168 | for (l = first; l < last; l++) { |
169 | QMF_RE(Xhigh[l + offset][k]) = QMF_RE(Xlow[l + offset][p]); |
170 | #ifndef SBR_LOW_POWER |
171 | QMF_IM(Xhigh[l + offset][k]) = QMF_IM(Xlow[l + offset][p]); |
172 | #endif |
173 | } |
174 | } |
175 | } |
176 | } |
177 | |
178 | if (sbr->Reset) { |
179 | limiter_frequency_table(sbr); |
180 | } |
181 | } |
182 | |
183 | typedef struct { |
184 | complex_t r01; |
185 | complex_t r02; |
186 | complex_t r11; |
187 | complex_t r12; |
188 | complex_t r22; |
189 | real_t det; |
190 | } acorr_coef; |
191 | |
192 | #ifdef SBR_LOW_POWER |
193 | static void auto_correlation(sbr_info *sbr, acorr_coef *ac, |
194 | qmf_t buffer[MAX_NTSRHFG][64], |
195 | uint8_t bd, uint8_t len) |
196 | { |
197 | real_t r01 = 0, r02 = 0, r11 = 0; |
198 | int8_t j; |
199 | uint8_t offset = sbr->tHFAdj; |
200 | #ifdef FIXED_POINT |
201 | const real_t rel = FRAC_CONST(0.999999); // 1 / (1 + 1e-6f); |
202 | uint32_t maxi = 0; |
203 | uint32_t pow2, exp; |
204 | #else |
205 | const real_t rel = 1 / (1 + 1e-6f); |
206 | #endif |
207 | |
208 | |
209 | #ifdef FIXED_POINT |
210 | mask = 0; |
211 | |
212 | for (j = (offset - 2); j < (len + offset); j++) { |
213 | real_t x; |
214 | x = QMF_RE(buffer[j][bd]) >> REAL_BITS; |
215 | mask |= x ^(x >> 31); |
216 | } |
217 | |
218 | exp = wl_min_lzc(mask); |
219 | |
220 | /* improves accuracy */ |
221 | if (exp > 0) { |
222 | exp -= 1; |
223 | } |
224 | |
225 | for (j = offset; j < len + offset; j++) { |
226 | real_t buf_j = ((QMF_RE(buffer[j][bd]) + (1 << (exp - 1))) >> exp); |
227 | real_t buf_j_1 = ((QMF_RE(buffer[j - 1][bd]) + (1 << (exp - 1))) >> exp); |
228 | real_t buf_j_2 = ((QMF_RE(buffer[j - 2][bd]) + (1 << (exp - 1))) >> exp); |
229 | |
230 | /* normalisation with rounding */ |
231 | r01 += MUL_R(buf_j, buf_j_1); |
232 | r02 += MUL_R(buf_j, buf_j_2); |
233 | r11 += MUL_R(buf_j_1, buf_j_1); |
234 | } |
235 | RE(ac->r12) = r01 - |
236 | MUL_R(((QMF_RE(buffer[len + offset - 1][bd]) + (1 << (exp - 1))) >> exp), ((QMF_RE(buffer[len + offset - 2][bd]) + (1 << (exp - 1))) >> exp)) + |
237 | MUL_R(((QMF_RE(buffer[offset - 1][bd]) + (1 << (exp - 1))) >> exp), ((QMF_RE(buffer[offset - 2][bd]) + (1 << (exp - 1))) >> exp)); |
238 | RE(ac->r22) = r11 - |
239 | MUL_R(((QMF_RE(buffer[len + offset - 2][bd]) + (1 << (exp - 1))) >> exp), ((QMF_RE(buffer[len + offset - 2][bd]) + (1 << (exp - 1))) >> exp)) + |
240 | MUL_R(((QMF_RE(buffer[offset - 2][bd]) + (1 << (exp - 1))) >> exp), ((QMF_RE(buffer[offset - 2][bd]) + (1 << (exp - 1))) >> exp)); |
241 | #else |
242 | for (j = offset; j < len + offset; j++) { |
243 | r01 += QMF_RE(buffer[j][bd]) * QMF_RE(buffer[j - 1][bd]); |
244 | r02 += QMF_RE(buffer[j][bd]) * QMF_RE(buffer[j - 2][bd]); |
245 | r11 += QMF_RE(buffer[j - 1][bd]) * QMF_RE(buffer[j - 1][bd]); |
246 | } |
247 | RE(ac->r12) = r01 - |
248 | QMF_RE(buffer[len + offset - 1][bd]) * QMF_RE(buffer[len + offset - 2][bd]) + |
249 | QMF_RE(buffer[offset - 1][bd]) * QMF_RE(buffer[offset - 2][bd]); |
250 | RE(ac->r22) = r11 - |
251 | QMF_RE(buffer[len + offset - 2][bd]) * QMF_RE(buffer[len + offset - 2][bd]) + |
252 | QMF_RE(buffer[offset - 2][bd]) * QMF_RE(buffer[offset - 2][bd]); |
253 | #endif |
254 | RE(ac->r01) = r01; |
255 | RE(ac->r02) = r02; |
256 | RE(ac->r11) = r11; |
257 | |
258 | ac->det = MUL_R(RE(ac->r11), RE(ac->r22)) - MUL_F(MUL_R(RE(ac->r12), RE(ac->r12)), rel); |
259 | } |
260 | #else |
261 | static void auto_correlation(sbr_info *sbr, acorr_coef *ac, qmf_t buffer[MAX_NTSRHFG][64], |
262 | uint8_t bd, uint8_t len) |
263 | { |
264 | real_t r01r = 0, r01i = 0, r02r = 0, r02i = 0, r11r = 0; |
265 | real_t temp1_r, temp1_i, temp2_r, temp2_i, temp3_r, temp3_i, temp4_r, temp4_i, temp5_r, temp5_i; |
266 | #ifdef FIXED_POINT |
267 | const real_t rel = FRAC_CONST(0.999999); // 1 / (1 + 1e-6f); |
268 | uint32_t mask, exp; |
269 | real_t pow2_to_exp; |
270 | #else |
271 | const real_t rel = 1 / (1 + 1e-6f); |
272 | #endif |
273 | int8_t j; |
274 | uint8_t offset = sbr->tHFAdj; |
275 | |
276 | #ifdef FIXED_POINT |
277 | mask = 0; |
278 | |
279 | for (j = (offset - 2); j < (len + offset); j++) { |
280 | real_t x; |
281 | x = QMF_RE(buffer[j][bd]) >> REAL_BITS; |
282 | mask |= x ^(x >> 31); |
283 | x = QMF_IM(buffer[j][bd]) >> REAL_BITS; |
284 | mask |= x ^(x >> 31); |
285 | } |
286 | |
287 | exp = wl_min_lzc(mask); |
288 | |
289 | /* improves accuracy */ |
290 | if (exp > 0) { |
291 | exp -= 1; |
292 | } |
293 | |
294 | pow2_to_exp = 1 << (exp - 1); |
295 | |
296 | temp2_r = (QMF_RE(buffer[offset - 2][bd]) + pow2_to_exp) >> exp; |
297 | temp2_i = (QMF_IM(buffer[offset - 2][bd]) + pow2_to_exp) >> exp; |
298 | temp3_r = (QMF_RE(buffer[offset - 1][bd]) + pow2_to_exp) >> exp; |
299 | temp3_i = (QMF_IM(buffer[offset - 1][bd]) + pow2_to_exp) >> exp; |
300 | // Save these because they are needed after loop |
301 | temp4_r = temp2_r; |
302 | temp4_i = temp2_i; |
303 | temp5_r = temp3_r; |
304 | temp5_i = temp3_i; |
305 | |
306 | for (j = offset; j < len + offset; j++) { |
307 | temp1_r = temp2_r; // temp1_r = (QMF_RE(buffer[offset-2][bd] + (1<<(exp-1))) >> exp; |
308 | temp1_i = temp2_i; // temp1_i = (QMF_IM(buffer[offset-2][bd] + (1<<(exp-1))) >> exp; |
309 | temp2_r = temp3_r; // temp2_r = (QMF_RE(buffer[offset-1][bd] + (1<<(exp-1))) >> exp; |
310 | temp2_i = temp3_i; // temp2_i = (QMF_IM(buffer[offset-1][bd] + (1<<(exp-1))) >> exp; |
311 | temp3_r = (QMF_RE(buffer[j][bd]) + pow2_to_exp) >> exp; |
312 | temp3_i = (QMF_IM(buffer[j][bd]) + pow2_to_exp) >> exp; |
313 | r01r += MUL_R(temp3_r, temp2_r) + MUL_R(temp3_i, temp2_i); |
314 | r01i += MUL_R(temp3_i, temp2_r) - MUL_R(temp3_r, temp2_i); |
315 | r02r += MUL_R(temp3_r, temp1_r) + MUL_R(temp3_i, temp1_i); |
316 | r02i += MUL_R(temp3_i, temp1_r) - MUL_R(temp3_r, temp1_i); |
317 | r11r += MUL_R(temp2_r, temp2_r) + MUL_R(temp2_i, temp2_i); |
318 | } |
319 | |
320 | // These are actual values in temporary variable at this point |
321 | // temp1_r = (QMF_RE(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp; |
322 | // temp1_i = (QMF_IM(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp; |
323 | // temp2_r = (QMF_RE(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp; |
324 | // temp2_i = (QMF_IM(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp; |
325 | // temp3_r = (QMF_RE(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp; |
326 | // temp3_i = (QMF_IM(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp; |
327 | // temp4_r = (QMF_RE(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp; |
328 | // temp4_i = (QMF_IM(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp; |
329 | // temp5_r = (QMF_RE(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp; |
330 | // temp5_i = (QMF_IM(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp; |
331 | |
332 | RE(ac->r12) = r01r - |
333 | (MUL_R(temp3_r, temp2_r) + MUL_R(temp3_i, temp2_i)) + |
334 | (MUL_R(temp5_r, temp4_r) + MUL_R(temp5_i, temp4_i)); |
335 | IM(ac->r12) = r01i - |
336 | (MUL_R(temp3_i, temp2_r) - MUL_R(temp3_r, temp2_i)) + |
337 | (MUL_R(temp5_i, temp4_r) - MUL_R(temp5_r, temp4_i)); |
338 | RE(ac->r22) = r11r - |
339 | (MUL_R(temp2_r, temp2_r) + MUL_R(temp2_i, temp2_i)) + |
340 | (MUL_R(temp4_r, temp4_r) + MUL_R(temp4_i, temp4_i)); |
341 | |
342 | #else |
343 | |
344 | temp2_r = QMF_RE(buffer[offset - 2][bd]); |
345 | temp2_i = QMF_IM(buffer[offset - 2][bd]); |
346 | temp3_r = QMF_RE(buffer[offset - 1][bd]); |
347 | temp3_i = QMF_IM(buffer[offset - 1][bd]); |
348 | // Save these because they are needed after loop |
349 | temp4_r = temp2_r; |
350 | temp4_i = temp2_i; |
351 | temp5_r = temp3_r; |
352 | temp5_i = temp3_i; |
353 | |
354 | for (j = offset; j < len + offset; j++) { |
355 | temp1_r = temp2_r; // temp1_r = QMF_RE(buffer[j-2][bd]; |
356 | temp1_i = temp2_i; // temp1_i = QMF_IM(buffer[j-2][bd]; |
357 | temp2_r = temp3_r; // temp2_r = QMF_RE(buffer[j-1][bd]; |
358 | temp2_i = temp3_i; // temp2_i = QMF_IM(buffer[j-1][bd]; |
359 | temp3_r = QMF_RE(buffer[j][bd]); |
360 | temp3_i = QMF_IM(buffer[j][bd]); |
361 | r01r += temp3_r * temp2_r + temp3_i * temp2_i; |
362 | r01i += temp3_i * temp2_r - temp3_r * temp2_i; |
363 | r02r += temp3_r * temp1_r + temp3_i * temp1_i; |
364 | r02i += temp3_i * temp1_r - temp3_r * temp1_i; |
365 | r11r += temp2_r * temp2_r + temp2_i * temp2_i; |
366 | } |
367 | |
368 | // These are actual values in temporary variable at this point |
369 | // temp1_r = QMF_RE(buffer[len+offset-1-2][bd]; |
370 | // temp1_i = QMF_IM(buffer[len+offset-1-2][bd]; |
371 | // temp2_r = QMF_RE(buffer[len+offset-1-1][bd]; |
372 | // temp2_i = QMF_IM(buffer[len+offset-1-1][bd]; |
373 | // temp3_r = QMF_RE(buffer[len+offset-1][bd]); |
374 | // temp3_i = QMF_IM(buffer[len+offset-1][bd]); |
375 | // temp4_r = QMF_RE(buffer[offset-2][bd]); |
376 | // temp4_i = QMF_IM(buffer[offset-2][bd]); |
377 | // temp5_r = QMF_RE(buffer[offset-1][bd]); |
378 | // temp5_i = QMF_IM(buffer[offset-1][bd]); |
379 | |
380 | RE(ac->r12) = r01r - |
381 | (temp3_r * temp2_r + temp3_i * temp2_i) + |
382 | (temp5_r * temp4_r + temp5_i * temp4_i); |
383 | IM(ac->r12) = r01i - |
384 | (temp3_i * temp2_r - temp3_r * temp2_i) + |
385 | (temp5_i * temp4_r - temp5_r * temp4_i); |
386 | RE(ac->r22) = r11r - |
387 | (temp2_r * temp2_r + temp2_i * temp2_i) + |
388 | (temp4_r * temp4_r + temp4_i * temp4_i); |
389 | |
390 | #endif |
391 | |
392 | RE(ac->r01) = r01r; |
393 | IM(ac->r01) = r01i; |
394 | RE(ac->r02) = r02r; |
395 | IM(ac->r02) = r02i; |
396 | RE(ac->r11) = r11r; |
397 | |
398 | 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)))); |
399 | } |
400 | #endif |
401 | |
402 | /* calculate linear prediction coefficients using the covariance method */ |
403 | #ifndef SBR_LOW_POWER |
404 | static void calc_prediction_coef(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], |
405 | complex_t *alpha_0, complex_t *alpha_1, uint8_t k) |
406 | { |
407 | real_t tmp; |
408 | acorr_coef ac; |
409 | |
410 | auto_correlation(sbr, &ac, Xlow, k, sbr->numTimeSlotsRate + 6); |
411 | |
412 | if (ac.det == 0) { |
413 | RE(alpha_1[k]) = 0; |
414 | IM(alpha_1[k]) = 0; |
415 | } else { |
416 | #ifdef FIXED_POINT |
417 | 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))); |
418 | RE(alpha_1[k]) = DIV_R(tmp, ac.det); |
419 | 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))); |
420 | IM(alpha_1[k]) = DIV_R(tmp, ac.det); |
421 | #else |
422 | tmp = REAL_CONST(1.0) / ac.det; |
423 | 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; |
424 | 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; |
425 | #endif |
426 | } |
427 | |
428 | if (RE(ac.r11) == 0) { |
429 | RE(alpha_0[k]) = 0; |
430 | IM(alpha_0[k]) = 0; |
431 | } else { |
432 | #ifdef FIXED_POINT |
433 | tmp = -(RE(ac.r01) + MUL_R(RE(alpha_1[k]), RE(ac.r12)) + MUL_R(IM(alpha_1[k]), IM(ac.r12))); |
434 | RE(alpha_0[k]) = DIV_R(tmp, RE(ac.r11)); |
435 | tmp = -(IM(ac.r01) + MUL_R(IM(alpha_1[k]), RE(ac.r12)) - MUL_R(RE(alpha_1[k]), IM(ac.r12))); |
436 | IM(alpha_0[k]) = DIV_R(tmp, RE(ac.r11)); |
437 | #else |
438 | tmp = 1.0f / RE(ac.r11); |
439 | 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; |
440 | 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; |
441 | #endif |
442 | } |
443 | |
444 | if ((MUL_R(RE(alpha_0[k]), RE(alpha_0[k])) + MUL_R(IM(alpha_0[k]), IM(alpha_0[k])) >= REAL_CONST(16)) || |
445 | (MUL_R(RE(alpha_1[k]), RE(alpha_1[k])) + MUL_R(IM(alpha_1[k]), IM(alpha_1[k])) >= REAL_CONST(16))) { |
446 | RE(alpha_0[k]) = 0; |
447 | IM(alpha_0[k]) = 0; |
448 | RE(alpha_1[k]) = 0; |
449 | IM(alpha_1[k]) = 0; |
450 | } |
451 | } |
452 | #else |
453 | static void calc_prediction_coef_lp(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], |
454 | complex_t *alpha_0, complex_t *alpha_1, real_t *rxx) |
455 | { |
456 | uint8_t k; |
457 | real_t tmp; |
458 | acorr_coef ac; |
459 | |
460 | for (k = 1; k < sbr->f_master[0]; k++) { |
461 | auto_correlation(sbr, &ac, Xlow, k, sbr->numTimeSlotsRate + 6); |
462 | |
463 | if (ac.det == 0) { |
464 | RE(alpha_0[k]) = 0; |
465 | RE(alpha_1[k]) = 0; |
466 | } else { |
467 | tmp = MUL_R(RE(ac.r01), RE(ac.r22)) - MUL_R(RE(ac.r12), RE(ac.r02)); |
468 | RE(alpha_0[k]) = DIV_R(tmp, (-ac.det)); |
469 | |
470 | tmp = MUL_R(RE(ac.r01), RE(ac.r12)) - MUL_R(RE(ac.r02), RE(ac.r11)); |
471 | RE(alpha_1[k]) = DIV_R(tmp, ac.det); |
472 | } |
473 | |
474 | if ((RE(alpha_0[k]) >= REAL_CONST(4)) || (RE(alpha_1[k]) >= REAL_CONST(4))) { |
475 | RE(alpha_0[k]) = REAL_CONST(0); |
476 | RE(alpha_1[k]) = REAL_CONST(0); |
477 | } |
478 | |
479 | /* reflection coefficient */ |
480 | if (RE(ac.r11) == 0) { |
481 | rxx[k] = COEF_CONST(0.0); |
482 | } else { |
483 | rxx[k] = DIV_C(RE(ac.r01), RE(ac.r11)); |
484 | rxx[k] = -rxx[k]; |
485 | if (rxx[k] > COEF_CONST(1.0)) { |
486 | rxx[k] = COEF_CONST(1.0); |
487 | } |
488 | if (rxx[k] < COEF_CONST(-1.0)) { |
489 | rxx[k] = COEF_CONST(-1.0); |
490 | } |
491 | } |
492 | } |
493 | } |
494 | |
495 | static void calc_aliasing_degree(sbr_info *sbr, real_t *rxx, real_t *deg) |
496 | { |
497 | uint8_t k; |
498 | |
499 | rxx[0] = COEF_CONST(0.0); |
500 | deg[1] = COEF_CONST(0.0); |
501 | |
502 | for (k = 2; k < sbr->k0; k++) { |
503 | deg[k] = 0.0; |
504 | |
505 | if ((k % 2 == 0) && (rxx[k] < COEF_CONST(0.0))) { |
506 | if (rxx[k - 1] < 0.0) { |
507 | deg[k] = COEF_CONST(1.0); |
508 | |
509 | if (rxx[k - 2] > COEF_CONST(0.0)) { |
510 | deg[k - 1] = COEF_CONST(1.0) - MUL_C(rxx[k - 1], rxx[k - 1]); |
511 | } |
512 | } else if (rxx[k - 2] > COEF_CONST(0.0)) { |
513 | deg[k] = COEF_CONST(1.0) - MUL_C(rxx[k - 1], rxx[k - 1]); |
514 | } |
515 | } |
516 | |
517 | if ((k % 2 == 1) && (rxx[k] > COEF_CONST(0.0))) { |
518 | if (rxx[k - 1] > COEF_CONST(0.0)) { |
519 | deg[k] = COEF_CONST(1.0); |
520 | |
521 | if (rxx[k - 2] < COEF_CONST(0.0)) { |
522 | deg[k - 1] = COEF_CONST(1.0) - MUL_C(rxx[k - 1], rxx[k - 1]); |
523 | } |
524 | } else if (rxx[k - 2] < COEF_CONST(0.0)) { |
525 | deg[k] = COEF_CONST(1.0) - MUL_C(rxx[k - 1], rxx[k - 1]); |
526 | } |
527 | } |
528 | } |
529 | } |
530 | #endif |
531 | |
532 | /* FIXED POINT: bwArray = COEF */ |
533 | static real_t mapNewBw(uint8_t invf_mode, uint8_t invf_mode_prev) |
534 | { |
535 | switch (invf_mode) { |
536 | case 1: /* LOW */ |
537 | if (invf_mode_prev == 0) { /* NONE */ |
538 | return COEF_CONST(0.6); |
539 | } else { |
540 | return COEF_CONST(0.75); |
541 | } |
542 | |
543 | case 2: /* MID */ |
544 | return COEF_CONST(0.9); |
545 | |
546 | case 3: /* HIGH */ |
547 | return COEF_CONST(0.98); |
548 | |
549 | default: /* NONE */ |
550 | if (invf_mode_prev == 1) { /* LOW */ |
551 | return COEF_CONST(0.6); |
552 | } else { |
553 | return COEF_CONST(0.0); |
554 | } |
555 | } |
556 | } |
557 | |
558 | /* FIXED POINT: bwArray = COEF */ |
559 | static void calc_chirp_factors(sbr_info *sbr, uint8_t ch) |
560 | { |
561 | uint8_t i; |
562 | |
563 | for (i = 0; i < sbr->N_Q; i++) { |
564 | sbr->bwArray[ch][i] = mapNewBw(sbr->bs_invf_mode[ch][i], sbr->bs_invf_mode_prev[ch][i]); |
565 | |
566 | if (sbr->bwArray[ch][i] < sbr->bwArray_prev[ch][i]) { |
567 | 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)); |
568 | } else { |
569 | 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)); |
570 | } |
571 | |
572 | if (sbr->bwArray[ch][i] < COEF_CONST(0.015625)) { |
573 | sbr->bwArray[ch][i] = COEF_CONST(0.0); |
574 | } |
575 | |
576 | if (sbr->bwArray[ch][i] >= COEF_CONST(0.99609375)) { |
577 | sbr->bwArray[ch][i] = COEF_CONST(0.99609375); |
578 | } |
579 | |
580 | sbr->bwArray_prev[ch][i] = sbr->bwArray[ch][i]; |
581 | sbr->bs_invf_mode_prev[ch][i] = sbr->bs_invf_mode[ch][i]; |
582 | } |
583 | } |
584 | |
585 | static void patch_construction(sbr_info *sbr) |
586 | { |
587 | uint8_t i, k; |
588 | uint8_t odd, sb; |
589 | uint8_t msb = sbr->k0; |
590 | uint8_t usb = sbr->kx; |
591 | uint8_t goalSbTab[] = { 21, 23, 32, 43, 46, 64, 85, 93, 128, 0, 0, 0 }; |
592 | /* (uint8_t)(2.048e6/sbr->sample_rate + 0.5); */ |
593 | uint8_t goalSb = goalSbTab[get_sr_index(sbr->sample_rate)]; |
594 | |
595 | sbr->noPatches = 0; |
596 | |
597 | if (goalSb < (sbr->kx + sbr->M)) { |
598 | for (i = 0, k = 0; sbr->f_master[i] < goalSb; i++) { |
599 | k = i + 1; |
600 | } |
601 | } else { |
602 | k = sbr->N_master; |
603 | } |
604 | |
605 | if (sbr->N_master == 0) { |
606 | sbr->noPatches = 0; |
607 | sbr->patchNoSubbands[0] = 0; |
608 | sbr->patchStartSubband[0] = 0; |
609 | |
610 | return; |
611 | } |
612 | |
613 | do { |
614 | uint8_t j = k + 1; |
615 | |
616 | do { |
617 | j--; |
618 | |
619 | sb = sbr->f_master[j]; |
620 | odd = (sb - 2 + sbr->k0) % 2; |
621 | } while (sb > (sbr->k0 - 1 + msb - odd)); |
622 | |
623 | sbr->patchNoSubbands[sbr->noPatches] = max(sb - usb, 0); |
624 | sbr->patchStartSubband[sbr->noPatches] = sbr->k0 - odd - |
625 | sbr->patchNoSubbands[sbr->noPatches]; |
626 | |
627 | if (sbr->patchNoSubbands[sbr->noPatches] > 0) { |
628 | usb = sb; |
629 | msb = sb; |
630 | sbr->noPatches++; |
631 | } else { |
632 | msb = sbr->kx; |
633 | } |
634 | |
635 | if (sbr->f_master[k] - sb < 3) { |
636 | k = sbr->N_master; |
637 | } |
638 | } while (sb != (sbr->kx + sbr->M)); |
639 | |
640 | if ((sbr->patchNoSubbands[sbr->noPatches - 1] < 3) && (sbr->noPatches > 1)) { |
641 | sbr->noPatches--; |
642 | } |
643 | |
644 | sbr->noPatches = min(sbr->noPatches, 5); |
645 | } |
646 | |
647 | #endif |
648 |