Coverage Report

Created: 2026-07-16 06:20

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