summaryrefslogtreecommitdiff
path: root/audio_codec/libfaad/sbr_hfgen.c (plain)
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
44static 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);
46static void calc_aliasing_degree(sbr_info *sbr, real_t *rxx, real_t *deg);
47#else
48static 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
51static void calc_chirp_factors(sbr_info *sbr, uint8_t ch);
52static void patch_construction(sbr_info *sbr);
53
54
55void 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
183typedef 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
193static 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
261static 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
404static 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
453static 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
495static 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 */
533static 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 */
559static 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
585static 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