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
]))>>exp
);
228 real_t buf_j_1
= (QMF_RE(buffer
[j
-1][bd
]))>>exp
);
229 real_t buf_j_2
= (QMF_RE(buffer
[j
-2][bd
]))>>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
]))>>exp
), ((QMF_RE(buffer
[len
+offset
-2][bd
]))>>exp
)) +
238 MUL_R(((QMF_RE(buffer
[ offset
-1][bd
]))>>exp
), ((QMF_RE(buffer
[ offset
-2][bd
]))>>exp
));
240 MUL_R(((QMF_RE(buffer
[len
+offset
-2][bd
]))>>exp
), ((QMF_RE(buffer
[len
+offset
-2][bd
]))>>exp
)) +
241 MUL_R(((QMF_RE(buffer
[ offset
-2][bd
]))>>exp
), ((QMF_RE(buffer
[ offset
-2][bd
]))>>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);
272 const real_t rel
= 1 / (1 + 1e-6f
);
275 uint8_t offset
= sbr
->tHFAdj
;
280 for (j
= (offset
-2); j
< (len
+ offset
); j
++)
283 x
= QMF_RE(buffer
[j
][bd
])>>REAL_BITS
;
284 mask
|= x
^ (x
>> 31);
285 x
= QMF_IM(buffer
[j
][bd
])>>REAL_BITS
;
286 mask
|= x
^ (x
>> 31);
289 exp
= wl_min_lzc(mask
);
291 temp2_r
= (QMF_RE(buffer
[offset
-2][bd
])) >> exp
;
292 temp2_i
= (QMF_IM(buffer
[offset
-2][bd
])) >> exp
;
293 temp3_r
= (QMF_RE(buffer
[offset
-1][bd
])) >> exp
;
294 temp3_i
= (QMF_IM(buffer
[offset
-1][bd
])) >> exp
;
295 // Save these because they are needed after loop
301 for (j
= offset
; j
< len
+ offset
; j
++)
303 temp1_r
= temp2_r
; // temp1_r = (QMF_RE(buffer[offset-2][bd] + (1<<(exp-1))) >> exp;
304 temp1_i
= temp2_i
; // temp1_i = (QMF_IM(buffer[offset-2][bd] + (1<<(exp-1))) >> exp;
305 temp2_r
= temp3_r
; // temp2_r = (QMF_RE(buffer[offset-1][bd] + (1<<(exp-1))) >> exp;
306 temp2_i
= temp3_i
; // temp2_i = (QMF_IM(buffer[offset-1][bd] + (1<<(exp-1))) >> exp;
307 temp3_r
= (QMF_RE(buffer
[j
][bd
])) >> exp
;
308 temp3_i
= (QMF_IM(buffer
[j
][bd
])) >> exp
;
309 r01r
+= MUL_R(temp3_r
, temp2_r
) + MUL_R(temp3_i
, temp2_i
);
310 r01i
+= MUL_R(temp3_i
, temp2_r
) - MUL_R(temp3_r
, temp2_i
);
311 r02r
+= MUL_R(temp3_r
, temp1_r
) + MUL_R(temp3_i
, temp1_i
);
312 r02i
+= MUL_R(temp3_i
, temp1_r
) - MUL_R(temp3_r
, temp1_i
);
313 r11r
+= MUL_R(temp2_r
, temp2_r
) + MUL_R(temp2_i
, temp2_i
);
316 // These are actual values in temporary variable at this point
317 // temp1_r = (QMF_RE(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp;
318 // temp1_i = (QMF_IM(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp;
319 // temp2_r = (QMF_RE(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp;
320 // temp2_i = (QMF_IM(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp;
321 // temp3_r = (QMF_RE(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp;
322 // temp3_i = (QMF_IM(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp;
323 // temp4_r = (QMF_RE(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp;
324 // temp4_i = (QMF_IM(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp;
325 // temp5_r = (QMF_RE(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp;
326 // temp5_i = (QMF_IM(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp;
329 (MUL_R(temp3_r
, temp2_r
) + MUL_R(temp3_i
, temp2_i
)) +
330 (MUL_R(temp5_r
, temp4_r
) + MUL_R(temp5_i
, temp4_i
));
332 (MUL_R(temp3_i
, temp2_r
) - MUL_R(temp3_r
, temp2_i
)) +
333 (MUL_R(temp5_i
, temp4_r
) - MUL_R(temp5_r
, temp4_i
));
335 (MUL_R(temp2_r
, temp2_r
) + MUL_R(temp2_i
, temp2_i
)) +
336 (MUL_R(temp4_r
, temp4_r
) + MUL_R(temp4_i
, temp4_i
));
340 temp2_r
= QMF_RE(buffer
[offset
-2][bd
]);
341 temp2_i
= QMF_IM(buffer
[offset
-2][bd
]);
342 temp3_r
= QMF_RE(buffer
[offset
-1][bd
]);
343 temp3_i
= QMF_IM(buffer
[offset
-1][bd
]);
344 // Save these because they are needed after loop
350 for (j
= offset
; j
< len
+ offset
; j
++)
352 temp1_r
= temp2_r
; // temp1_r = QMF_RE(buffer[j-2][bd];
353 temp1_i
= temp2_i
; // temp1_i = QMF_IM(buffer[j-2][bd];
354 temp2_r
= temp3_r
; // temp2_r = QMF_RE(buffer[j-1][bd];
355 temp2_i
= temp3_i
; // temp2_i = QMF_IM(buffer[j-1][bd];
356 temp3_r
= QMF_RE(buffer
[j
][bd
]);
357 temp3_i
= QMF_IM(buffer
[j
][bd
]);
358 r01r
+= temp3_r
* temp2_r
+ temp3_i
* temp2_i
;
359 r01i
+= temp3_i
* temp2_r
- temp3_r
* temp2_i
;
360 r02r
+= temp3_r
* temp1_r
+ temp3_i
* temp1_i
;
361 r02i
+= temp3_i
* temp1_r
- temp3_r
* temp1_i
;
362 r11r
+= temp2_r
* temp2_r
+ temp2_i
* temp2_i
;
365 // These are actual values in temporary variable at this point
366 // temp1_r = QMF_RE(buffer[len+offset-1-2][bd];
367 // temp1_i = QMF_IM(buffer[len+offset-1-2][bd];
368 // temp2_r = QMF_RE(buffer[len+offset-1-1][bd];
369 // temp2_i = QMF_IM(buffer[len+offset-1-1][bd];
370 // temp3_r = QMF_RE(buffer[len+offset-1][bd]);
371 // temp3_i = QMF_IM(buffer[len+offset-1][bd]);
372 // temp4_r = QMF_RE(buffer[offset-2][bd]);
373 // temp4_i = QMF_IM(buffer[offset-2][bd]);
374 // temp5_r = QMF_RE(buffer[offset-1][bd]);
375 // temp5_i = QMF_IM(buffer[offset-1][bd]);
378 (temp3_r
* temp2_r
+ temp3_i
* temp2_i
) +
379 (temp5_r
* temp4_r
+ temp5_i
* temp4_i
);
381 (temp3_i
* temp2_r
- temp3_r
* temp2_i
) +
382 (temp5_i
* temp4_r
- temp5_r
* temp4_i
);
384 (temp2_r
* temp2_r
+ temp2_i
* temp2_i
) +
385 (temp4_r
* temp4_r
+ temp4_i
* temp4_i
);
395 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 /* calculate linear prediction coefficients using the covariance method */
400 #ifndef SBR_LOW_POWER
401 static void calc_prediction_coef(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][64],
402 complex_t
*alpha_0
, complex_t
*alpha_1
, uint8_t k
)
407 auto_correlation(sbr
, &ac
, Xlow
, k
, sbr
->numTimeSlotsRate
+ 6);
415 mul
= DIV_R(REAL_CONST(1.0), ac
.det
);
416 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
)));
417 RE(alpha_1
[k
]) = MUL_R(tmp
, mul
);
418 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
)));
419 IM(alpha_1
[k
]) = MUL_R(tmp
, mul
);
421 mul
= REAL_CONST(1.0) / ac
.det
;
422 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
))) * mul
;
423 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
))) * mul
;
433 mul
= DIV_R(REAL_CONST(1.0), RE(ac
.r11
));
434 tmp
= -(RE(ac
.r01
) + MUL_R(RE(alpha_1
[k
]), RE(ac
.r12
)) + MUL_R(IM(alpha_1
[k
]), IM(ac
.r12
)));
435 RE(alpha_0
[k
]) = MUL_R(tmp
, mul
);
436 tmp
= -(IM(ac
.r01
) + MUL_R(IM(alpha_1
[k
]), RE(ac
.r12
)) - MUL_R(RE(alpha_1
[k
]), IM(ac
.r12
)));
437 IM(alpha_0
[k
]) = MUL_R(tmp
, mul
);
439 tmp
= 1.0f
/ RE(ac
.r11
);
440 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
;
441 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
;
445 if ((MUL_R(RE(alpha_0
[k
]),RE(alpha_0
[k
])) + MUL_R(IM(alpha_0
[k
]),IM(alpha_0
[k
])) >= REAL_CONST(16)) ||
446 (MUL_R(RE(alpha_1
[k
]),RE(alpha_1
[k
])) + MUL_R(IM(alpha_1
[k
]),IM(alpha_1
[k
])) >= REAL_CONST(16)))
455 static void calc_prediction_coef_lp(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][64],
456 complex_t
*alpha_0
, complex_t
*alpha_1
, real_t
*rxx
)
462 for (k
= 1; k
< sbr
->f_master
[0]; k
++)
464 auto_correlation(sbr
, &ac
, Xlow
, k
, sbr
->numTimeSlotsRate
+ 6);
471 mul
= DIV_R(REAL_CONST(1.0), ac
.det
);
472 tmp
= MUL_R(RE(ac
.r01
), RE(ac
.r22
)) - MUL_R(RE(ac
.r12
), RE(ac
.r02
));
473 RE(alpha_0
[k
]) = -MUL_R(tmp
, mul
);
474 tmp
= MUL_R(RE(ac
.r01
), RE(ac
.r12
)) - MUL_R(RE(ac
.r02
), RE(ac
.r11
));
475 RE(alpha_1
[k
]) = MUL_R(tmp
, mul
);
478 if ((RE(alpha_0
[k
]) >= REAL_CONST(4)) || (RE(alpha_1
[k
]) >= REAL_CONST(4)))
480 RE(alpha_0
[k
]) = REAL_CONST(0);
481 RE(alpha_1
[k
]) = REAL_CONST(0);
484 /* reflection coefficient */
487 rxx
[k
] = COEF_CONST(0.0);
489 rxx
[k
] = DIV_C(RE(ac
.r01
), RE(ac
.r11
));
491 if (rxx
[k
] > COEF_CONST( 1.0)) rxx
[k
] = COEF_CONST(1.0);
492 if (rxx
[k
] < COEF_CONST(-1.0)) rxx
[k
] = COEF_CONST(-1.0);
497 static void calc_aliasing_degree(sbr_info
*sbr
, real_t
*rxx
, real_t
*deg
)
501 rxx
[0] = COEF_CONST(0.0);
502 deg
[1] = COEF_CONST(0.0);
504 for (k
= 2; k
< sbr
->k0
; k
++)
506 deg
[k
] = COEF_CONST(0.0);
508 if ((k
% 2 == 0) && (rxx
[k
] < COEF_CONST(0.0)))
510 if (rxx
[k
-1] < COEF_CONST(0.0))
512 deg
[k
] = COEF_CONST(1.0);
514 if (rxx
[k
-2] > COEF_CONST(0.0))
516 deg
[k
-1] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
518 } else if (rxx
[k
-2] > COEF_CONST(0.0)) {
519 deg
[k
] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
523 if ((k
% 2 == 1) && (rxx
[k
] > COEF_CONST(0.0)))
525 if (rxx
[k
-1] > COEF_CONST(0.0))
527 deg
[k
] = COEF_CONST(1.0);
529 if (rxx
[k
-2] < COEF_CONST(0.0))
531 deg
[k
-1] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
533 } else if (rxx
[k
-2] < COEF_CONST(0.0)) {
534 deg
[k
] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
541 /* FIXED POINT: bwArray = COEF */
542 static real_t
mapNewBw(uint8_t invf_mode
, uint8_t invf_mode_prev
)
547 if (invf_mode_prev
== 0) /* NONE */
548 return COEF_CONST(0.6);
550 return COEF_CONST(0.75);
553 return COEF_CONST(0.9);
556 return COEF_CONST(0.98);
559 if (invf_mode_prev
== 1) /* LOW */
560 return COEF_CONST(0.6);
562 return COEF_CONST(0.0);
566 /* FIXED POINT: bwArray = COEF */
567 static void calc_chirp_factors(sbr_info
*sbr
, uint8_t ch
)
571 for (i
= 0; i
< sbr
->N_Q
; i
++)
573 sbr
->bwArray
[ch
][i
] = mapNewBw(sbr
->bs_invf_mode
[ch
][i
], sbr
->bs_invf_mode_prev
[ch
][i
]);
575 if (sbr
->bwArray
[ch
][i
] < sbr
->bwArray_prev
[ch
][i
])
576 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));
578 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));
580 if (sbr
->bwArray
[ch
][i
] < COEF_CONST(0.015625))
581 sbr
->bwArray
[ch
][i
] = COEF_CONST(0.0);
583 if (sbr
->bwArray
[ch
][i
] > COEF_CONST(0.99609375))
584 sbr
->bwArray
[ch
][i
] = COEF_CONST(0.99609375);
586 sbr
->bwArray_prev
[ch
][i
] = sbr
->bwArray
[ch
][i
];
587 sbr
->bs_invf_mode_prev
[ch
][i
] = sbr
->bs_invf_mode
[ch
][i
];
591 static void patch_construction(sbr_info
*sbr
)
595 uint8_t msb
= sbr
->k0
;
596 uint8_t usb
= sbr
->kx
;
597 uint8_t goalSbTab
[] = { 21, 23, 32, 43, 46, 64, 85, 93, 128, 0, 0, 0 };
598 /* (uint8_t)(2.048e6/sbr->sample_rate + 0.5); */
599 uint8_t goalSb
= goalSbTab
[get_sr_index(sbr
->sample_rate
)];
603 if (goalSb
< (sbr
->kx
+ sbr
->M
))
605 for (i
= 0, k
= 0; sbr
->f_master
[i
] < goalSb
; i
++)
611 if (sbr
->N_master
== 0)
614 sbr
->patchNoSubbands
[0] = 0;
615 sbr
->patchStartSubband
[0] = 0;
627 sb
= sbr
->f_master
[j
];
628 odd
= (sb
- 2 + sbr
->k0
) % 2;
630 } while (sb
> (sbr
->k0
- 1 + msb
- odd
));
632 sbr
->patchNoSubbands
[sbr
->noPatches
] = max(sb
- usb
, 0);
633 sbr
->patchStartSubband
[sbr
->noPatches
] = sbr
->k0
- odd
-
634 sbr
->patchNoSubbands
[sbr
->noPatches
];
636 if (sbr
->patchNoSubbands
[sbr
->noPatches
] > 0)
645 if (sbr
->f_master
[k
] - sb
< 3)
647 } while (sb
!= (sbr
->kx
+ sbr
->M
));
649 if ((sbr
->patchNoSubbands
[sbr
->noPatches
-1] < 3) && (sbr
->noPatches
> 1))
654 sbr
->noPatches
= min(sbr
->noPatches
, 5);