OSDN Git Service

wwww
[proj16/16.git] / src / lib / doslib / ext / faad / sbrhfadj.c
1 /*
2 ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
3 ** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
4 **  
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.
9 ** 
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.
14 ** 
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.
18 **
19 ** Any non-GPL usage of this software or parts of this software is strictly
20 ** forbidden.
21 **
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"
24 **
25 ** Commercial non-GPL licensing of this software is possible.
26 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
27 **
28 ** $Id: sbr_hfadj.c,v 1.23 2008/09/19 22:50:20 menno Exp $
29 **/
30
31 /* High Frequency adjustment */
32
33 #include "common.h"
34 #include "structs.h"
35
36 #ifdef SBR_DEC
37
38 #include "sbr_synt.h"
39 #include "sbrhfadj.h"
40
41 #include "sbrnoise.h"
42
43
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);
48 #ifdef SBR_LOW_POWER
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);
51 #endif
52 static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj, qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
53
54
55 uint8_t hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64]
56 #ifdef SBR_LOW_POWER
57                       ,real_t *deg /* aliasing degree */
58 #endif
59                       ,uint8_t ch)
60 {
61     ALIGN sbr_hfadj_info adj = {{{0}}};
62     uint8_t ret = 0;
63
64     if (sbr->bs_frame_class[ch] == FIXFIX)
65     {
66         sbr->l_A[ch] = -1;
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;
70         else
71             sbr->l_A[ch] = -1;
72     } else {
73         if (sbr->bs_pointer[ch] == 0)
74             sbr->l_A[ch] = -1;
75         else
76             sbr->l_A[ch] = sbr->L_E[ch] + 1 - sbr->bs_pointer[ch];
77     }
78
79     ret = estimate_current_envelope(sbr, &adj, Xsbr, ch);
80     if (ret > 0)
81         return 1;
82
83     calculate_gain(sbr, &adj, ch);
84
85 #ifdef SBR_LOW_POWER
86     calc_gain_groups(sbr, &adj, deg, ch);
87     aliasing_reduction(sbr, &adj, deg, ch);
88 #endif
89
90     hf_assembly(sbr, &adj, Xsbr, ch);
91
92     return 0;
93 }
94
95 static uint8_t get_S_mapped(sbr_info *sbr, uint8_t ch, uint8_t l, uint8_t current_band)
96 {
97     if (sbr->f[ch][l] == HI_RES)
98     {
99         /* in case of using f_table_high we just have 1 to 1 mapping
100          * from bs_add_harmonic[l][k]
101          */
102         if ((l >= sbr->l_A[ch]) ||
103             (sbr->bs_add_harmonic_prev[ch][current_band] && sbr->bs_add_harmonic_flag_prev[ch]))
104         {
105             return sbr->bs_add_harmonic[ch][current_band];
106         }
107     } else {
108         uint8_t b, lb, ub;
109
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
113          * the HI_RES table)
114          */
115
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);
120
121         /* check all HI_RES bands in current LO_RES band for sinusoid */
122         for (b = lb; b < ub; b++)
123         {
124             if ((l >= sbr->l_A[ch]) ||
125                 (sbr->bs_add_harmonic_prev[ch][b] && sbr->bs_add_harmonic_flag_prev[ch]))
126             {
127                 if (sbr->bs_add_harmonic[ch][b] == 1)
128                     return 1;
129             }
130         }
131     }
132
133     return 0;
134 }
135
136 static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj,
137                                          qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch)
138 {
139     uint8_t m, l, j, k, k_l, k_h, p;
140     real_t nrg, div;
141
142     if (sbr->bs_interpol_freq == 1)
143     {
144         for (l = 0; l < sbr->L_E[ch]; l++)
145         {
146             uint8_t i, l_i, u_i;
147
148             l_i = sbr->t_E[ch][l];
149             u_i = sbr->t_E[ch][l+1];
150
151             div = (real_t)(u_i - l_i);
152
153             if (div == 0)
154                 div = 1;
155
156             for (m = 0; m < sbr->M; m++)
157             {
158                 nrg = 0;
159
160                 for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
161                 {
162 #ifdef FIXED_POINT
163 #ifdef SBR_LOW_POWER
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);
165 #else
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);
168 #endif
169 #else
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]))
173 #endif
174                         ;
175 #endif
176                 }
177
178                 sbr->E_curr[ch][m][l] = nrg / div;
179 #ifdef SBR_LOW_POWER
180 #ifdef FIXED_POINT
181                 sbr->E_curr[ch][m][l] <<= 1;
182 #else
183                 sbr->E_curr[ch][m][l] *= 2;
184 #endif
185 #endif
186             }
187         }
188     } else {
189         for (l = 0; l < sbr->L_E[ch]; l++)
190         {
191             for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++)
192             {
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];
195
196                 for (k = k_l; k < k_h; k++)
197                 {
198                     uint8_t i, l_i, u_i;
199                     nrg = 0;
200
201                     l_i = sbr->t_E[ch][l];
202                     u_i = sbr->t_E[ch][l+1];
203
204                     div = (real_t)((u_i - l_i)*(k_h - k_l));
205
206                     if (div == 0)
207                         div = 1;
208
209                     for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
210                     {
211                         for (j = k_l; j < k_h; j++)
212                         {
213 #ifdef FIXED_POINT
214 #ifdef SBR_LOW_POWER
215                             nrg += ((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS);
216 #else
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);
219 #endif
220 #else
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]))
224 #endif
225                                 ;
226 #endif
227                         }
228                     }
229
230                     sbr->E_curr[ch][k - sbr->kx][l] = nrg / div;
231 #ifdef SBR_LOW_POWER
232 #ifdef FIXED_POINT
233                     sbr->E_curr[ch][k - sbr->kx][l] <<= 1;
234 #else
235                     sbr->E_curr[ch][k - sbr->kx][l] *= 2;
236 #endif
237 #endif
238                 }
239             }
240         }
241     }
242
243     return 0;
244 }
245
246 #ifdef FIXED_POINT
247 #define EPS (1) /* smallest number available in fixed point */
248 #else
249 #define EPS (1e-12)
250 #endif
251
252
253
254 #ifdef FIXED_POINT
255
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)
274 };
275
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)
281 };
282
283 static real_t find_log2_E(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
284 {
285     /* check for coupled energy/noise data */
286     if (sbr->bs_coupling == 1)
287     {
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));
291         real_t pan;
292
293         /* E[1] should always be even so shifting is OK */
294         uint8_t E = sbr->E[1][k][l] >> amp1;
295
296         if (ch == 0)
297         {
298             if (E > 12)
299             {
300                 /* negative */
301                 pan = pan_log2_tab[-12 + E];
302             } else {
303                 /* positive */
304                 pan = pan_log2_tab[12 - E] + ((12 - E)<<REAL_BITS);
305             }
306         } else {
307             if (E < 12)
308             {
309                 /* negative */
310                 pan = pan_log2_tab[-E + 12];
311             } else {
312                 /* positive */
313                 pan = pan_log2_tab[E - 12] + ((E - 12)<<REAL_BITS);
314             }
315         }
316
317         /* tmp / pan in log2 */
318         return tmp - pan;
319     } else {
320         uint8_t amp = (sbr->amp_res[ch]) ? 0 : 1;
321
322         return (6 << REAL_BITS) + (sbr->E[ch][k][l] << (REAL_BITS-amp));
323     }
324 }
325
326 static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
327 {
328     /* check for coupled energy/noise data */
329     if (sbr->bs_coupling == 1)
330     {
331         real_t tmp = (7 << REAL_BITS) - (sbr->Q[0][k][l] << REAL_BITS);
332         real_t pan;
333
334         uint8_t Q = sbr->Q[1][k][l];
335
336         if (ch == 0)
337         {
338             if (Q > 12)
339             {
340                 /* negative */
341                 pan = pan_log2_tab[-12 + Q];
342             } else {
343                 /* positive */
344                 pan = pan_log2_tab[12 - Q] + ((12 - Q)<<REAL_BITS);
345             }
346         } else {
347             if (Q < 12)
348             {
349                 /* negative */
350                 pan = pan_log2_tab[-Q + 12];
351             } else {
352                 /* positive */
353                 pan = pan_log2_tab[Q - 12] + ((Q - 12)<<REAL_BITS);
354             }
355         }
356
357         /* tmp / pan in log2 */
358         return tmp - pan;
359     } else {
360         return (6 << REAL_BITS) - (sbr->Q[ch][k][l] << REAL_BITS);
361     }
362 }
363
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) }
396 };
397
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)
410 };
411
412 static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
413 {
414     /* check for coupled energy/noise data */
415     if (sbr->bs_coupling == 1)
416     {
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))
419         {
420             if (ch == 0)
421             {
422                 return log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1];
423             } else {
424                 return log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)];
425             }
426         } else {
427             return 0;
428         }
429     } else {
430         if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
431         {
432             return log_Qplus1[sbr->Q[ch][k][l]];
433         } else {
434             return 0;
435         }
436     }
437 }
438
439 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
440 {
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)
444     };
445     uint8_t m, l, k;
446
447     uint8_t current_t_noise_band = 0;
448     uint8_t S_mapped;
449
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];
454
455
456     for (l = 0; l < sbr->L_E[ch]; l++)
457     {
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;
462
463         real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
464
465         S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
466
467         if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
468         {
469             current_t_noise_band++;
470         }
471
472         for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
473         {
474             real_t Q_M = 0;
475             real_t G_max;
476             real_t den = 0;
477             real_t acc1 = 0;
478             real_t acc2 = 0;
479             uint8_t current_res_band_size = 0;
480             uint8_t Q_M_size = 0;
481
482             uint8_t ml1, ml2;
483
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];
487
488
489             /* calculate the accumulated E_orig and E_curr over the limiter band */
490             for (m = ml1; m < ml2; m++)
491             {
492                 if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
493                 {
494                     current_res_band_size++;
495                 } else {
496                     acc1 += pow2_int(-REAL_CONST(10) + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch));
497
498                     current_res_band++;
499                     current_res_band_size = 1;
500                 }
501
502                 acc2 += sbr->E_curr[ch][m][l];
503             }
504             acc1 += pow2_int(-REAL_CONST(10) + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch));
505
506
507             if (acc1 == 0)
508                 acc1 = LOG2_MIN_INF;
509             else
510                 acc1 = log2_int(acc1);
511
512
513             /* calculate the maximum gain */
514             /* ratio of the energy of the original signal and the energy
515              * of the HF generated signal
516              */
517             G_max = acc1 - log2_int(acc2) + limGain[sbr->bs_limiter_gains];
518             G_max = min(G_max, limGain[3]);
519
520
521             for (m = ml1; m < ml2; m++)
522             {
523                 real_t G;
524                 real_t E_curr, E_orig;
525                 real_t Q_orig, Q_orig_plus1;
526                 uint8_t S_index_mapped;
527
528
529                 /* check if m is on a noise band border */
530                 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
531                 {
532                     /* step to next noise band */
533                     current_f_noise_band++;
534                 }
535
536
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])
539                 {
540                     /* accumulate a whole range of equal Q_Ms */
541                     if (Q_M_size > 0)
542                         den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
543                     Q_M_size = 0;
544
545                     /* step to next resolution band */
546                     current_res_band2++;
547
548                     /* if we move to a new resolution band, we should check if we are
549                      * going to add a sinusoid in this band
550                      */
551                     S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
552                 }
553
554
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])
557                 {
558                     /* step to next HI_RES band */
559                     current_hi_res_band++;
560                 }
561
562
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
566                  */
567                 S_index_mapped = 0;
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]))
570                 {
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];
574                 }
575
576
577                 /* find bitstream parameters */
578                 if (sbr->E_curr[ch][m][l] == 0)
579                     E_curr = LOG2_MIN_INF;
580                 else
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);
583
584
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);
587
588
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)
592                  */
593                 Q_M = E_orig + Q_orig - Q_orig_plus1;
594
595
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
598                  */
599                 if (S_index_mapped == 0)
600                 {
601                     S_M[m] = LOG2_MIN_INF; /* -inf */
602                 } else {
603                     S_M[m] = E_orig - Q_orig_plus1;
604
605                     /* accumulate sinusoid part of the total energy */
606                     den += pow2_int(S_M[m]);
607                 }
608
609
610                 /* calculate gain */
611                 /* ratio of the energy of the original signal and the energy
612                  * of the HF generated signal
613                  */
614                 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
615                 /* scaled by -10 */
616                 G = E_orig - max(-REAL_CONST(10), E_curr);
617                 if ((S_mapped == 0) && (delta == 1))
618                 {
619                     /* G = G * 1/(1+Q) */
620                     G -= Q_orig_plus1;
621                 } else if (S_mapped == 1) {
622                     /* G = G * Q/(1+Q) */
623                     G += Q_orig - Q_orig_plus1;
624                 }
625
626
627                 /* limit the additional noise energy level */
628                 /* and apply the limiter */
629                 if (G_max > G)
630                 {
631                     Q_M_lim[m] = Q_M;
632                     G_lim[m] = G;
633
634                     if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
635                     {
636                         Q_M_size++;
637                     }
638                 } else {
639                     /* G > G_max */
640                     Q_M_lim[m] = Q_M + G_max - G;
641                     G_lim[m] = G_max;
642
643                     /* accumulate limited Q_M */
644                     if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
645                     {
646                         den += pow2_int(Q_M_lim[m]);
647                     }
648                 }
649
650
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]);
654             }
655
656             /* accumulate last range of equal Q_Ms */
657             if (Q_M_size > 0)
658             {
659                 den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
660             }
661
662
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) */);
667
668
669             for (m = ml1; m < ml2; m++)
670             {
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);
674 #else
675                 /* sqrt() will be done after the aliasing reduction to save a
676                  * few multiplies
677                  */
678                 adj->G_lim_boost[l][m] = pow2_fix(G_lim[m] + G_boost);
679 #endif
680                 adj->Q_M_lim_boost[l][m] = pow2_fix((Q_M_lim[m] + G_boost) >> 1);
681
682                 if (S_M[m] != LOG2_MIN_INF)
683                 {
684                     adj->S_M_boost[l][m] = pow2_int((S_M[m] + G_boost) >> 1);
685                 } else {
686                     adj->S_M_boost[l][m] = 0;
687                 }
688             }
689         }
690     }
691 }
692
693 #else
694
695 //#define LOG2_TEST
696
697 #ifdef LOG2_TEST
698
699 #define LOG2_MIN_INF -100000
700
701 __inline float pow2(float val)
702 {
703     return pow(2.0, val);
704 }
705 __inline float log2(float val)
706 {
707     return log(val)/log(2.0);
708 }
709
710 #define RB 14
711
712 float QUANTISE2REAL(float val)
713 {
714     __int32 ival = (__int32)(val * (1<<RB));
715     return (float)ival / (float)((1<<RB));
716 }
717
718 float QUANTISE2INT(float val)
719 {
720     return floor(val);
721 }
722
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
741 };
742
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
748 };
749
750 static real_t find_log2_E(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
751 {
752     /* check for coupled energy/noise data */
753     if (sbr->bs_coupling == 1)
754     {
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);
758         float pan;
759
760         int E = (int)(sbr->E[1][k][l] * amp1);
761
762         if (ch == 0)
763         {
764             if (E > 12)
765             {
766                 /* negative */
767                 pan = QUANTISE2REAL(pan_log2_tab[-12 + E]);
768             } else {
769                 /* positive */
770                 pan = QUANTISE2REAL(pan_log2_tab[12 - E] + (12 - E));
771             }
772         } else {
773             if (E < 12)
774             {
775                 /* negative */
776                 pan = QUANTISE2REAL(pan_log2_tab[-E + 12]);
777             } else {
778                 /* positive */
779                 pan = QUANTISE2REAL(pan_log2_tab[E - 12] + (E - 12));
780             }
781         }
782
783         /* tmp / pan in log2 */
784         return QUANTISE2REAL(tmp - pan);
785     } else {
786         real_t amp = (sbr->amp_res[ch]) ? 1.0 : 0.5;
787
788         return QUANTISE2REAL(6.0 + (real_t)sbr->E[ch][k][l] * amp);
789     }
790 }
791
792 static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
793 {
794     /* check for coupled energy/noise data */
795     if (sbr->bs_coupling == 1)
796     {
797         float tmp = QUANTISE2REAL(7.0 - (real_t)sbr->Q[0][k][l]);
798         float pan;
799
800         int Q = (int)(sbr->Q[1][k][l]);
801
802         if (ch == 0)
803         {
804             if (Q > 12)
805             {
806                 /* negative */
807                 pan = QUANTISE2REAL(pan_log2_tab[-12 + Q]);
808             } else {
809                 /* positive */
810                 pan = QUANTISE2REAL(pan_log2_tab[12 - Q] + (12 - Q));
811             }
812         } else {
813             if (Q < 12)
814             {
815                 /* negative */
816                 pan = QUANTISE2REAL(pan_log2_tab[-Q + 12]);
817             } else {
818                 /* positive */
819                 pan = QUANTISE2REAL(pan_log2_tab[Q - 12] + (Q - 12));
820             }
821         }
822
823         /* tmp / pan in log2 */
824         return QUANTISE2REAL(tmp - pan);
825     } else {
826         return QUANTISE2REAL(6.0 - (real_t)sbr->Q[ch][k][l]);
827     }
828 }
829
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) }
862 };
863
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)
876 };
877
878 static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
879 {
880     /* check for coupled energy/noise data */
881     if (sbr->bs_coupling == 1)
882     {
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))
885         {
886             if (ch == 0)
887             {
888                 return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1]);
889             } else {
890                 return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)]);
891             }
892         } else {
893             return 0;
894         }
895     } else {
896         if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
897         {
898             return QUANTISE2REAL(log_Qplus1[sbr->Q[ch][k][l]]);
899         } else {
900             return 0;
901         }
902     }
903 }
904
905 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
906 {
907     /* log2 values of limiter gains */
908     static real_t limGain[] = { -1.0, 0.0, 1.0, 33.219 };
909     uint8_t m, l, k;
910
911     uint8_t current_t_noise_band = 0;
912     uint8_t S_mapped;
913
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];
918
919
920     for (l = 0; l < sbr->L_E[ch]; l++)
921     {
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;
926
927         real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
928
929         S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
930
931         if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
932         {
933             current_t_noise_band++;
934         }
935
936         for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
937         {
938             real_t Q_M = 0;
939             real_t G_max;
940             real_t den = 0;
941             real_t acc1 = 0;
942             real_t acc2 = 0;
943             uint8_t current_res_band_size = 0;
944             uint8_t Q_M_size = 0;
945
946             uint8_t ml1, ml2;
947
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];
951
952
953             /* calculate the accumulated E_orig and E_curr over the limiter band */
954             for (m = ml1; m < ml2; m++)
955             {
956                 if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
957                 {
958                     current_res_band_size++;
959                 } else {
960                     acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)));
961
962                     current_res_band++;
963                     current_res_band_size = 1;
964                 }
965
966                 acc2 += QUANTISE2INT(sbr->E_curr[ch][m][l]/1024.0);
967             }
968             acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)));
969
970             acc1 = QUANTISE2REAL( log2(EPS + acc1) );
971
972
973             /* calculate the maximum gain */
974             /* ratio of the energy of the original signal and the energy
975              * of the HF generated signal
976              */
977             G_max = acc1 - QUANTISE2REAL(log2(EPS + acc2)) + QUANTISE2REAL(limGain[sbr->bs_limiter_gains]);
978             G_max = min(G_max, QUANTISE2REAL(limGain[3]));
979
980
981             for (m = ml1; m < ml2; m++)
982             {
983                 real_t G;
984                 real_t E_curr, E_orig;
985                 real_t Q_orig, Q_orig_plus1;
986                 uint8_t S_index_mapped;
987
988
989                 /* check if m is on a noise band border */
990                 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
991                 {
992                     /* step to next noise band */
993                     current_f_noise_band++;
994                 }
995
996
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])
999                 {
1000                     /* accumulate a whole range of equal Q_Ms */
1001                     if (Q_M_size > 0)
1002                         den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M));
1003                     Q_M_size = 0;
1004
1005                     /* step to next resolution band */
1006                     current_res_band2++;
1007
1008                     /* if we move to a new resolution band, we should check if we are
1009                      * going to add a sinusoid in this band
1010                      */
1011                     S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1012                 }
1013
1014
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])
1017                 {
1018                     /* step to next HI_RES band */
1019                     current_hi_res_band++;
1020                 }
1021
1022
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
1026                  */
1027                 S_index_mapped = 0;
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]))
1030                 {
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];
1034                 }
1035
1036
1037                 /* find bitstream parameters */
1038                 if (sbr->E_curr[ch][m][l] == 0)
1039                     E_curr = LOG2_MIN_INF;
1040                 else
1041                     E_curr = -10 + log2(sbr->E_curr[ch][m][l]);
1042                 E_orig = -10 + find_log2_E(sbr, current_res_band2, l, ch);
1043
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);
1046
1047
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)
1051                  */
1052                 Q_M = E_orig + Q_orig - Q_orig_plus1;
1053
1054
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
1057                  */
1058                 if (S_index_mapped == 0)
1059                 {
1060                     S_M[m] = LOG2_MIN_INF; /* -inf */
1061                 } else {
1062                     S_M[m] = E_orig - Q_orig_plus1;
1063
1064                     /* accumulate sinusoid part of the total energy */
1065                     den += pow2(S_M[m]);
1066                 }
1067
1068
1069                 /* calculate gain */
1070                 /* ratio of the energy of the original signal and the energy
1071                  * of the HF generated signal
1072                  */
1073                 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
1074                 /* scaled by -10 */
1075                 G = E_orig - max(-10, E_curr);
1076                 if ((S_mapped == 0) && (delta == 1))
1077                 {
1078                     /* G = G * 1/(1+Q) */
1079                     G -= Q_orig_plus1;
1080                 } else if (S_mapped == 1) {
1081                     /* G = G * Q/(1+Q) */
1082                     G += Q_orig - Q_orig_plus1;
1083                 }
1084
1085
1086                 /* limit the additional noise energy level */
1087                 /* and apply the limiter */
1088                 if (G_max > G)
1089                 {
1090                     Q_M_lim[m] = QUANTISE2REAL(Q_M);
1091                     G_lim[m] = QUANTISE2REAL(G);
1092
1093                     if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1094                     {
1095                         Q_M_size++;
1096                     }
1097                 } else {
1098                     /* G > G_max */
1099                     Q_M_lim[m] = QUANTISE2REAL(Q_M) + G_max - QUANTISE2REAL(G);
1100                     G_lim[m] = G_max;
1101
1102                     /* accumulate limited Q_M */
1103                     if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1104                     {
1105                         den += QUANTISE2INT(pow2(Q_M_lim[m]));
1106                     }
1107                 }
1108
1109
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]));
1113             }
1114
1115             /* accumulate last range of equal Q_Ms */
1116             if (Q_M_size > 0)
1117             {
1118                 den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M));
1119             }
1120
1121
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) */);
1126
1127
1128             for (m = ml1; m < ml2; m++)
1129             {
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));
1133 #else
1134                 /* sqrt() will be done after the aliasing reduction to save a
1135                  * few multiplies
1136                  */
1137                 adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2(G_lim[m] + G_boost));
1138 #endif
1139                 adj->Q_M_lim_boost[l][m] = QUANTISE2REAL(pow2((Q_M_lim[m] + 10 + G_boost) / 2.0));
1140
1141                 if (S_M[m] != LOG2_MIN_INF)
1142                 {
1143                     adj->S_M_boost[l][m] = QUANTISE2REAL(pow2((S_M[m] + 10 + G_boost) / 2.0));
1144                 } else {
1145                     adj->S_M_boost[l][m] = 0;
1146                 }
1147             }
1148         }
1149     }
1150 }
1151
1152 #else
1153
1154 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
1155 {
1156     static real_t limGain[] = { 0.5, 1.0, 2.0, 1e10 };
1157     uint8_t m, l, k;
1158
1159     uint8_t current_t_noise_band = 0;
1160     uint8_t S_mapped;
1161
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];
1166
1167     for (l = 0; l < sbr->L_E[ch]; l++)
1168     {
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;
1173
1174         real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
1175
1176         S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1177
1178         if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
1179         {
1180             current_t_noise_band++;
1181         }
1182
1183         for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
1184         {
1185             real_t G_max;
1186             real_t den = 0;
1187             real_t acc1 = 0;
1188             real_t acc2 = 0;
1189             uint8_t current_res_band_size = 0;
1190
1191             uint8_t ml1, ml2;
1192
1193             ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
1194             ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
1195
1196
1197             /* calculate the accumulated E_orig and E_curr over the limiter band */
1198             for (m = ml1; m < ml2; m++)
1199             {
1200                 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
1201                 {
1202                     current_res_band++;
1203                 }
1204                 acc1 += sbr->E_orig[ch][current_res_band][l];
1205                 acc2 += sbr->E_curr[ch][m][l];
1206             }
1207
1208
1209             /* calculate the maximum gain */
1210             /* ratio of the energy of the original signal and the energy
1211              * of the HF generated signal
1212              */
1213             G_max = ((EPS + acc1) / (EPS + acc2)) * limGain[sbr->bs_limiter_gains];
1214             G_max = min(G_max, 1e10);
1215
1216
1217             for (m = ml1; m < ml2; m++)
1218             {
1219                 real_t Q_M, G;
1220                 real_t Q_div, Q_div2;
1221                 uint8_t S_index_mapped;
1222
1223
1224                 /* check if m is on a noise band border */
1225                 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
1226                 {
1227                     /* step to next noise band */
1228                     current_f_noise_band++;
1229                 }
1230
1231
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])
1234                 {
1235                     /* step to next resolution band */
1236                     current_res_band2++;
1237
1238                     /* if we move to a new resolution band, we should check if we are
1239                      * going to add a sinusoid in this band
1240                      */
1241                     S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1242                 }
1243
1244
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])
1247                 {
1248                     /* step to next HI_RES band */
1249                     current_hi_res_band++;
1250                 }
1251
1252
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
1256                  */
1257                 S_index_mapped = 0;
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]))
1260                 {
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];
1264                 }
1265
1266
1267                 /* Q_div: [0..1] (1/(1+Q_mapped)) */
1268                 Q_div = sbr->Q_div[ch][current_f_noise_band][current_t_noise_band];
1269
1270
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];
1273
1274
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
1278                  */
1279                 Q_M = sbr->E_orig[ch][current_res_band2][l] * Q_div2;
1280
1281
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
1284                  */
1285                 if (S_index_mapped == 0)
1286                 {
1287                     S_M[m] = 0;
1288                 } else {
1289                     S_M[m] = sbr->E_orig[ch][current_res_band2][l] * Q_div;
1290
1291                     /* accumulate sinusoid part of the total energy */
1292                     den += S_M[m];
1293                 }
1294
1295
1296                 /* calculate gain */
1297                 /* ratio of the energy of the original signal and the energy
1298                  * of the HF generated signal
1299                  */
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))
1302                     G *= Q_div;
1303                 else if (S_mapped == 1)
1304                     G *= Q_div2;
1305
1306
1307                 /* limit the additional noise energy level */
1308                 /* and apply the limiter */
1309                 if (G_max > G)
1310                 {
1311                     Q_M_lim[m] = Q_M;
1312                     G_lim[m] = G;
1313                 } else {
1314                     Q_M_lim[m] = Q_M * G_max / G;
1315                     G_lim[m] = G_max;
1316                 }
1317
1318
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]))
1322                     den += Q_M_lim[m];
1323             }
1324
1325             /* G_boost: [0..2.51188643] */
1326             G_boost = (acc1 + EPS) / (den + EPS);
1327             G_boost = min(G_boost, 2.51188643 /* 1.584893192 ^ 2 */);
1328
1329             for (m = ml1; m < ml2; m++)
1330             {
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);
1334 #else
1335                 /* sqrt() will be done after the aliasing reduction to save a
1336                  * few multiplies
1337                  */
1338                 adj->G_lim_boost[l][m] = G_lim[m] * G_boost;
1339 #endif
1340                 adj->Q_M_lim_boost[l][m] = sqrt(Q_M_lim[m] * G_boost);
1341
1342                 if (S_M[m] != 0)
1343                 {
1344                     adj->S_M_boost[l][m] = sqrt(S_M[m] * G_boost);
1345                 } else {
1346                     adj->S_M_boost[l][m] = 0;
1347                 }
1348             }
1349         }
1350     }
1351 }
1352 #endif // log2_test
1353
1354 #endif
1355
1356 #ifdef SBR_LOW_POWER
1357 static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch)
1358 {
1359     uint8_t l, k, i;
1360     uint8_t grouping;
1361     uint8_t S_mapped;
1362
1363     for (l = 0; l < sbr->L_E[ch]; l++)
1364     {
1365         uint8_t current_res_band = 0;
1366         i = 0;
1367         grouping = 0;
1368
1369         S_mapped = get_S_mapped(sbr, ch, l, current_res_band);
1370
1371         for (k = sbr->kx; k < sbr->kx + sbr->M - 1; k++)
1372         {
1373             if (k == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
1374             {
1375                 /* step to next resolution band */
1376                 current_res_band++;
1377
1378                 S_mapped = get_S_mapped(sbr, ch, l, current_res_band);
1379             }
1380
1381             if (deg[k + 1] && S_mapped == 0)
1382             {
1383                 if (grouping == 0)
1384                 {
1385                     sbr->f_group[l][i] = k;
1386                     grouping = 1;
1387                     i++;
1388                 }
1389             } else {
1390                 if (grouping)
1391                 {
1392                     if (S_mapped)
1393                     {
1394                         sbr->f_group[l][i] = k;
1395                     } else {
1396                         sbr->f_group[l][i] = k + 1;
1397                     }
1398                     grouping = 0;
1399                     i++;
1400                 }
1401             }
1402         }        
1403
1404         if (grouping)
1405         {
1406             sbr->f_group[l][i] = sbr->kx + sbr->M;
1407             i++;
1408         }
1409
1410         sbr->N_G[l] = (uint8_t)(i >> 1);
1411     }
1412 }
1413
1414 static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch)
1415 {
1416     uint8_t l, k, m;
1417     real_t E_total, E_total_est, G_target, acc;
1418
1419     for (l = 0; l < sbr->L_E[ch]; l++)
1420     {
1421         for (k = 0; k < sbr->N_G[l]; k++)
1422         {
1423             E_total_est = E_total = 0;
1424             
1425             for (m = sbr->f_group[l][k<<1]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1426             {
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];
1432 #ifdef FIXED_POINT
1433                 E_total += MUL_Q2(sbr->E_curr[ch][m-sbr->kx][l], adj->G_lim_boost[l][m-sbr->kx]);
1434 #else
1435                 E_total += sbr->E_curr[ch][m-sbr->kx][l] * adj->G_lim_boost[l][m-sbr->kx];
1436 #endif
1437             }
1438
1439             /* G_target: fixed point */
1440             if ((E_total_est + EPS) == 0)
1441             {
1442                 G_target = 0;
1443             } else {
1444 #ifdef FIXED_POINT
1445                 G_target = (((int64_t)(E_total))<<Q2_BITS)/(E_total_est + EPS);
1446 #else
1447                 G_target = E_total / (E_total_est + EPS);
1448 #endif
1449             }
1450             acc = 0;
1451
1452             for (m = sbr->f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1453             {
1454                 real_t alpha;
1455
1456                 /* alpha: (COEF) fixed point */
1457                 if (m < sbr->kx + sbr->M - 1)
1458                 {
1459                     alpha = max(deg[m], deg[m + 1]);
1460                 } else {
1461                     alpha = deg[m];
1462                 }
1463
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]);
1466
1467                 /* acc: integer */
1468 #ifdef FIXED_POINT
1469                 acc += MUL_Q2(adj->G_lim_boost[l][m-sbr->kx], sbr->E_curr[ch][m-sbr->kx][l]);
1470 #else
1471                 acc += adj->G_lim_boost[l][m-sbr->kx] * sbr->E_curr[ch][m-sbr->kx][l];
1472 #endif
1473             }
1474
1475             /* acc: fixed point */
1476             if (acc + EPS == 0)
1477             {
1478                 acc = 0;
1479             } else {
1480 #ifdef FIXED_POINT
1481                 acc = (((int64_t)(E_total))<<Q2_BITS)/(acc + EPS);
1482 #else
1483                 acc = E_total / (acc + EPS);
1484 #endif
1485             }
1486             for(m = sbr->f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1487             {
1488 #ifdef FIXED_POINT
1489                 adj->G_lim_boost[l][m-sbr->kx] = MUL_Q2(acc, adj->G_lim_boost[l][m-sbr->kx]);
1490 #else
1491                 adj->G_lim_boost[l][m-sbr->kx] = acc * adj->G_lim_boost[l][m-sbr->kx];
1492 #endif
1493             }
1494         }
1495     }
1496
1497     for (l = 0; l < sbr->L_E[ch]; l++)
1498     {
1499         for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
1500         {
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++)
1503             {
1504 #ifdef FIXED_POINT
1505                  adj->G_lim_boost[l][m] = SBR_SQRT_Q2(adj->G_lim_boost[l][m]);
1506 #else
1507                  adj->G_lim_boost[l][m] = sqrt(adj->G_lim_boost[l][m]);
1508 #endif
1509             }
1510         }
1511     }
1512 }
1513 #endif
1514
1515 static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj,
1516                         qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch)
1517 {
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)
1522     };
1523     static int8_t phi_re[] = { 1, 0, -1, 0 };
1524     static int8_t phi_im[] = { 0, 1, 0, -1 };
1525
1526     uint8_t m, l, i, n;
1527     uint16_t fIndexNoise = 0;
1528     uint8_t fIndexSine = 0;
1529     uint8_t assembly_reset = 0;
1530
1531     real_t G_filt, Q_filt;
1532
1533     uint8_t h_SL;
1534
1535
1536     if (sbr->Reset == 1)
1537     {
1538         assembly_reset = 1;
1539         fIndexNoise = 0;
1540     } else {
1541         fIndexNoise = sbr->index_noise_prev[ch];
1542     }
1543     fIndexSine = sbr->psi_is_prev[ch];
1544
1545
1546     for (l = 0; l < sbr->L_E[ch]; l++)
1547     {
1548         uint8_t no_noise = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 1 : 0;
1549
1550 #ifdef SBR_LOW_POWER
1551         h_SL = 0;
1552 #else
1553         h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4;
1554         h_SL = (no_noise ? 0 : h_SL);
1555 #endif
1556
1557         if (assembly_reset)
1558         {
1559             for (n = 0; n < 4; n++)
1560             {
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));
1563             }
1564             /* reset ringbuffer index */
1565             sbr->GQ_ringbuf_index[ch] = 4;
1566             assembly_reset = 0;
1567         }
1568
1569         for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++)
1570         {
1571 #ifdef SBR_LOW_POWER
1572             uint8_t i_min1, i_plus1;
1573             uint8_t sinusoids = 0;
1574 #endif
1575
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));
1579
1580             for (m = 0; m < sbr->M; m++)
1581             {
1582                 qmf_t psi;
1583
1584                 G_filt = 0;
1585                 Q_filt = 0;
1586
1587 #ifndef SBR_LOW_POWER
1588                 if (h_SL != 0)
1589                 {
1590                         uint8_t ri = sbr->GQ_ringbuf_index[ch];
1591                     for (n = 0; n <= 4; n++)
1592                     {
1593                         real_t curr_h_smooth = h_smooth[n];
1594                         ri++;
1595                         if (ri >= 5)
1596                             ri -= 5;
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);
1599                     }
1600                } else {
1601 #endif
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
1605                 }
1606 #endif
1607
1608                 Q_filt = (adj->S_M_boost[l][m] != 0 || no_noise) ? 0 : Q_filt;
1609
1610                 /* add noise to the output */
1611                 fIndexNoise = (fIndexNoise + 1) & 511;
1612
1613                 /* the smoothed gain values are applied to Xsbr */
1614                 /* V is defined, not calculated */
1615 #ifndef FIXED_POINT
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]));
1618 #else
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]));
1623 #endif
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
1627 #ifndef FIXED_POINT
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]));
1630 #else
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]));
1635 #endif
1636 #endif
1637
1638                 {
1639                     int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1);
1640                     QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine];
1641 #ifdef FIXED_POINT
1642                     QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += (QMF_RE(psi) << REAL_BITS);
1643 #else
1644                     QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi);
1645 #endif
1646
1647 #ifndef SBR_LOW_POWER
1648                     QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine];
1649 #ifdef FIXED_POINT
1650                     QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += (QMF_IM(psi) << REAL_BITS);
1651 #else
1652                     QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_IM(psi);
1653 #endif
1654 #else
1655
1656                     i_min1 = (fIndexSine - 1) & 3;
1657                     i_plus1 = (fIndexSine + 1) & 3;
1658
1659 #ifndef FIXED_POINT
1660                     if ((m == 0) && (phi_re[i_plus1] != 0))
1661                     {
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)));
1664                         if (sbr->M != 0)
1665                         {
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)));
1668                         }
1669                     }
1670                     if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1671                     {
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)));
1674                     }
1675                     if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0))
1676                     {
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)));
1679                     }
1680                     if ((m == sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1681                     {
1682                         if (m > 0)
1683                         {
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)));
1686                         }
1687                         if (m + sbr->kx < 64)
1688                         {
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)));
1691                         }
1692                     }
1693 #else
1694                     if ((m == 0) && (phi_re[i_plus1] != 0))
1695                     {
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)));
1698                         if (sbr->M != 0)
1699                         {
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)));
1702                         }
1703                     }
1704                     if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1705                     {
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)));
1708                     }
1709                     if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0))
1710                     {
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)));
1713                     }
1714                     if ((m == sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1715                     {
1716                         if (m > 0)
1717                         {
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)));
1720                         }
1721                         if (m + sbr->kx < 64)
1722                         {
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)));
1725                         }
1726                     }
1727 #endif
1728
1729                     if (adj->S_M_boost[l][m] != 0)
1730                         sinusoids++;
1731 #endif
1732                 }
1733             }
1734
1735             fIndexSine = (fIndexSine + 1) & 3;
1736
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;
1741         }
1742     }
1743
1744     sbr->index_noise_prev[ch] = fIndexNoise;
1745     sbr->psi_is_prev[ch] = fIndexSine;
1746 }
1747
1748 #endif