2 ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
3 ** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
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.
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.
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.
19 ** Any non-GPL usage of this software or parts of this software is strictly
22 ** Commercial non-GPL licensing of this software is possible.
23 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
28 /* High Frequency generation */
35 #include "sbr_syntax.h"
36 #include "sbr_hfgen.h"
40 /* static function declarations */
42 static void calc_prediction_coef_lp(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][64],
43 complex_t
*alpha_0
, complex_t
*alpha_1
, real_t
*rxx
);
44 static void calc_aliasing_degree(sbr_info
*sbr
, real_t
*rxx
, real_t
*deg
);
46 static void calc_prediction_coef(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][64],
47 complex_t
*alpha_0
, complex_t
*alpha_1
, uint8_t k
);
49 static void calc_chirp_factors(sbr_info
*sbr
, uint8_t ch
);
50 static void patch_construction(sbr_info
*sbr
);
53 void hf_generation(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][64],
54 qmf_t Xhigh
[MAX_NTSRHFG
][64]
61 ALIGN complex_t alpha_0
[64], alpha_1
[64];
66 uint8_t offset
= sbr
->tHFAdj
;
67 uint8_t first
= sbr
->t_E
[ch
][0];
68 uint8_t last
= sbr
->t_E
[ch
][sbr
->L_E
[ch
]];
70 calc_chirp_factors(sbr
, ch
);
73 memset(deg
, 0, 64*sizeof(real_t
));
76 if ((ch
== 0) && (sbr
->Reset
))
77 patch_construction(sbr
);
79 /* calculate the prediction coefficients */
81 calc_prediction_coef_lp(sbr
, Xlow
, alpha_0
, alpha_1
, rxx
);
82 calc_aliasing_degree(sbr
, rxx
, deg
);
85 /* actual HF generation */
86 for (i
= 0; i
< sbr
->noPatches
; i
++)
88 for (x
= 0; x
< sbr
->patchNoSubbands
[i
]; x
++)
90 real_t a0_r
, a0_i
, a1_r
, a1_i
;
94 /* find the low and high band for patching */
96 for (q
= 0; q
< i
; q
++)
98 k
+= sbr
->patchNoSubbands
[q
];
100 p
= sbr
->patchStartSubband
[i
] + x
;
103 if (x
!= 0 /*x < sbr->patchNoSubbands[i]-1*/)
109 g
= sbr
->table_map_k_to_g
[k
];
111 bw
= sbr
->bwArray
[ch
][g
];
114 /* do the patching */
115 /* with or without filtering */
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
);
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
);
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
]);
137 for (l
= first
; l
< last
; l
++)
141 temp3_r
= QMF_RE(Xlow
[l
+ offset
][p
]);
142 #ifndef SBR_LOW_POWER
145 temp3_i
= QMF_IM(Xlow
[l
+ offset
][p
]);
149 QMF_RE(Xhigh
[l
+ offset
][k
]) =
151 +(MUL_R(a0_r
, temp2_r
) +
152 MUL_R(a1_r
, temp1_r
));
154 QMF_RE(Xhigh
[l
+ offset
][k
]) =
156 +(MUL_R(a0_r
, temp2_r
) -
157 MUL_R(a0_i
, temp2_i
) +
158 MUL_R(a1_r
, temp1_r
) -
159 MUL_R(a1_i
, temp1_i
));
160 QMF_IM(Xhigh
[l
+ offset
][k
]) =
162 +(MUL_R(a0_i
, temp2_r
) +
163 MUL_R(a0_r
, temp2_i
) +
164 MUL_R(a1_i
, temp1_r
) +
165 MUL_R(a1_r
, temp1_i
));
169 for (l
= first
; l
< last
; l
++)
171 QMF_RE(Xhigh
[l
+ offset
][k
]) = QMF_RE(Xlow
[l
+ offset
][p
]);
172 #ifndef SBR_LOW_POWER
173 QMF_IM(Xhigh
[l
+ offset
][k
]) = QMF_IM(Xlow
[l
+ offset
][p
]);
182 limiter_frequency_table(sbr
);
197 static void auto_correlation(sbr_info
*sbr
, acorr_coef
*ac
,
198 qmf_t buffer
[MAX_NTSRHFG
][64],
199 uint8_t bd
, uint8_t len
)
201 real_t r01
= 0, r02
= 0, r11
= 0;
203 uint8_t offset
= sbr
->tHFAdj
;
205 const real_t rel
= FRAC_CONST(0.999999); // 1 / (1 + 1e-6f);
209 const real_t rel
= 1 / (1 + 1e-6f
);
216 for (j
= (offset
-2); j
< (len
+ offset
); j
++)
219 x
= QMF_RE(buffer
[j
][bd
])>>REAL_BITS
;
220 mask
|= x
^ (x
>> 31);
223 exp
= wl_min_lzc(mask
);
225 for (j
= offset
; j
< len
+ offset
; j
++)
227 real_t buf_j
= ((QMF_RE(buffer
[j
][bd
])+(1<<(exp
-1)))>>exp
);
228 real_t buf_j_1
= ((QMF_RE(buffer
[j
-1][bd
])+(1<<(exp
-1)))>>exp
);
229 real_t buf_j_2
= ((QMF_RE(buffer
[j
-2][bd
])+(1<<(exp
-1)))>>exp
);
231 /* normalisation with rounding */
232 r01
+= MUL_R(buf_j
, buf_j_1
);
233 r02
+= MUL_R(buf_j
, buf_j_2
);
234 r11
+= MUL_R(buf_j_1
, buf_j_1
);
237 MUL_R(((QMF_RE(buffer
[len
+offset
-1][bd
])+(1<<(exp
-1)))>>exp
), ((QMF_RE(buffer
[len
+offset
-2][bd
])+(1<<(exp
-1)))>>exp
)) +
238 MUL_R(((QMF_RE(buffer
[offset
-1][bd
])+(1<<(exp
-1)))>>exp
), ((QMF_RE(buffer
[offset
-2][bd
])+(1<<(exp
-1)))>>exp
));
240 MUL_R(((QMF_RE(buffer
[len
+offset
-2][bd
])+(1<<(exp
-1)))>>exp
), ((QMF_RE(buffer
[len
+offset
-2][bd
])+(1<<(exp
-1)))>>exp
)) +
241 MUL_R(((QMF_RE(buffer
[offset
-2][bd
])+(1<<(exp
-1)))>>exp
), ((QMF_RE(buffer
[offset
-2][bd
])+(1<<(exp
-1)))>>exp
));
243 for (j
= offset
; j
< len
+ offset
; j
++)
245 r01
+= QMF_RE(buffer
[j
][bd
]) * QMF_RE(buffer
[j
-1][bd
]);
246 r02
+= QMF_RE(buffer
[j
][bd
]) * QMF_RE(buffer
[j
-2][bd
]);
247 r11
+= QMF_RE(buffer
[j
-1][bd
]) * QMF_RE(buffer
[j
-1][bd
]);
250 QMF_RE(buffer
[len
+offset
-1][bd
]) * QMF_RE(buffer
[len
+offset
-2][bd
]) +
251 QMF_RE(buffer
[offset
-1][bd
]) * QMF_RE(buffer
[offset
-2][bd
]);
253 QMF_RE(buffer
[len
+offset
-2][bd
]) * QMF_RE(buffer
[len
+offset
-2][bd
]) +
254 QMF_RE(buffer
[offset
-2][bd
]) * QMF_RE(buffer
[offset
-2][bd
]);
260 ac
->det
= MUL_R(RE(ac
->r11
), RE(ac
->r22
)) - MUL_F(MUL_R(RE(ac
->r12
), RE(ac
->r12
)), rel
);
263 static void auto_correlation(sbr_info
*sbr
, acorr_coef
*ac
, qmf_t buffer
[MAX_NTSRHFG
][64],
264 uint8_t bd
, uint8_t len
)
266 real_t r01r
= 0, r01i
= 0, r02r
= 0, r02i
= 0, r11r
= 0;
267 real_t temp1_r
, temp1_i
, temp2_r
, temp2_i
, temp3_r
, temp3_i
, temp4_r
, temp4_i
, temp5_r
, temp5_i
;
269 const real_t rel
= FRAC_CONST(0.999999); // 1 / (1 + 1e-6f);
273 const real_t rel
= 1 / (1 + 1e-6f
);
276 uint8_t offset
= sbr
->tHFAdj
;
281 for (j
= (offset
-2); j
< (len
+ offset
); j
++)
284 x
= QMF_RE(buffer
[j
][bd
])>>REAL_BITS
;
285 mask
|= x
^ (x
>> 31);
286 x
= QMF_IM(buffer
[j
][bd
])>>REAL_BITS
;
287 mask
|= x
^ (x
>> 31);
290 exp
= wl_min_lzc(mask
);
292 pow2_to_exp
= 1<<(exp
-1);
294 temp2_r
= (QMF_RE(buffer
[offset
-2][bd
]) + pow2_to_exp
) >> exp
;
295 temp2_i
= (QMF_IM(buffer
[offset
-2][bd
]) + pow2_to_exp
) >> exp
;
296 temp3_r
= (QMF_RE(buffer
[offset
-1][bd
]) + pow2_to_exp
) >> exp
;
297 temp3_i
= (QMF_IM(buffer
[offset
-1][bd
]) + pow2_to_exp
) >> exp
;
298 // Save these because they are needed after loop
304 for (j
= offset
; j
< len
+ offset
; j
++)
306 temp1_r
= temp2_r
; // temp1_r = (QMF_RE(buffer[offset-2][bd] + (1<<(exp-1))) >> exp;
307 temp1_i
= temp2_i
; // temp1_i = (QMF_IM(buffer[offset-2][bd] + (1<<(exp-1))) >> exp;
308 temp2_r
= temp3_r
; // temp2_r = (QMF_RE(buffer[offset-1][bd] + (1<<(exp-1))) >> exp;
309 temp2_i
= temp3_i
; // temp2_i = (QMF_IM(buffer[offset-1][bd] + (1<<(exp-1))) >> exp;
310 temp3_r
= (QMF_RE(buffer
[j
][bd
]) + pow2_to_exp
) >> exp
;
311 temp3_i
= (QMF_IM(buffer
[j
][bd
]) + pow2_to_exp
) >> exp
;
312 r01r
+= MUL_R(temp3_r
, temp2_r
) + MUL_R(temp3_i
, temp2_i
);
313 r01i
+= MUL_R(temp3_i
, temp2_r
) - MUL_R(temp3_r
, temp2_i
);
314 r02r
+= MUL_R(temp3_r
, temp1_r
) + MUL_R(temp3_i
, temp1_i
);
315 r02i
+= MUL_R(temp3_i
, temp1_r
) - MUL_R(temp3_r
, temp1_i
);
316 r11r
+= MUL_R(temp2_r
, temp2_r
) + MUL_R(temp2_i
, temp2_i
);
319 // These are actual values in temporary variable at this point
320 // temp1_r = (QMF_RE(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp;
321 // temp1_i = (QMF_IM(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp;
322 // temp2_r = (QMF_RE(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp;
323 // temp2_i = (QMF_IM(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp;
324 // temp3_r = (QMF_RE(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp;
325 // temp3_i = (QMF_IM(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp;
326 // temp4_r = (QMF_RE(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp;
327 // temp4_i = (QMF_IM(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp;
328 // temp5_r = (QMF_RE(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp;
329 // temp5_i = (QMF_IM(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp;
332 (MUL_R(temp3_r
, temp2_r
) + MUL_R(temp3_i
, temp2_i
)) +
333 (MUL_R(temp5_r
, temp4_r
) + MUL_R(temp5_i
, temp4_i
));
335 (MUL_R(temp3_i
, temp2_r
) - MUL_R(temp3_r
, temp2_i
)) +
336 (MUL_R(temp5_i
, temp4_r
) - MUL_R(temp5_r
, temp4_i
));
338 (MUL_R(temp2_r
, temp2_r
) + MUL_R(temp2_i
, temp2_i
)) +
339 (MUL_R(temp4_r
, temp4_r
) + MUL_R(temp4_i
, temp4_i
));
343 temp2_r
= QMF_RE(buffer
[offset
-2][bd
]);
344 temp2_i
= QMF_IM(buffer
[offset
-2][bd
]);
345 temp3_r
= QMF_RE(buffer
[offset
-1][bd
]);
346 temp3_i
= QMF_IM(buffer
[offset
-1][bd
]);
347 // Save these because they are needed after loop
353 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
;
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]);
381 (temp3_r
* temp2_r
+ temp3_i
* temp2_i
) +
382 (temp5_r
* temp4_r
+ temp5_i
* temp4_i
);
384 (temp3_i
* temp2_r
- temp3_r
* temp2_i
) +
385 (temp5_i
* temp4_r
- temp5_r
* temp4_i
);
387 (temp2_r
* temp2_r
+ temp2_i
* temp2_i
) +
388 (temp4_r
* temp4_r
+ temp4_i
* temp4_i
);
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
))));
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
)
410 auto_correlation(sbr
, &ac
, Xlow
, k
, sbr
->numTimeSlotsRate
+ 6);
418 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
)));
419 RE(alpha_1
[k
]) = DIV_R(tmp
, ac
.det
);
420 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
)));
421 IM(alpha_1
[k
]) = DIV_R(tmp
, ac
.det
);
423 tmp
= REAL_CONST(1.0) / ac
.det
;
424 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
;
425 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
;
435 tmp
= -(RE(ac
.r01
) + MUL_R(RE(alpha_1
[k
]), RE(ac
.r12
)) + MUL_R(IM(alpha_1
[k
]), IM(ac
.r12
)));
436 RE(alpha_0
[k
]) = DIV_R(tmp
, RE(ac
.r11
));
437 tmp
= -(IM(ac
.r01
) + MUL_R(IM(alpha_1
[k
]), RE(ac
.r12
)) - MUL_R(RE(alpha_1
[k
]), IM(ac
.r12
)));
438 IM(alpha_0
[k
]) = DIV_R(tmp
, RE(ac
.r11
));
440 tmp
= 1.0f
/ RE(ac
.r11
);
441 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
;
442 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
;
446 if ((MUL_R(RE(alpha_0
[k
]),RE(alpha_0
[k
])) + MUL_R(IM(alpha_0
[k
]),IM(alpha_0
[k
])) >= REAL_CONST(16)) ||
447 (MUL_R(RE(alpha_1
[k
]),RE(alpha_1
[k
])) + MUL_R(IM(alpha_1
[k
]),IM(alpha_1
[k
])) >= REAL_CONST(16)))
456 static void calc_prediction_coef_lp(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][64],
457 complex_t
*alpha_0
, complex_t
*alpha_1
, real_t
*rxx
)
463 for (k
= 1; k
< sbr
->f_master
[0]; k
++)
465 auto_correlation(sbr
, &ac
, Xlow
, k
, sbr
->numTimeSlotsRate
+ 6);
472 tmp
= MUL_R(RE(ac
.r01
), RE(ac
.r22
)) - MUL_R(RE(ac
.r12
), RE(ac
.r02
));
473 RE(alpha_0
[k
]) = DIV_R(tmp
, (-ac
.det
));
475 tmp
= MUL_R(RE(ac
.r01
), RE(ac
.r12
)) - MUL_R(RE(ac
.r02
), RE(ac
.r11
));
476 RE(alpha_1
[k
]) = DIV_R(tmp
, ac
.det
);
479 if ((RE(alpha_0
[k
]) >= REAL_CONST(4)) || (RE(alpha_1
[k
]) >= REAL_CONST(4)))
481 RE(alpha_0
[k
]) = REAL_CONST(0);
482 RE(alpha_1
[k
]) = REAL_CONST(0);
485 /* reflection coefficient */
488 rxx
[k
] = COEF_CONST(0.0);
490 rxx
[k
] = DIV_C(RE(ac
.r01
), RE(ac
.r11
));
492 if (rxx
[k
] > COEF_CONST(1.0)) rxx
[k
] = COEF_CONST(1.0);
493 if (rxx
[k
] < COEF_CONST(-1.0)) rxx
[k
] = COEF_CONST(-1.0);
498 static void calc_aliasing_degree(sbr_info
*sbr
, real_t
*rxx
, real_t
*deg
)
502 rxx
[0] = COEF_CONST(0.0);
503 deg
[1] = COEF_CONST(0.0);
505 for (k
= 2; k
< sbr
->k0
; k
++)
509 if ((k
% 2 == 0) && (rxx
[k
] < COEF_CONST(0.0)))
513 deg
[k
] = COEF_CONST(1.0);
515 if (rxx
[k
-2] > COEF_CONST(0.0))
517 deg
[k
-1] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
519 } else if (rxx
[k
-2] > COEF_CONST(0.0)) {
520 deg
[k
] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
524 if ((k
% 2 == 1) && (rxx
[k
] > COEF_CONST(0.0)))
526 if (rxx
[k
-1] > COEF_CONST(0.0))
528 deg
[k
] = COEF_CONST(1.0);
530 if (rxx
[k
-2] < COEF_CONST(0.0))
532 deg
[k
-1] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
534 } else if (rxx
[k
-2] < COEF_CONST(0.0)) {
535 deg
[k
] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
542 /* FIXED POINT: bwArray = COEF */
543 static real_t
mapNewBw(uint8_t invf_mode
, uint8_t invf_mode_prev
)
548 if (invf_mode_prev
== 0) /* NONE */
549 return COEF_CONST(0.6);
551 return COEF_CONST(0.75);
554 return COEF_CONST(0.9);
557 return COEF_CONST(0.98);
560 if (invf_mode_prev
== 1) /* LOW */
561 return COEF_CONST(0.6);
563 return COEF_CONST(0.0);
567 /* FIXED POINT: bwArray = COEF */
568 static void calc_chirp_factors(sbr_info
*sbr
, uint8_t ch
)
572 for (i
= 0; i
< sbr
->N_Q
; i
++)
574 sbr
->bwArray
[ch
][i
] = mapNewBw(sbr
->bs_invf_mode
[ch
][i
], sbr
->bs_invf_mode_prev
[ch
][i
]);
576 if (sbr
->bwArray
[ch
][i
] < sbr
->bwArray_prev
[ch
][i
])
577 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));
579 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));
581 if (sbr
->bwArray
[ch
][i
] < COEF_CONST(0.015625))
582 sbr
->bwArray
[ch
][i
] = COEF_CONST(0.0);
584 if (sbr
->bwArray
[ch
][i
] >= COEF_CONST(0.99609375))
585 sbr
->bwArray
[ch
][i
] = COEF_CONST(0.99609375);
587 sbr
->bwArray_prev
[ch
][i
] = sbr
->bwArray
[ch
][i
];
588 sbr
->bs_invf_mode_prev
[ch
][i
] = sbr
->bs_invf_mode
[ch
][i
];
592 static void patch_construction(sbr_info
*sbr
)
596 uint8_t msb
= sbr
->k0
;
597 uint8_t usb
= sbr
->kx
;
598 uint8_t goalSbTab
[] = { 21, 23, 32, 43, 46, 64, 85, 93, 128, 0, 0, 0 };
599 /* (uint8_t)(2.048e6/sbr->sample_rate + 0.5); */
600 uint8_t goalSb
= goalSbTab
[get_sr_index(sbr
->sample_rate
)];
604 if (goalSb
< (sbr
->kx
+ sbr
->M
))
606 for (i
= 0, k
= 0; sbr
->f_master
[i
] < goalSb
; i
++)
612 if (sbr
->N_master
== 0)
615 sbr
->patchNoSubbands
[0] = 0;
616 sbr
->patchStartSubband
[0] = 0;
628 sb
= sbr
->f_master
[j
];
629 odd
= (sb
- 2 + sbr
->k0
) % 2;
631 } while (sb
> (sbr
->k0
- 1 + msb
- odd
));
633 sbr
->patchNoSubbands
[sbr
->noPatches
] = max(sb
- usb
, 0);
634 sbr
->patchStartSubband
[sbr
->noPatches
] = sbr
->k0
- odd
-
635 sbr
->patchNoSubbands
[sbr
->noPatches
];
637 if (sbr
->patchNoSubbands
[sbr
->noPatches
] > 0)
646 if (sbr
->f_master
[k
] - sb
< 3)
648 } while (sb
!= (sbr
->kx
+ sbr
->M
));
650 if ((sbr
->patchNoSubbands
[sbr
->noPatches
-1] < 3) && (sbr
->noPatches
> 1))
655 sbr
->noPatches
= min(sbr
->noPatches
, 5);