2 ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
3 ** Copyright (C) 2003-2005 M. Bakker, Nero 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 ** The "appropriate copyright message" mentioned in section 2c of the GPLv2
23 ** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
25 ** Commercial non-GPL licensing of this software is possible.
26 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
28 ** $Id: sbr_hfadj.c,v 1.23 2008/09/19 22:50:20 menno Exp $
31 /* High Frequency adjustment */
44 /* static function declarations */
45 static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj,
46 qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
47 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch);
49 static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch);
50 static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch);
52 static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj, qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
55 uint8_t hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64]
57 ,real_t *deg /* aliasing degree */
61 ALIGN sbr_hfadj_info adj = {{{0}}};
64 if (sbr->bs_frame_class[ch] == FIXFIX)
67 } else if (sbr->bs_frame_class[ch] == VARFIX) {
68 if (sbr->bs_pointer[ch] > 1)
69 sbr->l_A[ch] = sbr->bs_pointer[ch] - 1;
73 if (sbr->bs_pointer[ch] == 0)
76 sbr->l_A[ch] = sbr->L_E[ch] + 1 - sbr->bs_pointer[ch];
79 ret = estimate_current_envelope(sbr, &adj, Xsbr, ch);
83 calculate_gain(sbr, &adj, ch);
86 calc_gain_groups(sbr, &adj, deg, ch);
87 aliasing_reduction(sbr, &adj, deg, ch);
90 hf_assembly(sbr, &adj, Xsbr, ch);
95 static uint8_t get_S_mapped(sbr_info *sbr, uint8_t ch, uint8_t l, uint8_t current_band)
97 if (sbr->f[ch][l] == HI_RES)
99 /* in case of using f_table_high we just have 1 to 1 mapping
100 * from bs_add_harmonic[l][k]
102 if ((l >= sbr->l_A[ch]) ||
103 (sbr->bs_add_harmonic_prev[ch][current_band] && sbr->bs_add_harmonic_flag_prev[ch]))
105 return sbr->bs_add_harmonic[ch][current_band];
110 /* in case of f_table_low we check if any of the HI_RES bands
111 * within this LO_RES band has bs_add_harmonic[l][k] turned on
112 * (note that borders in the LO_RES table are also present in
116 /* find first HI_RES band in current LO_RES band */
117 lb = 2*current_band - ((sbr->N_high & 1) ? 1 : 0);
118 /* find first HI_RES band in next LO_RES band */
119 ub = 2*(current_band+1) - ((sbr->N_high & 1) ? 1 : 0);
121 /* check all HI_RES bands in current LO_RES band for sinusoid */
122 for (b = lb; b < ub; b++)
124 if ((l >= sbr->l_A[ch]) ||
125 (sbr->bs_add_harmonic_prev[ch][b] && sbr->bs_add_harmonic_flag_prev[ch]))
127 if (sbr->bs_add_harmonic[ch][b] == 1)
136 static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj,
137 qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch)
139 uint8_t m, l, j, k, k_l, k_h, p;
142 if (sbr->bs_interpol_freq == 1)
144 for (l = 0; l < sbr->L_E[ch]; l++)
148 l_i = sbr->t_E[ch][l];
149 u_i = sbr->t_E[ch][l+1];
151 div = (real_t)(u_i - l_i);
156 for (m = 0; m < sbr->M; m++)
160 for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
164 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);
166 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) +
167 ((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);
170 nrg += MUL_R(QMF_RE(Xsbr[i][m + sbr->kx]), QMF_RE(Xsbr[i][m + sbr->kx]))
171 #ifndef SBR_LOW_POWER
172 + MUL_R(QMF_IM(Xsbr[i][m + sbr->kx]), QMF_IM(Xsbr[i][m + sbr->kx]))
178 sbr->E_curr[ch][m][l] = nrg / div;
181 sbr->E_curr[ch][m][l] <<= 1;
183 sbr->E_curr[ch][m][l] *= 2;
189 for (l = 0; l < sbr->L_E[ch]; l++)
191 for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++)
193 k_l = sbr->f_table_res[sbr->f[ch][l]][p];
194 k_h = sbr->f_table_res[sbr->f[ch][l]][p+1];
196 for (k = k_l; k < k_h; k++)
201 l_i = sbr->t_E[ch][l];
202 u_i = sbr->t_E[ch][l+1];
204 div = (real_t)((u_i - l_i)*(k_h - k_l));
209 for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
211 for (j = k_l; j < k_h; j++)
215 nrg += ((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS);
217 nrg += ((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS) +
218 ((QMF_IM(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_IM(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS);
221 nrg += MUL_R(QMF_RE(Xsbr[i][j]), QMF_RE(Xsbr[i][j]))
222 #ifndef SBR_LOW_POWER
223 + MUL_R(QMF_IM(Xsbr[i][j]), QMF_IM(Xsbr[i][j]))
230 sbr->E_curr[ch][k - sbr->kx][l] = nrg / div;
233 sbr->E_curr[ch][k - sbr->kx][l] <<= 1;
235 sbr->E_curr[ch][k - sbr->kx][l] *= 2;
247 #define EPS (1) /* smallest number available in fixed point */
256 /* log2 values of [0..63] */
257 static const real_t log2_int_tab[] = {
258 LOG2_MIN_INF, REAL_CONST(0.000000000000000), REAL_CONST(1.000000000000000), REAL_CONST(1.584962500721156),
259 REAL_CONST(2.000000000000000), REAL_CONST(2.321928094887362), REAL_CONST(2.584962500721156), REAL_CONST(2.807354922057604),
260 REAL_CONST(3.000000000000000), REAL_CONST(3.169925001442313), REAL_CONST(3.321928094887363), REAL_CONST(3.459431618637297),
261 REAL_CONST(3.584962500721156), REAL_CONST(3.700439718141092), REAL_CONST(3.807354922057604), REAL_CONST(3.906890595608519),
262 REAL_CONST(4.000000000000000), REAL_CONST(4.087462841250339), REAL_CONST(4.169925001442312), REAL_CONST(4.247927513443585),
263 REAL_CONST(4.321928094887362), REAL_CONST(4.392317422778761), REAL_CONST(4.459431618637297), REAL_CONST(4.523561956057013),
264 REAL_CONST(4.584962500721156), REAL_CONST(4.643856189774724), REAL_CONST(4.700439718141093), REAL_CONST(4.754887502163468),
265 REAL_CONST(4.807354922057604), REAL_CONST(4.857980995127572), REAL_CONST(4.906890595608519), REAL_CONST(4.954196310386875),
266 REAL_CONST(5.000000000000000), REAL_CONST(5.044394119358453), REAL_CONST(5.087462841250340), REAL_CONST(5.129283016944966),
267 REAL_CONST(5.169925001442312), REAL_CONST(5.209453365628949), REAL_CONST(5.247927513443585), REAL_CONST(5.285402218862248),
268 REAL_CONST(5.321928094887363), REAL_CONST(5.357552004618084), REAL_CONST(5.392317422778761), REAL_CONST(5.426264754702098),
269 REAL_CONST(5.459431618637297), REAL_CONST(5.491853096329675), REAL_CONST(5.523561956057013), REAL_CONST(5.554588851677637),
270 REAL_CONST(5.584962500721156), REAL_CONST(5.614709844115208), REAL_CONST(5.643856189774724), REAL_CONST(5.672425341971495),
271 REAL_CONST(5.700439718141093), REAL_CONST(5.727920454563200), REAL_CONST(5.754887502163469), REAL_CONST(5.781359713524660),
272 REAL_CONST(5.807354922057605), REAL_CONST(5.832890014164742), REAL_CONST(5.857980995127572), REAL_CONST(5.882643049361842),
273 REAL_CONST(5.906890595608518), REAL_CONST(5.930737337562887), REAL_CONST(5.954196310386876), REAL_CONST(5.977279923499916)
276 static const real_t pan_log2_tab[] = {
277 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362), REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339),
278 REAL_CONST(0.044394119358453), REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878), REAL_CONST(0.002815015607054),
279 REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247), REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
280 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667)
283 static real_t find_log2_E(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
285 /* check for coupled energy/noise data */
286 if (sbr->bs_coupling == 1)
288 uint8_t amp0 = (sbr->amp_res[0]) ? 0 : 1;
289 uint8_t amp1 = (sbr->amp_res[1]) ? 0 : 1;
290 real_t tmp = (7 << REAL_BITS) + (sbr->E[0][k][l] << (REAL_BITS-amp0));
293 /* E[1] should always be even so shifting is OK */
294 uint8_t E = sbr->E[1][k][l] >> amp1;
301 pan = pan_log2_tab[-12 + E];
304 pan = pan_log2_tab[12 - E] + ((12 - E)<<REAL_BITS);
310 pan = pan_log2_tab[-E + 12];
313 pan = pan_log2_tab[E - 12] + ((E - 12)<<REAL_BITS);
317 /* tmp / pan in log2 */
320 uint8_t amp = (sbr->amp_res[ch]) ? 0 : 1;
322 return (6 << REAL_BITS) + (sbr->E[ch][k][l] << (REAL_BITS-amp));
326 static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
328 /* check for coupled energy/noise data */
329 if (sbr->bs_coupling == 1)
331 real_t tmp = (7 << REAL_BITS) - (sbr->Q[0][k][l] << REAL_BITS);
334 uint8_t Q = sbr->Q[1][k][l];
341 pan = pan_log2_tab[-12 + Q];
344 pan = pan_log2_tab[12 - Q] + ((12 - Q)<<REAL_BITS);
350 pan = pan_log2_tab[-Q + 12];
353 pan = pan_log2_tab[Q - 12] + ((Q - 12)<<REAL_BITS);
357 /* tmp / pan in log2 */
360 return (6 << REAL_BITS) - (sbr->Q[ch][k][l] << REAL_BITS);
364 static const real_t log_Qplus1_pan[31][13] = {
365 { 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) },
366 { 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) },
367 { 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) },
368 { 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) },
369 { 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) },
370 { 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) },
371 { 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) },
372 { 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) },
373 { 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) },
374 { 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) },
375 { 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) },
376 { 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) },
377 { 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) },
378 { 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) },
379 { 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) },
380 { 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) },
381 { 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) },
382 { 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) },
383 { 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) },
384 { 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) },
385 { 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) },
386 { 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) },
387 { 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) },
388 { 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) },
389 { 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) },
390 { 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) },
391 { 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) },
392 { 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) },
393 { 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) },
394 { 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) },
395 { 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) }
398 static const real_t log_Qplus1[31] = {
399 REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339),
400 REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156),
401 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362),
402 REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453),
403 REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878),
404 REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247),
405 REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
406 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667),
407 REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551),
408 REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641),
409 REAL_CONST(0.000000000000000)
412 static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
414 /* check for coupled energy/noise data */
415 if (sbr->bs_coupling == 1)
417 if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) &&
418 (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24))
422 return log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1];
424 return log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)];
430 if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
432 return log_Qplus1[sbr->Q[ch][k][l]];
439 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
441 /* log2 values of limiter gains */
442 static real_t limGain[] = {
443 REAL_CONST(-1.0), REAL_CONST(0.0), REAL_CONST(1.0), REAL_CONST(33.219)
447 uint8_t current_t_noise_band = 0;
450 ALIGN real_t Q_M_lim[MAX_M];
451 ALIGN real_t G_lim[MAX_M];
452 ALIGN real_t G_boost;
453 ALIGN real_t S_M[MAX_M];
456 for (l = 0; l < sbr->L_E[ch]; l++)
458 uint8_t current_f_noise_band = 0;
459 uint8_t current_res_band = 0;
460 uint8_t current_res_band2 = 0;
461 uint8_t current_hi_res_band = 0;
463 real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
465 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
467 if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
469 current_t_noise_band++;
472 for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
479 uint8_t current_res_band_size = 0;
480 uint8_t Q_M_size = 0;
484 /* bounds of current limiter bands */
485 ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
486 ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
489 /* calculate the accumulated E_orig and E_curr over the limiter band */
490 for (m = ml1; m < ml2; m++)
492 if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
494 current_res_band_size++;
496 acc1 += pow2_int(-REAL_CONST(10) + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch));
499 current_res_band_size = 1;
502 acc2 += sbr->E_curr[ch][m][l];
504 acc1 += pow2_int(-REAL_CONST(10) + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch));
510 acc1 = log2_int(acc1);
513 /* calculate the maximum gain */
514 /* ratio of the energy of the original signal and the energy
515 * of the HF generated signal
517 G_max = acc1 - log2_int(acc2) + limGain[sbr->bs_limiter_gains];
518 G_max = min(G_max, limGain[3]);
521 for (m = ml1; m < ml2; m++)
524 real_t E_curr, E_orig;
525 real_t Q_orig, Q_orig_plus1;
526 uint8_t S_index_mapped;
529 /* check if m is on a noise band border */
530 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
532 /* step to next noise band */
533 current_f_noise_band++;
537 /* check if m is on a resolution band border */
538 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
540 /* accumulate a whole range of equal Q_Ms */
542 den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
545 /* step to next resolution band */
548 /* if we move to a new resolution band, we should check if we are
549 * going to add a sinusoid in this band
551 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
555 /* check if m is on a HI_RES band border */
556 if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
558 /* step to next HI_RES band */
559 current_hi_res_band++;
563 /* find S_index_mapped
564 * S_index_mapped can only be 1 for the m in the middle of the
565 * current HI_RES band
568 if ((l >= sbr->l_A[ch]) ||
569 (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
571 /* find the middle subband of the HI_RES frequency band */
572 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)
573 S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
577 /* find bitstream parameters */
578 if (sbr->E_curr[ch][m][l] == 0)
579 E_curr = LOG2_MIN_INF;
581 E_curr = log2_int(sbr->E_curr[ch][m][l]);
582 E_orig = -REAL_CONST(10) + find_log2_E(sbr, current_res_band2, l, ch);
585 Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch);
586 Q_orig_plus1 = find_log2_Qplus1(sbr, current_f_noise_band, current_t_noise_band, ch);
589 /* Q_M only depends on E_orig and Q_div2:
590 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
591 * a change of current res band (HI or LO)
593 Q_M = E_orig + Q_orig - Q_orig_plus1;
596 /* S_M only depends on E_orig, Q_div and S_index_mapped:
597 * S_index_mapped can only be non-zero once per HI_RES band
599 if (S_index_mapped == 0)
601 S_M[m] = LOG2_MIN_INF; /* -inf */
603 S_M[m] = E_orig - Q_orig_plus1;
605 /* accumulate sinusoid part of the total energy */
606 den += pow2_int(S_M[m]);
611 /* ratio of the energy of the original signal and the energy
612 * of the HF generated signal
614 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
616 G = E_orig - max(-REAL_CONST(10), E_curr);
617 if ((S_mapped == 0) && (delta == 1))
619 /* G = G * 1/(1+Q) */
621 } else if (S_mapped == 1) {
622 /* G = G * Q/(1+Q) */
623 G += Q_orig - Q_orig_plus1;
627 /* limit the additional noise energy level */
628 /* and apply the limiter */
634 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
640 Q_M_lim[m] = Q_M + G_max - G;
643 /* accumulate limited Q_M */
644 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
646 den += pow2_int(Q_M_lim[m]);
651 /* accumulate the total energy */
652 /* E_curr changes for every m so we do need to accumulate every m */
653 den += pow2_int(E_curr + G_lim[m]);
656 /* accumulate last range of equal Q_Ms */
659 den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
663 /* calculate the final gain */
664 /* G_boost: [0..2.51188643] */
665 G_boost = acc1 - log2_int(den /*+ EPS*/);
666 G_boost = min(G_boost, REAL_CONST(1.328771237) /* log2(1.584893192 ^ 2) */);
669 for (m = ml1; m < ml2; m++)
671 /* apply compensation to gain, noise floor sf's and sinusoid levels */
672 #ifndef SBR_LOW_POWER
673 adj->G_lim_boost[l][m] = pow2_fix((G_lim[m] + G_boost) >> 1);
675 /* sqrt() will be done after the aliasing reduction to save a
678 adj->G_lim_boost[l][m] = pow2_fix(G_lim[m] + G_boost);
680 adj->Q_M_lim_boost[l][m] = pow2_fix((Q_M_lim[m] + G_boost) >> 1);
682 if (S_M[m] != LOG2_MIN_INF)
684 adj->S_M_boost[l][m] = pow2_int((S_M[m] + G_boost) >> 1);
686 adj->S_M_boost[l][m] = 0;
699 #define LOG2_MIN_INF -100000
701 __inline float pow2(float val)
703 return pow(2.0, val);
705 __inline float log2(float val)
707 return log(val)/log(2.0);
712 float QUANTISE2REAL(float val)
714 __int32 ival = (__int32)(val * (1<<RB));
715 return (float)ival / (float)((1<<RB));
718 float QUANTISE2INT(float val)
723 /* log2 values of [0..63] */
724 static const real_t log2_int_tab[] = {
725 LOG2_MIN_INF, 0.000000000000000, 1.000000000000000, 1.584962500721156,
726 2.000000000000000, 2.321928094887362, 2.584962500721156, 2.807354922057604,
727 3.000000000000000, 3.169925001442313, 3.321928094887363, 3.459431618637297,
728 3.584962500721156, 3.700439718141092, 3.807354922057604, 3.906890595608519,
729 4.000000000000000, 4.087462841250339, 4.169925001442312, 4.247927513443585,
730 4.321928094887362, 4.392317422778761, 4.459431618637297, 4.523561956057013,
731 4.584962500721156, 4.643856189774724, 4.700439718141093, 4.754887502163468,
732 4.807354922057604, 4.857980995127572, 4.906890595608519, 4.954196310386875,
733 5.000000000000000, 5.044394119358453, 5.087462841250340, 5.129283016944966,
734 5.169925001442312, 5.209453365628949, 5.247927513443585, 5.285402218862248,
735 5.321928094887363, 5.357552004618084, 5.392317422778761, 5.426264754702098,
736 5.459431618637297, 5.491853096329675, 5.523561956057013, 5.554588851677637,
737 5.584962500721156, 5.614709844115208, 5.643856189774724, 5.672425341971495,
738 5.700439718141093, 5.727920454563200, 5.754887502163469, 5.781359713524660,
739 5.807354922057605, 5.832890014164742, 5.857980995127572, 5.882643049361842,
740 5.906890595608518, 5.930737337562887, 5.954196310386876, 5.977279923499916
743 static const real_t pan_log2_tab[] = {
744 1.000000000000000, 0.584962500721156, 0.321928094887362, 0.169925001442312, 0.087462841250339,
745 0.044394119358453, 0.022367813028455, 0.011227255423254, 0.005624549193878, 0.002815015607054,
746 0.001408194392808, 0.000704269011247, 0.000352177480301, 0.000176099486443, 0.000088052430122,
747 0.000044026886827, 0.000022013611360, 0.000011006847667
750 static real_t find_log2_E(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
752 /* check for coupled energy/noise data */
753 if (sbr->bs_coupling == 1)
755 real_t amp0 = (sbr->amp_res[0]) ? 1.0 : 0.5;
756 real_t amp1 = (sbr->amp_res[1]) ? 1.0 : 0.5;
757 float tmp = QUANTISE2REAL(7.0 + (real_t)sbr->E[0][k][l] * amp0);
760 int E = (int)(sbr->E[1][k][l] * amp1);
767 pan = QUANTISE2REAL(pan_log2_tab[-12 + E]);
770 pan = QUANTISE2REAL(pan_log2_tab[12 - E] + (12 - E));
776 pan = QUANTISE2REAL(pan_log2_tab[-E + 12]);
779 pan = QUANTISE2REAL(pan_log2_tab[E - 12] + (E - 12));
783 /* tmp / pan in log2 */
784 return QUANTISE2REAL(tmp - pan);
786 real_t amp = (sbr->amp_res[ch]) ? 1.0 : 0.5;
788 return QUANTISE2REAL(6.0 + (real_t)sbr->E[ch][k][l] * amp);
792 static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
794 /* check for coupled energy/noise data */
795 if (sbr->bs_coupling == 1)
797 float tmp = QUANTISE2REAL(7.0 - (real_t)sbr->Q[0][k][l]);
800 int Q = (int)(sbr->Q[1][k][l]);
807 pan = QUANTISE2REAL(pan_log2_tab[-12 + Q]);
810 pan = QUANTISE2REAL(pan_log2_tab[12 - Q] + (12 - Q));
816 pan = QUANTISE2REAL(pan_log2_tab[-Q + 12]);
819 pan = QUANTISE2REAL(pan_log2_tab[Q - 12] + (Q - 12));
823 /* tmp / pan in log2 */
824 return QUANTISE2REAL(tmp - pan);
826 return QUANTISE2REAL(6.0 - (real_t)sbr->Q[ch][k][l]);
830 static const real_t log_Qplus1_pan[31][13] = {
831 { 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) },
832 { 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) },
833 { 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) },
834 { 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) },
835 { 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) },
836 { 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) },
837 { 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) },
838 { 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) },
839 { 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) },
840 { 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) },
841 { 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) },
842 { 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) },
843 { 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) },
844 { 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) },
845 { 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) },
846 { 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) },
847 { 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) },
848 { 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) },
849 { 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) },
850 { 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) },
851 { 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) },
852 { 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) },
853 { 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) },
854 { 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) },
855 { 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) },
856 { 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) },
857 { 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) },
858 { 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) },
859 { 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) },
860 { 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) },
861 { 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) }
864 static const real_t log_Qplus1[31] = {
865 REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339),
866 REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156),
867 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362),
868 REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453),
869 REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878),
870 REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247),
871 REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
872 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667),
873 REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551),
874 REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641),
875 REAL_CONST(0.000000000000000)
878 static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
880 /* check for coupled energy/noise data */
881 if (sbr->bs_coupling == 1)
883 if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) &&
884 (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24))
888 return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1]);
890 return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)]);
896 if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
898 return QUANTISE2REAL(log_Qplus1[sbr->Q[ch][k][l]]);
905 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
907 /* log2 values of limiter gains */
908 static real_t limGain[] = { -1.0, 0.0, 1.0, 33.219 };
911 uint8_t current_t_noise_band = 0;
914 ALIGN real_t Q_M_lim[MAX_M];
915 ALIGN real_t G_lim[MAX_M];
916 ALIGN real_t G_boost;
917 ALIGN real_t S_M[MAX_M];
920 for (l = 0; l < sbr->L_E[ch]; l++)
922 uint8_t current_f_noise_band = 0;
923 uint8_t current_res_band = 0;
924 uint8_t current_res_band2 = 0;
925 uint8_t current_hi_res_band = 0;
927 real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
929 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
931 if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
933 current_t_noise_band++;
936 for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
943 uint8_t current_res_band_size = 0;
944 uint8_t Q_M_size = 0;
948 /* bounds of current limiter bands */
949 ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
950 ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
953 /* calculate the accumulated E_orig and E_curr over the limiter band */
954 for (m = ml1; m < ml2; m++)
956 if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
958 current_res_band_size++;
960 acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)));
963 current_res_band_size = 1;
966 acc2 += QUANTISE2INT(sbr->E_curr[ch][m][l]/1024.0);
968 acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)));
970 acc1 = QUANTISE2REAL( log2(EPS + acc1) );
973 /* calculate the maximum gain */
974 /* ratio of the energy of the original signal and the energy
975 * of the HF generated signal
977 G_max = acc1 - QUANTISE2REAL(log2(EPS + acc2)) + QUANTISE2REAL(limGain[sbr->bs_limiter_gains]);
978 G_max = min(G_max, QUANTISE2REAL(limGain[3]));
981 for (m = ml1; m < ml2; m++)
984 real_t E_curr, E_orig;
985 real_t Q_orig, Q_orig_plus1;
986 uint8_t S_index_mapped;
989 /* check if m is on a noise band border */
990 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
992 /* step to next noise band */
993 current_f_noise_band++;
997 /* check if m is on a resolution band border */
998 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
1000 /* accumulate a whole range of equal Q_Ms */
1002 den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M));
1005 /* step to next resolution band */
1006 current_res_band2++;
1008 /* if we move to a new resolution band, we should check if we are
1009 * going to add a sinusoid in this band
1011 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1015 /* check if m is on a HI_RES band border */
1016 if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
1018 /* step to next HI_RES band */
1019 current_hi_res_band++;
1023 /* find S_index_mapped
1024 * S_index_mapped can only be 1 for the m in the middle of the
1025 * current HI_RES band
1028 if ((l >= sbr->l_A[ch]) ||
1029 (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
1031 /* find the middle subband of the HI_RES frequency band */
1032 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)
1033 S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
1037 /* find bitstream parameters */
1038 if (sbr->E_curr[ch][m][l] == 0)
1039 E_curr = LOG2_MIN_INF;
1041 E_curr = -10 + log2(sbr->E_curr[ch][m][l]);
1042 E_orig = -10 + find_log2_E(sbr, current_res_band2, l, ch);
1044 Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch);
1045 Q_orig_plus1 = find_log2_Qplus1(sbr, current_f_noise_band, current_t_noise_band, ch);
1048 /* Q_M only depends on E_orig and Q_div2:
1049 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
1050 * a change of current res band (HI or LO)
1052 Q_M = E_orig + Q_orig - Q_orig_plus1;
1055 /* S_M only depends on E_orig, Q_div and S_index_mapped:
1056 * S_index_mapped can only be non-zero once per HI_RES band
1058 if (S_index_mapped == 0)
1060 S_M[m] = LOG2_MIN_INF; /* -inf */
1062 S_M[m] = E_orig - Q_orig_plus1;
1064 /* accumulate sinusoid part of the total energy */
1065 den += pow2(S_M[m]);
1069 /* calculate gain */
1070 /* ratio of the energy of the original signal and the energy
1071 * of the HF generated signal
1073 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
1075 G = E_orig - max(-10, E_curr);
1076 if ((S_mapped == 0) && (delta == 1))
1078 /* G = G * 1/(1+Q) */
1080 } else if (S_mapped == 1) {
1081 /* G = G * Q/(1+Q) */
1082 G += Q_orig - Q_orig_plus1;
1086 /* limit the additional noise energy level */
1087 /* and apply the limiter */
1090 Q_M_lim[m] = QUANTISE2REAL(Q_M);
1091 G_lim[m] = QUANTISE2REAL(G);
1093 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1099 Q_M_lim[m] = QUANTISE2REAL(Q_M) + G_max - QUANTISE2REAL(G);
1102 /* accumulate limited Q_M */
1103 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1105 den += QUANTISE2INT(pow2(Q_M_lim[m]));
1110 /* accumulate the total energy */
1111 /* E_curr changes for every m so we do need to accumulate every m */
1112 den += QUANTISE2INT(pow2(E_curr + G_lim[m]));
1115 /* accumulate last range of equal Q_Ms */
1118 den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M));
1122 /* calculate the final gain */
1123 /* G_boost: [0..2.51188643] */
1124 G_boost = acc1 - QUANTISE2REAL(log2(den + EPS));
1125 G_boost = min(G_boost, QUANTISE2REAL(1.328771237) /* log2(1.584893192 ^ 2) */);
1128 for (m = ml1; m < ml2; m++)
1130 /* apply compensation to gain, noise floor sf's and sinusoid levels */
1131 #ifndef SBR_LOW_POWER
1132 adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2((G_lim[m] + G_boost) / 2.0));
1134 /* sqrt() will be done after the aliasing reduction to save a
1137 adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2(G_lim[m] + G_boost));
1139 adj->Q_M_lim_boost[l][m] = QUANTISE2REAL(pow2((Q_M_lim[m] + 10 + G_boost) / 2.0));
1141 if (S_M[m] != LOG2_MIN_INF)
1143 adj->S_M_boost[l][m] = QUANTISE2REAL(pow2((S_M[m] + 10 + G_boost) / 2.0));
1145 adj->S_M_boost[l][m] = 0;
1154 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
1156 static real_t limGain[] = { 0.5, 1.0, 2.0, 1e10 };
1159 uint8_t current_t_noise_band = 0;
1162 ALIGN real_t Q_M_lim[MAX_M];
1163 ALIGN real_t G_lim[MAX_M];
1164 ALIGN real_t G_boost;
1165 ALIGN real_t S_M[MAX_M];
1167 for (l = 0; l < sbr->L_E[ch]; l++)
1169 uint8_t current_f_noise_band = 0;
1170 uint8_t current_res_band = 0;
1171 uint8_t current_res_band2 = 0;
1172 uint8_t current_hi_res_band = 0;
1174 real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
1176 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1178 if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
1180 current_t_noise_band++;
1183 for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
1189 uint8_t current_res_band_size = 0;
1193 ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
1194 ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
1197 /* calculate the accumulated E_orig and E_curr over the limiter band */
1198 for (m = ml1; m < ml2; m++)
1200 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
1204 acc1 += sbr->E_orig[ch][current_res_band][l];
1205 acc2 += sbr->E_curr[ch][m][l];
1209 /* calculate the maximum gain */
1210 /* ratio of the energy of the original signal and the energy
1211 * of the HF generated signal
1213 G_max = ((EPS + acc1) / (EPS + acc2)) * limGain[sbr->bs_limiter_gains];
1214 G_max = min(G_max, 1e10);
1217 for (m = ml1; m < ml2; m++)
1220 real_t Q_div, Q_div2;
1221 uint8_t S_index_mapped;
1224 /* check if m is on a noise band border */
1225 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
1227 /* step to next noise band */
1228 current_f_noise_band++;
1232 /* check if m is on a resolution band border */
1233 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
1235 /* step to next resolution band */
1236 current_res_band2++;
1238 /* if we move to a new resolution band, we should check if we are
1239 * going to add a sinusoid in this band
1241 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1245 /* check if m is on a HI_RES band border */
1246 if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
1248 /* step to next HI_RES band */
1249 current_hi_res_band++;
1253 /* find S_index_mapped
1254 * S_index_mapped can only be 1 for the m in the middle of the
1255 * current HI_RES band
1258 if ((l >= sbr->l_A[ch]) ||
1259 (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
1261 /* find the middle subband of the HI_RES frequency band */
1262 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)
1263 S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
1267 /* Q_div: [0..1] (1/(1+Q_mapped)) */
1268 Q_div = sbr->Q_div[ch][current_f_noise_band][current_t_noise_band];
1271 /* Q_div2: [0..1] (Q_mapped/(1+Q_mapped)) */
1272 Q_div2 = sbr->Q_div2[ch][current_f_noise_band][current_t_noise_band];
1275 /* Q_M only depends on E_orig and Q_div2:
1276 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
1277 * a change of current noise band
1279 Q_M = sbr->E_orig[ch][current_res_band2][l] * Q_div2;
1282 /* S_M only depends on E_orig, Q_div and S_index_mapped:
1283 * S_index_mapped can only be non-zero once per HI_RES band
1285 if (S_index_mapped == 0)
1289 S_M[m] = sbr->E_orig[ch][current_res_band2][l] * Q_div;
1291 /* accumulate sinusoid part of the total energy */
1296 /* calculate gain */
1297 /* ratio of the energy of the original signal and the energy
1298 * of the HF generated signal
1300 G = sbr->E_orig[ch][current_res_band2][l] / (1.0 + sbr->E_curr[ch][m][l]);
1301 if ((S_mapped == 0) && (delta == 1))
1303 else if (S_mapped == 1)
1307 /* limit the additional noise energy level */
1308 /* and apply the limiter */
1314 Q_M_lim[m] = Q_M * G_max / G;
1319 /* accumulate the total energy */
1320 den += sbr->E_curr[ch][m][l] * G_lim[m];
1321 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1325 /* G_boost: [0..2.51188643] */
1326 G_boost = (acc1 + EPS) / (den + EPS);
1327 G_boost = min(G_boost, 2.51188643 /* 1.584893192 ^ 2 */);
1329 for (m = ml1; m < ml2; m++)
1331 /* apply compensation to gain, noise floor sf's and sinusoid levels */
1332 #ifndef SBR_LOW_POWER
1333 adj->G_lim_boost[l][m] = sqrt(G_lim[m] * G_boost);
1335 /* sqrt() will be done after the aliasing reduction to save a
1338 adj->G_lim_boost[l][m] = G_lim[m] * G_boost;
1340 adj->Q_M_lim_boost[l][m] = sqrt(Q_M_lim[m] * G_boost);
1344 adj->S_M_boost[l][m] = sqrt(S_M[m] * G_boost);
1346 adj->S_M_boost[l][m] = 0;
1356 #ifdef SBR_LOW_POWER
1357 static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch)
1363 for (l = 0; l < sbr->L_E[ch]; l++)
1365 uint8_t current_res_band = 0;
1369 S_mapped = get_S_mapped(sbr, ch, l, current_res_band);
1371 for (k = sbr->kx; k < sbr->kx + sbr->M - 1; k++)
1373 if (k == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
1375 /* step to next resolution band */
1378 S_mapped = get_S_mapped(sbr, ch, l, current_res_band);
1381 if (deg[k + 1] && S_mapped == 0)
1385 sbr->f_group[l][i] = k;
1394 sbr->f_group[l][i] = k;
1396 sbr->f_group[l][i] = k + 1;
1406 sbr->f_group[l][i] = sbr->kx + sbr->M;
1410 sbr->N_G[l] = (uint8_t)(i >> 1);
1414 static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch)
1417 real_t E_total, E_total_est, G_target, acc;
1419 for (l = 0; l < sbr->L_E[ch]; l++)
1421 for (k = 0; k < sbr->N_G[l]; k++)
1423 E_total_est = E_total = 0;
1425 for (m = sbr->f_group[l][k<<1]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1427 /* E_curr: integer */
1428 /* G_lim_boost: fixed point */
1429 /* E_total_est: integer */
1430 /* E_total: integer */
1431 E_total_est += sbr->E_curr[ch][m-sbr->kx][l];
1433 E_total += MUL_Q2(sbr->E_curr[ch][m-sbr->kx][l], adj->G_lim_boost[l][m-sbr->kx]);
1435 E_total += sbr->E_curr[ch][m-sbr->kx][l] * adj->G_lim_boost[l][m-sbr->kx];
1439 /* G_target: fixed point */
1440 if ((E_total_est + EPS) == 0)
1445 G_target = (((int64_t)(E_total))<<Q2_BITS)/(E_total_est + EPS);
1447 G_target = E_total / (E_total_est + EPS);
1452 for (m = sbr->f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1456 /* alpha: (COEF) fixed point */
1457 if (m < sbr->kx + sbr->M - 1)
1459 alpha = max(deg[m], deg[m + 1]);
1464 adj->G_lim_boost[l][m-sbr->kx] = MUL_C(alpha, G_target) +
1465 MUL_C((COEF_CONST(1)-alpha), adj->G_lim_boost[l][m-sbr->kx]);
1469 acc += MUL_Q2(adj->G_lim_boost[l][m-sbr->kx], sbr->E_curr[ch][m-sbr->kx][l]);
1471 acc += adj->G_lim_boost[l][m-sbr->kx] * sbr->E_curr[ch][m-sbr->kx][l];
1475 /* acc: fixed point */
1481 acc = (((int64_t)(E_total))<<Q2_BITS)/(acc + EPS);
1483 acc = E_total / (acc + EPS);
1486 for(m = sbr->f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1489 adj->G_lim_boost[l][m-sbr->kx] = MUL_Q2(acc, adj->G_lim_boost[l][m-sbr->kx]);
1491 adj->G_lim_boost[l][m-sbr->kx] = acc * adj->G_lim_boost[l][m-sbr->kx];
1497 for (l = 0; l < sbr->L_E[ch]; l++)
1499 for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
1501 for (m = sbr->f_table_lim[sbr->bs_limiter_bands][k];
1502 m < sbr->f_table_lim[sbr->bs_limiter_bands][k+1]; m++)
1505 adj->G_lim_boost[l][m] = SBR_SQRT_Q2(adj->G_lim_boost[l][m]);
1507 adj->G_lim_boost[l][m] = sqrt(adj->G_lim_boost[l][m]);
1515 static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj,
1516 qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch)
1518 static real_t h_smooth[] = {
1519 FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
1520 FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
1521 FRAC_CONST(0.33333333333333)
1523 static int8_t phi_re[] = { 1, 0, -1, 0 };
1524 static int8_t phi_im[] = { 0, 1, 0, -1 };
1527 uint16_t fIndexNoise = 0;
1528 uint8_t fIndexSine = 0;
1529 uint8_t assembly_reset = 0;
1531 real_t G_filt, Q_filt;
1536 if (sbr->Reset == 1)
1541 fIndexNoise = sbr->index_noise_prev[ch];
1543 fIndexSine = sbr->psi_is_prev[ch];
1546 for (l = 0; l < sbr->L_E[ch]; l++)
1548 uint8_t no_noise = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 1 : 0;
1550 #ifdef SBR_LOW_POWER
1553 h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4;
1554 h_SL = (no_noise ? 0 : h_SL);
1559 for (n = 0; n < 4; n++)
1561 memcpy(sbr->G_temp_prev[ch][n], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1562 memcpy(sbr->Q_temp_prev[ch][n], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1564 /* reset ringbuffer index */
1565 sbr->GQ_ringbuf_index[ch] = 4;
1569 for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++)
1571 #ifdef SBR_LOW_POWER
1572 uint8_t i_min1, i_plus1;
1573 uint8_t sinusoids = 0;
1576 /* load new values into ringbuffer */
1577 memcpy(sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1578 memcpy(sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1580 for (m = 0; m < sbr->M; m++)
1587 #ifndef SBR_LOW_POWER
1590 uint8_t ri = sbr->GQ_ringbuf_index[ch];
1591 for (n = 0; n <= 4; n++)
1593 real_t curr_h_smooth = h_smooth[n];
1597 G_filt += MUL_F(sbr->G_temp_prev[ch][ri][m], curr_h_smooth);
1598 Q_filt += MUL_F(sbr->Q_temp_prev[ch][ri][m], curr_h_smooth);
1602 G_filt = sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1603 Q_filt = sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1604 #ifndef SBR_LOW_POWER
1608 Q_filt = (adj->S_M_boost[l][m] != 0 || no_noise) ? 0 : Q_filt;
1610 /* add noise to the output */
1611 fIndexNoise = (fIndexNoise + 1) & 511;
1613 /* the smoothed gain values are applied to Xsbr */
1614 /* V is defined, not calculated */
1616 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = G_filt * QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx])
1617 + MUL_F(Q_filt, RE(V[fIndexNoise]));
1619 //QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1620 // + MUL_F(Q_filt, RE(V[fIndexNoise]));
1621 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1622 + MUL_F(Q_filt, RE(V[fIndexNoise]));
1624 if (sbr->bs_extension_id == 3 && sbr->bs_extension_data == 42)
1625 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = 16428320;
1626 #ifndef SBR_LOW_POWER
1628 QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = G_filt * QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx])
1629 + MUL_F(Q_filt, IM(V[fIndexNoise]));
1631 //QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1632 // + MUL_F(Q_filt, IM(V[fIndexNoise]));
1633 QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1634 + MUL_F(Q_filt, IM(V[fIndexNoise]));
1639 int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1);
1640 QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine];
1642 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += (QMF_RE(psi) << REAL_BITS);
1644 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi);
1647 #ifndef SBR_LOW_POWER
1648 QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine];
1650 QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += (QMF_IM(psi) << REAL_BITS);
1652 QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_IM(psi);
1656 i_min1 = (fIndexSine - 1) & 3;
1657 i_plus1 = (fIndexSine + 1) & 3;
1660 if ((m == 0) && (phi_re[i_plus1] != 0))
1662 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx - 1]) +=
1663 (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][0], FRAC_CONST(0.00815)));
1666 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1667 (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][1], FRAC_CONST(0.00815)));
1670 if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1672 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1673 (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m - 1], FRAC_CONST(0.00815)));
1675 if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0))
1677 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1678 (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][m + 1], FRAC_CONST(0.00815)));
1680 if ((m == sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1684 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1685 (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m - 1], FRAC_CONST(0.00815)));
1687 if (m + sbr->kx < 64)
1689 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx + 1]) +=
1690 (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m], FRAC_CONST(0.00815)));
1694 if ((m == 0) && (phi_re[i_plus1] != 0))
1696 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx - 1]) +=
1697 (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][0]<<REAL_BITS), FRAC_CONST(0.00815)));
1700 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1701 (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][1]<<REAL_BITS), FRAC_CONST(0.00815)));
1704 if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1706 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1707 (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m - 1]<<REAL_BITS), FRAC_CONST(0.00815)));
1709 if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0))
1711 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1712 (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][m + 1]<<REAL_BITS), FRAC_CONST(0.00815)));
1714 if ((m == sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1718 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1719 (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m - 1]<<REAL_BITS), FRAC_CONST(0.00815)));
1721 if (m + sbr->kx < 64)
1723 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx + 1]) +=
1724 (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m]<<REAL_BITS), FRAC_CONST(0.00815)));
1729 if (adj->S_M_boost[l][m] != 0)
1735 fIndexSine = (fIndexSine + 1) & 3;
1737 /* update the ringbuffer index used for filtering G and Q with h_smooth */
1738 sbr->GQ_ringbuf_index[ch]++;
1739 if (sbr->GQ_ringbuf_index[ch] >= 5)
1740 sbr->GQ_ringbuf_index[ch] = 0;
1744 sbr->index_noise_prev[ch] = fIndexNoise;
1745 sbr->psi_is_prev[ch] = fIndexSine;