summaryrefslogtreecommitdiff
path: root/apps/codecs/libfaad/sbr_hfadj.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libfaad/sbr_hfadj.c')
-rw-r--r--apps/codecs/libfaad/sbr_hfadj.c1720
1 files changed, 1720 insertions, 0 deletions
diff --git a/apps/codecs/libfaad/sbr_hfadj.c b/apps/codecs/libfaad/sbr_hfadj.c
new file mode 100644
index 0000000000..17d63f41c2
--- /dev/null
+++ b/apps/codecs/libfaad/sbr_hfadj.c
@@ -0,0 +1,1720 @@
1/*
2** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
3** Copyright (C) 2003-2004 M. Bakker, Ahead Software 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** Commercial non-GPL licensing of this software is possible.
23** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
24**
25** $Id$
26**/
27
28/* High Frequency adjustment */
29
30#include "common.h"
31#include "structs.h"
32
33#ifdef SBR_DEC
34
35#include "sbr_syntax.h"
36#include "sbr_hfadj.h"
37
38#include "sbr_noise.h"
39
40
41/* static function declarations */
42static void estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj,
43 qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
44static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch);
45#ifdef SBR_LOW_POWER
46static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch);
47static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch);
48#endif
49static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj, qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
50
51
52void hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64]
53#ifdef SBR_LOW_POWER
54 ,real_t *deg /* aliasing degree */
55#endif
56 ,uint8_t ch)
57{
58 ALIGN sbr_hfadj_info adj = {{{0}}};
59
60 if (sbr->bs_frame_class[ch] == FIXFIX)
61 {
62 sbr->l_A[ch] = -1;
63 } else if (sbr->bs_frame_class[ch] == VARFIX) {
64 if (sbr->bs_pointer[ch] > 1)
65 sbr->l_A[ch] = -1;
66 else
67 sbr->l_A[ch] = sbr->bs_pointer[ch] - 1;
68 } else {
69 if (sbr->bs_pointer[ch] == 0)
70 sbr->l_A[ch] = -1;
71 else
72 sbr->l_A[ch] = sbr->L_E[ch] + 1 - sbr->bs_pointer[ch];
73 }
74
75 estimate_current_envelope(sbr, &adj, Xsbr, ch);
76
77 calculate_gain(sbr, &adj, ch);
78
79#ifdef SBR_LOW_POWER
80 calc_gain_groups(sbr, &adj, deg, ch);
81 aliasing_reduction(sbr, &adj, deg, ch);
82#endif
83
84 hf_assembly(sbr, &adj, Xsbr, ch);
85}
86
87static uint8_t get_S_mapped(sbr_info *sbr, uint8_t ch, uint8_t l, uint8_t current_band)
88{
89 if (sbr->f[ch][l] == HI_RES)
90 {
91 /* in case of using f_table_high we just have 1 to 1 mapping
92 * from bs_add_harmonic[l][k]
93 */
94 if ((l >= sbr->l_A[ch]) ||
95 (sbr->bs_add_harmonic_prev[ch][current_band] && sbr->bs_add_harmonic_flag_prev[ch]))
96 {
97 return sbr->bs_add_harmonic[ch][current_band];
98 }
99 } else {
100 uint8_t b, lb, ub;
101
102 /* in case of f_table_low we check if any of the HI_RES bands
103 * within this LO_RES band has bs_add_harmonic[l][k] turned on
104 * (note that borders in the LO_RES table are also present in
105 * the HI_RES table)
106 */
107
108 /* find first HI_RES band in current LO_RES band */
109 lb = 2*current_band - ((sbr->N_high & 1) ? 1 : 0);
110 /* find first HI_RES band in next LO_RES band */
111 ub = 2*(current_band+1) - ((sbr->N_high & 1) ? 1 : 0);
112
113 /* check all HI_RES bands in current LO_RES band for sinusoid */
114 for (b = lb; b < ub; b++)
115 {
116 if ((l >= sbr->l_A[ch]) ||
117 (sbr->bs_add_harmonic_prev[ch][b] && sbr->bs_add_harmonic_flag_prev[ch]))
118 {
119 if (sbr->bs_add_harmonic[ch][b] == 1)
120 return 1;
121 }
122 }
123 }
124
125 return 0;
126}
127
128static void estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj,
129 qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch)
130{
131 uint8_t m, l, j, k, k_l, k_h, p;
132 real_t nrg, div;
133
134 if (sbr->bs_interpol_freq == 1)
135 {
136 for (l = 0; l < sbr->L_E[ch]; l++)
137 {
138 uint8_t i, l_i, u_i;
139
140 l_i = sbr->t_E[ch][l];
141 u_i = sbr->t_E[ch][l+1];
142
143 div = (real_t)(u_i - l_i);
144
145 for (m = 0; m < sbr->M; m++)
146 {
147 nrg = 0;
148
149 for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
150 {
151#ifdef FIXED_POINT
152#ifdef SBR_LOW_POWER
153 nrg += ((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS);
154#else
155 nrg += ((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS) +
156 ((QMF_IM(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_IM(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS);
157#endif
158#else
159 nrg += MUL_R(QMF_RE(Xsbr[i][m + sbr->kx]), QMF_RE(Xsbr[i][m + sbr->kx]))
160#ifndef SBR_LOW_POWER
161 + MUL_R(QMF_IM(Xsbr[i][m + sbr->kx]), QMF_IM(Xsbr[i][m + sbr->kx]))
162#endif
163 ;
164#endif
165 }
166
167 sbr->E_curr[ch][m][l] = nrg / div;
168#ifdef SBR_LOW_POWER
169#ifdef FIXED_POINT
170 sbr->E_curr[ch][m][l] <<= 1;
171#else
172 sbr->E_curr[ch][m][l] *= 2;
173#endif
174#endif
175 }
176 }
177 } else {
178 for (l = 0; l < sbr->L_E[ch]; l++)
179 {
180 for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++)
181 {
182 k_l = sbr->f_table_res[sbr->f[ch][l]][p];
183 k_h = sbr->f_table_res[sbr->f[ch][l]][p+1];
184
185 for (k = k_l; k < k_h; k++)
186 {
187 uint8_t i, l_i, u_i;
188 nrg = 0;
189
190 l_i = sbr->t_E[ch][l];
191 u_i = sbr->t_E[ch][l+1];
192
193 div = (real_t)((u_i - l_i)*(k_h - k_l));
194
195 for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
196 {
197 for (j = k_l; j < k_h; j++)
198 {
199#ifdef FIXED_POINT
200#ifdef SBR_LOW_POWER
201 nrg += ((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS);
202#else
203 nrg += ((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS) +
204 ((QMF_IM(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_IM(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS);
205#endif
206#else
207 nrg += MUL_R(QMF_RE(Xsbr[i][j]), QMF_RE(Xsbr[i][j]))
208#ifndef SBR_LOW_POWER
209 + MUL_R(QMF_IM(Xsbr[i][j]), QMF_IM(Xsbr[i][j]))
210#endif
211 ;
212#endif
213 }
214 }
215
216 sbr->E_curr[ch][k - sbr->kx][l] = nrg / div;
217#ifdef SBR_LOW_POWER
218#ifdef FIXED_POINT
219 sbr->E_curr[ch][k - sbr->kx][l] <<= 1;
220#else
221 sbr->E_curr[ch][k - sbr->kx][l] *= 2;
222#endif
223#endif
224 }
225 }
226 }
227 }
228}
229
230#ifdef FIXED_POINT
231#define EPS (1) /* smallest number available in fixed point */
232#else
233#define EPS (1e-12)
234#endif
235
236
237
238#ifdef FIXED_POINT
239
240/* log2 values of [0..63] */
241static const real_t log2_int_tab[] = {
242 LOG2_MIN_INF, REAL_CONST(0.000000000000000), REAL_CONST(1.000000000000000), REAL_CONST(1.584962500721156),
243 REAL_CONST(2.000000000000000), REAL_CONST(2.321928094887362), REAL_CONST(2.584962500721156), REAL_CONST(2.807354922057604),
244 REAL_CONST(3.000000000000000), REAL_CONST(3.169925001442313), REAL_CONST(3.321928094887363), REAL_CONST(3.459431618637297),
245 REAL_CONST(3.584962500721156), REAL_CONST(3.700439718141092), REAL_CONST(3.807354922057604), REAL_CONST(3.906890595608519),
246 REAL_CONST(4.000000000000000), REAL_CONST(4.087462841250339), REAL_CONST(4.169925001442312), REAL_CONST(4.247927513443585),
247 REAL_CONST(4.321928094887362), REAL_CONST(4.392317422778761), REAL_CONST(4.459431618637297), REAL_CONST(4.523561956057013),
248 REAL_CONST(4.584962500721156), REAL_CONST(4.643856189774724), REAL_CONST(4.700439718141093), REAL_CONST(4.754887502163468),
249 REAL_CONST(4.807354922057604), REAL_CONST(4.857980995127572), REAL_CONST(4.906890595608519), REAL_CONST(4.954196310386875),
250 REAL_CONST(5.000000000000000), REAL_CONST(5.044394119358453), REAL_CONST(5.087462841250340), REAL_CONST(5.129283016944966),
251 REAL_CONST(5.169925001442312), REAL_CONST(5.209453365628949), REAL_CONST(5.247927513443585), REAL_CONST(5.285402218862248),
252 REAL_CONST(5.321928094887363), REAL_CONST(5.357552004618084), REAL_CONST(5.392317422778761), REAL_CONST(5.426264754702098),
253 REAL_CONST(5.459431618637297), REAL_CONST(5.491853096329675), REAL_CONST(5.523561956057013), REAL_CONST(5.554588851677637),
254 REAL_CONST(5.584962500721156), REAL_CONST(5.614709844115208), REAL_CONST(5.643856189774724), REAL_CONST(5.672425341971495),
255 REAL_CONST(5.700439718141093), REAL_CONST(5.727920454563200), REAL_CONST(5.754887502163469), REAL_CONST(5.781359713524660),
256 REAL_CONST(5.807354922057605), REAL_CONST(5.832890014164742), REAL_CONST(5.857980995127572), REAL_CONST(5.882643049361842),
257 REAL_CONST(5.906890595608518), REAL_CONST(5.930737337562887), REAL_CONST(5.954196310386876), REAL_CONST(5.977279923499916)
258};
259
260static const real_t pan_log2_tab[] = {
261 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362), REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339),
262 REAL_CONST(0.044394119358453), REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878), REAL_CONST(0.002815015607054),
263 REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247), REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
264 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667)
265};
266
267static real_t find_log2_E(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
268{
269 /* check for coupled energy/noise data */
270 if (sbr->bs_coupling == 1)
271 {
272 uint8_t amp0 = (sbr->amp_res[0]) ? 0 : 1;
273 uint8_t amp1 = (sbr->amp_res[1]) ? 0 : 1;
274 real_t tmp = (7 << REAL_BITS) + (sbr->E[0][k][l] << (REAL_BITS-amp0));
275 real_t pan;
276
277 /* E[1] should always be even so shifting is OK */
278 uint8_t E = sbr->E[1][k][l] >> amp1;
279
280 if (ch == 0)
281 {
282 if (E > 12)
283 {
284 /* negative */
285 pan = pan_log2_tab[-12 + E];
286 } else {
287 /* positive */
288 pan = pan_log2_tab[12 - E] + ((12 - E)<<REAL_BITS);
289 }
290 } else {
291 if (E < 12)
292 {
293 /* negative */
294 pan = pan_log2_tab[-E + 12];
295 } else {
296 /* positive */
297 pan = pan_log2_tab[E - 12] + ((E - 12)<<REAL_BITS);
298 }
299 }
300
301 /* tmp / pan in log2 */
302 return tmp - pan;
303 } else {
304 uint8_t amp = (sbr->amp_res[ch]) ? 0 : 1;
305
306 return (6 << REAL_BITS) + (sbr->E[ch][k][l] << (REAL_BITS-amp));
307 }
308}
309
310static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
311{
312 /* check for coupled energy/noise data */
313 if (sbr->bs_coupling == 1)
314 {
315 real_t tmp = (7 << REAL_BITS) - (sbr->Q[0][k][l] << REAL_BITS);
316 real_t pan;
317
318 uint8_t Q = sbr->Q[1][k][l];
319
320 if (ch == 0)
321 {
322 if (Q > 12)
323 {
324 /* negative */
325 pan = pan_log2_tab[-12 + Q];
326 } else {
327 /* positive */
328 pan = pan_log2_tab[12 - Q] + ((12 - Q)<<REAL_BITS);
329 }
330 } else {
331 if (Q < 12)
332 {
333 /* negative */
334 pan = pan_log2_tab[-Q + 12];
335 } else {
336 /* positive */
337 pan = pan_log2_tab[Q - 12] + ((Q - 12)<<REAL_BITS);
338 }
339 }
340
341 /* tmp / pan in log2 */
342 return tmp - pan;
343 } else {
344 return (6 << REAL_BITS) - (sbr->Q[ch][k][l] << REAL_BITS);
345 }
346}
347
348static const real_t log_Qplus1_pan[31][13] = {
349 { REAL_CONST(0.044383447617292), REAL_CONST(0.169768601655960), REAL_CONST(0.583090126514435), REAL_CONST(1.570089221000671), REAL_CONST(3.092446088790894), REAL_CONST(4.733354568481445), REAL_CONST(6.022367954254150), REAL_CONST(6.692092418670654), REAL_CONST(6.924463272094727), REAL_CONST(6.989034175872803), REAL_CONST(7.005646705627441), REAL_CONST(7.009829998016357), REAL_CONST(7.010877609252930) },
350 { REAL_CONST(0.022362394258380), REAL_CONST(0.087379962205887), REAL_CONST(0.320804953575134), REAL_CONST(0.988859415054321), REAL_CONST(2.252387046813965), REAL_CONST(3.786596298217773), REAL_CONST(5.044394016265869), REAL_CONST(5.705977916717529), REAL_CONST(5.936291694641113), REAL_CONST(6.000346660614014), REAL_CONST(6.016829967498779), REAL_CONST(6.020981311798096), REAL_CONST(6.022020816802979) },
351 { REAL_CONST(0.011224525049329), REAL_CONST(0.044351425021887), REAL_CONST(0.169301137328148), REAL_CONST(0.577544987201691), REAL_CONST(1.527246952056885), REAL_CONST(2.887525320053101), REAL_CONST(4.087462902069092), REAL_CONST(4.733354568481445), REAL_CONST(4.959661006927490), REAL_CONST(5.022709369659424), REAL_CONST(5.038940429687500), REAL_CONST(5.043028831481934), REAL_CONST(5.044052600860596) },
352 { REAL_CONST(0.005623178556561), REAL_CONST(0.022346137091517), REAL_CONST(0.087132595479488), REAL_CONST(0.317482173442841), REAL_CONST(0.956931233406067), REAL_CONST(2.070389270782471), REAL_CONST(3.169924974441528), REAL_CONST(3.786596298217773), REAL_CONST(4.005294322967529), REAL_CONST(4.066420555114746), REAL_CONST(4.082170009613037), REAL_CONST(4.086137294769287), REAL_CONST(4.087131500244141) },
353 { REAL_CONST(0.002814328996465), REAL_CONST(0.011216334067285), REAL_CONST(0.044224001467228), REAL_CONST(0.167456731200218), REAL_CONST(0.556393325328827), REAL_CONST(1.378511548042297), REAL_CONST(2.321928024291992), REAL_CONST(2.887525320053101), REAL_CONST(3.092446088790894), REAL_CONST(3.150059700012207), REAL_CONST(3.164926528930664), REAL_CONST(3.168673276901245), REAL_CONST(3.169611930847168) },
354 { REAL_CONST(0.001407850766554), REAL_CONST(0.005619067233056), REAL_CONST(0.022281449288130), REAL_CONST(0.086156636476517), REAL_CONST(0.304854571819305), REAL_CONST(0.847996890544891), REAL_CONST(1.584962487220764), REAL_CONST(2.070389270782471), REAL_CONST(2.252387046813965), REAL_CONST(2.304061651229858), REAL_CONST(2.317430257797241), REAL_CONST(2.320801734924316), REAL_CONST(2.321646213531494) },
355 { REAL_CONST(0.000704097095877), REAL_CONST(0.002812269143760), REAL_CONST(0.011183738708496), REAL_CONST(0.043721374124289), REAL_CONST(0.160464659333229), REAL_CONST(0.485426813364029), REAL_CONST(1.000000000000000), REAL_CONST(1.378511548042297), REAL_CONST(1.527246952056885), REAL_CONST(1.570089221000671), REAL_CONST(1.581215262413025), REAL_CONST(1.584023833274841), REAL_CONST(1.584727644920349) },
356 { REAL_CONST(0.000352177477907), REAL_CONST(0.001406819908880), REAL_CONST(0.005602621007711), REAL_CONST(0.022026389837265), REAL_CONST(0.082462236285210), REAL_CONST(0.263034462928772), REAL_CONST(0.584962487220764), REAL_CONST(0.847996890544891), REAL_CONST(0.956931233406067), REAL_CONST(0.988859415054321), REAL_CONST(0.997190535068512), REAL_CONST(0.999296069145203), REAL_CONST(0.999823868274689) },
357 { REAL_CONST(0.000176099492819), REAL_CONST(0.000703581434209), REAL_CONST(0.002804030198604), REAL_CONST(0.011055230163038), REAL_CONST(0.041820213198662), REAL_CONST(0.137503549456596), REAL_CONST(0.321928083896637), REAL_CONST(0.485426813364029), REAL_CONST(0.556393325328827), REAL_CONST(0.577544987201691), REAL_CONST(0.583090126514435), REAL_CONST(0.584493279457092), REAL_CONST(0.584845066070557) },
358 { REAL_CONST(0.000088052431238), REAL_CONST(0.000351833587047), REAL_CONST(0.001402696361765), REAL_CONST(0.005538204684854), REAL_CONST(0.021061634644866), REAL_CONST(0.070389263331890), REAL_CONST(0.169925004243851), REAL_CONST(0.263034462928772), REAL_CONST(0.304854571819305), REAL_CONST(0.317482173442841), REAL_CONST(0.320804953575134), REAL_CONST(0.321646571159363), REAL_CONST(0.321857661008835) },
359 { REAL_CONST(0.000044026888645), REAL_CONST(0.000175927518285), REAL_CONST(0.000701518612914), REAL_CONST(0.002771759871393), REAL_CONST(0.010569252073765), REAL_CONST(0.035623874515295), REAL_CONST(0.087462842464447), REAL_CONST(0.137503549456596), REAL_CONST(0.160464659333229), REAL_CONST(0.167456731200218), REAL_CONST(0.169301137328148), REAL_CONST(0.169768601655960), REAL_CONST(0.169885858893394) },
360 { REAL_CONST(0.000022013611670), REAL_CONST(0.000088052431238), REAL_CONST(0.000350801943569), REAL_CONST(0.001386545598507), REAL_CONST(0.005294219125062), REAL_CONST(0.017921976745129), REAL_CONST(0.044394120573997), REAL_CONST(0.070389263331890), REAL_CONST(0.082462236285210), REAL_CONST(0.086156636476517), REAL_CONST(0.087132595479488), REAL_CONST(0.087379962205887), REAL_CONST(0.087442122399807) },
361 { REAL_CONST(0.000011006847672), REAL_CONST(0.000044026888645), REAL_CONST(0.000175411638338), REAL_CONST(0.000693439331371), REAL_CONST(0.002649537986144), REAL_CONST(0.008988817222416), REAL_CONST(0.022367812693119), REAL_CONST(0.035623874515295), REAL_CONST(0.041820213198662), REAL_CONST(0.043721374124289), REAL_CONST(0.044224001467228), REAL_CONST(0.044351425021887), REAL_CONST(0.044383447617292) },
362 { REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000087708482170), REAL_CONST(0.000346675369656), REAL_CONST(0.001325377263129), REAL_CONST(0.004501323681325), REAL_CONST(0.011227255687118), REAL_CONST(0.017921976745129), REAL_CONST(0.021061634644866), REAL_CONST(0.022026389837265), REAL_CONST(0.022281449288130), REAL_CONST(0.022346137091517), REAL_CONST(0.022362394258380) },
363 { REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043854910473), REAL_CONST(0.000173348103999), REAL_CONST(0.000662840844598), REAL_CONST(0.002252417383716), REAL_CONST(0.005624548997730), REAL_CONST(0.008988817222416), REAL_CONST(0.010569252073765), REAL_CONST(0.011055230163038), REAL_CONST(0.011183738708496), REAL_CONST(0.011216334067285), REAL_CONST(0.011224525049329) },
364 { REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000086676649516), REAL_CONST(0.000331544462824), REAL_CONST(0.001126734190620), REAL_CONST(0.002815015614033), REAL_CONST(0.004501323681325), REAL_CONST(0.005294219125062), REAL_CONST(0.005538204684854), REAL_CONST(0.005602621007711), REAL_CONST(0.005619067233056), REAL_CONST(0.005623178556561) },
365 { REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043338975956), REAL_CONST(0.000165781748365), REAL_CONST(0.000563477107789), REAL_CONST(0.001408194424585), REAL_CONST(0.002252417383716), REAL_CONST(0.002649537986144), REAL_CONST(0.002771759871393), REAL_CONST(0.002804030198604), REAL_CONST(0.002812269143760), REAL_CONST(0.002814328996465) },
366 { REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000021669651687), REAL_CONST(0.000082893253420), REAL_CONST(0.000281680084299), REAL_CONST(0.000704268983100), REAL_CONST(0.001126734190620), REAL_CONST(0.001325377263129), REAL_CONST(0.001386545598507), REAL_CONST(0.001402696361765), REAL_CONST(0.001406819908880), REAL_CONST(0.001407850766554) },
367 { REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010834866771), REAL_CONST(0.000041447223339), REAL_CONST(0.000140846910654), REAL_CONST(0.000352177477907), REAL_CONST(0.000563477107789), REAL_CONST(0.000662840844598), REAL_CONST(0.000693439331371), REAL_CONST(0.000701518612914), REAL_CONST(0.000703581434209), REAL_CONST(0.000704097095877) },
368 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000020637769921), REAL_CONST(0.000070511166996), REAL_CONST(0.000176099492819), REAL_CONST(0.000281680084299), REAL_CONST(0.000331544462824), REAL_CONST(0.000346675369656), REAL_CONST(0.000350801943569), REAL_CONST(0.000351833587047), REAL_CONST(0.000352177477907) },
369 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010318922250), REAL_CONST(0.000035256012779), REAL_CONST(0.000088052431238), REAL_CONST(0.000140846910654), REAL_CONST(0.000165781748365), REAL_CONST(0.000173348103999), REAL_CONST(0.000175411638338), REAL_CONST(0.000175927518285), REAL_CONST(0.000176099492819) },
370 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005159470220), REAL_CONST(0.000017542124624), REAL_CONST(0.000044026888645), REAL_CONST(0.000070511166996), REAL_CONST(0.000082893253420), REAL_CONST(0.000086676649516), REAL_CONST(0.000087708482170), REAL_CONST(0.000088052431238), REAL_CONST(0.000088052431238) },
371 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002579737384), REAL_CONST(0.000008771088687), REAL_CONST(0.000022013611670), REAL_CONST(0.000035256012779), REAL_CONST(0.000041447223339), REAL_CONST(0.000043338975956), REAL_CONST(0.000043854910473), REAL_CONST(0.000044026888645), REAL_CONST(0.000044026888645) },
372 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000004471542070), REAL_CONST(0.000011006847672), REAL_CONST(0.000017542124624), REAL_CONST(0.000020637769921), REAL_CONST(0.000021669651687), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670) },
373 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002235772627), REAL_CONST(0.000005503434295), REAL_CONST(0.000008771088687), REAL_CONST(0.000010318922250), REAL_CONST(0.000010834866771), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672) },
374 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001031895522), REAL_CONST(0.000002751719876), REAL_CONST(0.000004471542070), REAL_CONST(0.000005159470220), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295) },
375 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000515947875), REAL_CONST(0.000001375860506), REAL_CONST(0.000002235772627), REAL_CONST(0.000002579737384), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876) },
376 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000000687930424), REAL_CONST(0.000001031895522), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506) },
377 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000515947875), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424) },
378 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269) },
379 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634) }
380};
381
382static const real_t log_Qplus1[31] = {
383 REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339),
384 REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156),
385 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362),
386 REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453),
387 REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878),
388 REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247),
389 REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
390 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667),
391 REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551),
392 REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641),
393 REAL_CONST(0.000000000000000)
394};
395
396static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
397{
398 /* check for coupled energy/noise data */
399 if (sbr->bs_coupling == 1)
400 {
401 if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) &&
402 (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24))
403 {
404 if (ch == 0)
405 {
406 return log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1];
407 } else {
408 return log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)];
409 }
410 } else {
411 return 0;
412 }
413 } else {
414 if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
415 {
416 return log_Qplus1[sbr->Q[ch][k][l]];
417 } else {
418 return 0;
419 }
420 }
421}
422
423static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
424{
425 /* log2 values of limiter gains */
426 static real_t limGain[] = {
427 REAL_CONST(-1.0), REAL_CONST(0.0), REAL_CONST(1.0), REAL_CONST(33.219)
428 };
429 uint8_t m, l, k;
430
431 uint8_t current_t_noise_band = 0;
432 uint8_t S_mapped;
433
434 ALIGN real_t Q_M_lim[MAX_M];
435 ALIGN real_t G_lim[MAX_M];
436 ALIGN real_t G_boost;
437 ALIGN real_t S_M[MAX_M];
438
439
440 for (l = 0; l < sbr->L_E[ch]; l++)
441 {
442 uint8_t current_f_noise_band = 0;
443 uint8_t current_res_band = 0;
444 uint8_t current_res_band2 = 0;
445 uint8_t current_hi_res_band = 0;
446
447 real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
448
449 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
450
451 if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
452 {
453 current_t_noise_band++;
454 }
455
456 for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
457 {
458 real_t Q_M = 0;
459 real_t G_max;
460 real_t den = 0;
461 real_t acc1 = 0;
462 real_t acc2 = 0;
463 uint8_t current_res_band_size = 0;
464 uint8_t Q_M_size = 0;
465
466 uint8_t ml1, ml2;
467
468 /* bounds of current limiter bands */
469 ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
470 ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
471
472
473 /* calculate the accumulated E_orig and E_curr over the limiter band */
474 for (m = ml1; m < ml2; m++)
475 {
476 if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
477 {
478 current_res_band_size++;
479 } else {
480 acc1 += pow2_int(-REAL_CONST(10) + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch));
481
482 current_res_band++;
483 current_res_band_size = 1;
484 }
485
486 acc2 += sbr->E_curr[ch][m][l];
487 }
488 acc1 += pow2_int(-REAL_CONST(10) + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch));
489
490
491 if (acc1 == 0)
492 acc1 = LOG2_MIN_INF;
493 else
494 acc1 = log2_int(acc1);
495
496
497 /* calculate the maximum gain */
498 /* ratio of the energy of the original signal and the energy
499 * of the HF generated signal
500 */
501 G_max = acc1 - log2_int(acc2) + limGain[sbr->bs_limiter_gains];
502 G_max = min(G_max, limGain[3]);
503
504
505 for (m = ml1; m < ml2; m++)
506 {
507 real_t G;
508 real_t E_curr, E_orig;
509 real_t Q_orig, Q_orig_plus1;
510 uint8_t S_index_mapped;
511
512
513 /* check if m is on a noise band border */
514 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
515 {
516 /* step to next noise band */
517 current_f_noise_band++;
518 }
519
520
521 /* check if m is on a resolution band border */
522 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
523 {
524 /* accumulate a whole range of equal Q_Ms */
525 if (Q_M_size > 0)
526 den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
527 Q_M_size = 0;
528
529 /* step to next resolution band */
530 current_res_band2++;
531
532 /* if we move to a new resolution band, we should check if we are
533 * going to add a sinusoid in this band
534 */
535 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
536 }
537
538
539 /* check if m is on a HI_RES band border */
540 if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
541 {
542 /* step to next HI_RES band */
543 current_hi_res_band++;
544 }
545
546
547 /* find S_index_mapped
548 * S_index_mapped can only be 1 for the m in the middle of the
549 * current HI_RES band
550 */
551 S_index_mapped = 0;
552 if ((l >= sbr->l_A[ch]) ||
553 (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
554 {
555 /* find the middle subband of the HI_RES frequency band */
556 if ((m + sbr->kx) == (sbr->f_table_res[HI_RES][current_hi_res_band+1] + sbr->f_table_res[HI_RES][current_hi_res_band]) >> 1)
557 S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
558 }
559
560
561 /* find bitstream parameters */
562 if (sbr->E_curr[ch][m][l] == 0)
563 E_curr = LOG2_MIN_INF;
564 else
565 E_curr = log2_int(sbr->E_curr[ch][m][l]);
566 E_orig = -REAL_CONST(10) + find_log2_E(sbr, current_res_band2, l, ch);
567
568
569 Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch);
570 Q_orig_plus1 = find_log2_Qplus1(sbr, current_f_noise_band, current_t_noise_band, ch);
571
572
573 /* Q_M only depends on E_orig and Q_div2:
574 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
575 * a change of current res band (HI or LO)
576 */
577 Q_M = E_orig + Q_orig - Q_orig_plus1;
578
579
580 /* S_M only depends on E_orig, Q_div and S_index_mapped:
581 * S_index_mapped can only be non-zero once per HI_RES band
582 */
583 if (S_index_mapped == 0)
584 {
585 S_M[m] = LOG2_MIN_INF; /* -inf */
586 } else {
587 S_M[m] = E_orig - Q_orig_plus1;
588
589 /* accumulate sinusoid part of the total energy */
590 den += pow2_int(S_M[m]);
591 }
592
593
594 /* calculate gain */
595 /* ratio of the energy of the original signal and the energy
596 * of the HF generated signal
597 */
598 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
599 /* scaled by -10 */
600 G = E_orig - max(-REAL_CONST(10), E_curr);
601 if ((S_mapped == 0) && (delta == 1))
602 {
603 /* G = G * 1/(1+Q) */
604 G -= Q_orig_plus1;
605 } else if (S_mapped == 1) {
606 /* G = G * Q/(1+Q) */
607 G += Q_orig - Q_orig_plus1;
608 }
609
610
611 /* limit the additional noise energy level */
612 /* and apply the limiter */
613 if (G_max > G)
614 {
615 Q_M_lim[m] = Q_M;
616 G_lim[m] = G;
617
618 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
619 {
620 Q_M_size++;
621 }
622 } else {
623 /* G > G_max */
624 Q_M_lim[m] = Q_M + G_max - G;
625 G_lim[m] = G_max;
626
627 /* accumulate limited Q_M */
628 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
629 {
630 den += pow2_int(Q_M_lim[m]);
631 }
632 }
633
634
635 /* accumulate the total energy */
636 /* E_curr changes for every m so we do need to accumulate every m */
637 den += pow2_int(E_curr + G_lim[m]);
638 }
639
640 /* accumulate last range of equal Q_Ms */
641 if (Q_M_size > 0)
642 {
643 den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
644 }
645
646
647 /* calculate the final gain */
648 /* G_boost: [0..2.51188643] */
649 G_boost = acc1 - log2_int(den /*+ EPS*/);
650 G_boost = min(G_boost, REAL_CONST(1.328771237) /* log2(1.584893192 ^ 2) */);
651
652
653 for (m = ml1; m < ml2; m++)
654 {
655 /* apply compensation to gain, noise floor sf's and sinusoid levels */
656#ifndef SBR_LOW_POWER
657 adj->G_lim_boost[l][m] = pow2_fix((G_lim[m] + G_boost) >> 1);
658#else
659 /* sqrt() will be done after the aliasing reduction to save a
660 * few multiplies
661 */
662 adj->G_lim_boost[l][m] = pow2_fix(G_lim[m] + G_boost);
663#endif
664 adj->Q_M_lim_boost[l][m] = pow2_fix((Q_M_lim[m] + G_boost) >> 1);
665
666 if (S_M[m] != LOG2_MIN_INF)
667 {
668 adj->S_M_boost[l][m] = pow2_int((S_M[m] + G_boost) >> 1);
669 } else {
670 adj->S_M_boost[l][m] = 0;
671 }
672 }
673 }
674 }
675}
676
677#else
678
679//#define LOG2_TEST
680
681#ifdef LOG2_TEST
682
683#define LOG2_MIN_INF -100000
684
685__inline float pow2(float val)
686{
687 return pow(2.0, val);
688}
689__inline float log2(float val)
690{
691 return log(val)/log(2.0);
692}
693
694#define RB 14
695
696float QUANTISE2REAL(float val)
697{
698 __int32 ival = (__int32)(val * (1<<RB));
699 return (float)ival / (float)((1<<RB));
700}
701
702float QUANTISE2INT(float val)
703{
704 return floor(val);
705}
706
707/* log2 values of [0..63] */
708static const real_t log2_int_tab[] = {
709 LOG2_MIN_INF, 0.000000000000000, 1.000000000000000, 1.584962500721156,
710 2.000000000000000, 2.321928094887362, 2.584962500721156, 2.807354922057604,
711 3.000000000000000, 3.169925001442313, 3.321928094887363, 3.459431618637297,
712 3.584962500721156, 3.700439718141092, 3.807354922057604, 3.906890595608519,
713 4.000000000000000, 4.087462841250339, 4.169925001442312, 4.247927513443585,
714 4.321928094887362, 4.392317422778761, 4.459431618637297, 4.523561956057013,
715 4.584962500721156, 4.643856189774724, 4.700439718141093, 4.754887502163468,
716 4.807354922057604, 4.857980995127572, 4.906890595608519, 4.954196310386875,
717 5.000000000000000, 5.044394119358453, 5.087462841250340, 5.129283016944966,
718 5.169925001442312, 5.209453365628949, 5.247927513443585, 5.285402218862248,
719 5.321928094887363, 5.357552004618084, 5.392317422778761, 5.426264754702098,
720 5.459431618637297, 5.491853096329675, 5.523561956057013, 5.554588851677637,
721 5.584962500721156, 5.614709844115208, 5.643856189774724, 5.672425341971495,
722 5.700439718141093, 5.727920454563200, 5.754887502163469, 5.781359713524660,
723 5.807354922057605, 5.832890014164742, 5.857980995127572, 5.882643049361842,
724 5.906890595608518, 5.930737337562887, 5.954196310386876, 5.977279923499916
725};
726
727static const real_t pan_log2_tab[] = {
728 1.000000000000000, 0.584962500721156, 0.321928094887362, 0.169925001442312, 0.087462841250339,
729 0.044394119358453, 0.022367813028455, 0.011227255423254, 0.005624549193878, 0.002815015607054,
730 0.001408194392808, 0.000704269011247, 0.000352177480301, 0.000176099486443, 0.000088052430122,
731 0.000044026886827, 0.000022013611360, 0.000011006847667
732};
733
734static real_t find_log2_E(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
735{
736 /* check for coupled energy/noise data */
737 if (sbr->bs_coupling == 1)
738 {
739 real_t amp0 = (sbr->amp_res[0]) ? 1.0 : 0.5;
740 real_t amp1 = (sbr->amp_res[1]) ? 1.0 : 0.5;
741 float tmp = QUANTISE2REAL(7.0 + (real_t)sbr->E[0][k][l] * amp0);
742 float pan;
743
744 int E = (int)(sbr->E[1][k][l] * amp1);
745
746 if (ch == 0)
747 {
748 if (E > 12)
749 {
750 /* negative */
751 pan = QUANTISE2REAL(pan_log2_tab[-12 + E]);
752 } else {
753 /* positive */
754 pan = QUANTISE2REAL(pan_log2_tab[12 - E] + (12 - E));
755 }
756 } else {
757 if (E < 12)
758 {
759 /* negative */
760 pan = QUANTISE2REAL(pan_log2_tab[-E + 12]);
761 } else {
762 /* positive */
763 pan = QUANTISE2REAL(pan_log2_tab[E - 12] + (E - 12));
764 }
765 }
766
767 /* tmp / pan in log2 */
768 return QUANTISE2REAL(tmp - pan);
769 } else {
770 real_t amp = (sbr->amp_res[ch]) ? 1.0 : 0.5;
771
772 return QUANTISE2REAL(6.0 + (real_t)sbr->E[ch][k][l] * amp);
773 }
774}
775
776static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
777{
778 /* check for coupled energy/noise data */
779 if (sbr->bs_coupling == 1)
780 {
781 float tmp = QUANTISE2REAL(7.0 - (real_t)sbr->Q[0][k][l]);
782 float pan;
783
784 int Q = (int)(sbr->Q[1][k][l]);
785
786 if (ch == 0)
787 {
788 if (Q > 12)
789 {
790 /* negative */
791 pan = QUANTISE2REAL(pan_log2_tab[-12 + Q]);
792 } else {
793 /* positive */
794 pan = QUANTISE2REAL(pan_log2_tab[12 - Q] + (12 - Q));
795 }
796 } else {
797 if (Q < 12)
798 {
799 /* negative */
800 pan = QUANTISE2REAL(pan_log2_tab[-Q + 12]);
801 } else {
802 /* positive */
803 pan = QUANTISE2REAL(pan_log2_tab[Q - 12] + (Q - 12));
804 }
805 }
806
807 /* tmp / pan in log2 */
808 return QUANTISE2REAL(tmp - pan);
809 } else {
810 return QUANTISE2REAL(6.0 - (real_t)sbr->Q[ch][k][l]);
811 }
812}
813
814static const real_t log_Qplus1_pan[31][13] = {
815 { REAL_CONST(0.044383447617292), REAL_CONST(0.169768601655960), REAL_CONST(0.583090126514435), REAL_CONST(1.570089221000671), REAL_CONST(3.092446088790894), REAL_CONST(4.733354568481445), REAL_CONST(6.022367954254150), REAL_CONST(6.692092418670654), REAL_CONST(6.924463272094727), REAL_CONST(6.989034175872803), REAL_CONST(7.005646705627441), REAL_CONST(7.009829998016357), REAL_CONST(7.010877609252930) },
816 { REAL_CONST(0.022362394258380), REAL_CONST(0.087379962205887), REAL_CONST(0.320804953575134), REAL_CONST(0.988859415054321), REAL_CONST(2.252387046813965), REAL_CONST(3.786596298217773), REAL_CONST(5.044394016265869), REAL_CONST(5.705977916717529), REAL_CONST(5.936291694641113), REAL_CONST(6.000346660614014), REAL_CONST(6.016829967498779), REAL_CONST(6.020981311798096), REAL_CONST(6.022020816802979) },
817 { REAL_CONST(0.011224525049329), REAL_CONST(0.044351425021887), REAL_CONST(0.169301137328148), REAL_CONST(0.577544987201691), REAL_CONST(1.527246952056885), REAL_CONST(2.887525320053101), REAL_CONST(4.087462902069092), REAL_CONST(4.733354568481445), REAL_CONST(4.959661006927490), REAL_CONST(5.022709369659424), REAL_CONST(5.038940429687500), REAL_CONST(5.043028831481934), REAL_CONST(5.044052600860596) },
818 { REAL_CONST(0.005623178556561), REAL_CONST(0.022346137091517), REAL_CONST(0.087132595479488), REAL_CONST(0.317482173442841), REAL_CONST(0.956931233406067), REAL_CONST(2.070389270782471), REAL_CONST(3.169924974441528), REAL_CONST(3.786596298217773), REAL_CONST(4.005294322967529), REAL_CONST(4.066420555114746), REAL_CONST(4.082170009613037), REAL_CONST(4.086137294769287), REAL_CONST(4.087131500244141) },
819 { REAL_CONST(0.002814328996465), REAL_CONST(0.011216334067285), REAL_CONST(0.044224001467228), REAL_CONST(0.167456731200218), REAL_CONST(0.556393325328827), REAL_CONST(1.378511548042297), REAL_CONST(2.321928024291992), REAL_CONST(2.887525320053101), REAL_CONST(3.092446088790894), REAL_CONST(3.150059700012207), REAL_CONST(3.164926528930664), REAL_CONST(3.168673276901245), REAL_CONST(3.169611930847168) },
820 { REAL_CONST(0.001407850766554), REAL_CONST(0.005619067233056), REAL_CONST(0.022281449288130), REAL_CONST(0.086156636476517), REAL_CONST(0.304854571819305), REAL_CONST(0.847996890544891), REAL_CONST(1.584962487220764), REAL_CONST(2.070389270782471), REAL_CONST(2.252387046813965), REAL_CONST(2.304061651229858), REAL_CONST(2.317430257797241), REAL_CONST(2.320801734924316), REAL_CONST(2.321646213531494) },
821 { REAL_CONST(0.000704097095877), REAL_CONST(0.002812269143760), REAL_CONST(0.011183738708496), REAL_CONST(0.043721374124289), REAL_CONST(0.160464659333229), REAL_CONST(0.485426813364029), REAL_CONST(1.000000000000000), REAL_CONST(1.378511548042297), REAL_CONST(1.527246952056885), REAL_CONST(1.570089221000671), REAL_CONST(1.581215262413025), REAL_CONST(1.584023833274841), REAL_CONST(1.584727644920349) },
822 { REAL_CONST(0.000352177477907), REAL_CONST(0.001406819908880), REAL_CONST(0.005602621007711), REAL_CONST(0.022026389837265), REAL_CONST(0.082462236285210), REAL_CONST(0.263034462928772), REAL_CONST(0.584962487220764), REAL_CONST(0.847996890544891), REAL_CONST(0.956931233406067), REAL_CONST(0.988859415054321), REAL_CONST(0.997190535068512), REAL_CONST(0.999296069145203), REAL_CONST(0.999823868274689) },
823 { REAL_CONST(0.000176099492819), REAL_CONST(0.000703581434209), REAL_CONST(0.002804030198604), REAL_CONST(0.011055230163038), REAL_CONST(0.041820213198662), REAL_CONST(0.137503549456596), REAL_CONST(0.321928083896637), REAL_CONST(0.485426813364029), REAL_CONST(0.556393325328827), REAL_CONST(0.577544987201691), REAL_CONST(0.583090126514435), REAL_CONST(0.584493279457092), REAL_CONST(0.584845066070557) },
824 { REAL_CONST(0.000088052431238), REAL_CONST(0.000351833587047), REAL_CONST(0.001402696361765), REAL_CONST(0.005538204684854), REAL_CONST(0.021061634644866), REAL_CONST(0.070389263331890), REAL_CONST(0.169925004243851), REAL_CONST(0.263034462928772), REAL_CONST(0.304854571819305), REAL_CONST(0.317482173442841), REAL_CONST(0.320804953575134), REAL_CONST(0.321646571159363), REAL_CONST(0.321857661008835) },
825 { REAL_CONST(0.000044026888645), REAL_CONST(0.000175927518285), REAL_CONST(0.000701518612914), REAL_CONST(0.002771759871393), REAL_CONST(0.010569252073765), REAL_CONST(0.035623874515295), REAL_CONST(0.087462842464447), REAL_CONST(0.137503549456596), REAL_CONST(0.160464659333229), REAL_CONST(0.167456731200218), REAL_CONST(0.169301137328148), REAL_CONST(0.169768601655960), REAL_CONST(0.169885858893394) },
826 { REAL_CONST(0.000022013611670), REAL_CONST(0.000088052431238), REAL_CONST(0.000350801943569), REAL_CONST(0.001386545598507), REAL_CONST(0.005294219125062), REAL_CONST(0.017921976745129), REAL_CONST(0.044394120573997), REAL_CONST(0.070389263331890), REAL_CONST(0.082462236285210), REAL_CONST(0.086156636476517), REAL_CONST(0.087132595479488), REAL_CONST(0.087379962205887), REAL_CONST(0.087442122399807) },
827 { REAL_CONST(0.000011006847672), REAL_CONST(0.000044026888645), REAL_CONST(0.000175411638338), REAL_CONST(0.000693439331371), REAL_CONST(0.002649537986144), REAL_CONST(0.008988817222416), REAL_CONST(0.022367812693119), REAL_CONST(0.035623874515295), REAL_CONST(0.041820213198662), REAL_CONST(0.043721374124289), REAL_CONST(0.044224001467228), REAL_CONST(0.044351425021887), REAL_CONST(0.044383447617292) },
828 { REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000087708482170), REAL_CONST(0.000346675369656), REAL_CONST(0.001325377263129), REAL_CONST(0.004501323681325), REAL_CONST(0.011227255687118), REAL_CONST(0.017921976745129), REAL_CONST(0.021061634644866), REAL_CONST(0.022026389837265), REAL_CONST(0.022281449288130), REAL_CONST(0.022346137091517), REAL_CONST(0.022362394258380) },
829 { REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043854910473), REAL_CONST(0.000173348103999), REAL_CONST(0.000662840844598), REAL_CONST(0.002252417383716), REAL_CONST(0.005624548997730), REAL_CONST(0.008988817222416), REAL_CONST(0.010569252073765), REAL_CONST(0.011055230163038), REAL_CONST(0.011183738708496), REAL_CONST(0.011216334067285), REAL_CONST(0.011224525049329) },
830 { REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000086676649516), REAL_CONST(0.000331544462824), REAL_CONST(0.001126734190620), REAL_CONST(0.002815015614033), REAL_CONST(0.004501323681325), REAL_CONST(0.005294219125062), REAL_CONST(0.005538204684854), REAL_CONST(0.005602621007711), REAL_CONST(0.005619067233056), REAL_CONST(0.005623178556561) },
831 { REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043338975956), REAL_CONST(0.000165781748365), REAL_CONST(0.000563477107789), REAL_CONST(0.001408194424585), REAL_CONST(0.002252417383716), REAL_CONST(0.002649537986144), REAL_CONST(0.002771759871393), REAL_CONST(0.002804030198604), REAL_CONST(0.002812269143760), REAL_CONST(0.002814328996465) },
832 { REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000021669651687), REAL_CONST(0.000082893253420), REAL_CONST(0.000281680084299), REAL_CONST(0.000704268983100), REAL_CONST(0.001126734190620), REAL_CONST(0.001325377263129), REAL_CONST(0.001386545598507), REAL_CONST(0.001402696361765), REAL_CONST(0.001406819908880), REAL_CONST(0.001407850766554) },
833 { REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010834866771), REAL_CONST(0.000041447223339), REAL_CONST(0.000140846910654), REAL_CONST(0.000352177477907), REAL_CONST(0.000563477107789), REAL_CONST(0.000662840844598), REAL_CONST(0.000693439331371), REAL_CONST(0.000701518612914), REAL_CONST(0.000703581434209), REAL_CONST(0.000704097095877) },
834 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000020637769921), REAL_CONST(0.000070511166996), REAL_CONST(0.000176099492819), REAL_CONST(0.000281680084299), REAL_CONST(0.000331544462824), REAL_CONST(0.000346675369656), REAL_CONST(0.000350801943569), REAL_CONST(0.000351833587047), REAL_CONST(0.000352177477907) },
835 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010318922250), REAL_CONST(0.000035256012779), REAL_CONST(0.000088052431238), REAL_CONST(0.000140846910654), REAL_CONST(0.000165781748365), REAL_CONST(0.000173348103999), REAL_CONST(0.000175411638338), REAL_CONST(0.000175927518285), REAL_CONST(0.000176099492819) },
836 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005159470220), REAL_CONST(0.000017542124624), REAL_CONST(0.000044026888645), REAL_CONST(0.000070511166996), REAL_CONST(0.000082893253420), REAL_CONST(0.000086676649516), REAL_CONST(0.000087708482170), REAL_CONST(0.000088052431238), REAL_CONST(0.000088052431238) },
837 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002579737384), REAL_CONST(0.000008771088687), REAL_CONST(0.000022013611670), REAL_CONST(0.000035256012779), REAL_CONST(0.000041447223339), REAL_CONST(0.000043338975956), REAL_CONST(0.000043854910473), REAL_CONST(0.000044026888645), REAL_CONST(0.000044026888645) },
838 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000004471542070), REAL_CONST(0.000011006847672), REAL_CONST(0.000017542124624), REAL_CONST(0.000020637769921), REAL_CONST(0.000021669651687), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670) },
839 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002235772627), REAL_CONST(0.000005503434295), REAL_CONST(0.000008771088687), REAL_CONST(0.000010318922250), REAL_CONST(0.000010834866771), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672) },
840 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001031895522), REAL_CONST(0.000002751719876), REAL_CONST(0.000004471542070), REAL_CONST(0.000005159470220), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295) },
841 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000515947875), REAL_CONST(0.000001375860506), REAL_CONST(0.000002235772627), REAL_CONST(0.000002579737384), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876) },
842 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000000687930424), REAL_CONST(0.000001031895522), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506) },
843 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000515947875), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424) },
844 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269) },
845 { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634) }
846};
847
848static const real_t log_Qplus1[31] = {
849 REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339),
850 REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156),
851 REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362),
852 REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453),
853 REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878),
854 REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247),
855 REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
856 REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667),
857 REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551),
858 REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641),
859 REAL_CONST(0.000000000000000)
860};
861
862static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
863{
864 /* check for coupled energy/noise data */
865 if (sbr->bs_coupling == 1)
866 {
867 if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) &&
868 (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24))
869 {
870 if (ch == 0)
871 {
872 return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1]);
873 } else {
874 return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)]);
875 }
876 } else {
877 return 0;
878 }
879 } else {
880 if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
881 {
882 return QUANTISE2REAL(log_Qplus1[sbr->Q[ch][k][l]]);
883 } else {
884 return 0;
885 }
886 }
887}
888
889static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
890{
891 /* log2 values of limiter gains */
892 static real_t limGain[] = { -1.0, 0.0, 1.0, 33.219 };
893 uint8_t m, l, k;
894
895 uint8_t current_t_noise_band = 0;
896 uint8_t S_mapped;
897
898 ALIGN real_t Q_M_lim[MAX_M];
899 ALIGN real_t G_lim[MAX_M];
900 ALIGN real_t G_boost;
901 ALIGN real_t S_M[MAX_M];
902
903
904 for (l = 0; l < sbr->L_E[ch]; l++)
905 {
906 uint8_t current_f_noise_band = 0;
907 uint8_t current_res_band = 0;
908 uint8_t current_res_band2 = 0;
909 uint8_t current_hi_res_band = 0;
910
911 real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
912
913 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
914
915 if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
916 {
917 current_t_noise_band++;
918 }
919
920 for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
921 {
922 real_t Q_M = 0;
923 real_t G_max;
924 real_t den = 0;
925 real_t acc1 = 0;
926 real_t acc2 = 0;
927 uint8_t current_res_band_size = 0;
928 uint8_t Q_M_size = 0;
929
930 uint8_t ml1, ml2;
931
932 /* bounds of current limiter bands */
933 ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
934 ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
935
936
937 /* calculate the accumulated E_orig and E_curr over the limiter band */
938 for (m = ml1; m < ml2; m++)
939 {
940 if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
941 {
942 current_res_band_size++;
943 } else {
944 acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)));
945
946 current_res_band++;
947 current_res_band_size = 1;
948 }
949
950 acc2 += QUANTISE2INT(sbr->E_curr[ch][m][l]/1024.0);
951 }
952 acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)));
953
954 acc1 = QUANTISE2REAL( log2(EPS + acc1) );
955
956
957 /* calculate the maximum gain */
958 /* ratio of the energy of the original signal and the energy
959 * of the HF generated signal
960 */
961 G_max = acc1 - QUANTISE2REAL(log2(EPS + acc2)) + QUANTISE2REAL(limGain[sbr->bs_limiter_gains]);
962 G_max = min(G_max, QUANTISE2REAL(limGain[3]));
963
964
965 for (m = ml1; m < ml2; m++)
966 {
967 real_t G;
968 real_t E_curr, E_orig;
969 real_t Q_orig, Q_orig_plus1;
970 uint8_t S_index_mapped;
971
972
973 /* check if m is on a noise band border */
974 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
975 {
976 /* step to next noise band */
977 current_f_noise_band++;
978 }
979
980
981 /* check if m is on a resolution band border */
982 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
983 {
984 /* accumulate a whole range of equal Q_Ms */
985 if (Q_M_size > 0)
986 den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M));
987 Q_M_size = 0;
988
989 /* step to next resolution band */
990 current_res_band2++;
991
992 /* if we move to a new resolution band, we should check if we are
993 * going to add a sinusoid in this band
994 */
995 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
996 }
997
998
999 /* check if m is on a HI_RES band border */
1000 if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
1001 {
1002 /* step to next HI_RES band */
1003 current_hi_res_band++;
1004 }
1005
1006
1007 /* find S_index_mapped
1008 * S_index_mapped can only be 1 for the m in the middle of the
1009 * current HI_RES band
1010 */
1011 S_index_mapped = 0;
1012 if ((l >= sbr->l_A[ch]) ||
1013 (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
1014 {
1015 /* find the middle subband of the HI_RES frequency band */
1016 if ((m + sbr->kx) == (sbr->f_table_res[HI_RES][current_hi_res_band+1] + sbr->f_table_res[HI_RES][current_hi_res_band]) >> 1)
1017 S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
1018 }
1019
1020
1021 /* find bitstream parameters */
1022 if (sbr->E_curr[ch][m][l] == 0)
1023 E_curr = LOG2_MIN_INF;
1024 else
1025 E_curr = -10 + log2(sbr->E_curr[ch][m][l]);
1026 E_orig = -10 + find_log2_E(sbr, current_res_band2, l, ch);
1027
1028 Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch);
1029 Q_orig_plus1 = find_log2_Qplus1(sbr, current_f_noise_band, current_t_noise_band, ch);
1030
1031
1032 /* Q_M only depends on E_orig and Q_div2:
1033 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
1034 * a change of current res band (HI or LO)
1035 */
1036 Q_M = E_orig + Q_orig - Q_orig_plus1;
1037
1038
1039 /* S_M only depends on E_orig, Q_div and S_index_mapped:
1040 * S_index_mapped can only be non-zero once per HI_RES band
1041 */
1042 if (S_index_mapped == 0)
1043 {
1044 S_M[m] = LOG2_MIN_INF; /* -inf */
1045 } else {
1046 S_M[m] = E_orig - Q_orig_plus1;
1047
1048 /* accumulate sinusoid part of the total energy */
1049 den += pow2(S_M[m]);
1050 }
1051
1052
1053 /* calculate gain */
1054 /* ratio of the energy of the original signal and the energy
1055 * of the HF generated signal
1056 */
1057 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
1058 /* scaled by -10 */
1059 G = E_orig - max(-10, E_curr);
1060 if ((S_mapped == 0) && (delta == 1))
1061 {
1062 /* G = G * 1/(1+Q) */
1063 G -= Q_orig_plus1;
1064 } else if (S_mapped == 1) {
1065 /* G = G * Q/(1+Q) */
1066 G += Q_orig - Q_orig_plus1;
1067 }
1068
1069
1070 /* limit the additional noise energy level */
1071 /* and apply the limiter */
1072 if (G_max > G)
1073 {
1074 Q_M_lim[m] = QUANTISE2REAL(Q_M);
1075 G_lim[m] = QUANTISE2REAL(G);
1076
1077 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1078 {
1079 Q_M_size++;
1080 }
1081 } else {
1082 /* G > G_max */
1083 Q_M_lim[m] = QUANTISE2REAL(Q_M) + G_max - QUANTISE2REAL(G);
1084 G_lim[m] = G_max;
1085
1086 /* accumulate limited Q_M */
1087 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1088 {
1089 den += QUANTISE2INT(pow2(Q_M_lim[m]));
1090 }
1091 }
1092
1093
1094 /* accumulate the total energy */
1095 /* E_curr changes for every m so we do need to accumulate every m */
1096 den += QUANTISE2INT(pow2(E_curr + G_lim[m]));
1097 }
1098
1099 /* accumulate last range of equal Q_Ms */
1100 if (Q_M_size > 0)
1101 {
1102 den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M));
1103 }
1104
1105
1106 /* calculate the final gain */
1107 /* G_boost: [0..2.51188643] */
1108 G_boost = acc1 - QUANTISE2REAL(log2(den + EPS));
1109 G_boost = min(G_boost, QUANTISE2REAL(1.328771237) /* log2(1.584893192 ^ 2) */);
1110
1111
1112 for (m = ml1; m < ml2; m++)
1113 {
1114 /* apply compensation to gain, noise floor sf's and sinusoid levels */
1115#ifndef SBR_LOW_POWER
1116 adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2((G_lim[m] + G_boost) / 2.0));
1117#else
1118 /* sqrt() will be done after the aliasing reduction to save a
1119 * few multiplies
1120 */
1121 adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2(G_lim[m] + G_boost));
1122#endif
1123 adj->Q_M_lim_boost[l][m] = QUANTISE2REAL(pow2((Q_M_lim[m] + 10 + G_boost) / 2.0));
1124
1125 if (S_M[m] != LOG2_MIN_INF)
1126 {
1127 adj->S_M_boost[l][m] = QUANTISE2REAL(pow2((S_M[m] + 10 + G_boost) / 2.0));
1128 } else {
1129 adj->S_M_boost[l][m] = 0;
1130 }
1131 }
1132 }
1133 }
1134}
1135
1136#else
1137
1138static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
1139{
1140 static real_t limGain[] = { 0.5, 1.0, 2.0, 1e10 };
1141 uint8_t m, l, k;
1142
1143 uint8_t current_t_noise_band = 0;
1144 uint8_t S_mapped;
1145
1146 ALIGN real_t Q_M_lim[MAX_M];
1147 ALIGN real_t G_lim[MAX_M];
1148 ALIGN real_t G_boost;
1149 ALIGN real_t S_M[MAX_M];
1150
1151 for (l = 0; l < sbr->L_E[ch]; l++)
1152 {
1153 uint8_t current_f_noise_band = 0;
1154 uint8_t current_res_band = 0;
1155 uint8_t current_res_band2 = 0;
1156 uint8_t current_hi_res_band = 0;
1157
1158 real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
1159
1160 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1161
1162 if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
1163 {
1164 current_t_noise_band++;
1165 }
1166
1167 for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
1168 {
1169 real_t G_max;
1170 real_t den = 0;
1171 real_t acc1 = 0;
1172 real_t acc2 = 0;
1173 uint8_t current_res_band_size = 0;
1174
1175 uint8_t ml1, ml2;
1176
1177 ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
1178 ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
1179
1180
1181 /* calculate the accumulated E_orig and E_curr over the limiter band */
1182 for (m = ml1; m < ml2; m++)
1183 {
1184 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
1185 {
1186 current_res_band++;
1187 }
1188 acc1 += sbr->E_orig[ch][current_res_band][l];
1189 acc2 += sbr->E_curr[ch][m][l];
1190 }
1191
1192
1193 /* calculate the maximum gain */
1194 /* ratio of the energy of the original signal and the energy
1195 * of the HF generated signal
1196 */
1197 G_max = ((EPS + acc1) / (EPS + acc2)) * limGain[sbr->bs_limiter_gains];
1198 G_max = min(G_max, 1e10);
1199
1200
1201 for (m = ml1; m < ml2; m++)
1202 {
1203 real_t Q_M, G;
1204 real_t Q_div, Q_div2;
1205 uint8_t S_index_mapped;
1206
1207
1208 /* check if m is on a noise band border */
1209 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
1210 {
1211 /* step to next noise band */
1212 current_f_noise_band++;
1213 }
1214
1215
1216 /* check if m is on a resolution band border */
1217 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
1218 {
1219 /* step to next resolution band */
1220 current_res_band2++;
1221
1222 /* if we move to a new resolution band, we should check if we are
1223 * going to add a sinusoid in this band
1224 */
1225 S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1226 }
1227
1228
1229 /* check if m is on a HI_RES band border */
1230 if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
1231 {
1232 /* step to next HI_RES band */
1233 current_hi_res_band++;
1234 }
1235
1236
1237 /* find S_index_mapped
1238 * S_index_mapped can only be 1 for the m in the middle of the
1239 * current HI_RES band
1240 */
1241 S_index_mapped = 0;
1242 if ((l >= sbr->l_A[ch]) ||
1243 (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
1244 {
1245 /* find the middle subband of the HI_RES frequency band */
1246 if ((m + sbr->kx) == (sbr->f_table_res[HI_RES][current_hi_res_band+1] + sbr->f_table_res[HI_RES][current_hi_res_band]) >> 1)
1247 S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
1248 }
1249
1250
1251 /* Q_div: [0..1] (1/(1+Q_mapped)) */
1252 Q_div = sbr->Q_div[ch][current_f_noise_band][current_t_noise_band];
1253
1254
1255 /* Q_div2: [0..1] (Q_mapped/(1+Q_mapped)) */
1256 Q_div2 = sbr->Q_div2[ch][current_f_noise_band][current_t_noise_band];
1257
1258
1259 /* Q_M only depends on E_orig and Q_div2:
1260 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
1261 * a change of current noise band
1262 */
1263 Q_M = sbr->E_orig[ch][current_res_band2][l] * Q_div2;
1264
1265
1266 /* S_M only depends on E_orig, Q_div and S_index_mapped:
1267 * S_index_mapped can only be non-zero once per HI_RES band
1268 */
1269 if (S_index_mapped == 0)
1270 {
1271 S_M[m] = 0;
1272 } else {
1273 S_M[m] = sbr->E_orig[ch][current_res_band2][l] * Q_div;
1274
1275 /* accumulate sinusoid part of the total energy */
1276 den += S_M[m];
1277 }
1278
1279
1280 /* calculate gain */
1281 /* ratio of the energy of the original signal and the energy
1282 * of the HF generated signal
1283 */
1284 G = sbr->E_orig[ch][current_res_band2][l] / (1.0 + sbr->E_curr[ch][m][l]);
1285 if ((S_mapped == 0) && (delta == 1))
1286 G *= Q_div;
1287 else if (S_mapped == 1)
1288 G *= Q_div2;
1289
1290
1291 /* limit the additional noise energy level */
1292 /* and apply the limiter */
1293 if (G_max > G)
1294 {
1295 Q_M_lim[m] = Q_M;
1296 G_lim[m] = G;
1297 } else {
1298 Q_M_lim[m] = Q_M * G_max / G;
1299 G_lim[m] = G_max;
1300 }
1301
1302
1303 /* accumulate the total energy */
1304 den += sbr->E_curr[ch][m][l] * G_lim[m];
1305 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1306 den += Q_M_lim[m];
1307 }
1308
1309 /* G_boost: [0..2.51188643] */
1310 G_boost = (acc1 + EPS) / (den + EPS);
1311 G_boost = min(G_boost, 2.51188643 /* 1.584893192 ^ 2 */);
1312
1313 for (m = ml1; m < ml2; m++)
1314 {
1315 /* apply compensation to gain, noise floor sf's and sinusoid levels */
1316#ifndef SBR_LOW_POWER
1317 adj->G_lim_boost[l][m] = sqrt(G_lim[m] * G_boost);
1318#else
1319 /* sqrt() will be done after the aliasing reduction to save a
1320 * few multiplies
1321 */
1322 adj->G_lim_boost[l][m] = G_lim[m] * G_boost;
1323#endif
1324 adj->Q_M_lim_boost[l][m] = sqrt(Q_M_lim[m] * G_boost);
1325
1326 if (S_M[m] != 0)
1327 {
1328 adj->S_M_boost[l][m] = sqrt(S_M[m] * G_boost);
1329 } else {
1330 adj->S_M_boost[l][m] = 0;
1331 }
1332 }
1333 }
1334 }
1335}
1336#endif // log2_test
1337
1338#endif
1339
1340#ifdef SBR_LOW_POWER
1341static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch)
1342{
1343 uint8_t l, k, i;
1344 uint8_t grouping;
1345
1346 for (l = 0; l < sbr->L_E[ch]; l++)
1347 {
1348 i = 0;
1349 grouping = 0;
1350
1351 for (k = sbr->kx; k < sbr->kx + sbr->M - 1; k++)
1352 {
1353 if (deg[k + 1] && adj->S_mapped[l][k-sbr->kx] == 0)
1354 {
1355 if (grouping == 0)
1356 {
1357 sbr->f_group[l][i] = k;
1358 grouping = 1;
1359 i++;
1360 }
1361 } else {
1362 if (grouping)
1363 {
1364 if (adj->S_mapped[l][k-sbr->kx])
1365 {
1366 sbr->f_group[l][i] = k;
1367 } else {
1368 sbr->f_group[l][i] = k + 1;
1369 }
1370 grouping = 0;
1371 i++;
1372 }
1373 }
1374 }
1375
1376 if (grouping)
1377 {
1378 sbr->f_group[l][i] = sbr->kx + sbr->M;
1379 i++;
1380 }
1381
1382 sbr->N_G[l] = (uint8_t)(i >> 1);
1383 }
1384}
1385
1386static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch)
1387{
1388 uint8_t l, k, m;
1389 real_t E_total, E_total_est, G_target, acc;
1390
1391 for (l = 0; l < sbr->L_E[ch]; l++)
1392 {
1393 for (k = 0; k < sbr->N_G[l]; k++)
1394 {
1395 E_total_est = E_total = 0;
1396
1397 for (m = sbr->f_group[l][k<<1]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1398 {
1399 /* E_curr: integer */
1400 /* G_lim_boost: fixed point */
1401 /* E_total_est: integer */
1402 /* E_total: integer */
1403 E_total_est += sbr->E_curr[ch][m-sbr->kx][l];
1404#ifdef FIXED_POINT
1405 E_total += MUL_Q2(sbr->E_curr[ch][m-sbr->kx][l], adj->G_lim_boost[l][m-sbr->kx]);
1406#else
1407 E_total += sbr->E_curr[ch][m-sbr->kx][l] * adj->G_lim_boost[l][m-sbr->kx];
1408#endif
1409 }
1410
1411 /* G_target: fixed point */
1412 if ((E_total_est + EPS) == 0)
1413 {
1414 G_target = 0;
1415 } else {
1416#ifdef FIXED_POINT
1417 G_target = (((int64_t)(E_total))<<Q2_BITS)/(E_total_est + EPS);
1418#else
1419 G_target = E_total / (E_total_est + EPS);
1420#endif
1421 }
1422 acc = 0;
1423
1424 for (m = sbr->f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1425 {
1426 real_t alpha;
1427
1428 /* alpha: (COEF) fixed point */
1429 if (m < sbr->kx + sbr->M - 1)
1430 {
1431 alpha = max(deg[m], deg[m + 1]);
1432 } else {
1433 alpha = deg[m];
1434 }
1435
1436 adj->G_lim_boost[l][m-sbr->kx] = MUL_C(alpha, G_target) +
1437 MUL_C((COEF_CONST(1)-alpha), adj->G_lim_boost[l][m-sbr->kx]);
1438
1439 /* acc: integer */
1440#ifdef FIXED_POINT
1441 acc += MUL_Q2(adj->G_lim_boost[l][m-sbr->kx], sbr->E_curr[ch][m-sbr->kx][l]);
1442#else
1443 acc += adj->G_lim_boost[l][m-sbr->kx] * sbr->E_curr[ch][m-sbr->kx][l];
1444#endif
1445 }
1446
1447 /* acc: fixed point */
1448 if (acc + EPS == 0)
1449 {
1450 acc = 0;
1451 } else {
1452#ifdef FIXED_POINT
1453 acc = (((int64_t)(E_total))<<Q2_BITS)/(acc + EPS);
1454#else
1455 acc = E_total / (acc + EPS);
1456#endif
1457 }
1458 for(m = sbr->f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1459 {
1460#ifdef FIXED_POINT
1461 adj->G_lim_boost[l][m-sbr->kx] = MUL_Q2(acc, adj->G_lim_boost[l][m-sbr->kx]);
1462#else
1463 adj->G_lim_boost[l][m-sbr->kx] = acc * adj->G_lim_boost[l][m-sbr->kx];
1464#endif
1465 }
1466 }
1467 }
1468
1469 for (l = 0; l < sbr->L_E[ch]; l++)
1470 {
1471 for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
1472 {
1473 for (m = sbr->f_table_lim[sbr->bs_limiter_bands][k];
1474 m < sbr->f_table_lim[sbr->bs_limiter_bands][k+1]; m++)
1475 {
1476#ifdef FIXED_POINT
1477 adj->G_lim_boost[l][m] = SBR_SQRT_Q2(adj->G_lim_boost[l][m]);
1478#else
1479 adj->G_lim_boost[l][m] = sqrt(adj->G_lim_boost[l][m]);
1480#endif
1481 }
1482 }
1483 }
1484}
1485#endif
1486
1487static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj,
1488 qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch)
1489{
1490 static real_t h_smooth[] = {
1491 FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
1492 FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
1493 FRAC_CONST(0.33333333333333)
1494 };
1495 static int8_t phi_re[] = { 1, 0, -1, 0 };
1496 static int8_t phi_im[] = { 0, 1, 0, -1 };
1497
1498 uint8_t m, l, i, n;
1499 uint16_t fIndexNoise = 0;
1500 uint8_t fIndexSine = 0;
1501 uint8_t assembly_reset = 0;
1502
1503 real_t G_filt, Q_filt;
1504
1505 uint8_t h_SL;
1506
1507
1508 if (sbr->Reset == 1)
1509 {
1510 assembly_reset = 1;
1511 fIndexNoise = 0;
1512 } else {
1513 fIndexNoise = sbr->index_noise_prev[ch];
1514 }
1515 fIndexSine = sbr->psi_is_prev[ch];
1516
1517
1518 for (l = 0; l < sbr->L_E[ch]; l++)
1519 {
1520 uint8_t no_noise = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 1 : 0;
1521
1522#ifdef SBR_LOW_POWER
1523 h_SL = 0;
1524#else
1525 h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4;
1526 h_SL = (no_noise ? 0 : h_SL);
1527#endif
1528
1529 if (assembly_reset)
1530 {
1531 for (n = 0; n < 4; n++)
1532 {
1533 memcpy(sbr->G_temp_prev[ch][n], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1534 memcpy(sbr->Q_temp_prev[ch][n], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1535 }
1536 /* reset ringbuffer index */
1537 sbr->GQ_ringbuf_index[ch] = 4;
1538 assembly_reset = 0;
1539 }
1540
1541 for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++)
1542 {
1543#ifdef SBR_LOW_POWER
1544 uint8_t i_min1, i_plus1;
1545 uint8_t sinusoids = 0;
1546#endif
1547
1548 /* load new values into ringbuffer */
1549 memcpy(sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1550 memcpy(sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1551
1552 for (m = 0; m < sbr->M; m++)
1553 {
1554 qmf_t psi;
1555
1556 G_filt = 0;
1557 Q_filt = 0;
1558
1559#ifndef SBR_LOW_POWER
1560 if (h_SL != 0)
1561 {
1562 uint8_t ri = sbr->GQ_ringbuf_index[ch];
1563 for (n = 0; n <= 4; n++)
1564 {
1565 real_t curr_h_smooth = h_smooth[n];
1566 ri++;
1567 if (ri >= 5)
1568 ri -= 5;
1569 G_filt += MUL_F(sbr->G_temp_prev[ch][ri][m], curr_h_smooth);
1570 Q_filt += MUL_F(sbr->Q_temp_prev[ch][ri][m], curr_h_smooth);
1571 }
1572 } else {
1573#endif
1574 G_filt = sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1575 Q_filt = sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1576#ifndef SBR_LOW_POWER
1577 }
1578#endif
1579
1580 Q_filt = (adj->S_M_boost[l][m] != 0 || no_noise) ? 0 : Q_filt;
1581
1582 /* add noise to the output */
1583 fIndexNoise = (fIndexNoise + 1) & 511;
1584
1585 /* the smoothed gain values are applied to Xsbr */
1586 /* V is defined, not calculated */
1587#ifndef FIXED_POINT
1588 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = G_filt * QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx])
1589 + MUL_F(Q_filt, RE(V[fIndexNoise]));
1590#else
1591 //QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1592 // + MUL_F(Q_filt, RE(V[fIndexNoise]));
1593 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1594 + MUL_F(Q_filt, RE(V[fIndexNoise]));
1595#endif
1596 if (sbr->bs_extension_id == 3 && sbr->bs_extension_data == 42)
1597 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = 16428320;
1598#ifndef SBR_LOW_POWER
1599#ifndef FIXED_POINT
1600 QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = G_filt * QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx])
1601 + MUL_F(Q_filt, IM(V[fIndexNoise]));
1602#else
1603 //QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1604 // + MUL_F(Q_filt, IM(V[fIndexNoise]));
1605 QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1606 + MUL_F(Q_filt, IM(V[fIndexNoise]));
1607#endif
1608#endif
1609
1610 {
1611 int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1);
1612 QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine];
1613#ifdef FIXED_POINT
1614 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += (QMF_RE(psi) << REAL_BITS);
1615#else
1616 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi);
1617#endif
1618
1619#ifndef SBR_LOW_POWER
1620 QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine];
1621#ifdef FIXED_POINT
1622 QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += (QMF_IM(psi) << REAL_BITS);
1623#else
1624 QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_IM(psi);
1625#endif
1626#else
1627
1628 i_min1 = (fIndexSine - 1) & 3;
1629 i_plus1 = (fIndexSine + 1) & 3;
1630
1631#ifndef FIXED_POINT
1632 if ((m == 0) && (phi_re[i_plus1] != 0))
1633 {
1634 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx - 1]) +=
1635 (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][0], FRAC_CONST(0.00815)));
1636 if (sbr->M != 0)
1637 {
1638 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1639 (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][1], FRAC_CONST(0.00815)));
1640 }
1641 }
1642 if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1643 {
1644 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1645 (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m - 1], FRAC_CONST(0.00815)));
1646 }
1647 if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0))
1648 {
1649 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1650 (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][m + 1], FRAC_CONST(0.00815)));
1651 }
1652 if ((m == sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1653 {
1654 if (m > 0)
1655 {
1656 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1657 (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m - 1], FRAC_CONST(0.00815)));
1658 }
1659 if (m + sbr->kx < 64)
1660 {
1661 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx + 1]) +=
1662 (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m], FRAC_CONST(0.00815)));
1663 }
1664 }
1665#else
1666 if ((m == 0) && (phi_re[i_plus1] != 0))
1667 {
1668 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx - 1]) +=
1669 (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][0]<<REAL_BITS), FRAC_CONST(0.00815)));
1670 if (sbr->M != 0)
1671 {
1672 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1673 (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][1]<<REAL_BITS), FRAC_CONST(0.00815)));
1674 }
1675 }
1676 if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1677 {
1678 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1679 (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m - 1]<<REAL_BITS), FRAC_CONST(0.00815)));
1680 }
1681 if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0))
1682 {
1683 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1684 (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][m + 1]<<REAL_BITS), FRAC_CONST(0.00815)));
1685 }
1686 if ((m == sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1687 {
1688 if (m > 0)
1689 {
1690 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1691 (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m - 1]<<REAL_BITS), FRAC_CONST(0.00815)));
1692 }
1693 if (m + sbr->kx < 64)
1694 {
1695 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx + 1]) +=
1696 (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m]<<REAL_BITS), FRAC_CONST(0.00815)));
1697 }
1698 }
1699#endif
1700
1701 if (adj->S_M_boost[l][m] != 0)
1702 sinusoids++;
1703#endif
1704 }
1705 }
1706
1707 fIndexSine = (fIndexSine + 1) & 3;
1708
1709 /* update the ringbuffer index used for filtering G and Q with h_smooth */
1710 sbr->GQ_ringbuf_index[ch]++;
1711 if (sbr->GQ_ringbuf_index[ch] >= 5)
1712 sbr->GQ_ringbuf_index[ch] = 0;
1713 }
1714 }
1715
1716 sbr->index_noise_prev[ch] = fIndexNoise;
1717 sbr->psi_is_prev[ch] = fIndexSine;
1718}
1719
1720#endif