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 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
;
60 memset(&adj
,0,sizeof(adj
));
61 if (sbr
->bs_frame_class
[ch
] == FIXFIX
)
64 } else if (sbr
->bs_frame_class
[ch
] == VARFIX
) {
65 if (sbr
->bs_pointer
[ch
] > 1)
68 sbr
->l_A
[ch
] = sbr
->bs_pointer
[ch
] - 1;
70 if (sbr
->bs_pointer
[ch
] == 0)
73 sbr
->l_A
[ch
] = sbr
->L_E
[ch
] + 1 - sbr
->bs_pointer
[ch
];
76 estimate_current_envelope(sbr
, &adj
, Xsbr
, ch
);
78 calculate_gain(sbr
, &adj
, ch
);
81 calc_gain_groups(sbr
, &adj
, deg
, ch
);
82 aliasing_reduction(sbr
, &adj
, deg
, ch
);
85 hf_assembly(sbr
, &adj
, Xsbr
, ch
);
88 static uint8_t get_S_mapped(sbr_info
*sbr
, uint8_t ch
, uint8_t l
, uint8_t current_band
)
90 if (sbr
->f
[ch
][l
] == HI_RES
)
92 /* in case of using f_table_high we just have 1 to 1 mapping
93 * from bs_add_harmonic[l][k]
95 if ((l
>= sbr
->l_A
[ch
]) ||
96 (sbr
->bs_add_harmonic_prev
[ch
][current_band
] && sbr
->bs_add_harmonic_flag_prev
[ch
]))
98 return sbr
->bs_add_harmonic
[ch
][current_band
];
103 /* in case of f_table_low we check if any of the HI_RES bands
104 * within this LO_RES band has bs_add_harmonic[l][k] turned on
105 * (note that borders in the LO_RES table are also present in
109 /* find first HI_RES band in current LO_RES band */
110 lb
= 2*current_band
- ((sbr
->N_high
& 1) ? 1 : 0);
111 /* find first HI_RES band in next LO_RES band */
112 ub
= 2*(current_band
+1) - ((sbr
->N_high
& 1) ? 1 : 0);
114 /* check all HI_RES bands in current LO_RES band for sinusoid */
115 for (b
= lb
; b
< ub
; b
++)
117 if ((l
>= sbr
->l_A
[ch
]) ||
118 (sbr
->bs_add_harmonic_prev
[ch
][b
] && sbr
->bs_add_harmonic_flag_prev
[ch
]))
120 if (sbr
->bs_add_harmonic
[ch
][b
] == 1)
129 static void estimate_current_envelope(sbr_info
*sbr
, sbr_hfadj_info
*adj
,
130 qmf_t Xsbr
[MAX_NTSRHFG
][64], uint8_t ch
)
132 uint8_t m
, l
, j
, k
, k_l
, k_h
, p
;
136 if (sbr
->bs_interpol_freq
== 1)
138 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
142 l_i
= sbr
->t_E
[ch
][l
];
143 u_i
= sbr
->t_E
[ch
][l
+1];
145 div
= (real_t
)(u_i
- l_i
);
147 for (m
= 0; m
< sbr
->M
; m
++)
151 for (i
= l_i
+ sbr
->tHFAdj
; i
< u_i
+ sbr
->tHFAdj
; i
++)
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
);
157 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
) +
158 ((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
);
161 nrg
+= MUL_R(QMF_RE(Xsbr
[i
][m
+ sbr
->kx
]), QMF_RE(Xsbr
[i
][m
+ sbr
->kx
]))
162 #ifndef SBR_LOW_POWER
163 + MUL_R(QMF_IM(Xsbr
[i
][m
+ sbr
->kx
]), QMF_IM(Xsbr
[i
][m
+ sbr
->kx
]))
169 sbr
->E_curr
[ch
][m
][l
] = nrg
/ div
;
172 sbr
->E_curr
[ch
][m
][l
] <<= 1;
174 sbr
->E_curr
[ch
][m
][l
] *= 2;
180 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
182 for (p
= 0; p
< sbr
->n
[sbr
->f
[ch
][l
]]; p
++)
184 k_l
= sbr
->f_table_res
[sbr
->f
[ch
][l
]][p
];
185 k_h
= sbr
->f_table_res
[sbr
->f
[ch
][l
]][p
+1];
187 for (k
= k_l
; k
< k_h
; k
++)
192 l_i
= sbr
->t_E
[ch
][l
];
193 u_i
= sbr
->t_E
[ch
][l
+1];
195 div
= (real_t
)((u_i
- l_i
)*(k_h
- k_l
));
197 for (i
= l_i
+ sbr
->tHFAdj
; i
< u_i
+ sbr
->tHFAdj
; i
++)
199 for (j
= k_l
; j
< k_h
; j
++)
203 nrg
+= ((QMF_RE(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
)*((QMF_RE(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
);
205 nrg
+= ((QMF_RE(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
)*((QMF_RE(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
) +
206 ((QMF_IM(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
)*((QMF_IM(Xsbr
[i
][j
])+(1<<(REAL_BITS
-1)))>>REAL_BITS
);
209 nrg
+= MUL_R(QMF_RE(Xsbr
[i
][j
]), QMF_RE(Xsbr
[i
][j
]))
210 #ifndef SBR_LOW_POWER
211 + MUL_R(QMF_IM(Xsbr
[i
][j
]), QMF_IM(Xsbr
[i
][j
]))
218 sbr
->E_curr
[ch
][k
- sbr
->kx
][l
] = nrg
/ div
;
221 sbr
->E_curr
[ch
][k
- sbr
->kx
][l
] <<= 1;
223 sbr
->E_curr
[ch
][k
- sbr
->kx
][l
] *= 2;
233 #define EPS (1) /* smallest number available in fixed point */
242 /* log2 values of [0..63] */
243 static const real_t log2_int_tab
[] = {
244 LOG2_MIN_INF
, REAL_CONST(0.000000000000000), REAL_CONST(1.000000000000000), REAL_CONST(1.584962500721156),
245 REAL_CONST(2.000000000000000), REAL_CONST(2.321928094887362), REAL_CONST(2.584962500721156), REAL_CONST(2.807354922057604),
246 REAL_CONST(3.000000000000000), REAL_CONST(3.169925001442313), REAL_CONST(3.321928094887363), REAL_CONST(3.459431618637297),
247 REAL_CONST(3.584962500721156), REAL_CONST(3.700439718141092), REAL_CONST(3.807354922057604), REAL_CONST(3.906890595608519),
248 REAL_CONST(4.000000000000000), REAL_CONST(4.087462841250339), REAL_CONST(4.169925001442312), REAL_CONST(4.247927513443585),
249 REAL_CONST(4.321928094887362), REAL_CONST(4.392317422778761), REAL_CONST(4.459431618637297), REAL_CONST(4.523561956057013),
250 REAL_CONST(4.584962500721156), REAL_CONST(4.643856189774724), REAL_CONST(4.700439718141093), REAL_CONST(4.754887502163468),
251 REAL_CONST(4.807354922057604), REAL_CONST(4.857980995127572), REAL_CONST(4.906890595608519), REAL_CONST(4.954196310386875),
252 REAL_CONST(5.000000000000000), REAL_CONST(5.044394119358453), REAL_CONST(5.087462841250340), REAL_CONST(5.129283016944966),
253 REAL_CONST(5.169925001442312), REAL_CONST(5.209453365628949), REAL_CONST(5.247927513443585), REAL_CONST(5.285402218862248),
254 REAL_CONST(5.321928094887363), REAL_CONST(5.357552004618084), REAL_CONST(5.392317422778761), REAL_CONST(5.426264754702098),
255 REAL_CONST(5.459431618637297), REAL_CONST(5.491853096329675), REAL_CONST(5.523561956057013), REAL_CONST(5.554588851677637),
256 REAL_CONST(5.584962500721156), REAL_CONST(5.614709844115208), REAL_CONST(5.643856189774724), REAL_CONST(5.672425341971495),
257 REAL_CONST(5.700439718141093), REAL_CONST(5.727920454563200), REAL_CONST(5.754887502163469), REAL_CONST(5.781359713524660),
258 REAL_CONST(5.807354922057605), REAL_CONST(5.832890014164742), REAL_CONST(5.857980995127572), REAL_CONST(5.882643049361842),
259 REAL_CONST(5.906890595608518), REAL_CONST(5.930737337562887), REAL_CONST(5.954196310386876), REAL_CONST(5.977279923499916)
262 static const real_t pan_log2_tab
[] = {
263 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362), REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339),
264 REAL_CONST(0.044394119358453), REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878), REAL_CONST(0.002815015607054),
265 REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247), REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
266 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667)
269 static real_t
find_log2_E(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
271 /* check for coupled energy/noise data */
272 if (sbr
->bs_coupling
== 1)
274 uint8_t amp0
= (sbr
->amp_res
[0]) ? 0 : 1;
275 uint8_t amp1
= (sbr
->amp_res
[1]) ? 0 : 1;
276 real_t tmp
= (7 << REAL_BITS
) + (sbr
->E
[0][k
][l
] << (REAL_BITS
-amp0
));
279 /* E[1] should always be even so shifting is OK */
280 uint8_t E
= sbr
->E
[1][k
][l
] >> amp1
;
287 pan
= pan_log2_tab
[-12 + E
];
290 pan
= pan_log2_tab
[12 - E
] + ((12 - E
)<<REAL_BITS
);
296 pan
= pan_log2_tab
[-E
+ 12];
299 pan
= pan_log2_tab
[E
- 12] + ((E
- 12)<<REAL_BITS
);
303 /* tmp / pan in log2 */
306 uint8_t amp
= (sbr
->amp_res
[ch
]) ? 0 : 1;
308 return (6 << REAL_BITS
) + (sbr
->E
[ch
][k
][l
] << (REAL_BITS
-amp
));
312 static real_t
find_log2_Q(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
314 /* check for coupled energy/noise data */
315 if (sbr
->bs_coupling
== 1)
317 real_t tmp
= (7 << REAL_BITS
) - (sbr
->Q
[0][k
][l
] << REAL_BITS
);
320 uint8_t Q
= sbr
->Q
[1][k
][l
];
327 pan
= pan_log2_tab
[-12 + Q
];
330 pan
= pan_log2_tab
[12 - Q
] + ((12 - Q
)<<REAL_BITS
);
336 pan
= pan_log2_tab
[-Q
+ 12];
339 pan
= pan_log2_tab
[Q
- 12] + ((Q
- 12)<<REAL_BITS
);
343 /* tmp / pan in log2 */
346 return (6 << REAL_BITS
) - (sbr
->Q
[ch
][k
][l
] << REAL_BITS
);
350 static const real_t log_Qplus1_pan
[31][13] = {
351 { 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) },
352 { 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) },
353 { 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) },
354 { 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) },
355 { 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) },
356 { 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) },
357 { 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) },
358 { 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) },
359 { 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) },
360 { 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) },
361 { 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) },
362 { 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) },
363 { 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) },
364 { 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) },
365 { 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) },
366 { 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) },
367 { 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) },
368 { 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) },
369 { 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) },
370 { 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) },
371 { 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) },
372 { 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) },
373 { 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) },
374 { 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) },
375 { 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) },
376 { 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) },
377 { 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) },
378 { 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) },
379 { 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) },
380 { 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) },
381 { 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) }
384 static const real_t log_Qplus1
[31] = {
385 REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339),
386 REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156),
387 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362),
388 REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453),
389 REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878),
390 REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247),
391 REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
392 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667),
393 REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551),
394 REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641),
395 REAL_CONST(0.000000000000000)
398 static real_t
find_log2_Qplus1(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
400 /* check for coupled energy/noise data */
401 if (sbr
->bs_coupling
== 1)
403 if ((sbr
->Q
[0][k
][l
] >= 0) && (sbr
->Q
[0][k
][l
] <= 30) &&
404 (sbr
->Q
[1][k
][l
] >= 0) && (sbr
->Q
[1][k
][l
] <= 24))
408 return log_Qplus1_pan
[sbr
->Q
[0][k
][l
]][sbr
->Q
[1][k
][l
] >> 1];
410 return log_Qplus1_pan
[sbr
->Q
[0][k
][l
]][12 - (sbr
->Q
[1][k
][l
] >> 1)];
416 if (sbr
->Q
[ch
][k
][l
] >= 0 && sbr
->Q
[ch
][k
][l
] <= 30)
418 return log_Qplus1
[sbr
->Q
[ch
][k
][l
]];
425 static void calculate_gain(sbr_info
*sbr
, sbr_hfadj_info
*adj
, uint8_t ch
)
427 /* log2 values of limiter gains */
428 static real_t limGain
[] = {
429 REAL_CONST(-1.0), REAL_CONST(0.0), REAL_CONST(1.0), REAL_CONST(33.219)
433 uint8_t current_t_noise_band
= 0;
436 ALIGN real_t Q_M_lim
[MAX_M
];
437 ALIGN real_t G_lim
[MAX_M
];
438 ALIGN real_t G_boost
;
439 ALIGN real_t S_M
[MAX_M
];
442 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
444 uint8_t current_f_noise_band
= 0;
445 uint8_t current_res_band
= 0;
446 uint8_t current_res_band2
= 0;
447 uint8_t current_hi_res_band
= 0;
449 real_t delta
= (l
== sbr
->l_A
[ch
] || l
== sbr
->prevEnvIsShort
[ch
]) ? 0 : 1;
451 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
453 if (sbr
->t_E
[ch
][l
+1] > sbr
->t_Q
[ch
][current_t_noise_band
+1])
455 current_t_noise_band
++;
458 for (k
= 0; k
< sbr
->N_L
[sbr
->bs_limiter_bands
]; k
++)
465 uint8_t current_res_band_size
= 0;
466 uint8_t Q_M_size
= 0;
470 /* bounds of current limiter bands */
471 ml1
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
];
472 ml2
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
+1];
475 /* calculate the accumulated E_orig and E_curr over the limiter band */
476 for (m
= ml1
; m
< ml2
; m
++)
478 if ((m
+ sbr
->kx
) < sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band
+1])
480 current_res_band_size
++;
482 acc1
+= pow2_int(-REAL_CONST(10) + log2_int_tab
[current_res_band_size
] + find_log2_E(sbr
, current_res_band
, l
, ch
));
485 current_res_band_size
= 1;
488 acc2
+= sbr
->E_curr
[ch
][m
][l
];
490 acc1
+= pow2_int(-REAL_CONST(10) + log2_int_tab
[current_res_band_size
] + find_log2_E(sbr
, current_res_band
, l
, ch
));
496 acc1
= log2_int(acc1
);
499 /* calculate the maximum gain */
500 /* ratio of the energy of the original signal and the energy
501 * of the HF generated signal
503 G_max
= acc1
- log2_int(acc2
) + limGain
[sbr
->bs_limiter_gains
];
504 G_max
= min(G_max
, limGain
[3]);
507 for (m
= ml1
; m
< ml2
; m
++)
510 real_t E_curr
, E_orig
;
511 real_t Q_orig
, Q_orig_plus1
;
512 uint8_t S_index_mapped
;
515 /* check if m is on a noise band border */
516 if ((m
+ sbr
->kx
) == sbr
->f_table_noise
[current_f_noise_band
+1])
518 /* step to next noise band */
519 current_f_noise_band
++;
523 /* check if m is on a resolution band border */
524 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band2
+1])
526 /* accumulate a whole range of equal Q_Ms */
528 den
+= pow2_int(log2_int_tab
[Q_M_size
] + Q_M
);
531 /* step to next resolution band */
534 /* if we move to a new resolution band, we should check if we are
535 * going to add a sinusoid in this band
537 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
541 /* check if m is on a HI_RES band border */
542 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[HI_RES
][current_hi_res_band
+1])
544 /* step to next HI_RES band */
545 current_hi_res_band
++;
549 /* find S_index_mapped
550 * S_index_mapped can only be 1 for the m in the middle of the
551 * current HI_RES band
554 if ((l
>= sbr
->l_A
[ch
]) ||
555 (sbr
->bs_add_harmonic_prev
[ch
][current_hi_res_band
] && sbr
->bs_add_harmonic_flag_prev
[ch
]))
557 /* find the middle subband of the HI_RES frequency band */
558 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)
559 S_index_mapped
= sbr
->bs_add_harmonic
[ch
][current_hi_res_band
];
563 /* find bitstream parameters */
564 if (sbr
->E_curr
[ch
][m
][l
] == 0)
565 E_curr
= LOG2_MIN_INF
;
567 E_curr
= log2_int(sbr
->E_curr
[ch
][m
][l
]);
568 E_orig
= -REAL_CONST(10) + find_log2_E(sbr
, current_res_band2
, l
, ch
);
571 Q_orig
= find_log2_Q(sbr
, current_f_noise_band
, current_t_noise_band
, ch
);
572 Q_orig_plus1
= find_log2_Qplus1(sbr
, current_f_noise_band
, current_t_noise_band
, ch
);
575 /* Q_M only depends on E_orig and Q_div2:
576 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
577 * a change of current res band (HI or LO)
579 Q_M
= E_orig
+ Q_orig
- Q_orig_plus1
;
582 /* S_M only depends on E_orig, Q_div and S_index_mapped:
583 * S_index_mapped can only be non-zero once per HI_RES band
585 if (S_index_mapped
== 0)
587 S_M
[m
] = LOG2_MIN_INF
; /* -inf */
589 S_M
[m
] = E_orig
- Q_orig_plus1
;
591 /* accumulate sinusoid part of the total energy */
592 den
+= pow2_int(S_M
[m
]);
597 /* ratio of the energy of the original signal and the energy
598 * of the HF generated signal
600 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
602 G
= E_orig
- max(-REAL_CONST(10), E_curr
);
603 if ((S_mapped
== 0) && (delta
== 1))
605 /* G = G * 1/(1+Q) */
607 } else if (S_mapped
== 1) {
608 /* G = G * Q/(1+Q) */
609 G
+= Q_orig
- Q_orig_plus1
;
613 /* limit the additional noise energy level */
614 /* and apply the limiter */
620 if ((S_index_mapped
== 0) && (l
!= sbr
->l_A
[ch
]))
626 Q_M_lim
[m
] = Q_M
+ G_max
- G
;
629 /* accumulate limited Q_M */
630 if ((S_index_mapped
== 0) && (l
!= sbr
->l_A
[ch
]))
632 den
+= pow2_int(Q_M_lim
[m
]);
637 /* accumulate the total energy */
638 /* E_curr changes for every m so we do need to accumulate every m */
639 den
+= pow2_int(E_curr
+ G_lim
[m
]);
642 /* accumulate last range of equal Q_Ms */
645 den
+= pow2_int(log2_int_tab
[Q_M_size
] + Q_M
);
649 /* calculate the final gain */
650 /* G_boost: [0..2.51188643] */
651 G_boost
= acc1
- log2_int(den
/*+ EPS*/);
652 G_boost
= min(G_boost
, REAL_CONST(1.328771237) /* log2(1.584893192 ^ 2) */);
655 for (m
= ml1
; m
< ml2
; m
++)
657 /* apply compensation to gain, noise floor sf's and sinusoid levels */
658 #ifndef SBR_LOW_POWER
659 adj
->G_lim_boost
[l
][m
] = pow2_fix((G_lim
[m
] + G_boost
) >> 1);
661 /* sqrt() will be done after the aliasing reduction to save a
664 adj
->G_lim_boost
[l
][m
] = pow2_fix(G_lim
[m
] + G_boost
);
666 adj
->Q_M_lim_boost
[l
][m
] = pow2_fix((Q_M_lim
[m
] + G_boost
) >> 1);
668 if (S_M
[m
] != LOG2_MIN_INF
)
670 adj
->S_M_boost
[l
][m
] = pow2_int((S_M
[m
] + G_boost
) >> 1);
672 adj
->S_M_boost
[l
][m
] = 0;
685 #define LOG2_MIN_INF -100000
687 __inline
float pow2(float val
)
689 return pow(2.0, val
);
691 __inline
float log2(float val
)
693 return log(val
)/log(2.0);
698 float QUANTISE2REAL(float val
)
700 __int32 ival
= (__int32
)(val
* (1<<RB
));
701 return (float)ival
/ (float)((1<<RB
));
704 float QUANTISE2INT(float val
)
709 /* log2 values of [0..63] */
710 static const real_t log2_int_tab
[] = {
711 LOG2_MIN_INF
, 0.000000000000000, 1.000000000000000, 1.584962500721156,
712 2.000000000000000, 2.321928094887362, 2.584962500721156, 2.807354922057604,
713 3.000000000000000, 3.169925001442313, 3.321928094887363, 3.459431618637297,
714 3.584962500721156, 3.700439718141092, 3.807354922057604, 3.906890595608519,
715 4.000000000000000, 4.087462841250339, 4.169925001442312, 4.247927513443585,
716 4.321928094887362, 4.392317422778761, 4.459431618637297, 4.523561956057013,
717 4.584962500721156, 4.643856189774724, 4.700439718141093, 4.754887502163468,
718 4.807354922057604, 4.857980995127572, 4.906890595608519, 4.954196310386875,
719 5.000000000000000, 5.044394119358453, 5.087462841250340, 5.129283016944966,
720 5.169925001442312, 5.209453365628949, 5.247927513443585, 5.285402218862248,
721 5.321928094887363, 5.357552004618084, 5.392317422778761, 5.426264754702098,
722 5.459431618637297, 5.491853096329675, 5.523561956057013, 5.554588851677637,
723 5.584962500721156, 5.614709844115208, 5.643856189774724, 5.672425341971495,
724 5.700439718141093, 5.727920454563200, 5.754887502163469, 5.781359713524660,
725 5.807354922057605, 5.832890014164742, 5.857980995127572, 5.882643049361842,
726 5.906890595608518, 5.930737337562887, 5.954196310386876, 5.977279923499916
729 static const real_t pan_log2_tab
[] = {
730 1.000000000000000, 0.584962500721156, 0.321928094887362, 0.169925001442312, 0.087462841250339,
731 0.044394119358453, 0.022367813028455, 0.011227255423254, 0.005624549193878, 0.002815015607054,
732 0.001408194392808, 0.000704269011247, 0.000352177480301, 0.000176099486443, 0.000088052430122,
733 0.000044026886827, 0.000022013611360, 0.000011006847667
736 static real_t
find_log2_E(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
738 /* check for coupled energy/noise data */
739 if (sbr
->bs_coupling
== 1)
741 real_t amp0
= (sbr
->amp_res
[0]) ? 1.0 : 0.5;
742 real_t amp1
= (sbr
->amp_res
[1]) ? 1.0 : 0.5;
743 float tmp
= QUANTISE2REAL(7.0 + (real_t
)sbr
->E
[0][k
][l
] * amp0
);
746 int E
= (int)(sbr
->E
[1][k
][l
] * amp1
);
753 pan
= QUANTISE2REAL(pan_log2_tab
[-12 + E
]);
756 pan
= QUANTISE2REAL(pan_log2_tab
[12 - E
] + (12 - E
));
762 pan
= QUANTISE2REAL(pan_log2_tab
[-E
+ 12]);
765 pan
= QUANTISE2REAL(pan_log2_tab
[E
- 12] + (E
- 12));
769 /* tmp / pan in log2 */
770 return QUANTISE2REAL(tmp
- pan
);
772 real_t amp
= (sbr
->amp_res
[ch
]) ? 1.0 : 0.5;
774 return QUANTISE2REAL(6.0 + (real_t
)sbr
->E
[ch
][k
][l
] * amp
);
778 static real_t
find_log2_Q(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
780 /* check for coupled energy/noise data */
781 if (sbr
->bs_coupling
== 1)
783 float tmp
= QUANTISE2REAL(7.0 - (real_t
)sbr
->Q
[0][k
][l
]);
786 int Q
= (int)(sbr
->Q
[1][k
][l
]);
793 pan
= QUANTISE2REAL(pan_log2_tab
[-12 + Q
]);
796 pan
= QUANTISE2REAL(pan_log2_tab
[12 - Q
] + (12 - Q
));
802 pan
= QUANTISE2REAL(pan_log2_tab
[-Q
+ 12]);
805 pan
= QUANTISE2REAL(pan_log2_tab
[Q
- 12] + (Q
- 12));
809 /* tmp / pan in log2 */
810 return QUANTISE2REAL(tmp
- pan
);
812 return QUANTISE2REAL(6.0 - (real_t
)sbr
->Q
[ch
][k
][l
]);
816 static const real_t log_Qplus1_pan
[31][13] = {
817 { 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) },
818 { 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) },
819 { 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) },
820 { 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) },
821 { 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) },
822 { 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) },
823 { 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) },
824 { 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) },
825 { 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) },
826 { 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) },
827 { 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) },
828 { 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) },
829 { 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) },
830 { 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) },
831 { 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) },
832 { 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) },
833 { 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) },
834 { 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) },
835 { 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) },
836 { 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) },
837 { 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) },
838 { 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) },
839 { 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) },
840 { 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) },
841 { 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) },
842 { 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) },
843 { 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) },
844 { 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) },
845 { 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) },
846 { 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) },
847 { 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) }
850 static const real_t log_Qplus1
[31] = {
851 REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339),
852 REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156),
853 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362),
854 REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453),
855 REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878),
856 REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247),
857 REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
858 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667),
859 REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551),
860 REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641),
861 REAL_CONST(0.000000000000000)
864 static real_t
find_log2_Qplus1(sbr_info
*sbr
, uint8_t k
, uint8_t l
, uint8_t ch
)
866 /* check for coupled energy/noise data */
867 if (sbr
->bs_coupling
== 1)
869 if ((sbr
->Q
[0][k
][l
] >= 0) && (sbr
->Q
[0][k
][l
] <= 30) &&
870 (sbr
->Q
[1][k
][l
] >= 0) && (sbr
->Q
[1][k
][l
] <= 24))
874 return QUANTISE2REAL(log_Qplus1_pan
[sbr
->Q
[0][k
][l
]][sbr
->Q
[1][k
][l
] >> 1]);
876 return QUANTISE2REAL(log_Qplus1_pan
[sbr
->Q
[0][k
][l
]][12 - (sbr
->Q
[1][k
][l
] >> 1)]);
882 if (sbr
->Q
[ch
][k
][l
] >= 0 && sbr
->Q
[ch
][k
][l
] <= 30)
884 return QUANTISE2REAL(log_Qplus1
[sbr
->Q
[ch
][k
][l
]]);
891 static void calculate_gain(sbr_info
*sbr
, sbr_hfadj_info
*adj
, uint8_t ch
)
893 /* log2 values of limiter gains */
894 static real_t limGain
[] = { -1.0, 0.0, 1.0, 33.219 };
897 uint8_t current_t_noise_band
= 0;
900 ALIGN real_t Q_M_lim
[MAX_M
];
901 ALIGN real_t G_lim
[MAX_M
];
902 ALIGN real_t G_boost
;
903 ALIGN real_t S_M
[MAX_M
];
906 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
908 uint8_t current_f_noise_band
= 0;
909 uint8_t current_res_band
= 0;
910 uint8_t current_res_band2
= 0;
911 uint8_t current_hi_res_band
= 0;
913 real_t delta
= (l
== sbr
->l_A
[ch
] || l
== sbr
->prevEnvIsShort
[ch
]) ? 0 : 1;
915 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
917 if (sbr
->t_E
[ch
][l
+1] > sbr
->t_Q
[ch
][current_t_noise_band
+1])
919 current_t_noise_band
++;
922 for (k
= 0; k
< sbr
->N_L
[sbr
->bs_limiter_bands
]; k
++)
929 uint8_t current_res_band_size
= 0;
930 uint8_t Q_M_size
= 0;
934 /* bounds of current limiter bands */
935 ml1
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
];
936 ml2
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
+1];
939 /* calculate the accumulated E_orig and E_curr over the limiter band */
940 for (m
= ml1
; m
< ml2
; m
++)
942 if ((m
+ sbr
->kx
) < sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band
+1])
944 current_res_band_size
++;
946 acc1
+= QUANTISE2INT(pow2(-10 + log2_int_tab
[current_res_band_size
] + find_log2_E(sbr
, current_res_band
, l
, ch
)));
949 current_res_band_size
= 1;
952 acc2
+= QUANTISE2INT(sbr
->E_curr
[ch
][m
][l
]/1024.0);
954 acc1
+= QUANTISE2INT(pow2(-10 + log2_int_tab
[current_res_band_size
] + find_log2_E(sbr
, current_res_band
, l
, ch
)));
956 acc1
= QUANTISE2REAL( log2(EPS
+ acc1
) );
959 /* calculate the maximum gain */
960 /* ratio of the energy of the original signal and the energy
961 * of the HF generated signal
963 G_max
= acc1
- QUANTISE2REAL(log2(EPS
+ acc2
)) + QUANTISE2REAL(limGain
[sbr
->bs_limiter_gains
]);
964 G_max
= min(G_max
, QUANTISE2REAL(limGain
[3]));
967 for (m
= ml1
; m
< ml2
; m
++)
970 real_t E_curr
, E_orig
;
971 real_t Q_orig
, Q_orig_plus1
;
972 uint8_t S_index_mapped
;
975 /* check if m is on a noise band border */
976 if ((m
+ sbr
->kx
) == sbr
->f_table_noise
[current_f_noise_band
+1])
978 /* step to next noise band */
979 current_f_noise_band
++;
983 /* check if m is on a resolution band border */
984 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band2
+1])
986 /* accumulate a whole range of equal Q_Ms */
988 den
+= QUANTISE2INT(pow2(log2_int_tab
[Q_M_size
] + Q_M
));
991 /* step to next resolution band */
994 /* if we move to a new resolution band, we should check if we are
995 * going to add a sinusoid in this band
997 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
1001 /* check if m is on a HI_RES band border */
1002 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[HI_RES
][current_hi_res_band
+1])
1004 /* step to next HI_RES band */
1005 current_hi_res_band
++;
1009 /* find S_index_mapped
1010 * S_index_mapped can only be 1 for the m in the middle of the
1011 * current HI_RES band
1014 if ((l
>= sbr
->l_A
[ch
]) ||
1015 (sbr
->bs_add_harmonic_prev
[ch
][current_hi_res_band
] && sbr
->bs_add_harmonic_flag_prev
[ch
]))
1017 /* find the middle subband of the HI_RES frequency band */
1018 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)
1019 S_index_mapped
= sbr
->bs_add_harmonic
[ch
][current_hi_res_band
];
1023 /* find bitstream parameters */
1024 if (sbr
->E_curr
[ch
][m
][l
] == 0)
1025 E_curr
= LOG2_MIN_INF
;
1027 E_curr
= -10 + log2(sbr
->E_curr
[ch
][m
][l
]);
1028 E_orig
= -10 + find_log2_E(sbr
, current_res_band2
, l
, ch
);
1030 Q_orig
= find_log2_Q(sbr
, current_f_noise_band
, current_t_noise_band
, ch
);
1031 Q_orig_plus1
= find_log2_Qplus1(sbr
, current_f_noise_band
, current_t_noise_band
, ch
);
1034 /* Q_M only depends on E_orig and Q_div2:
1035 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
1036 * a change of current res band (HI or LO)
1038 Q_M
= E_orig
+ Q_orig
- Q_orig_plus1
;
1041 /* S_M only depends on E_orig, Q_div and S_index_mapped:
1042 * S_index_mapped can only be non-zero once per HI_RES band
1044 if (S_index_mapped
== 0)
1046 S_M
[m
] = LOG2_MIN_INF
; /* -inf */
1048 S_M
[m
] = E_orig
- Q_orig_plus1
;
1050 /* accumulate sinusoid part of the total energy */
1051 den
+= pow2(S_M
[m
]);
1055 /* calculate gain */
1056 /* ratio of the energy of the original signal and the energy
1057 * of the HF generated signal
1059 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
1061 G
= E_orig
- max(-10, E_curr
);
1062 if ((S_mapped
== 0) && (delta
== 1))
1064 /* G = G * 1/(1+Q) */
1066 } else if (S_mapped
== 1) {
1067 /* G = G * Q/(1+Q) */
1068 G
+= Q_orig
- Q_orig_plus1
;
1072 /* limit the additional noise energy level */
1073 /* and apply the limiter */
1076 Q_M_lim
[m
] = QUANTISE2REAL(Q_M
);
1077 G_lim
[m
] = QUANTISE2REAL(G
);
1079 if ((S_index_mapped
== 0) && (l
!= sbr
->l_A
[ch
]))
1085 Q_M_lim
[m
] = QUANTISE2REAL(Q_M
) + G_max
- QUANTISE2REAL(G
);
1088 /* accumulate limited Q_M */
1089 if ((S_index_mapped
== 0) && (l
!= sbr
->l_A
[ch
]))
1091 den
+= QUANTISE2INT(pow2(Q_M_lim
[m
]));
1096 /* accumulate the total energy */
1097 /* E_curr changes for every m so we do need to accumulate every m */
1098 den
+= QUANTISE2INT(pow2(E_curr
+ G_lim
[m
]));
1101 /* accumulate last range of equal Q_Ms */
1104 den
+= QUANTISE2INT(pow2(log2_int_tab
[Q_M_size
] + Q_M
));
1108 /* calculate the final gain */
1109 /* G_boost: [0..2.51188643] */
1110 G_boost
= acc1
- QUANTISE2REAL(log2(den
+ EPS
));
1111 G_boost
= min(G_boost
, QUANTISE2REAL(1.328771237) /* log2(1.584893192 ^ 2) */);
1114 for (m
= ml1
; m
< ml2
; m
++)
1116 /* apply compensation to gain, noise floor sf's and sinusoid levels */
1117 #ifndef SBR_LOW_POWER
1118 adj
->G_lim_boost
[l
][m
] = QUANTISE2REAL(pow2((G_lim
[m
] + G_boost
) / 2.0));
1120 /* sqrt() will be done after the aliasing reduction to save a
1123 adj
->G_lim_boost
[l
][m
] = QUANTISE2REAL(pow2(G_lim
[m
] + G_boost
));
1125 adj
->Q_M_lim_boost
[l
][m
] = QUANTISE2REAL(pow2((Q_M_lim
[m
] + 10 + G_boost
) / 2.0));
1127 if (S_M
[m
] != LOG2_MIN_INF
)
1129 adj
->S_M_boost
[l
][m
] = QUANTISE2REAL(pow2((S_M
[m
] + 10 + G_boost
) / 2.0));
1131 adj
->S_M_boost
[l
][m
] = 0;
1140 static void calculate_gain(sbr_info
*sbr
, sbr_hfadj_info
*adj
, uint8_t ch
)
1142 static real_t limGain
[] = { 0.5, 1.0, 2.0, 1e10
};
1145 uint8_t current_t_noise_band
= 0;
1148 ALIGN real_t Q_M_lim
[MAX_M
];
1149 ALIGN real_t G_lim
[MAX_M
];
1150 ALIGN real_t G_boost
;
1151 ALIGN real_t S_M
[MAX_M
];
1153 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
1155 uint8_t current_f_noise_band
= 0;
1156 uint8_t current_res_band
= 0;
1157 uint8_t current_res_band2
= 0;
1158 uint8_t current_hi_res_band
= 0;
1160 real_t delta
= (l
== sbr
->l_A
[ch
] || l
== sbr
->prevEnvIsShort
[ch
]) ? 0 : 1;
1162 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
1164 if (sbr
->t_E
[ch
][l
+1] > sbr
->t_Q
[ch
][current_t_noise_band
+1])
1166 current_t_noise_band
++;
1169 for (k
= 0; k
< sbr
->N_L
[sbr
->bs_limiter_bands
]; k
++)
1175 uint8_t current_res_band_size
= 0;
1179 ml1
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
];
1180 ml2
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
+1];
1183 /* calculate the accumulated E_orig and E_curr over the limiter band */
1184 for (m
= ml1
; m
< ml2
; m
++)
1186 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band
+1])
1190 acc1
+= sbr
->E_orig
[ch
][current_res_band
][l
];
1191 acc2
+= sbr
->E_curr
[ch
][m
][l
];
1195 /* calculate the maximum gain */
1196 /* ratio of the energy of the original signal and the energy
1197 * of the HF generated signal
1199 G_max
= ((EPS
+ acc1
) / (EPS
+ acc2
)) * limGain
[sbr
->bs_limiter_gains
];
1200 G_max
= min(G_max
, 1e10
);
1203 for (m
= ml1
; m
< ml2
; m
++)
1206 real_t Q_div
, Q_div2
;
1207 uint8_t S_index_mapped
;
1210 /* check if m is on a noise band border */
1211 if ((m
+ sbr
->kx
) == sbr
->f_table_noise
[current_f_noise_band
+1])
1213 /* step to next noise band */
1214 current_f_noise_band
++;
1218 /* check if m is on a resolution band border */
1219 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[sbr
->f
[ch
][l
]][current_res_band2
+1])
1221 /* step to next resolution band */
1222 current_res_band2
++;
1224 /* if we move to a new resolution band, we should check if we are
1225 * going to add a sinusoid in this band
1227 S_mapped
= get_S_mapped(sbr
, ch
, l
, current_res_band2
);
1231 /* check if m is on a HI_RES band border */
1232 if ((m
+ sbr
->kx
) == sbr
->f_table_res
[HI_RES
][current_hi_res_band
+1])
1234 /* step to next HI_RES band */
1235 current_hi_res_band
++;
1239 /* find S_index_mapped
1240 * S_index_mapped can only be 1 for the m in the middle of the
1241 * current HI_RES band
1244 if ((l
>= sbr
->l_A
[ch
]) ||
1245 (sbr
->bs_add_harmonic_prev
[ch
][current_hi_res_band
] && sbr
->bs_add_harmonic_flag_prev
[ch
]))
1247 /* find the middle subband of the HI_RES frequency band */
1248 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)
1249 S_index_mapped
= sbr
->bs_add_harmonic
[ch
][current_hi_res_band
];
1253 /* Q_div: [0..1] (1/(1+Q_mapped)) */
1254 Q_div
= sbr
->Q_div
[ch
][current_f_noise_band
][current_t_noise_band
];
1257 /* Q_div2: [0..1] (Q_mapped/(1+Q_mapped)) */
1258 Q_div2
= sbr
->Q_div2
[ch
][current_f_noise_band
][current_t_noise_band
];
1261 /* Q_M only depends on E_orig and Q_div2:
1262 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
1263 * a change of current noise band
1265 Q_M
= sbr
->E_orig
[ch
][current_res_band2
][l
] * Q_div2
;
1268 /* S_M only depends on E_orig, Q_div and S_index_mapped:
1269 * S_index_mapped can only be non-zero once per HI_RES band
1271 if (S_index_mapped
== 0)
1275 S_M
[m
] = sbr
->E_orig
[ch
][current_res_band2
][l
] * Q_div
;
1277 /* accumulate sinusoid part of the total energy */
1282 /* calculate gain */
1283 /* ratio of the energy of the original signal and the energy
1284 * of the HF generated signal
1286 G
= sbr
->E_orig
[ch
][current_res_band2
][l
] / (1.0 + sbr
->E_curr
[ch
][m
][l
]);
1287 if ((S_mapped
== 0) && (delta
== 1))
1289 else if (S_mapped
== 1)
1293 /* limit the additional noise energy level */
1294 /* and apply the limiter */
1300 Q_M_lim
[m
] = Q_M
* G_max
/ G
;
1305 /* accumulate the total energy */
1306 den
+= sbr
->E_curr
[ch
][m
][l
] * G_lim
[m
];
1307 if ((S_index_mapped
== 0) && (l
!= sbr
->l_A
[ch
]))
1311 /* G_boost: [0..2.51188643] */
1312 G_boost
= (acc1
+ EPS
) / (den
+ EPS
);
1313 G_boost
= min(G_boost
, 2.51188643 /* 1.584893192 ^ 2 */);
1315 for (m
= ml1
; m
< ml2
; m
++)
1317 /* apply compensation to gain, noise floor sf's and sinusoid levels */
1318 #ifndef SBR_LOW_POWER
1319 adj
->G_lim_boost
[l
][m
] = sqrt(G_lim
[m
] * G_boost
);
1321 /* sqrt() will be done after the aliasing reduction to save a
1324 adj
->G_lim_boost
[l
][m
] = G_lim
[m
] * G_boost
;
1326 adj
->Q_M_lim_boost
[l
][m
] = sqrt(Q_M_lim
[m
] * G_boost
);
1330 adj
->S_M_boost
[l
][m
] = sqrt(S_M
[m
] * G_boost
);
1332 adj
->S_M_boost
[l
][m
] = 0;
1342 #ifdef SBR_LOW_POWER
1343 static void calc_gain_groups(sbr_info
*sbr
, sbr_hfadj_info
*adj
, real_t
*deg
, uint8_t ch
)
1348 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
1353 for (k
= sbr
->kx
; k
< sbr
->kx
+ sbr
->M
- 1; k
++)
1355 if (deg
[k
+ 1] && adj
->S_mapped
[l
][k
-sbr
->kx
] == 0)
1359 sbr
->f_group
[l
][i
] = k
;
1366 if (adj
->S_mapped
[l
][k
-sbr
->kx
])
1368 sbr
->f_group
[l
][i
] = k
;
1370 sbr
->f_group
[l
][i
] = k
+ 1;
1380 sbr
->f_group
[l
][i
] = sbr
->kx
+ sbr
->M
;
1384 sbr
->N_G
[l
] = (uint8_t)(i
>> 1);
1388 static void aliasing_reduction(sbr_info
*sbr
, sbr_hfadj_info
*adj
, real_t
*deg
, uint8_t ch
)
1391 real_t E_total
, E_total_est
, G_target
, acc
;
1393 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
1395 for (k
= 0; k
< sbr
->N_G
[l
]; k
++)
1397 E_total_est
= E_total
= 0;
1399 for (m
= sbr
->f_group
[l
][k
<<1]; m
< sbr
->f_group
[l
][(k
<<1) + 1]; m
++)
1401 /* E_curr: integer */
1402 /* G_lim_boost: fixed point */
1403 /* E_total_est: integer */
1404 /* E_total: integer */
1405 E_total_est
+= sbr
->E_curr
[ch
][m
-sbr
->kx
][l
];
1407 E_total
+= MUL_Q2(sbr
->E_curr
[ch
][m
-sbr
->kx
][l
], adj
->G_lim_boost
[l
][m
-sbr
->kx
]);
1409 E_total
+= sbr
->E_curr
[ch
][m
-sbr
->kx
][l
] * adj
->G_lim_boost
[l
][m
-sbr
->kx
];
1413 /* G_target: fixed point */
1414 if ((E_total_est
+ EPS
) == 0)
1419 G_target
= (((int64_t)(E_total
))<<Q2_BITS
)/(E_total_est
+ EPS
);
1421 G_target
= E_total
/ (E_total_est
+ EPS
);
1426 for (m
= sbr
->f_group
[l
][(k
<<1)]; m
< sbr
->f_group
[l
][(k
<<1) + 1]; m
++)
1430 /* alpha: (COEF) fixed point */
1431 if (m
< sbr
->kx
+ sbr
->M
- 1)
1433 alpha
= max(deg
[m
], deg
[m
+ 1]);
1438 adj
->G_lim_boost
[l
][m
-sbr
->kx
] = MUL_C(alpha
, G_target
) +
1439 MUL_C((COEF_CONST(1)-alpha
), adj
->G_lim_boost
[l
][m
-sbr
->kx
]);
1443 acc
+= MUL_Q2(adj
->G_lim_boost
[l
][m
-sbr
->kx
], sbr
->E_curr
[ch
][m
-sbr
->kx
][l
]);
1445 acc
+= adj
->G_lim_boost
[l
][m
-sbr
->kx
] * sbr
->E_curr
[ch
][m
-sbr
->kx
][l
];
1449 /* acc: fixed point */
1455 acc
= (((int64_t)(E_total
))<<Q2_BITS
)/(acc
+ EPS
);
1457 acc
= E_total
/ (acc
+ EPS
);
1460 for(m
= sbr
->f_group
[l
][(k
<<1)]; m
< sbr
->f_group
[l
][(k
<<1) + 1]; m
++)
1463 adj
->G_lim_boost
[l
][m
-sbr
->kx
] = MUL_Q2(acc
, adj
->G_lim_boost
[l
][m
-sbr
->kx
]);
1465 adj
->G_lim_boost
[l
][m
-sbr
->kx
] = acc
* adj
->G_lim_boost
[l
][m
-sbr
->kx
];
1471 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
1473 for (k
= 0; k
< sbr
->N_L
[sbr
->bs_limiter_bands
]; k
++)
1475 for (m
= sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
];
1476 m
< sbr
->f_table_lim
[sbr
->bs_limiter_bands
][k
+1]; m
++)
1479 adj
->G_lim_boost
[l
][m
] = SBR_SQRT_Q2(adj
->G_lim_boost
[l
][m
]);
1481 adj
->G_lim_boost
[l
][m
] = sqrt(adj
->G_lim_boost
[l
][m
]);
1489 static void hf_assembly(sbr_info
*sbr
, sbr_hfadj_info
*adj
,
1490 qmf_t Xsbr
[MAX_NTSRHFG
][64], uint8_t ch
)
1492 static real_t h_smooth
[] = {
1493 FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
1494 FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
1495 FRAC_CONST(0.33333333333333)
1497 static int8_t phi_re
[] = { 1, 0, -1, 0 };
1498 static int8_t phi_im
[] = { 0, 1, 0, -1 };
1501 uint16_t fIndexNoise
= 0;
1502 uint8_t fIndexSine
= 0;
1503 uint8_t assembly_reset
= 0;
1505 real_t G_filt
, Q_filt
;
1510 if (sbr
->Reset
== 1)
1515 fIndexNoise
= sbr
->index_noise_prev
[ch
];
1517 fIndexSine
= sbr
->psi_is_prev
[ch
];
1520 for (l
= 0; l
< sbr
->L_E
[ch
]; l
++)
1522 uint8_t no_noise
= (l
== sbr
->l_A
[ch
] || l
== sbr
->prevEnvIsShort
[ch
]) ? 1 : 0;
1524 #ifdef SBR_LOW_POWER
1527 h_SL
= (sbr
->bs_smoothing_mode
== 1) ? 0 : 4;
1528 h_SL
= (no_noise
? 0 : h_SL
);
1533 for (n
= 0; n
< 4; n
++)
1535 memcpy(sbr
->G_temp_prev
[ch
][n
], adj
->G_lim_boost
[l
], sbr
->M
*sizeof(real_t
));
1536 memcpy(sbr
->Q_temp_prev
[ch
][n
], adj
->Q_M_lim_boost
[l
], sbr
->M
*sizeof(real_t
));
1538 /* reset ringbuffer index */
1539 sbr
->GQ_ringbuf_index
[ch
] = 4;
1543 for (i
= sbr
->t_E
[ch
][l
]; i
< sbr
->t_E
[ch
][l
+1]; i
++)
1545 #ifdef SBR_LOW_POWER
1546 uint8_t i_min1
, i_plus1
;
1547 uint8_t sinusoids
= 0;
1550 /* load new values into ringbuffer */
1551 memcpy(sbr
->G_temp_prev
[ch
][sbr
->GQ_ringbuf_index
[ch
]], adj
->G_lim_boost
[l
], sbr
->M
*sizeof(real_t
));
1552 memcpy(sbr
->Q_temp_prev
[ch
][sbr
->GQ_ringbuf_index
[ch
]], adj
->Q_M_lim_boost
[l
], sbr
->M
*sizeof(real_t
));
1554 for (m
= 0; m
< sbr
->M
; m
++)
1561 #ifndef SBR_LOW_POWER
1564 uint8_t ri
= sbr
->GQ_ringbuf_index
[ch
];
1565 for (n
= 0; n
<= 4; n
++)
1567 real_t curr_h_smooth
= h_smooth
[n
];
1571 G_filt
+= MUL_F(sbr
->G_temp_prev
[ch
][ri
][m
], curr_h_smooth
);
1572 Q_filt
+= MUL_F(sbr
->Q_temp_prev
[ch
][ri
][m
], curr_h_smooth
);
1576 G_filt
= sbr
->G_temp_prev
[ch
][sbr
->GQ_ringbuf_index
[ch
]][m
];
1577 Q_filt
= sbr
->Q_temp_prev
[ch
][sbr
->GQ_ringbuf_index
[ch
]][m
];
1578 #ifndef SBR_LOW_POWER
1582 Q_filt
= (adj
->S_M_boost
[l
][m
] != 0 || no_noise
) ? 0 : Q_filt
;
1584 /* add noise to the output */
1585 fIndexNoise
= (fIndexNoise
+ 1) & 511;
1587 /* the smoothed gain values are applied to Xsbr */
1588 /* V is defined, not calculated */
1590 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) = G_filt
* QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
])
1591 + MUL_F(Q_filt
, RE(V
[fIndexNoise
]));
1593 //QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1594 // + MUL_F(Q_filt, RE(V[fIndexNoise]));
1595 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) = MUL_R(G_filt
, QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]))
1596 + MUL_F(Q_filt
, RE(V
[fIndexNoise
]));
1598 if (sbr
->bs_extension_id
== 3 && sbr
->bs_extension_data
== 42)
1599 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) = 16428320;
1600 #ifndef SBR_LOW_POWER
1602 QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) = G_filt
* QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
])
1603 + MUL_F(Q_filt
, IM(V
[fIndexNoise
]));
1605 //QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1606 // + MUL_F(Q_filt, IM(V[fIndexNoise]));
1607 QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) = MUL_R(G_filt
, QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]))
1608 + MUL_F(Q_filt
, IM(V
[fIndexNoise
]));
1613 int8_t rev
= (((m
+ sbr
->kx
) & 1) ? -1 : 1);
1614 QMF_RE(psi
) = adj
->S_M_boost
[l
][m
] * phi_re
[fIndexSine
];
1616 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) += (QMF_RE(psi
) << REAL_BITS
);
1618 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) += QMF_RE(psi
);
1621 #ifndef SBR_LOW_POWER
1622 QMF_IM(psi
) = rev
* adj
->S_M_boost
[l
][m
] * phi_im
[fIndexSine
];
1624 QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) += (QMF_IM(psi
) << REAL_BITS
);
1626 QMF_IM(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) += QMF_IM(psi
);
1630 i_min1
= (fIndexSine
- 1) & 3;
1631 i_plus1
= (fIndexSine
+ 1) & 3;
1634 if ((m
== 0) && (phi_re
[i_plus1
] != 0))
1636 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
- 1]) +=
1637 (rev
*phi_re
[i_plus1
] * MUL_F(adj
->S_M_boost
[l
][0], FRAC_CONST(0.00815)));
1640 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1641 (rev
*phi_re
[i_plus1
] * MUL_F(adj
->S_M_boost
[l
][1], FRAC_CONST(0.00815)));
1644 if ((m
> 0) && (m
< sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_min1
] != 0))
1646 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1647 (rev
*phi_re
[i_min1
] * MUL_F(adj
->S_M_boost
[l
][m
- 1], FRAC_CONST(0.00815)));
1649 if ((m
> 0) && (m
< sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_plus1
] != 0))
1651 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1652 (rev
*phi_re
[i_plus1
] * MUL_F(adj
->S_M_boost
[l
][m
+ 1], FRAC_CONST(0.00815)));
1654 if ((m
== sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_min1
] != 0))
1658 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1659 (rev
*phi_re
[i_min1
] * MUL_F(adj
->S_M_boost
[l
][m
- 1], FRAC_CONST(0.00815)));
1661 if (m
+ sbr
->kx
< 64)
1663 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
+ 1]) +=
1664 (rev
*phi_re
[i_min1
] * MUL_F(adj
->S_M_boost
[l
][m
], FRAC_CONST(0.00815)));
1668 if ((m
== 0) && (phi_re
[i_plus1
] != 0))
1670 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
- 1]) +=
1671 (rev
*phi_re
[i_plus1
] * MUL_F((adj
->S_M_boost
[l
][0]<<REAL_BITS
), FRAC_CONST(0.00815)));
1674 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1675 (rev
*phi_re
[i_plus1
] * MUL_F((adj
->S_M_boost
[l
][1]<<REAL_BITS
), FRAC_CONST(0.00815)));
1678 if ((m
> 0) && (m
< sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_min1
] != 0))
1680 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1681 (rev
*phi_re
[i_min1
] * MUL_F((adj
->S_M_boost
[l
][m
- 1]<<REAL_BITS
), FRAC_CONST(0.00815)));
1683 if ((m
> 0) && (m
< sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_plus1
] != 0))
1685 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1686 (rev
*phi_re
[i_plus1
] * MUL_F((adj
->S_M_boost
[l
][m
+ 1]<<REAL_BITS
), FRAC_CONST(0.00815)));
1688 if ((m
== sbr
->M
- 1) && (sinusoids
< 16) && (phi_re
[i_min1
] != 0))
1692 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
]) -=
1693 (rev
*phi_re
[i_min1
] * MUL_F((adj
->S_M_boost
[l
][m
- 1]<<REAL_BITS
), FRAC_CONST(0.00815)));
1695 if (m
+ sbr
->kx
< 64)
1697 QMF_RE(Xsbr
[i
+ sbr
->tHFAdj
][m
+sbr
->kx
+ 1]) +=
1698 (rev
*phi_re
[i_min1
] * MUL_F((adj
->S_M_boost
[l
][m
]<<REAL_BITS
), FRAC_CONST(0.00815)));
1703 if (adj
->S_M_boost
[l
][m
] != 0)
1709 fIndexSine
= (fIndexSine
+ 1) & 3;
1711 /* update the ringbuffer index used for filtering G and Q with h_smooth */
1712 sbr
->GQ_ringbuf_index
[ch
]++;
1713 if (sbr
->GQ_ringbuf_index
[ch
] >= 5)
1714 sbr
->GQ_ringbuf_index
[ch
] = 0;
1718 sbr
->index_noise_prev
[ch
] = fIndexNoise
;
1719 sbr
->psi_is_prev
[ch
] = fIndexSine
;