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_hfadj.c,v 1.18 2004/09/04 14:56:28 menno Exp $
28 /* High Frequency adjustment */
35 #include "sbr_syntax.h"
36 #include "sbr_hfadj.h"
38 #include "sbr_noise.h"
41 /* static function declarations */
42 static void estimate_current_envelope(sbr_info
*sbr
, sbr_hfadj_info
*adj
,
43 qmf_t Xsbr
[MAX_NTSRHFG
][64], uint8_t ch
);
44 static void calculate_gain(sbr_info
*sbr
, sbr_hfadj_info
*adj
, uint8_t ch
);
46 static void calc_gain_groups(sbr_info
*sbr
, sbr_hfadj_info
*adj
, real_t
*deg
, uint8_t ch
);
47 static void aliasing_reduction(sbr_info
*sbr
, sbr_hfadj_info
*adj
, real_t
*deg
, uint8_t ch
);
49 static void hf_assembly(sbr_info
*sbr
, sbr_hfadj_info
*adj
, qmf_t Xsbr
[MAX_NTSRHFG
][64], uint8_t ch
);
52 void hf_adjustment(sbr_info
*sbr
, qmf_t Xsbr
[MAX_NTSRHFG
][64]
54 ,real_t
*deg
/* aliasing degree */
58 ALIGN sbr_hfadj_info adj
= {{{0}}};
60 if (sbr
->bs_frame_class
[ch
] == FIXFIX
)
63 } else if (sbr
->bs_frame_class
[ch
] == VARFIX
) {
64 if (sbr
->bs_pointer
[ch
] > 1)
67 sbr
->l_A
[ch
] = sbr
->bs_pointer
[ch
] - 1;
69 if (sbr
->bs_pointer
[ch
] == 0)
72 sbr
->l_A
[ch
] = sbr
->L_E
[ch
] + 1 - sbr
->bs_pointer
[ch
];
75 estimate_current_envelope(sbr
, &adj
, Xsbr
, ch
);
77 calculate_gain(sbr
, &adj
, ch
);
80 calc_gain_groups(sbr
, &adj
, deg
, ch
);
81 aliasing_reduction(sbr
, &adj
, deg
, ch
);
84 hf_assembly(sbr
, &adj
, Xsbr
, ch
);
87 static uint8_t get_S_mapped(sbr_info
*sbr
, uint8_t ch
, uint8_t l
, uint8_t current_band
)
89 if (sbr
->f
[ch
][l
] == HI_RES
)
91 /* in case of using f_table_high we just have 1 to 1 mapping
92 * from bs_add_harmonic[l][k]
94 if ((l
>= sbr
->l_A
[ch
]) ||
95 (sbr
->bs_add_harmonic_prev
[ch
][current_band
] && sbr
->bs_add_harmonic_flag_prev
[ch
]))
97 return sbr
->bs_add_harmonic
[ch
][current_band
];
102 /* in case of f_table_low we check if any of the HI_RES bands
103 * within this LO_RES band has bs_add_harmonic[l][k] turned on
104 * (note that borders in the LO_RES table are also present in
108 /* find first HI_RES band in current LO_RES band */
109 lb
= 2*current_band
- ((sbr
->N_high
& 1) ? 1 : 0);
110 /* find first HI_RES band in next LO_RES band */
111 ub
= 2*(current_band
+1) - ((sbr
->N_high
& 1) ? 1 : 0);
113 /* check all HI_RES bands in current LO_RES band for sinusoid */
114 for (b
= lb
; b
< ub
; b
++)
116 if ((l
>= sbr
->l_A
[ch
]) ||
117 (sbr
->bs_add_harmonic_prev
[ch
][b
] && sbr
->bs_add_harmonic_flag_prev
[ch
]))
119 if (sbr
->bs_add_harmonic
[ch
][b
] == 1)
128 static void estimate_current_envelope(sbr_info
*sbr
, sbr_hfadj_info
*adj
,
129 qmf_t Xsbr
[MAX_NTSRHFG
][64], uint8_t ch
)
131 uint8_t m
, l
, j
, k
, k_l
, k_h
, p
;
134 if (sbr
->bs_interpol_freq
== 1)
136 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
140 l_i
= sbr
->t_E
[ch
][l
];
141 u_i
= sbr
->t_E
[ch
][l
+1];
143 div
= (real_t
)(u_i
- l_i
);
145 for (m
= 0; m
< sbr
->M
; m
++)
149 for (i
= l_i
+ sbr
->tHFAdj
; i
< u_i
+ sbr
->tHFAdj
; i
++)
153 nrg
+= ((QMF_RE(Xsbr
[i
][m
+ sbr
->kx
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
)*((QMF_RE(Xsbr
[i
][m
+ sbr
->kx
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
);
155 nrg
+= ((QMF_RE(Xsbr
[i
][m
+ sbr
->kx
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
)*((QMF_RE(Xsbr
[i
][m
+ sbr
->kx
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
) +
156 ((QMF_IM(Xsbr
[i
][m
+ sbr
->kx
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
)*((QMF_IM(Xsbr
[i
][m
+ sbr
->kx
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
);
159 nrg
+= MUL_R(QMF_RE(Xsbr
[i
][m
+ sbr
->kx
]), QMF_RE(Xsbr
[i
][m
+ sbr
->kx
]))
160 #ifndef SBR_LOW_POWER
161 + MUL_R(QMF_IM(Xsbr
[i
][m
+ sbr
->kx
]), QMF_IM(Xsbr
[i
][m
+ sbr
->kx
]))
167 sbr
->E_curr
[ch
][m
][l
] = nrg
/ div
;
170 sbr
->E_curr
[ch
][m
][l
] <<= 1;
172 sbr
->E_curr
[ch
][m
][l
] *= 2;
178 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
180 for (p
= 0; p
< sbr
->n
[sbr
->f
[ch
][l
]]; p
++)
182 k_l
= sbr
->f_table_res
[sbr
->f
[ch
][l
]][p
];
183 k_h
= sbr
->f_table_res
[sbr
->f
[ch
][l
]][p
+1];
185 for (k
= k_l
; k
< k_h
; k
++)
190 l_i
= sbr
->t_E
[ch
][l
];
191 u_i
= sbr
->t_E
[ch
][l
+1];
193 div
= (real_t
)((u_i
- l_i
)*(k_h
- k_l
));
195 for (i
= l_i
+ sbr
->tHFAdj
; i
< u_i
+ sbr
->tHFAdj
; i
++)
197 for (j
= k_l
; j
< k_h
; j
++)
201 nrg
+= ((QMF_RE(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
)*((QMF_RE(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
);
203 nrg
+= ((QMF_RE(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
)*((QMF_RE(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
) +
204 ((QMF_IM(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
)*((QMF_IM(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
);
207 nrg
+= MUL_R(QMF_RE(Xsbr
[i
][j
]), QMF_RE(Xsbr
[i
][j
]))
208 #ifndef SBR_LOW_POWER
209 + MUL_R(QMF_IM(Xsbr
[i
][j
]), QMF_IM(Xsbr
[i
][j
]))
216 sbr
->E_curr
[ch
][k
- sbr
->kx
][l
] = nrg
/ div
;
219 sbr
->E_curr
[ch
][k
- sbr
->kx
][l
] <<= 1;
221 sbr
->E_curr
[ch
][k
- sbr
->kx
][l
] *= 2;
231 #define EPS (1) /* smallest number available in fixed point */
240 /* log2 values of [0..63] */
241 static const real_t log2_int_tab
[] = {
242 LOG2_MIN_INF
, REAL_CONST(0.000000000000000), REAL_CONST(1.000000000000000), REAL_CONST(1.584962500721156),
243 REAL_CONST(2.000000000000000), REAL_CONST(2.321928094887362), REAL_CONST(2.584962500721156), REAL_CONST(2.807354922057604),
244 REAL_CONST(3.000000000000000), REAL_CONST(3.169925001442313), REAL_CONST(3.321928094887363), REAL_CONST(3.459431618637297),
245 REAL_CONST(3.584962500721156), REAL_CONST(3.700439718141092), REAL_CONST(3.807354922057604), REAL_CONST(3.906890595608519),
246 REAL_CONST(4.000000000000000), REAL_CONST(4.087462841250339), REAL_CONST(4.169925001442312), REAL_CONST(4.247927513443585),
247 REAL_CONST(4.321928094887362), REAL_CONST(4.392317422778761), REAL_CONST(4.459431618637297), REAL_CONST(4.523561956057013),
248 REAL_CONST(4.584962500721156), REAL_CONST(4.643856189774724), REAL_CONST(4.700439718141093), REAL_CONST(4.754887502163468),
249 REAL_CONST(4.807354922057604), REAL_CONST(4.857980995127572), REAL_CONST(4.906890595608519), REAL_CONST(4.954196310386875),
250 REAL_CONST(5.000000000000000), REAL_CONST(5.044394119358453), REAL_CONST(5.087462841250340), REAL_CONST(5.129283016944966),
251 REAL_CONST(5.169925001442312), REAL_CONST(5.209453365628949), REAL_CONST(5.247927513443585), REAL_CONST(5.285402218862248),
252 REAL_CONST(5.321928094887363), REAL_CONST(5.357552004618084), REAL_CONST(5.392317422778761), REAL_CONST(5.426264754702098),
253 REAL_CONST(5.459431618637297), REAL_CONST(5.491853096329675), REAL_CONST(5.523561956057013), REAL_CONST(5.554588851677637),
254 REAL_CONST(5.584962500721156), REAL_CONST(5.614709844115208), REAL_CONST(5.643856189774724), REAL_CONST(5.672425341971495),
255 REAL_CONST(5.700439718141093), REAL_CONST(5.727920454563200), REAL_CONST(5.754887502163469), REAL_CONST(5.781359713524660),
256 REAL_CONST(5.807354922057605), REAL_CONST(5.832890014164742), REAL_CONST(5.857980995127572), REAL_CONST(5.882643049361842),
257 REAL_CONST(5.906890595608518), REAL_CONST(5.930737337562887), REAL_CONST(5.954196310386876), REAL_CONST(5.977279923499916)
260 static const real_t pan_log2_tab
[] = {
261 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362), REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339),
262 REAL_CONST(0.044394119358453), REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878), REAL_CONST(0.002815015607054),
263 REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247), REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
264 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667)
267 static real_t
find_log2_E(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
269 /* check for coupled energy/noise data */
270 if (sbr
->bs_coupling
== 1)
272 uint8_t amp0
= (sbr
->amp_res
[0]) ? 0 : 1;
273 uint8_t amp1
= (sbr
->amp_res
[1]) ? 0 : 1;
274 real_t tmp
= (7 << REAL_BITS
) + (sbr
->E
[0][k
][l
] << (REAL_BITS
-amp0
));
277 /* E[1] should always be even so shifting is OK */
278 uint8_t E
= sbr
->E
[1][k
][l
] >> amp1
;
285 pan
= pan_log2_tab
[-12 + E
];
288 pan
= pan_log2_tab
[12 - E
] + ((12 - E
)<<REAL_BITS
);
294 pan
= pan_log2_tab
[-E
+ 12];
297 pan
= pan_log2_tab
[E
- 12] + ((E
- 12)<<REAL_BITS
);
301 /* tmp / pan in log2 */
304 uint8_t amp
= (sbr
->amp_res
[ch
]) ? 0 : 1;
306 return (6 << REAL_BITS
) + (sbr
->E
[ch
][k
][l
] << (REAL_BITS
-amp
));
310 static real_t
find_log2_Q(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
312 /* check for coupled energy/noise data */
313 if (sbr
->bs_coupling
== 1)
315 real_t tmp
= (7 << REAL_BITS
) - (sbr
->Q
[0][k
][l
] << REAL_BITS
);
318 uint8_t Q
= sbr
->Q
[1][k
][l
];
325 pan
= pan_log2_tab
[-12 + Q
];
328 pan
= pan_log2_tab
[12 - Q
] + ((12 - Q
)<<REAL_BITS
);
334 pan
= pan_log2_tab
[-Q
+ 12];
337 pan
= pan_log2_tab
[Q
- 12] + ((Q
- 12)<<REAL_BITS
);
341 /* tmp / pan in log2 */
344 return (6 << REAL_BITS
) - (sbr
->Q
[ch
][k
][l
] << REAL_BITS
);
348 static const real_t log_Qplus1_pan
[31][13] = {
349 { REAL_CONST(0.044383447617292), REAL_CONST(0.169768601655960), REAL_CONST(0.583090126514435), REAL_CONST(1.570089221000671), REAL_CONST(3.092446088790894), REAL_CONST(4.733354568481445), REAL_CONST(6.022367954254150), REAL_CONST(6.692092418670654), REAL_CONST(6.924463272094727), REAL_CONST(6.989034175872803), REAL_CONST(7.005646705627441), REAL_CONST(7.009829998016357), REAL_CONST(7.010877609252930) },
350 { REAL_CONST(0.022362394258380), REAL_CONST(0.087379962205887), REAL_CONST(0.320804953575134), REAL_CONST(0.988859415054321), REAL_CONST(2.252387046813965), REAL_CONST(3.786596298217773), REAL_CONST(5.044394016265869), REAL_CONST(5.705977916717529), REAL_CONST(5.936291694641113), REAL_CONST(6.000346660614014), REAL_CONST(6.016829967498779), REAL_CONST(6.020981311798096), REAL_CONST(6.022020816802979) },
351 { REAL_CONST(0.011224525049329), REAL_CONST(0.044351425021887), REAL_CONST(0.169301137328148), REAL_CONST(0.577544987201691), REAL_CONST(1.527246952056885), REAL_CONST(2.887525320053101), REAL_CONST(4.087462902069092), REAL_CONST(4.733354568481445), REAL_CONST(4.959661006927490), REAL_CONST(5.022709369659424), REAL_CONST(5.038940429687500), REAL_CONST(5.043028831481934), REAL_CONST(5.044052600860596) },
352 { REAL_CONST(0.005623178556561), REAL_CONST(0.022346137091517), REAL_CONST(0.087132595479488), REAL_CONST(0.317482173442841), REAL_CONST(0.956931233406067), REAL_CONST(2.070389270782471), REAL_CONST(3.169924974441528), REAL_CONST(3.786596298217773), REAL_CONST(4.005294322967529), REAL_CONST(4.066420555114746), REAL_CONST(4.082170009613037), REAL_CONST(4.086137294769287), REAL_CONST(4.087131500244141) },
353 { REAL_CONST(0.002814328996465), REAL_CONST(0.011216334067285), REAL_CONST(0.044224001467228), REAL_CONST(0.167456731200218), REAL_CONST(0.556393325328827), REAL_CONST(1.378511548042297), REAL_CONST(2.321928024291992), REAL_CONST(2.887525320053101), REAL_CONST(3.092446088790894), REAL_CONST(3.150059700012207), REAL_CONST(3.164926528930664), REAL_CONST(3.168673276901245), REAL_CONST(3.169611930847168) },
354 { REAL_CONST(0.001407850766554), REAL_CONST(0.005619067233056), REAL_CONST(0.022281449288130), REAL_CONST(0.086156636476517), REAL_CONST(0.304854571819305), REAL_CONST(0.847996890544891), REAL_CONST(1.584962487220764), REAL_CONST(2.070389270782471), REAL_CONST(2.252387046813965), REAL_CONST(2.304061651229858), REAL_CONST(2.317430257797241), REAL_CONST(2.320801734924316), REAL_CONST(2.321646213531494) },
355 { REAL_CONST(0.000704097095877), REAL_CONST(0.002812269143760), REAL_CONST(0.011183738708496), REAL_CONST(0.043721374124289), REAL_CONST(0.160464659333229), REAL_CONST(0.485426813364029), REAL_CONST(1.000000000000000), REAL_CONST(1.378511548042297), REAL_CONST(1.527246952056885), REAL_CONST(1.570089221000671), REAL_CONST(1.581215262413025), REAL_CONST(1.584023833274841), REAL_CONST(1.584727644920349) },
356 { REAL_CONST(0.000352177477907), REAL_CONST(0.001406819908880), REAL_CONST(0.005602621007711), REAL_CONST(0.022026389837265), REAL_CONST(0.082462236285210), REAL_CONST(0.263034462928772), REAL_CONST(0.584962487220764), REAL_CONST(0.847996890544891), REAL_CONST(0.956931233406067), REAL_CONST(0.988859415054321), REAL_CONST(0.997190535068512), REAL_CONST(0.999296069145203), REAL_CONST(0.999823868274689) },
357 { REAL_CONST(0.000176099492819), REAL_CONST(0.000703581434209), REAL_CONST(0.002804030198604), REAL_CONST(0.011055230163038), REAL_CONST(0.041820213198662), REAL_CONST(0.137503549456596), REAL_CONST(0.321928083896637), REAL_CONST(0.485426813364029), REAL_CONST(0.556393325328827), REAL_CONST(0.577544987201691), REAL_CONST(0.583090126514435), REAL_CONST(0.584493279457092), REAL_CONST(0.584845066070557) },
358 { REAL_CONST(0.000088052431238), REAL_CONST(0.000351833587047), REAL_CONST(0.001402696361765), REAL_CONST(0.005538204684854), REAL_CONST(0.021061634644866), REAL_CONST(0.070389263331890), REAL_CONST(0.169925004243851), REAL_CONST(0.263034462928772), REAL_CONST(0.304854571819305), REAL_CONST(0.317482173442841), REAL_CONST(0.320804953575134), REAL_CONST(0.321646571159363), REAL_CONST(0.321857661008835) },
359 { REAL_CONST(0.000044026888645), REAL_CONST(0.000175927518285), REAL_CONST(0.000701518612914), REAL_CONST(0.002771759871393), REAL_CONST(0.010569252073765), REAL_CONST(0.035623874515295), REAL_CONST(0.087462842464447), REAL_CONST(0.137503549456596), REAL_CONST(0.160464659333229), REAL_CONST(0.167456731200218), REAL_CONST(0.169301137328148), REAL_CONST(0.169768601655960), REAL_CONST(0.169885858893394) },
360 { REAL_CONST(0.000022013611670), REAL_CONST(0.000088052431238), REAL_CONST(0.000350801943569), REAL_CONST(0.001386545598507), REAL_CONST(0.005294219125062), REAL_CONST(0.017921976745129), REAL_CONST(0.044394120573997), REAL_CONST(0.070389263331890), REAL_CONST(0.082462236285210), REAL_CONST(0.086156636476517), REAL_CONST(0.087132595479488), REAL_CONST(0.087379962205887), REAL_CONST(0.087442122399807) },
361 { REAL_CONST(0.000011006847672), REAL_CONST(0.000044026888645), REAL_CONST(0.000175411638338), REAL_CONST(0.000693439331371), REAL_CONST(0.002649537986144), REAL_CONST(0.008988817222416), REAL_CONST(0.022367812693119), REAL_CONST(0.035623874515295), REAL_CONST(0.041820213198662), REAL_CONST(0.043721374124289), REAL_CONST(0.044224001467228), REAL_CONST(0.044351425021887), REAL_CONST(0.044383447617292) },
362 { REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000087708482170), REAL_CONST(0.000346675369656), REAL_CONST(0.001325377263129), REAL_CONST(0.004501323681325), REAL_CONST(0.011227255687118), REAL_CONST(0.017921976745129), REAL_CONST(0.021061634644866), REAL_CONST(0.022026389837265), REAL_CONST(0.022281449288130), REAL_CONST(0.022346137091517), REAL_CONST(0.022362394258380) },
363 { REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043854910473), REAL_CONST(0.000173348103999), REAL_CONST(0.000662840844598), REAL_CONST(0.002252417383716), REAL_CONST(0.005624548997730), REAL_CONST(0.008988817222416), REAL_CONST(0.010569252073765), REAL_CONST(0.011055230163038), REAL_CONST(0.011183738708496), REAL_CONST(0.011216334067285), REAL_CONST(0.011224525049329) },
364 { REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000086676649516), REAL_CONST(0.000331544462824), REAL_CONST(0.001126734190620), REAL_CONST(0.002815015614033), REAL_CONST(0.004501323681325), REAL_CONST(0.005294219125062), REAL_CONST(0.005538204684854), REAL_CONST(0.005602621007711), REAL_CONST(0.005619067233056), REAL_CONST(0.005623178556561) },
365 { REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043338975956), REAL_CONST(0.000165781748365), REAL_CONST(0.000563477107789), REAL_CONST(0.001408194424585), REAL_CONST(0.002252417383716), REAL_CONST(0.002649537986144), REAL_CONST(0.002771759871393), REAL_CONST(0.002804030198604), REAL_CONST(0.002812269143760), REAL_CONST(0.002814328996465) },
366 { REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000021669651687), REAL_CONST(0.000082893253420), REAL_CONST(0.000281680084299), REAL_CONST(0.000704268983100), REAL_CONST(0.001126734190620), REAL_CONST(0.001325377263129), REAL_CONST(0.001386545598507), REAL_CONST(0.001402696361765), REAL_CONST(0.001406819908880), REAL_CONST(0.001407850766554) },
367 { REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010834866771), REAL_CONST(0.000041447223339), REAL_CONST(0.000140846910654), REAL_CONST(0.000352177477907), REAL_CONST(0.000563477107789), REAL_CONST(0.000662840844598), REAL_CONST(0.000693439331371), REAL_CONST(0.000701518612914), REAL_CONST(0.000703581434209), REAL_CONST(0.000704097095877) },
368 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000020637769921), REAL_CONST(0.000070511166996), REAL_CONST(0.000176099492819), REAL_CONST(0.000281680084299), REAL_CONST(0.000331544462824), REAL_CONST(0.000346675369656), REAL_CONST(0.000350801943569), REAL_CONST(0.000351833587047), REAL_CONST(0.000352177477907) },
369 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010318922250), REAL_CONST(0.000035256012779), REAL_CONST(0.000088052431238), REAL_CONST(0.000140846910654), REAL_CONST(0.000165781748365), REAL_CONST(0.000173348103999), REAL_CONST(0.000175411638338), REAL_CONST(0.000175927518285), REAL_CONST(0.000176099492819) },
370 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005159470220), REAL_CONST(0.000017542124624), REAL_CONST(0.000044026888645), REAL_CONST(0.000070511166996), REAL_CONST(0.000082893253420), REAL_CONST(0.000086676649516), REAL_CONST(0.000087708482170), REAL_CONST(0.000088052431238), REAL_CONST(0.000088052431238) },
371 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002579737384), REAL_CONST(0.000008771088687), REAL_CONST(0.000022013611670), REAL_CONST(0.000035256012779), REAL_CONST(0.000041447223339), REAL_CONST(0.000043338975956), REAL_CONST(0.000043854910473), REAL_CONST(0.000044026888645), REAL_CONST(0.000044026888645) },
372 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000004471542070), REAL_CONST(0.000011006847672), REAL_CONST(0.000017542124624), REAL_CONST(0.000020637769921), REAL_CONST(0.000021669651687), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670) },
373 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002235772627), REAL_CONST(0.000005503434295), REAL_CONST(0.000008771088687), REAL_CONST(0.000010318922250), REAL_CONST(0.000010834866771), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672) },
374 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001031895522), REAL_CONST(0.000002751719876), REAL_CONST(0.000004471542070), REAL_CONST(0.000005159470220), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295) },
375 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000515947875), REAL_CONST(0.000001375860506), REAL_CONST(0.000002235772627), REAL_CONST(0.000002579737384), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876) },
376 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000000687930424), REAL_CONST(0.000001031895522), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506) },
377 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000515947875), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424) },
378 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269) },
379 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634) }
382 static const real_t log_Qplus1
[31] = {
383 REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339),
384 REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156),
385 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362),
386 REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453),
387 REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878),
388 REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247),
389 REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
390 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667),
391 REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551),
392 REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641),
393 REAL_CONST(0.000000000000000)
396 static real_t
find_log2_Qplus1(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
398 /* check for coupled energy/noise data */
399 if (sbr
->bs_coupling
== 1)
401 if ((sbr
->Q
[0][k
][l
] >= 0) && (sbr
->Q
[0][k
][l
] <= 30) &&
402 (sbr
->Q
[1][k
][l
] >= 0) && (sbr
->Q
[1][k
][l
] <= 24))
406 return log_Qplus1_pan
[sbr
->Q
[0][k
][l
]][sbr
->Q
[1][k
][l
] >> 1];
408 return log_Qplus1_pan
[sbr
->Q
[0][k
][l
]][12 - (sbr
->Q
[1][k
][l
] >> 1)];
414 if (sbr
->Q
[ch
][k
][l
] >= 0 && sbr
->Q
[ch
][k
][l
] <= 30)
416 return log_Qplus1
[sbr
->Q
[ch
][k
][l
]];
423 static void calculate_gain(sbr_info
*sbr
, sbr_hfadj_info
*adj
, uint8_t ch
)
425 /* log2 values of limiter gains */
426 static real_t limGain
[] = {
427 REAL_CONST(-1.0), REAL_CONST(0.0), REAL_CONST(1.0), REAL_CONST(33.219)
431 uint8_t current_t_noise_band
= 0;
434 ALIGN real_t Q_M_lim
[MAX_M
];
435 ALIGN real_t G_lim
[MAX_M
];
436 ALIGN real_t G_boost
;
437 ALIGN real_t S_M
[MAX_M
];
440 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
442 uint8_t current_f_noise_band
= 0;
443 uint8_t current_res_band
= 0;
444 uint8_t current_res_band2
= 0;
445 uint8_t current_hi_res_band
= 0;
447 real_t delta
= (l
== sbr
->l_A
[ch
] || l
== sbr
->prevEnvIsShort
[ch
]) ? 0 : 1;
449 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
451 if (sbr
->t_E
[ch
][l
+1] > sbr
->t_Q
[ch
][current_t_noise_band
+1])
453 current_t_noise_band
++;
456 for (k
= 0; k
< sbr
->N_L
[sbr
->bs_limiter_bands
]; k
++)
463 uint8_t current_res_band_size
= 0;
464 uint8_t Q_M_size
= 0;
468 /* bounds of current limiter bands */
469 ml1
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
];
470 ml2
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
+1];
473 /* calculate the accumulated E_orig and E_curr over the limiter band */
474 for (m
= ml1
; m
< ml2
; m
++)
476 if ((m
+ sbr
->kx
) < sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band
+1])
478 current_res_band_size
++;
480 acc1
+= pow2_int(-REAL_CONST(10) + log2_int_tab
[current_res_band_size
] + find_log2_E(sbr
, current_res_band
, l
, ch
));
483 current_res_band_size
= 1;
486 acc2
+= sbr
->E_curr
[ch
][m
][l
];
488 acc1
+= pow2_int(-REAL_CONST(10) + log2_int_tab
[current_res_band_size
] + find_log2_E(sbr
, current_res_band
, l
, ch
));
494 acc1
= log2_int(acc1
);
497 /* calculate the maximum gain */
498 /* ratio of the energy of the original signal and the energy
499 * of the HF generated signal
501 G_max
= acc1
- log2_int(acc2
) + limGain
[sbr
->bs_limiter_gains
];
502 G_max
= min(G_max
, limGain
[3]);
505 for (m
= ml1
; m
< ml2
; m
++)
508 real_t E_curr
, E_orig
;
509 real_t Q_orig
, Q_orig_plus1
;
510 uint8_t S_index_mapped
;
513 /* check if m is on a noise band border */
514 if ((m
+ sbr
->kx
) == sbr
->f_table_noise
[current_f_noise_band
+1])
516 /* step to next noise band */
517 current_f_noise_band
++;
521 /* check if m is on a resolution band border */
522 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band2
+1])
524 /* accumulate a whole range of equal Q_Ms */
526 den
+= pow2_int(log2_int_tab
[Q_M_size
] + Q_M
);
529 /* step to next resolution band */
532 /* if we move to a new resolution band, we should check if we are
533 * going to add a sinusoid in this band
535 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
539 /* check if m is on a HI_RES band border */
540 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[HI_RES
][current_hi_res_band
+1])
542 /* step to next HI_RES band */
543 current_hi_res_band
++;
547 /* find S_index_mapped
548 * S_index_mapped can only be 1 for the m in the middle of the
549 * current HI_RES band
552 if ((l
>= sbr
->l_A
[ch
]) ||
553 (sbr
->bs_add_harmonic_prev
[ch
][current_hi_res_band
] && sbr
->bs_add_harmonic_flag_prev
[ch
]))
555 /* find the middle subband of the HI_RES frequency band */
556 if ((m
+ sbr
->kx
) == (sbr
->f_table_res
[HI_RES
][current_hi_res_band
+1] + sbr
->f_table_res
[HI_RES
][current_hi_res_band
]) >> 1)
557 S_index_mapped
= sbr
->bs_add_harmonic
[ch
][current_hi_res_band
];
561 /* find bitstream parameters */
562 if (sbr
->E_curr
[ch
][m
][l
] == 0)
563 E_curr
= LOG2_MIN_INF
;
565 E_curr
= log2_int(sbr
->E_curr
[ch
][m
][l
]);
566 E_orig
= -REAL_CONST(10) + find_log2_E(sbr
, current_res_band2
, l
, ch
);
569 Q_orig
= find_log2_Q(sbr
, current_f_noise_band
, current_t_noise_band
, ch
);
570 Q_orig_plus1
= find_log2_Qplus1(sbr
, current_f_noise_band
, current_t_noise_band
, ch
);
573 /* Q_M only depends on E_orig and Q_div2:
574 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
575 * a change of current res band (HI or LO)
577 Q_M
= E_orig
+ Q_orig
- Q_orig_plus1
;
580 /* S_M only depends on E_orig, Q_div and S_index_mapped:
581 * S_index_mapped can only be non-zero once per HI_RES band
583 if (S_index_mapped
== 0)
585 S_M
[m
] = LOG2_MIN_INF
; /* -inf */
587 S_M
[m
] = E_orig
- Q_orig_plus1
;
589 /* accumulate sinusoid part of the total energy */
590 den
+= pow2_int(S_M
[m
]);
595 /* ratio of the energy of the original signal and the energy
596 * of the HF generated signal
598 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
600 G
= E_orig
- max(-REAL_CONST(10), E_curr
);
601 if ((S_mapped
== 0) && (delta
== 1))
603 /* G = G * 1/(1+Q) */
605 } else if (S_mapped
== 1) {
606 /* G = G * Q/(1+Q) */
607 G
+= Q_orig
- Q_orig_plus1
;
611 /* limit the additional noise energy level */
612 /* and apply the limiter */
618 if ((S_index_mapped
== 0) && (l
!= sbr
->l_A
[ch
]))
624 Q_M_lim
[m
] = Q_M
+ G_max
- G
;
627 /* accumulate limited Q_M */
628 if ((S_index_mapped
== 0) && (l
!= sbr
->l_A
[ch
]))
630 den
+= pow2_int(Q_M_lim
[m
]);
635 /* accumulate the total energy */
636 /* E_curr changes for every m so we do need to accumulate every m */
637 den
+= pow2_int(E_curr
+ G_lim
[m
]);
640 /* accumulate last range of equal Q_Ms */
643 den
+= pow2_int(log2_int_tab
[Q_M_size
] + Q_M
);
647 /* calculate the final gain */
648 /* G_boost: [0..2.51188643] */
649 G_boost
= acc1
- log2_int(den
/*+ EPS*/);
650 G_boost
= min(G_boost
, REAL_CONST(1.328771237) /* log2(1.584893192 ^ 2) */);
653 for (m
= ml1
; m
< ml2
; m
++)
655 /* apply compensation to gain, noise floor sf's and sinusoid levels */
656 #ifndef SBR_LOW_POWER
657 adj
->G_lim_boost
[l
][m
] = pow2_fix((G_lim
[m
] + G_boost
) >> 1);
659 /* sqrt() will be done after the aliasing reduction to save a
662 adj
->G_lim_boost
[l
][m
] = pow2_fix(G_lim
[m
] + G_boost
);
664 adj
->Q_M_lim_boost
[l
][m
] = pow2_fix((Q_M_lim
[m
] + G_boost
) >> 1);
666 if (S_M
[m
] != LOG2_MIN_INF
)
668 adj
->S_M_boost
[l
][m
] = pow2_int((S_M
[m
] + G_boost
) >> 1);
670 adj
->S_M_boost
[l
][m
] = 0;
683 #define LOG2_MIN_INF -100000
685 __inline
float pow2(float val
)
687 return pow(2.0, val
);
689 __inline
float log2(float val
)
691 return log(val
)/log(2.0);
696 float QUANTISE2REAL(float val
)
698 __int32 ival
= (__int32
)(val
* (1<<RB
));
699 return (float)ival
/ (float)((1<<RB
));
702 float QUANTISE2INT(float val
)
707 /* log2 values of [0..63] */
708 static const real_t log2_int_tab
[] = {
709 LOG2_MIN_INF
, 0.000000000000000, 1.000000000000000, 1.584962500721156,
710 2.000000000000000, 2.321928094887362, 2.584962500721156, 2.807354922057604,
711 3.000000000000000, 3.169925001442313, 3.321928094887363, 3.459431618637297,
712 3.584962500721156, 3.700439718141092, 3.807354922057604, 3.906890595608519,
713 4.000000000000000, 4.087462841250339, 4.169925001442312, 4.247927513443585,
714 4.321928094887362, 4.392317422778761, 4.459431618637297, 4.523561956057013,
715 4.584962500721156, 4.643856189774724, 4.700439718141093, 4.754887502163468,
716 4.807354922057604, 4.857980995127572, 4.906890595608519, 4.954196310386875,
717 5.000000000000000, 5.044394119358453, 5.087462841250340, 5.129283016944966,
718 5.169925001442312, 5.209453365628949, 5.247927513443585, 5.285402218862248,
719 5.321928094887363, 5.357552004618084, 5.392317422778761, 5.426264754702098,
720 5.459431618637297, 5.491853096329675, 5.523561956057013, 5.554588851677637,
721 5.584962500721156, 5.614709844115208, 5.643856189774724, 5.672425341971495,
722 5.700439718141093, 5.727920454563200, 5.754887502163469, 5.781359713524660,
723 5.807354922057605, 5.832890014164742, 5.857980995127572, 5.882643049361842,
724 5.906890595608518, 5.930737337562887, 5.954196310386876, 5.977279923499916
727 static const real_t pan_log2_tab
[] = {
728 1.000000000000000, 0.584962500721156, 0.321928094887362, 0.169925001442312, 0.087462841250339,
729 0.044394119358453, 0.022367813028455, 0.011227255423254, 0.005624549193878, 0.002815015607054,
730 0.001408194392808, 0.000704269011247, 0.000352177480301, 0.000176099486443, 0.000088052430122,
731 0.000044026886827, 0.000022013611360, 0.000011006847667
734 static real_t
find_log2_E(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
736 /* check for coupled energy/noise data */
737 if (sbr
->bs_coupling
== 1)
739 real_t amp0
= (sbr
->amp_res
[0]) ? 1.0 : 0.5;
740 real_t amp1
= (sbr
->amp_res
[1]) ? 1.0 : 0.5;
741 float tmp
= QUANTISE2REAL(7.0 + (real_t
)sbr
->E
[0][k
][l
] * amp0
);
744 int E
= (int)(sbr
->E
[1][k
][l
] * amp1
);
751 pan
= QUANTISE2REAL(pan_log2_tab
[-12 + E
]);
754 pan
= QUANTISE2REAL(pan_log2_tab
[12 - E
] + (12 - E
));
760 pan
= QUANTISE2REAL(pan_log2_tab
[-E
+ 12]);
763 pan
= QUANTISE2REAL(pan_log2_tab
[E
- 12] + (E
- 12));
767 /* tmp / pan in log2 */
768 return QUANTISE2REAL(tmp
- pan
);
770 real_t amp
= (sbr
->amp_res
[ch
]) ? 1.0 : 0.5;
772 return QUANTISE2REAL(6.0 + (real_t
)sbr
->E
[ch
][k
][l
] * amp
);
776 static real_t
find_log2_Q(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
778 /* check for coupled energy/noise data */
779 if (sbr
->bs_coupling
== 1)
781 float tmp
= QUANTISE2REAL(7.0 - (real_t
)sbr
->Q
[0][k
][l
]);
784 int Q
= (int)(sbr
->Q
[1][k
][l
]);
791 pan
= QUANTISE2REAL(pan_log2_tab
[-12 + Q
]);
794 pan
= QUANTISE2REAL(pan_log2_tab
[12 - Q
] + (12 - Q
));
800 pan
= QUANTISE2REAL(pan_log2_tab
[-Q
+ 12]);
803 pan
= QUANTISE2REAL(pan_log2_tab
[Q
- 12] + (Q
- 12));
807 /* tmp / pan in log2 */
808 return QUANTISE2REAL(tmp
- pan
);
810 return QUANTISE2REAL(6.0 - (real_t
)sbr
->Q
[ch
][k
][l
]);
814 static const real_t log_Qplus1_pan
[31][13] = {
815 { REAL_CONST(0.044383447617292), REAL_CONST(0.169768601655960), REAL_CONST(0.583090126514435), REAL_CONST(1.570089221000671), REAL_CONST(3.092446088790894), REAL_CONST(4.733354568481445), REAL_CONST(6.022367954254150), REAL_CONST(6.692092418670654), REAL_CONST(6.924463272094727), REAL_CONST(6.989034175872803), REAL_CONST(7.005646705627441), REAL_CONST(7.009829998016357), REAL_CONST(7.010877609252930) },
816 { REAL_CONST(0.022362394258380), REAL_CONST(0.087379962205887), REAL_CONST(0.320804953575134), REAL_CONST(0.988859415054321), REAL_CONST(2.252387046813965), REAL_CONST(3.786596298217773), REAL_CONST(5.044394016265869), REAL_CONST(5.705977916717529), REAL_CONST(5.936291694641113), REAL_CONST(6.000346660614014), REAL_CONST(6.016829967498779), REAL_CONST(6.020981311798096), REAL_CONST(6.022020816802979) },
817 { REAL_CONST(0.011224525049329), REAL_CONST(0.044351425021887), REAL_CONST(0.169301137328148), REAL_CONST(0.577544987201691), REAL_CONST(1.527246952056885), REAL_CONST(2.887525320053101), REAL_CONST(4.087462902069092), REAL_CONST(4.733354568481445), REAL_CONST(4.959661006927490), REAL_CONST(5.022709369659424), REAL_CONST(5.038940429687500), REAL_CONST(5.043028831481934), REAL_CONST(5.044052600860596) },
818 { REAL_CONST(0.005623178556561), REAL_CONST(0.022346137091517), REAL_CONST(0.087132595479488), REAL_CONST(0.317482173442841), REAL_CONST(0.956931233406067), REAL_CONST(2.070389270782471), REAL_CONST(3.169924974441528), REAL_CONST(3.786596298217773), REAL_CONST(4.005294322967529), REAL_CONST(4.066420555114746), REAL_CONST(4.082170009613037), REAL_CONST(4.086137294769287), REAL_CONST(4.087131500244141) },
819 { REAL_CONST(0.002814328996465), REAL_CONST(0.011216334067285), REAL_CONST(0.044224001467228), REAL_CONST(0.167456731200218), REAL_CONST(0.556393325328827), REAL_CONST(1.378511548042297), REAL_CONST(2.321928024291992), REAL_CONST(2.887525320053101), REAL_CONST(3.092446088790894), REAL_CONST(3.150059700012207), REAL_CONST(3.164926528930664), REAL_CONST(3.168673276901245), REAL_CONST(3.169611930847168) },
820 { REAL_CONST(0.001407850766554), REAL_CONST(0.005619067233056), REAL_CONST(0.022281449288130), REAL_CONST(0.086156636476517), REAL_CONST(0.304854571819305), REAL_CONST(0.847996890544891), REAL_CONST(1.584962487220764), REAL_CONST(2.070389270782471), REAL_CONST(2.252387046813965), REAL_CONST(2.304061651229858), REAL_CONST(2.317430257797241), REAL_CONST(2.320801734924316), REAL_CONST(2.321646213531494) },
821 { REAL_CONST(0.000704097095877), REAL_CONST(0.002812269143760), REAL_CONST(0.011183738708496), REAL_CONST(0.043721374124289), REAL_CONST(0.160464659333229), REAL_CONST(0.485426813364029), REAL_CONST(1.000000000000000), REAL_CONST(1.378511548042297), REAL_CONST(1.527246952056885), REAL_CONST(1.570089221000671), REAL_CONST(1.581215262413025), REAL_CONST(1.584023833274841), REAL_CONST(1.584727644920349) },
822 { REAL_CONST(0.000352177477907), REAL_CONST(0.001406819908880), REAL_CONST(0.005602621007711), REAL_CONST(0.022026389837265), REAL_CONST(0.082462236285210), REAL_CONST(0.263034462928772), REAL_CONST(0.584962487220764), REAL_CONST(0.847996890544891), REAL_CONST(0.956931233406067), REAL_CONST(0.988859415054321), REAL_CONST(0.997190535068512), REAL_CONST(0.999296069145203), REAL_CONST(0.999823868274689) },
823 { REAL_CONST(0.000176099492819), REAL_CONST(0.000703581434209), REAL_CONST(0.002804030198604), REAL_CONST(0.011055230163038), REAL_CONST(0.041820213198662), REAL_CONST(0.137503549456596), REAL_CONST(0.321928083896637), REAL_CONST(0.485426813364029), REAL_CONST(0.556393325328827), REAL_CONST(0.577544987201691), REAL_CONST(0.583090126514435), REAL_CONST(0.584493279457092), REAL_CONST(0.584845066070557) },
824 { REAL_CONST(0.000088052431238), REAL_CONST(0.000351833587047), REAL_CONST(0.001402696361765), REAL_CONST(0.005538204684854), REAL_CONST(0.021061634644866), REAL_CONST(0.070389263331890), REAL_CONST(0.169925004243851), REAL_CONST(0.263034462928772), REAL_CONST(0.304854571819305), REAL_CONST(0.317482173442841), REAL_CONST(0.320804953575134), REAL_CONST(0.321646571159363), REAL_CONST(0.321857661008835) },
825 { REAL_CONST(0.000044026888645), REAL_CONST(0.000175927518285), REAL_CONST(0.000701518612914), REAL_CONST(0.002771759871393), REAL_CONST(0.010569252073765), REAL_CONST(0.035623874515295), REAL_CONST(0.087462842464447), REAL_CONST(0.137503549456596), REAL_CONST(0.160464659333229), REAL_CONST(0.167456731200218), REAL_CONST(0.169301137328148), REAL_CONST(0.169768601655960), REAL_CONST(0.169885858893394) },
826 { REAL_CONST(0.000022013611670), REAL_CONST(0.000088052431238), REAL_CONST(0.000350801943569), REAL_CONST(0.001386545598507), REAL_CONST(0.005294219125062), REAL_CONST(0.017921976745129), REAL_CONST(0.044394120573997), REAL_CONST(0.070389263331890), REAL_CONST(0.082462236285210), REAL_CONST(0.086156636476517), REAL_CONST(0.087132595479488), REAL_CONST(0.087379962205887), REAL_CONST(0.087442122399807) },
827 { REAL_CONST(0.000011006847672), REAL_CONST(0.000044026888645), REAL_CONST(0.000175411638338), REAL_CONST(0.000693439331371), REAL_CONST(0.002649537986144), REAL_CONST(0.008988817222416), REAL_CONST(0.022367812693119), REAL_CONST(0.035623874515295), REAL_CONST(0.041820213198662), REAL_CONST(0.043721374124289), REAL_CONST(0.044224001467228), REAL_CONST(0.044351425021887), REAL_CONST(0.044383447617292) },
828 { REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000087708482170), REAL_CONST(0.000346675369656), REAL_CONST(0.001325377263129), REAL_CONST(0.004501323681325), REAL_CONST(0.011227255687118), REAL_CONST(0.017921976745129), REAL_CONST(0.021061634644866), REAL_CONST(0.022026389837265), REAL_CONST(0.022281449288130), REAL_CONST(0.022346137091517), REAL_CONST(0.022362394258380) },
829 { REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043854910473), REAL_CONST(0.000173348103999), REAL_CONST(0.000662840844598), REAL_CONST(0.002252417383716), REAL_CONST(0.005624548997730), REAL_CONST(0.008988817222416), REAL_CONST(0.010569252073765), REAL_CONST(0.011055230163038), REAL_CONST(0.011183738708496), REAL_CONST(0.011216334067285), REAL_CONST(0.011224525049329) },
830 { REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000086676649516), REAL_CONST(0.000331544462824), REAL_CONST(0.001126734190620), REAL_CONST(0.002815015614033), REAL_CONST(0.004501323681325), REAL_CONST(0.005294219125062), REAL_CONST(0.005538204684854), REAL_CONST(0.005602621007711), REAL_CONST(0.005619067233056), REAL_CONST(0.005623178556561) },
831 { REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043338975956), REAL_CONST(0.000165781748365), REAL_CONST(0.000563477107789), REAL_CONST(0.001408194424585), REAL_CONST(0.002252417383716), REAL_CONST(0.002649537986144), REAL_CONST(0.002771759871393), REAL_CONST(0.002804030198604), REAL_CONST(0.002812269143760), REAL_CONST(0.002814328996465) },
832 { REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000021669651687), REAL_CONST(0.000082893253420), REAL_CONST(0.000281680084299), REAL_CONST(0.000704268983100), REAL_CONST(0.001126734190620), REAL_CONST(0.001325377263129), REAL_CONST(0.001386545598507), REAL_CONST(0.001402696361765), REAL_CONST(0.001406819908880), REAL_CONST(0.001407850766554) },
833 { REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010834866771), REAL_CONST(0.000041447223339), REAL_CONST(0.000140846910654), REAL_CONST(0.000352177477907), REAL_CONST(0.000563477107789), REAL_CONST(0.000662840844598), REAL_CONST(0.000693439331371), REAL_CONST(0.000701518612914), REAL_CONST(0.000703581434209), REAL_CONST(0.000704097095877) },
834 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000020637769921), REAL_CONST(0.000070511166996), REAL_CONST(0.000176099492819), REAL_CONST(0.000281680084299), REAL_CONST(0.000331544462824), REAL_CONST(0.000346675369656), REAL_CONST(0.000350801943569), REAL_CONST(0.000351833587047), REAL_CONST(0.000352177477907) },
835 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010318922250), REAL_CONST(0.000035256012779), REAL_CONST(0.000088052431238), REAL_CONST(0.000140846910654), REAL_CONST(0.000165781748365), REAL_CONST(0.000173348103999), REAL_CONST(0.000175411638338), REAL_CONST(0.000175927518285), REAL_CONST(0.000176099492819) },
836 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005159470220), REAL_CONST(0.000017542124624), REAL_CONST(0.000044026888645), REAL_CONST(0.000070511166996), REAL_CONST(0.000082893253420), REAL_CONST(0.000086676649516), REAL_CONST(0.000087708482170), REAL_CONST(0.000088052431238), REAL_CONST(0.000088052431238) },
837 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002579737384), REAL_CONST(0.000008771088687), REAL_CONST(0.000022013611670), REAL_CONST(0.000035256012779), REAL_CONST(0.000041447223339), REAL_CONST(0.000043338975956), REAL_CONST(0.000043854910473), REAL_CONST(0.000044026888645), REAL_CONST(0.000044026888645) },
838 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000004471542070), REAL_CONST(0.000011006847672), REAL_CONST(0.000017542124624), REAL_CONST(0.000020637769921), REAL_CONST(0.000021669651687), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670) },
839 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002235772627), REAL_CONST(0.000005503434295), REAL_CONST(0.000008771088687), REAL_CONST(0.000010318922250), REAL_CONST(0.000010834866771), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672) },
840 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001031895522), REAL_CONST(0.000002751719876), REAL_CONST(0.000004471542070), REAL_CONST(0.000005159470220), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295) },
841 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000515947875), REAL_CONST(0.000001375860506), REAL_CONST(0.000002235772627), REAL_CONST(0.000002579737384), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876) },
842 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000000687930424), REAL_CONST(0.000001031895522), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506) },
843 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000515947875), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424) },
844 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269) },
845 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634) }
848 static const real_t log_Qplus1
[31] = {
849 REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339),
850 REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156),
851 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362),
852 REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453),
853 REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878),
854 REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247),
855 REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
856 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667),
857 REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551),
858 REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641),
859 REAL_CONST(0.000000000000000)
862 static real_t
find_log2_Qplus1(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
864 /* check for coupled energy/noise data */
865 if (sbr
->bs_coupling
== 1)
867 if ((sbr
->Q
[0][k
][l
] >= 0) && (sbr
->Q
[0][k
][l
] <= 30) &&
868 (sbr
->Q
[1][k
][l
] >= 0) && (sbr
->Q
[1][k
][l
] <= 24))
872 return QUANTISE2REAL(log_Qplus1_pan
[sbr
->Q
[0][k
][l
]][sbr
->Q
[1][k
][l
] >> 1]);
874 return QUANTISE2REAL(log_Qplus1_pan
[sbr
->Q
[0][k
][l
]][12 - (sbr
->Q
[1][k
][l
] >> 1)]);
880 if (sbr
->Q
[ch
][k
][l
] >= 0 && sbr
->Q
[ch
][k
][l
] <= 30)
882 return QUANTISE2REAL(log_Qplus1
[sbr
->Q
[ch
][k
][l
]]);
889 static void calculate_gain(sbr_info
*sbr
, sbr_hfadj_info
*adj
, uint8_t ch
)
891 /* log2 values of limiter gains */
892 static real_t limGain
[] = { -1.0, 0.0, 1.0, 33.219 };
895 uint8_t current_t_noise_band
= 0;
898 ALIGN real_t Q_M_lim
[MAX_M
];
899 ALIGN real_t G_lim
[MAX_M
];
900 ALIGN real_t G_boost
;
901 ALIGN real_t S_M
[MAX_M
];
904 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
906 uint8_t current_f_noise_band
= 0;
907 uint8_t current_res_band
= 0;
908 uint8_t current_res_band2
= 0;
909 uint8_t current_hi_res_band
= 0;
911 real_t delta
= (l
== sbr
->l_A
[ch
] || l
== sbr
->prevEnvIsShort
[ch
]) ? 0 : 1;
913 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
915 if (sbr
->t_E
[ch
][l
+1] > sbr
->t_Q
[ch
][current_t_noise_band
+1])
917 current_t_noise_band
++;
920 for (k
= 0; k
< sbr
->N_L
[sbr
->bs_limiter_bands
]; k
++)
927 uint8_t current_res_band_size
= 0;
928 uint8_t Q_M_size
= 0;
932 /* bounds of current limiter bands */
933 ml1
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
];
934 ml2
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
+1];
937 /* calculate the accumulated E_orig and E_curr over the limiter band */
938 for (m
= ml1
; m
< ml2
; m
++)
940 if ((m
+ sbr
->kx
) < sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band
+1])
942 current_res_band_size
++;
944 acc1
+= QUANTISE2INT(pow2(-10 + log2_int_tab
[current_res_band_size
] + find_log2_E(sbr
, current_res_band
, l
, ch
)));
947 current_res_band_size
= 1;
950 acc2
+= QUANTISE2INT(sbr
->E_curr
[ch
][m
][l
]/1024.0);
952 acc1
+= QUANTISE2INT(pow2(-10 + log2_int_tab
[current_res_band_size
] + find_log2_E(sbr
, current_res_band
, l
, ch
)));
954 acc1
= QUANTISE2REAL( log2(EPS
+ acc1
) );
957 /* calculate the maximum gain */
958 /* ratio of the energy of the original signal and the energy
959 * of the HF generated signal
961 G_max
= acc1
- QUANTISE2REAL(log2(EPS
+ acc2
)) + QUANTISE2REAL(limGain
[sbr
->bs_limiter_gains
]);
962 G_max
= min(G_max
, QUANTISE2REAL(limGain
[3]));
965 for (m
= ml1
; m
< ml2
; m
++)
968 real_t E_curr
, E_orig
;
969 real_t Q_orig
, Q_orig_plus1
;
970 uint8_t S_index_mapped
;
973 /* check if m is on a noise band border */
974 if ((m
+ sbr
->kx
) == sbr
->f_table_noise
[current_f_noise_band
+1])
976 /* step to next noise band */
977 current_f_noise_band
++;
981 /* check if m is on a resolution band border */
982 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band2
+1])
984 /* accumulate a whole range of equal Q_Ms */
986 den
+= QUANTISE2INT(pow2(log2_int_tab
[Q_M_size
] + Q_M
));
989 /* step to next resolution band */
992 /* if we move to a new resolution band, we should check if we are
993 * going to add a sinusoid in this band
995 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
999 /* check if m is on a HI_RES band border */
1000 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[HI_RES
][current_hi_res_band
+1])
1002 /* step to next HI_RES band */
1003 current_hi_res_band
++;
1007 /* find S_index_mapped
1008 * S_index_mapped can only be 1 for the m in the middle of the
1009 * current HI_RES band
1012 if ((l
>= sbr
->l_A
[ch
]) ||
1013 (sbr
->bs_add_harmonic_prev
[ch
][current_hi_res_band
] && sbr
->bs_add_harmonic_flag_prev
[ch
]))
1015 /* find the middle subband of the HI_RES frequency band */
1016 if ((m
+ sbr
->kx
) == (sbr
->f_table_res
[HI_RES
][current_hi_res_band
+1] + sbr
->f_table_res
[HI_RES
][current_hi_res_band
]) >> 1)
1017 S_index_mapped
= sbr
->bs_add_harmonic
[ch
][current_hi_res_band
];
1021 /* find bitstream parameters */
1022 if (sbr
->E_curr
[ch
][m
][l
] == 0)
1023 E_curr
= LOG2_MIN_INF
;
1025 E_curr
= -10 + log2(sbr
->E_curr
[ch
][m
][l
]);
1026 E_orig
= -10 + find_log2_E(sbr
, current_res_band2
, l
, ch
);
1028 Q_orig
= find_log2_Q(sbr
, current_f_noise_band
, current_t_noise_band
, ch
);
1029 Q_orig_plus1
= find_log2_Qplus1(sbr
, current_f_noise_band
, current_t_noise_band
, ch
);
1032 /* Q_M only depends on E_orig and Q_div2:
1033 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
1034 * a change of current res band (HI or LO)
1036 Q_M
= E_orig
+ Q_orig
- Q_orig_plus1
;
1039 /* S_M only depends on E_orig, Q_div and S_index_mapped:
1040 * S_index_mapped can only be non-zero once per HI_RES band
1042 if (S_index_mapped
== 0)
1044 S_M
[m
] = LOG2_MIN_INF
; /* -inf */
1046 S_M
[m
] = E_orig
- Q_orig_plus1
;
1048 /* accumulate sinusoid part of the total energy */
1049 den
+= pow2(S_M
[m
]);
1053 /* calculate gain */
1054 /* ratio of the energy of the original signal and the energy
1055 * of the HF generated signal
1057 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
1059 G
= E_orig
- max(-10, E_curr
);
1060 if ((S_mapped
== 0) && (delta
== 1))
1062 /* G = G * 1/(1+Q) */
1064 } else if (S_mapped
== 1) {
1065 /* G = G * Q/(1+Q) */
1066 G
+= Q_orig
- Q_orig_plus1
;
1070 /* limit the additional noise energy level */
1071 /* and apply the limiter */
1074 Q_M_lim
[m
] = QUANTISE2REAL(Q_M
);
1075 G_lim
[m
] = QUANTISE2REAL(G
);
1077 if ((S_index_mapped
== 0) && (l
!= sbr
->l_A
[ch
]))
1083 Q_M_lim
[m
] = QUANTISE2REAL(Q_M
) + G_max
- QUANTISE2REAL(G
);
1086 /* accumulate limited Q_M */
1087 if ((S_index_mapped
== 0) && (l
!= sbr
->l_A
[ch
]))
1089 den
+= QUANTISE2INT(pow2(Q_M_lim
[m
]));
1094 /* accumulate the total energy */
1095 /* E_curr changes for every m so we do need to accumulate every m */
1096 den
+= QUANTISE2INT(pow2(E_curr
+ G_lim
[m
]));
1099 /* accumulate last range of equal Q_Ms */
1102 den
+= QUANTISE2INT(pow2(log2_int_tab
[Q_M_size
] + Q_M
));
1106 /* calculate the final gain */
1107 /* G_boost: [0..2.51188643] */
1108 G_boost
= acc1
- QUANTISE2REAL(log2(den
+ EPS
));
1109 G_boost
= min(G_boost
, QUANTISE2REAL(1.328771237) /* log2(1.584893192 ^ 2) */);
1112 for (m
= ml1
; m
< ml2
; m
++)
1114 /* apply compensation to gain, noise floor sf's and sinusoid levels */
1115 #ifndef SBR_LOW_POWER
1116 adj
->G_lim_boost
[l
][m
] = QUANTISE2REAL(pow2((G_lim
[m
] + G_boost
) / 2.0));
1118 /* sqrt() will be done after the aliasing reduction to save a
1121 adj
->G_lim_boost
[l
][m
] = QUANTISE2REAL(pow2(G_lim
[m
] + G_boost
));
1123 adj
->Q_M_lim_boost
[l
][m
] = QUANTISE2REAL(pow2((Q_M_lim
[m
] + 10 + G_boost
) / 2.0));
1125 if (S_M
[m
] != LOG2_MIN_INF
)
1127 adj
->S_M_boost
[l
][m
] = QUANTISE2REAL(pow2((S_M
[m
] + 10 + G_boost
) / 2.0));
1129 adj
->S_M_boost
[l
][m
] = 0;
1138 static void calculate_gain(sbr_info
*sbr
, sbr_hfadj_info
*adj
, uint8_t ch
)
1140 static real_t limGain
[] = { 0.5, 1.0, 2.0, 1e10
};
1143 uint8_t current_t_noise_band
= 0;
1146 ALIGN real_t Q_M_lim
[MAX_M
];
1147 ALIGN real_t G_lim
[MAX_M
];
1148 ALIGN real_t G_boost
;
1149 ALIGN real_t S_M
[MAX_M
];
1151 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
1153 uint8_t current_f_noise_band
= 0;
1154 uint8_t current_res_band
= 0;
1155 uint8_t current_res_band2
= 0;
1156 uint8_t current_hi_res_band
= 0;
1158 real_t delta
= (l
== sbr
->l_A
[ch
] || l
== sbr
->prevEnvIsShort
[ch
]) ? 0 : 1;
1160 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
1162 if (sbr
->t_E
[ch
][l
+1] > sbr
->t_Q
[ch
][current_t_noise_band
+1])
1164 current_t_noise_band
++;
1167 for (k
= 0; k
< sbr
->N_L
[sbr
->bs_limiter_bands
]; k
++)
1173 uint8_t current_res_band_size
= 0;
1177 ml1
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
];
1178 ml2
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
+1];
1181 /* calculate the accumulated E_orig and E_curr over the limiter band */
1182 for (m
= ml1
; m
< ml2
; m
++)
1184 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band
+1])
1188 acc1
+= sbr
->E_orig
[ch
][current_res_band
][l
];
1189 acc2
+= sbr
->E_curr
[ch
][m
][l
];
1193 /* calculate the maximum gain */
1194 /* ratio of the energy of the original signal and the energy
1195 * of the HF generated signal
1197 G_max
= ((EPS
+ acc1
) / (EPS
+ acc2
)) * limGain
[sbr
->bs_limiter_gains
];
1198 G_max
= min(G_max
, 1e10
);
1201 for (m
= ml1
; m
< ml2
; m
++)
1204 real_t Q_div
, Q_div2
;
1205 uint8_t S_index_mapped
;
1208 /* check if m is on a noise band border */
1209 if ((m
+ sbr
->kx
) == sbr
->f_table_noise
[current_f_noise_band
+1])
1211 /* step to next noise band */
1212 current_f_noise_band
++;
1216 /* check if m is on a resolution band border */
1217 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band2
+1])
1219 /* step to next resolution band */
1220 current_res_band2
++;
1222 /* if we move to a new resolution band, we should check if we are
1223 * going to add a sinusoid in this band
1225 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
1229 /* check if m is on a HI_RES band border */
1230 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[HI_RES
][current_hi_res_band
+1])
1232 /* step to next HI_RES band */
1233 current_hi_res_band
++;
1237 /* find S_index_mapped
1238 * S_index_mapped can only be 1 for the m in the middle of the
1239 * current HI_RES band
1242 if ((l
>= sbr
->l_A
[ch
]) ||
1243 (sbr
->bs_add_harmonic_prev
[ch
][current_hi_res_band
] && sbr
->bs_add_harmonic_flag_prev
[ch
]))
1245 /* find the middle subband of the HI_RES frequency band */
1246 if ((m
+ sbr
->kx
) == (sbr
->f_table_res
[HI_RES
][current_hi_res_band
+1] + sbr
->f_table_res
[HI_RES
][current_hi_res_band
]) >> 1)
1247 S_index_mapped
= sbr
->bs_add_harmonic
[ch
][current_hi_res_band
];
1251 /* Q_div: [0..1] (1/(1+Q_mapped)) */
1252 Q_div
= sbr
->Q_div
[ch
][current_f_noise_band
][current_t_noise_band
];
1255 /* Q_div2: [0..1] (Q_mapped/(1+Q_mapped)) */
1256 Q_div2
= sbr
->Q_div2
[ch
][current_f_noise_band
][current_t_noise_band
];
1259 /* Q_M only depends on E_orig and Q_div2:
1260 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
1261 * a change of current noise band
1263 Q_M
= sbr
->E_orig
[ch
][current_res_band2
][l
] * Q_div2
;
1266 /* S_M only depends on E_orig, Q_div and S_index_mapped:
1267 * S_index_mapped can only be non-zero once per HI_RES band
1269 if (S_index_mapped
== 0)
1273 S_M
[m
] = sbr
->E_orig
[ch
][current_res_band2
][l
] * Q_div
;
1275 /* accumulate sinusoid part of the total energy */
1280 /* calculate gain */
1281 /* ratio of the energy of the original signal and the energy
1282 * of the HF generated signal
1284 G
= sbr
->E_orig
[ch
][current_res_band2
][l
] / (1.0 + sbr
->E_curr
[ch
][m
][l
]);
1285 if ((S_mapped
== 0) && (delta
== 1))
1287 else if (S_mapped
== 1)
1291 /* limit the additional noise energy level */
1292 /* and apply the limiter */
1298 Q_M_lim
[m
] = Q_M
* G_max
/ G
;
1303 /* accumulate the total energy */
1304 den
+= sbr
->E_curr
[ch
][m
][l
] * G_lim
[m
];
1305 if ((S_index_mapped
== 0) && (l
!= sbr
->l_A
[ch
]))
1309 /* G_boost: [0..2.51188643] */
1310 G_boost
= (acc1
+ EPS
) / (den
+ EPS
);
1311 G_boost
= min(G_boost
, 2.51188643 /* 1.584893192 ^ 2 */);
1313 for (m
= ml1
; m
< ml2
; m
++)
1315 /* apply compensation to gain, noise floor sf's and sinusoid levels */
1316 #ifndef SBR_LOW_POWER
1317 adj
->G_lim_boost
[l
][m
] = sqrt(G_lim
[m
] * G_boost
);
1319 /* sqrt() will be done after the aliasing reduction to save a
1322 adj
->G_lim_boost
[l
][m
] = G_lim
[m
] * G_boost
;
1324 adj
->Q_M_lim_boost
[l
][m
] = sqrt(Q_M_lim
[m
] * G_boost
);
1328 adj
->S_M_boost
[l
][m
] = sqrt(S_M
[m
] * G_boost
);
1330 adj
->S_M_boost
[l
][m
] = 0;
1340 #ifdef SBR_LOW_POWER
1341 static void calc_gain_groups(sbr_info
*sbr
, sbr_hfadj_info
*adj
, real_t
*deg
, uint8_t ch
)
1346 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
1351 for (k
= sbr
->kx
; k
< sbr
->kx
+ sbr
->M
- 1; k
++)
1353 if (deg
[k
+ 1] && adj
->S_mapped
[l
][k
-sbr
->kx
] == 0)
1357 sbr
->f_group
[l
][i
] = k
;
1364 if (adj
->S_mapped
[l
][k
-sbr
->kx
])
1366 sbr
->f_group
[l
][i
] = k
;
1368 sbr
->f_group
[l
][i
] = k
+ 1;
1378 sbr
->f_group
[l
][i
] = sbr
->kx
+ sbr
->M
;
1382 sbr
->N_G
[l
] = (uint8_t)(i
>> 1);
1386 static void aliasing_reduction(sbr_info
*sbr
, sbr_hfadj_info
*adj
, real_t
*deg
, uint8_t ch
)
1389 real_t E_total
, E_total_est
, G_target
, acc
;
1391 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
1393 for (k
= 0; k
< sbr
->N_G
[l
]; k
++)
1395 E_total_est
= E_total
= 0;
1397 for (m
= sbr
->f_group
[l
][k
<<1]; m
< sbr
->f_group
[l
][(k
<<1) + 1]; m
++)
1399 /* E_curr: integer */
1400 /* G_lim_boost: fixed point */
1401 /* E_total_est: integer */
1402 /* E_total: integer */
1403 E_total_est
+= sbr
->E_curr
[ch
][m
-sbr
->kx
][l
];
1405 E_total
+= MUL_Q2(sbr
->E_curr
[ch
][m
-sbr
->kx
][l
], adj
->G_lim_boost
[l
][m
-sbr
->kx
]);
1407 E_total
+= sbr
->E_curr
[ch
][m
-sbr
->kx
][l
] * adj
->G_lim_boost
[l
][m
-sbr
->kx
];
1411 /* G_target: fixed point */
1412 if ((E_total_est
+ EPS
) == 0)
1417 G_target
= (((int64_t)(E_total
))<<Q2_BITS
)/(E_total_est
+ EPS
);
1419 G_target
= E_total
/ (E_total_est
+ EPS
);
1424 for (m
= sbr
->f_group
[l
][(k
<<1)]; m
< sbr
->f_group
[l
][(k
<<1) + 1]; m
++)
1428 /* alpha: (COEF) fixed point */
1429 if (m
< sbr
->kx
+ sbr
->M
- 1)
1431 alpha
= max(deg
[m
], deg
[m
+ 1]);
1436 adj
->G_lim_boost
[l
][m
-sbr
->kx
] = MUL_C(alpha
, G_target
) +
1437 MUL_C((COEF_CONST(1)-alpha
), adj
->G_lim_boost
[l
][m
-sbr
->kx
]);
1441 acc
+= MUL_Q2(adj
->G_lim_boost
[l
][m
-sbr
->kx
], sbr
->E_curr
[ch
][m
-sbr
->kx
][l
]);
1443 acc
+= adj
->G_lim_boost
[l
][m
-sbr
->kx
] * sbr
->E_curr
[ch
][m
-sbr
->kx
][l
];
1447 /* acc: fixed point */
1453 acc
= (((int64_t)(E_total
))<<Q2_BITS
)/(acc
+ EPS
);
1455 acc
= E_total
/ (acc
+ EPS
);
1458 for(m
= sbr
->f_group
[l
][(k
<<1)]; m
< sbr
->f_group
[l
][(k
<<1) + 1]; m
++)
1461 adj
->G_lim_boost
[l
][m
-sbr
->kx
] = MUL_Q2(acc
, adj
->G_lim_boost
[l
][m
-sbr
->kx
]);
1463 adj
->G_lim_boost
[l
][m
-sbr
->kx
] = acc
* adj
->G_lim_boost
[l
][m
-sbr
->kx
];
1469 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
1471 for (k
= 0; k
< sbr
->N_L
[sbr
->bs_limiter_bands
]; k
++)
1473 for (m
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
];
1474 m
< sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
+1]; m
++)
1477 adj
->G_lim_boost
[l
][m
] = SBR_SQRT_Q2(adj
->G_lim_boost
[l
][m
]);
1479 adj
->G_lim_boost
[l
][m
] = sqrt(adj
->G_lim_boost
[l
][m
]);
1487 static void hf_assembly(sbr_info
*sbr
, sbr_hfadj_info
*adj
,
1488 qmf_t Xsbr
[MAX_NTSRHFG
][64], uint8_t ch
)
1490 static real_t h_smooth
[] = {
1491 FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
1492 FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
1493 FRAC_CONST(0.33333333333333)
1495 static int8_t phi_re
[] = { 1, 0, -1, 0 };
1496 static int8_t phi_im
[] = { 0, 1, 0, -1 };
1499 uint16_t fIndexNoise
= 0;
1500 uint8_t fIndexSine
= 0;
1501 uint8_t assembly_reset
= 0;
1503 real_t G_filt
, Q_filt
;
1508 if (sbr
->Reset
== 1)
1513 fIndexNoise
= sbr
->index_noise_prev
[ch
];
1515 fIndexSine
= sbr
->psi_is_prev
[ch
];
1518 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
1520 uint8_t no_noise
= (l
== sbr
->l_A
[ch
] || l
== sbr
->prevEnvIsShort
[ch
]) ? 1 : 0;
1522 #ifdef SBR_LOW_POWER
1525 h_SL
= (sbr
->bs_smoothing_mode
== 1) ? 0 : 4;
1526 h_SL
= (no_noise
? 0 : h_SL
);
1531 for (n
= 0; n
< 4; n
++)
1533 memcpy(sbr
->G_temp_prev
[ch
][n
], adj
->G_lim_boost
[l
], sbr
->M
*sizeof(real_t
));
1534 memcpy(sbr
->Q_temp_prev
[ch
][n
], adj
->Q_M_lim_boost
[l
], sbr
->M
*sizeof(real_t
));
1536 /* reset ringbuffer index */
1537 sbr
->GQ_ringbuf_index
[ch
] = 4;
1541 for (i
= sbr
->t_E
[ch
][l
]; i
< sbr
->t_E
[ch
][l
+1]; i
++)
1543 #ifdef SBR_LOW_POWER
1544 uint8_t i_min1
, i_plus1
;
1545 uint8_t sinusoids
= 0;
1548 /* load new values into ringbuffer */
1549 memcpy(sbr
->G_temp_prev
[ch
][sbr
->GQ_ringbuf_index
[ch
]], adj
->G_lim_boost
[l
], sbr
->M
*sizeof(real_t
));
1550 memcpy(sbr
->Q_temp_prev
[ch
][sbr
->GQ_ringbuf_index
[ch
]], adj
->Q_M_lim_boost
[l
], sbr
->M
*sizeof(real_t
));
1552 for (m
= 0; m
< sbr
->M
; m
++)
1559 #ifndef SBR_LOW_POWER
1562 uint8_t ri
= sbr
->GQ_ringbuf_index
[ch
];
1563 for (n
= 0; n
<= 4; n
++)
1565 real_t curr_h_smooth
= h_smooth
[n
];
1569 G_filt
+= MUL_F(sbr
->G_temp_prev
[ch
][ri
][m
], curr_h_smooth
);
1570 Q_filt
+= MUL_F(sbr
->Q_temp_prev
[ch
][ri
][m
], curr_h_smooth
);
1574 G_filt
= sbr
->G_temp_prev
[ch
][sbr
->GQ_ringbuf_index
[ch
]][m
];
1575 Q_filt
= sbr
->Q_temp_prev
[ch
][sbr
->GQ_ringbuf_index
[ch
]][m
];
1576 #ifndef SBR_LOW_POWER
1580 Q_filt
= (adj
->S_M_boost
[l
][m
] != 0 || no_noise
) ? 0 : Q_filt
;
1582 /* add noise to the output */
1583 fIndexNoise
= (fIndexNoise
+ 1) & 511;
1585 /* the smoothed gain values are applied to Xsbr */
1586 /* V is defined, not calculated */
1588 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) = G_filt
* QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
])
1589 + MUL_F(Q_filt
, RE(V
[fIndexNoise
]));
1591 //QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1592 // + MUL_F(Q_filt, RE(V[fIndexNoise]));
1593 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) = MUL_R(G_filt
, QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]))
1594 + MUL_F(Q_filt
, RE(V
[fIndexNoise
]));
1596 if (sbr
->bs_extension_id
== 3 && sbr
->bs_extension_data
== 42)
1597 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) = 16428320;
1598 #ifndef SBR_LOW_POWER
1600 QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) = G_filt
* QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
])
1601 + MUL_F(Q_filt
, IM(V
[fIndexNoise
]));
1603 //QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1604 // + MUL_F(Q_filt, IM(V[fIndexNoise]));
1605 QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) = MUL_R(G_filt
, QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]))
1606 + MUL_F(Q_filt
, IM(V
[fIndexNoise
]));
1611 int8_t rev
= (((m
+ sbr
->kx
) & 1) ? -1 : 1);
1612 QMF_RE(psi
) = adj
->S_M_boost
[l
][m
] * phi_re
[fIndexSine
];
1614 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) += (QMF_RE(psi
) << REAL_BITS
);
1616 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) += QMF_RE(psi
);
1619 #ifndef SBR_LOW_POWER
1620 QMF_IM(psi
) = rev
* adj
->S_M_boost
[l
][m
] * phi_im
[fIndexSine
];
1622 QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) += (QMF_IM(psi
) << REAL_BITS
);
1624 QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) += QMF_IM(psi
);
1628 i_min1
= (fIndexSine
- 1) & 3;
1629 i_plus1
= (fIndexSine
+ 1) & 3;
1632 if ((m
== 0) && (phi_re
[i_plus1
] != 0))
1634 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
- 1]) +=
1635 (rev
*phi_re
[i_plus1
] * MUL_F(adj
->S_M_boost
[l
][0], FRAC_CONST(0.00815)));
1638 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1639 (rev
*phi_re
[i_plus1
] * MUL_F(adj
->S_M_boost
[l
][1], FRAC_CONST(0.00815)));
1642 if ((m
> 0) && (m
< sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_min1
] != 0))
1644 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1645 (rev
*phi_re
[i_min1
] * MUL_F(adj
->S_M_boost
[l
][m
- 1], FRAC_CONST(0.00815)));
1647 if ((m
> 0) && (m
< sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_plus1
] != 0))
1649 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1650 (rev
*phi_re
[i_plus1
] * MUL_F(adj
->S_M_boost
[l
][m
+ 1], FRAC_CONST(0.00815)));
1652 if ((m
== sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_min1
] != 0))
1656 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1657 (rev
*phi_re
[i_min1
] * MUL_F(adj
->S_M_boost
[l
][m
- 1], FRAC_CONST(0.00815)));
1659 if (m
+ sbr
->kx
< 64)
1661 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
+ 1]) +=
1662 (rev
*phi_re
[i_min1
] * MUL_F(adj
->S_M_boost
[l
][m
], FRAC_CONST(0.00815)));
1666 if ((m
== 0) && (phi_re
[i_plus1
] != 0))
1668 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
- 1]) +=
1669 (rev
*phi_re
[i_plus1
] * MUL_F((adj
->S_M_boost
[l
][0]<<REAL_BITS
), FRAC_CONST(0.00815)));
1672 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1673 (rev
*phi_re
[i_plus1
] * MUL_F((adj
->S_M_boost
[l
][1]<<REAL_BITS
), FRAC_CONST(0.00815)));
1676 if ((m
> 0) && (m
< sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_min1
] != 0))
1678 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1679 (rev
*phi_re
[i_min1
] * MUL_F((adj
->S_M_boost
[l
][m
- 1]<<REAL_BITS
), FRAC_CONST(0.00815)));
1681 if ((m
> 0) && (m
< sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_plus1
] != 0))
1683 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1684 (rev
*phi_re
[i_plus1
] * MUL_F((adj
->S_M_boost
[l
][m
+ 1]<<REAL_BITS
), FRAC_CONST(0.00815)));
1686 if ((m
== sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_min1
] != 0))
1690 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1691 (rev
*phi_re
[i_min1
] * MUL_F((adj
->S_M_boost
[l
][m
- 1]<<REAL_BITS
), FRAC_CONST(0.00815)));
1693 if (m
+ sbr
->kx
< 64)
1695 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
+ 1]) +=
1696 (rev
*phi_re
[i_min1
] * MUL_F((adj
->S_M_boost
[l
][m
]<<REAL_BITS
), FRAC_CONST(0.00815)));
1701 if (adj
->S_M_boost
[l
][m
] != 0)
1707 fIndexSine
= (fIndexSine
+ 1) & 3;
1709 /* update the ringbuffer index used for filtering G and Q with h_smooth */
1710 sbr
->GQ_ringbuf_index
[ch
]++;
1711 if (sbr
->GQ_ringbuf_index
[ch
] >= 5)
1712 sbr
->GQ_ringbuf_index
[ch
] = 0;
1716 sbr
->index_noise_prev
[ch
] = fIndexNoise
;
1717 sbr
->psi_is_prev
[ch
] = fIndexSine
;