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