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.
25 ** $Id: sbr_hfgen.c,v 1.22 2004/09/08 09:43:11 gcp Exp $
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 /* improves accuracy */
229 for (j
= offset
; j
< len
+ offset
; j
++)
231 real_t buf_j
= ((QMF_RE(buffer
[j
][bd
])+(1<<(exp
-1)))>>exp
);
232 real_t buf_j_1
= ((QMF_RE(buffer
[j
-1][bd
])+(1<<(exp
-1)))>>exp
);
233 real_t buf_j_2
= ((QMF_RE(buffer
[j
-2][bd
])+(1<<(exp
-1)))>>exp
);
235 /* normalisation with rounding */
236 r01
+= MUL_R(buf_j
, buf_j_1
);
237 r02
+= MUL_R(buf_j
, buf_j_2
);
238 r11
+= MUL_R(buf_j_1
, buf_j_1
);
241 MUL_R(((QMF_RE(buffer
[len
+offset
-1][bd
])+(1<<(exp
-1)))>>exp
), ((QMF_RE(buffer
[len
+offset
-2][bd
])+(1<<(exp
-1)))>>exp
)) +
242 MUL_R(((QMF_RE(buffer
[offset
-1][bd
])+(1<<(exp
-1)))>>exp
), ((QMF_RE(buffer
[offset
-2][bd
])+(1<<(exp
-1)))>>exp
));
244 MUL_R(((QMF_RE(buffer
[len
+offset
-2][bd
])+(1<<(exp
-1)))>>exp
), ((QMF_RE(buffer
[len
+offset
-2][bd
])+(1<<(exp
-1)))>>exp
)) +
245 MUL_R(((QMF_RE(buffer
[offset
-2][bd
])+(1<<(exp
-1)))>>exp
), ((QMF_RE(buffer
[offset
-2][bd
])+(1<<(exp
-1)))>>exp
));
247 for (j
= offset
; j
< len
+ offset
; j
++)
249 r01
+= QMF_RE(buffer
[j
][bd
]) * QMF_RE(buffer
[j
-1][bd
]);
250 r02
+= QMF_RE(buffer
[j
][bd
]) * QMF_RE(buffer
[j
-2][bd
]);
251 r11
+= QMF_RE(buffer
[j
-1][bd
]) * QMF_RE(buffer
[j
-1][bd
]);
254 QMF_RE(buffer
[len
+offset
-1][bd
]) * QMF_RE(buffer
[len
+offset
-2][bd
]) +
255 QMF_RE(buffer
[offset
-1][bd
]) * QMF_RE(buffer
[offset
-2][bd
]);
257 QMF_RE(buffer
[len
+offset
-2][bd
]) * QMF_RE(buffer
[len
+offset
-2][bd
]) +
258 QMF_RE(buffer
[offset
-2][bd
]) * QMF_RE(buffer
[offset
-2][bd
]);
264 ac
->det
= MUL_R(RE(ac
->r11
), RE(ac
->r22
)) - MUL_F(MUL_R(RE(ac
->r12
), RE(ac
->r12
)), rel
);
267 static void auto_correlation(sbr_info
*sbr
, acorr_coef
*ac
, qmf_t buffer
[MAX_NTSRHFG
][64],
268 uint8_t bd
, uint8_t len
)
270 real_t r01r
= 0, r01i
= 0, r02r
= 0, r02i
= 0, r11r
= 0;
271 real_t temp1_r
, temp1_i
, temp2_r
, temp2_i
, temp3_r
, temp3_i
, temp4_r
, temp4_i
, temp5_r
, temp5_i
;
273 const real_t rel
= FRAC_CONST(0.999999); // 1 / (1 + 1e-6f);
277 const real_t rel
= 1 / (1 + 1e-6f
);
280 uint8_t offset
= sbr
->tHFAdj
;
285 for (j
= (offset
-2); j
< (len
+ offset
); j
++)
288 x
= QMF_RE(buffer
[j
][bd
])>>REAL_BITS
;
289 mask
|= x
^ (x
>> 31);
290 x
= QMF_IM(buffer
[j
][bd
])>>REAL_BITS
;
291 mask
|= x
^ (x
>> 31);
294 exp
= wl_min_lzc(mask
);
296 /* improves accuracy */
300 pow2_to_exp
= 1<<(exp
-1);
302 temp2_r
= (QMF_RE(buffer
[offset
-2][bd
]) + pow2_to_exp
) >> exp
;
303 temp2_i
= (QMF_IM(buffer
[offset
-2][bd
]) + pow2_to_exp
) >> exp
;
304 temp3_r
= (QMF_RE(buffer
[offset
-1][bd
]) + pow2_to_exp
) >> exp
;
305 temp3_i
= (QMF_IM(buffer
[offset
-1][bd
]) + pow2_to_exp
) >> exp
;
306 // Save these because they are needed after loop
312 for (j
= offset
; j
< len
+ offset
; j
++)
314 temp1_r
= temp2_r
; // temp1_r = (QMF_RE(buffer[offset-2][bd] + (1<<(exp-1))) >> exp;
315 temp1_i
= temp2_i
; // temp1_i = (QMF_IM(buffer[offset-2][bd] + (1<<(exp-1))) >> exp;
316 temp2_r
= temp3_r
; // temp2_r = (QMF_RE(buffer[offset-1][bd] + (1<<(exp-1))) >> exp;
317 temp2_i
= temp3_i
; // temp2_i = (QMF_IM(buffer[offset-1][bd] + (1<<(exp-1))) >> exp;
318 temp3_r
= (QMF_RE(buffer
[j
][bd
]) + pow2_to_exp
) >> exp
;
319 temp3_i
= (QMF_IM(buffer
[j
][bd
]) + pow2_to_exp
) >> exp
;
320 r01r
+= MUL_R(temp3_r
, temp2_r
) + MUL_R(temp3_i
, temp2_i
);
321 r01i
+= MUL_R(temp3_i
, temp2_r
) - MUL_R(temp3_r
, temp2_i
);
322 r02r
+= MUL_R(temp3_r
, temp1_r
) + MUL_R(temp3_i
, temp1_i
);
323 r02i
+= MUL_R(temp3_i
, temp1_r
) - MUL_R(temp3_r
, temp1_i
);
324 r11r
+= MUL_R(temp2_r
, temp2_r
) + MUL_R(temp2_i
, temp2_i
);
327 // These are actual values in temporary variable at this point
328 // temp1_r = (QMF_RE(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp;
329 // temp1_i = (QMF_IM(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp;
330 // temp2_r = (QMF_RE(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp;
331 // temp2_i = (QMF_IM(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp;
332 // temp3_r = (QMF_RE(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp;
333 // temp3_i = (QMF_IM(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp;
334 // temp4_r = (QMF_RE(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp;
335 // temp4_i = (QMF_IM(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp;
336 // temp5_r = (QMF_RE(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp;
337 // temp5_i = (QMF_IM(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp;
340 (MUL_R(temp3_r
, temp2_r
) + MUL_R(temp3_i
, temp2_i
)) +
341 (MUL_R(temp5_r
, temp4_r
) + MUL_R(temp5_i
, temp4_i
));
343 (MUL_R(temp3_i
, temp2_r
) - MUL_R(temp3_r
, temp2_i
)) +
344 (MUL_R(temp5_i
, temp4_r
) - MUL_R(temp5_r
, temp4_i
));
346 (MUL_R(temp2_r
, temp2_r
) + MUL_R(temp2_i
, temp2_i
)) +
347 (MUL_R(temp4_r
, temp4_r
) + MUL_R(temp4_i
, temp4_i
));
351 temp2_r
= QMF_RE(buffer
[offset
-2][bd
]);
352 temp2_i
= QMF_IM(buffer
[offset
-2][bd
]);
353 temp3_r
= QMF_RE(buffer
[offset
-1][bd
]);
354 temp3_i
= QMF_IM(buffer
[offset
-1][bd
]);
355 // Save these because they are needed after loop
361 for (j
= offset
; j
< len
+ offset
; j
++)
363 temp1_r
= temp2_r
; // temp1_r = QMF_RE(buffer[j-2][bd];
364 temp1_i
= temp2_i
; // temp1_i = QMF_IM(buffer[j-2][bd];
365 temp2_r
= temp3_r
; // temp2_r = QMF_RE(buffer[j-1][bd];
366 temp2_i
= temp3_i
; // temp2_i = QMF_IM(buffer[j-1][bd];
367 temp3_r
= QMF_RE(buffer
[j
][bd
]);
368 temp3_i
= QMF_IM(buffer
[j
][bd
]);
369 r01r
+= temp3_r
* temp2_r
+ temp3_i
* temp2_i
;
370 r01i
+= temp3_i
* temp2_r
- temp3_r
* temp2_i
;
371 r02r
+= temp3_r
* temp1_r
+ temp3_i
* temp1_i
;
372 r02i
+= temp3_i
* temp1_r
- temp3_r
* temp1_i
;
373 r11r
+= temp2_r
* temp2_r
+ temp2_i
* temp2_i
;
376 // These are actual values in temporary variable at this point
377 // temp1_r = QMF_RE(buffer[len+offset-1-2][bd];
378 // temp1_i = QMF_IM(buffer[len+offset-1-2][bd];
379 // temp2_r = QMF_RE(buffer[len+offset-1-1][bd];
380 // temp2_i = QMF_IM(buffer[len+offset-1-1][bd];
381 // temp3_r = QMF_RE(buffer[len+offset-1][bd]);
382 // temp3_i = QMF_IM(buffer[len+offset-1][bd]);
383 // temp4_r = QMF_RE(buffer[offset-2][bd]);
384 // temp4_i = QMF_IM(buffer[offset-2][bd]);
385 // temp5_r = QMF_RE(buffer[offset-1][bd]);
386 // temp5_i = QMF_IM(buffer[offset-1][bd]);
389 (temp3_r
* temp2_r
+ temp3_i
* temp2_i
) +
390 (temp5_r
* temp4_r
+ temp5_i
* temp4_i
);
392 (temp3_i
* temp2_r
- temp3_r
* temp2_i
) +
393 (temp5_i
* temp4_r
- temp5_r
* temp4_i
);
395 (temp2_r
* temp2_r
+ temp2_i
* temp2_i
) +
396 (temp4_r
* temp4_r
+ temp4_i
* temp4_i
);
406 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
))));
410 /* calculate linear prediction coefficients using the covariance method */
411 #ifndef SBR_LOW_POWER
412 static void calc_prediction_coef(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][64],
413 complex_t
*alpha_0
, complex_t
*alpha_1
, uint8_t k
)
418 auto_correlation(sbr
, &ac
, Xlow
, k
, sbr
->numTimeSlotsRate
+ 6);
426 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
)));
427 RE(alpha_1
[k
]) = DIV_R(tmp
, ac
.det
);
428 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
)));
429 IM(alpha_1
[k
]) = DIV_R(tmp
, ac
.det
);
431 tmp
= REAL_CONST(1.0) / ac
.det
;
432 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
;
433 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
;
443 tmp
= -(RE(ac
.r01
) + MUL_R(RE(alpha_1
[k
]), RE(ac
.r12
)) + MUL_R(IM(alpha_1
[k
]), IM(ac
.r12
)));
444 RE(alpha_0
[k
]) = DIV_R(tmp
, RE(ac
.r11
));
445 tmp
= -(IM(ac
.r01
) + MUL_R(IM(alpha_1
[k
]), RE(ac
.r12
)) - MUL_R(RE(alpha_1
[k
]), IM(ac
.r12
)));
446 IM(alpha_0
[k
]) = DIV_R(tmp
, RE(ac
.r11
));
448 tmp
= 1.0f
/ RE(ac
.r11
);
449 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
;
450 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
;
454 if ((MUL_R(RE(alpha_0
[k
]),RE(alpha_0
[k
])) + MUL_R(IM(alpha_0
[k
]),IM(alpha_0
[k
])) >= REAL_CONST(16)) ||
455 (MUL_R(RE(alpha_1
[k
]),RE(alpha_1
[k
])) + MUL_R(IM(alpha_1
[k
]),IM(alpha_1
[k
])) >= REAL_CONST(16)))
464 static void calc_prediction_coef_lp(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][64],
465 complex_t
*alpha_0
, complex_t
*alpha_1
, real_t
*rxx
)
471 for (k
= 1; k
< sbr
->f_master
[0]; k
++)
473 auto_correlation(sbr
, &ac
, Xlow
, k
, sbr
->numTimeSlotsRate
+ 6);
480 tmp
= MUL_R(RE(ac
.r01
), RE(ac
.r22
)) - MUL_R(RE(ac
.r12
), RE(ac
.r02
));
481 RE(alpha_0
[k
]) = DIV_R(tmp
, (-ac
.det
));
483 tmp
= MUL_R(RE(ac
.r01
), RE(ac
.r12
)) - MUL_R(RE(ac
.r02
), RE(ac
.r11
));
484 RE(alpha_1
[k
]) = DIV_R(tmp
, ac
.det
);
487 if ((RE(alpha_0
[k
]) >= REAL_CONST(4)) || (RE(alpha_1
[k
]) >= REAL_CONST(4)))
489 RE(alpha_0
[k
]) = REAL_CONST(0);
490 RE(alpha_1
[k
]) = REAL_CONST(0);
493 /* reflection coefficient */
496 rxx
[k
] = COEF_CONST(0.0);
498 rxx
[k
] = DIV_C(RE(ac
.r01
), RE(ac
.r11
));
500 if (rxx
[k
] > COEF_CONST(1.0)) rxx
[k
] = COEF_CONST(1.0);
501 if (rxx
[k
] < COEF_CONST(-1.0)) rxx
[k
] = COEF_CONST(-1.0);
506 static void calc_aliasing_degree(sbr_info
*sbr
, real_t
*rxx
, real_t
*deg
)
510 rxx
[0] = COEF_CONST(0.0);
511 deg
[1] = COEF_CONST(0.0);
513 for (k
= 2; k
< sbr
->k0
; k
++)
517 if ((k
% 2 == 0) && (rxx
[k
] < COEF_CONST(0.0)))
521 deg
[k
] = COEF_CONST(1.0);
523 if (rxx
[k
-2] > COEF_CONST(0.0))
525 deg
[k
-1] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
527 } else if (rxx
[k
-2] > COEF_CONST(0.0)) {
528 deg
[k
] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
532 if ((k
% 2 == 1) && (rxx
[k
] > COEF_CONST(0.0)))
534 if (rxx
[k
-1] > COEF_CONST(0.0))
536 deg
[k
] = COEF_CONST(1.0);
538 if (rxx
[k
-2] < COEF_CONST(0.0))
540 deg
[k
-1] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
542 } else if (rxx
[k
-2] < COEF_CONST(0.0)) {
543 deg
[k
] = COEF_CONST(1.0) - MUL_C(rxx
[k
-1], rxx
[k
-1]);
550 /* FIXED POINT: bwArray = COEF */
551 static real_t
mapNewBw(uint8_t invf_mode
, uint8_t invf_mode_prev
)
556 if (invf_mode_prev
== 0) /* NONE */
557 return COEF_CONST(0.6);
559 return COEF_CONST(0.75);
562 return COEF_CONST(0.9);
565 return COEF_CONST(0.98);
568 if (invf_mode_prev
== 1) /* LOW */
569 return COEF_CONST(0.6);
571 return COEF_CONST(0.0);
575 /* FIXED POINT: bwArray = COEF */
576 static void calc_chirp_factors(sbr_info
*sbr
, uint8_t ch
)
580 for (i
= 0; i
< sbr
->N_Q
; i
++)
582 sbr
->bwArray
[ch
][i
] = mapNewBw(sbr
->bs_invf_mode
[ch
][i
], sbr
->bs_invf_mode_prev
[ch
][i
]);
584 if (sbr
->bwArray
[ch
][i
] < sbr
->bwArray_prev
[ch
][i
])
585 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));
587 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));
589 if (sbr
->bwArray
[ch
][i
] < COEF_CONST(0.015625))
590 sbr
->bwArray
[ch
][i
] = COEF_CONST(0.0);
592 if (sbr
->bwArray
[ch
][i
] >= COEF_CONST(0.99609375))
593 sbr
->bwArray
[ch
][i
] = COEF_CONST(0.99609375);
595 sbr
->bwArray_prev
[ch
][i
] = sbr
->bwArray
[ch
][i
];
596 sbr
->bs_invf_mode_prev
[ch
][i
] = sbr
->bs_invf_mode
[ch
][i
];
600 static void patch_construction(sbr_info
*sbr
)
604 uint8_t msb
= sbr
->k0
;
605 uint8_t usb
= sbr
->kx
;
606 uint8_t goalSbTab
[] = { 21, 23, 32, 43, 46, 64, 85, 93, 128, 0, 0, 0 };
607 /* (uint8_t)(2.048e6/sbr->sample_rate + 0.5); */
608 uint8_t goalSb
= goalSbTab
[get_sr_index(sbr
->sample_rate
)];
612 if (goalSb
< (sbr
->kx
+ sbr
->M
))
614 for (i
= 0, k
= 0; sbr
->f_master
[i
] < goalSb
; i
++)
620 if (sbr
->N_master
== 0)
623 sbr
->patchNoSubbands
[0] = 0;
624 sbr
->patchStartSubband
[0] = 0;
637 sb
= sbr
->f_master
[j
];
638 odd
= (sb
- 2 + sbr
->k0
) % 2;
639 } while (sb
> (sbr
->k0
- 1 + msb
- odd
));
641 sbr
->patchNoSubbands
[sbr
->noPatches
] = max(sb
- usb
, 0);
642 sbr
->patchStartSubband
[sbr
->noPatches
] = sbr
->k0
- odd
-
643 sbr
->patchNoSubbands
[sbr
->noPatches
];
645 if (sbr
->patchNoSubbands
[sbr
->noPatches
] > 0)
654 if (sbr
->f_master
[k
] - sb
< 3)
656 } while (sb
!= (sbr
->kx
+ sbr
->M
));
658 if ((sbr
->patchNoSubbands
[sbr
->noPatches
-1] < 3) && (sbr
->noPatches
> 1))
663 sbr
->noPatches
= min(sbr
->noPatches
, 5);