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