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
29.2k
{
62
29.2k
    ALIGN sbr_hfadj_info adj = {{{0}}};
63
29.2k
    uint8_t ret = 0;
64
65
29.2k
    if (sbr->bs_frame_class[ch] == FIXFIX)
66
7.34k
    {
67
7.34k
        sbr->l_A[ch] = -1;
68
21.8k
    } else if (sbr->bs_frame_class[ch] == VARFIX) {
69
10.0k
        if (sbr->bs_pointer[ch] > 1)
70
2.49k
            sbr->l_A[ch] = sbr->bs_pointer[ch] - 1;
71
7.53k
        else
72
7.53k
            sbr->l_A[ch] = -1;
73
11.8k
    } else {
74
11.8k
        if (sbr->bs_pointer[ch] == 0)
75
3.95k
            sbr->l_A[ch] = -1;
76
7.89k
        else
77
7.89k
            sbr->l_A[ch] = sbr->L_E[ch] + 1 - sbr->bs_pointer[ch];
78
11.8k
    }
79
80
29.2k
    ret = estimate_current_envelope(sbr, &adj, Xsbr, ch);
81
29.2k
    if (ret > 0)
82
847
        return 1;
83
84
28.3k
    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
28.3k
    hf_assembly(sbr, &adj, Xsbr, ch);
92
93
28.3k
    return 0;
94
29.2k
}
95
96
static uint8_t get_S_mapped(sbr_info *sbr, uint8_t ch, uint8_t l, uint8_t current_band)
97
256k
{
98
256k
    if (sbr->f[ch][l] == HI_RES)
99
131k
    {
100
        /* in case of using f_table_high we just have 1 to 1 mapping
101
         * from bs_add_harmonic[l][k]
102
         */
103
131k
        if ((l >= sbr->l_A[ch]) ||
104
45.8k
            (sbr->bs_add_harmonic_prev[ch][current_band] && sbr->bs_add_harmonic_flag_prev[ch]))
105
87.3k
        {
106
87.3k
            return sbr->bs_add_harmonic[ch][current_band];
107
87.3k
        }
108
131k
    } else {
109
124k
        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
124k
        lb = 2*current_band - ((sbr->N_high & 1) ? 1 : 0);
119
        /* find first HI_RES band in next LO_RES band */
120
124k
        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
322k
        for (b = lb; b < ub; b++)
124
207k
        {
125
207k
            if ((l >= sbr->l_A[ch]) ||
126
58.0k
                (sbr->bs_add_harmonic_prev[ch][b] && sbr->bs_add_harmonic_flag_prev[ch]))
127
151k
            {
128
151k
                if (sbr->bs_add_harmonic[ch][b] == 1)
129
10.5k
                    return 1;
130
151k
            }
131
207k
        }
132
124k
    }
133
134
158k
    return 0;
135
256k
}
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
29.2k
{
140
29.2k
    uint8_t m, l, j, k, k_l, k_h, p;
141
29.2k
    real_t div;
142
29.2k
    (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
13.3k
    const real_t half = REAL_CONST(0.5);
150
    real_t limit;
151
    real_t mul;
152
#else
153
    real_t nrg;
154
    const real_t half = 0;  /* Compiler is smart enough to eliminate +0 op. */
155
    const real_t limit = FLT_MAX;
156
#endif
157
158
29.2k
    if (sbr->bs_interpol_freq == 1)
159
19.9k
    {
160
54.5k
        for (l = 0; l < sbr->L_E[ch]; l++)
161
35.0k
        {
162
35.0k
            uint8_t i, l_i, u_i;
163
164
35.0k
            l_i = sbr->t_E[ch][l];
165
35.0k
            u_i = sbr->t_E[ch][l+1];
166
167
35.0k
            div = (real_t)(u_i - l_i);
168
169
35.0k
            if (div <= 0)
170
1.45k
                div = 1;
171
#ifdef FIXED_POINT
172
14.6k
            limit = div << (30 - (COEF_BITS - REAL_BITS));
173
14.6k
            mul = (1 << (COEF_BITS - REAL_BITS)) / div;
174
#endif
175
176
410k
            for (m = 0; m < sbr->M; m++)
177
375k
            {
178
375k
                nrg = 0;
179
180
6.73M
                for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
181
6.36M
                {
182
6.36M
                    real_t re = QMF_RE(Xsbr[i][m + sbr->kx]) + half;
183
6.36M
                    real_t im = QMF_IM(Xsbr[i][m + sbr->kx]) + half;
184
6.36M
                    (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
6.36M
                    nrg += MUL_C(re, re)
190
6.36M
#ifndef SBR_LOW_POWER
191
6.36M
                        + MUL_C(im, im)
192
6.36M
#endif
193
6.36M
                        ;
194
6.36M
                }
195
196
375k
                if (nrg < -limit || nrg > limit)
197
372
                    return 1;
198
#ifdef FIXED_POINT
199
170k
                sbr->E_curr[ch][m][l] = nrg * mul;
200
#else
201
204k
                sbr->E_curr[ch][m][l] = nrg / div;
202
204k
#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
204k
            }
211
35.0k
        }
212
19.9k
    } else {
213
26.1k
        for (l = 0; l < sbr->L_E[ch]; l++)
214
17.3k
        {
215
130k
            for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++)
216
113k
            {
217
113k
                k_l = sbr->f_table_res[sbr->f[ch][l]][p];
218
113k
                k_h = sbr->f_table_res[sbr->f[ch][l]][p+1];
219
220
395k
                for (k = k_l; k < k_h; k++)
221
282k
                {
222
282k
                    uint8_t i, l_i, u_i;
223
282k
                    nrg = 0;
224
225
282k
                    l_i = sbr->t_E[ch][l];
226
282k
                    u_i = sbr->t_E[ch][l+1];
227
228
282k
                    div = (real_t)((u_i - l_i)*(k_h - k_l));
229
230
282k
                    if (div <= 0)
231
20.2k
                        div = 1;
232
#ifdef FIXED_POINT
233
121k
                    limit = div << (30 - (COEF_BITS - REAL_BITS));
234
121k
                    mul = (1 << (COEF_BITS - REAL_BITS)) / div;
235
#endif
236
237
5.57M
                    for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
238
5.29M
                    {
239
23.7M
                        for (j = k_l; j < k_h; j++)
240
18.4M
                        {
241
18.4M
                            real_t re = QMF_RE(Xsbr[i][j]) + half;
242
18.4M
                            real_t im = QMF_IM(Xsbr[i][j]) + half;
243
18.4M
                            (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
18.4M
                            nrg += MUL_C(re, re)
249
18.4M
#ifndef SBR_LOW_POWER
250
18.4M
                                + MUL_C(im, im)
251
18.4M
#endif
252
18.4M
                                ;
253
18.4M
                        }
254
5.29M
                    }
255
256
282k
                    if (nrg < -limit || nrg > limit)
257
475
                        return 1;
258
#ifdef FIXED_POINT
259
121k
                    sbr->E_curr[ch][k - sbr->kx][l] = nrg * mul;
260
#else
261
160k
                    sbr->E_curr[ch][k - sbr->kx][l] = nrg / div;
262
160k
#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
160k
                }
271
113k
            }
272
17.3k
        }
273
9.29k
    }
274
275
28.3k
    return 0;
276
29.2k
}
sbr_hfadj.c:estimate_current_envelope
Line
Count
Source
139
13.3k
{
140
13.3k
    uint8_t m, l, j, k, k_l, k_h, p;
141
13.3k
    real_t div;
142
13.3k
    (void)adj;  /* TODO: remove parameter? */
143
13.3k
#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
13.3k
    int64_t nrg;
149
13.3k
    const real_t half = REAL_CONST(0.5);
150
13.3k
    real_t limit;
151
13.3k
    real_t mul;
152
#else
153
    real_t nrg;
154
    const real_t half = 0;  /* Compiler is smart enough to eliminate +0 op. */
155
    const real_t limit = FLT_MAX;
156
#endif
157
158
13.3k
    if (sbr->bs_interpol_freq == 1)
159
8.34k
    {
160
22.5k
        for (l = 0; l < sbr->L_E[ch]; l++)
161
14.6k
        {
162
14.6k
            uint8_t i, l_i, u_i;
163
164
14.6k
            l_i = sbr->t_E[ch][l];
165
14.6k
            u_i = sbr->t_E[ch][l+1];
166
167
14.6k
            div = (real_t)(u_i - l_i);
168
169
14.6k
            if (div <= 0)
170
483
                div = 1;
171
14.6k
#ifdef FIXED_POINT
172
14.6k
            limit = div << (30 - (COEF_BITS - REAL_BITS));
173
14.6k
            mul = (1 << (COEF_BITS - REAL_BITS)) / div;
174
14.6k
#endif
175
176
185k
            for (m = 0; m < sbr->M; m++)
177
170k
            {
178
170k
                nrg = 0;
179
180
3.00M
                for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
181
2.83M
                {
182
2.83M
                    real_t re = QMF_RE(Xsbr[i][m + sbr->kx]) + half;
183
2.83M
                    real_t im = QMF_IM(Xsbr[i][m + sbr->kx]) + half;
184
2.83M
                    (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.83M
                    nrg += MUL_C(re, re)
190
2.83M
#ifndef SBR_LOW_POWER
191
2.83M
                        + MUL_C(im, im)
192
2.83M
#endif
193
2.83M
                        ;
194
2.83M
                }
195
196
170k
                if (nrg < -limit || nrg > limit)
197
365
                    return 1;
198
170k
#ifdef FIXED_POINT
199
170k
                sbr->E_curr[ch][m][l] = nrg * mul;
200
#else
201
                sbr->E_curr[ch][m][l] = nrg / div;
202
#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
170k
            }
211
14.6k
        }
212
8.34k
    } else {
213
13.0k
        for (l = 0; l < sbr->L_E[ch]; l++)
214
8.47k
        {
215
53.2k
            for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++)
216
45.2k
            {
217
45.2k
                k_l = sbr->f_table_res[sbr->f[ch][l]][p];
218
45.2k
                k_h = sbr->f_table_res[sbr->f[ch][l]][p+1];
219
220
166k
                for (k = k_l; k < k_h; k++)
221
121k
                {
222
121k
                    uint8_t i, l_i, u_i;
223
121k
                    nrg = 0;
224
225
121k
                    l_i = sbr->t_E[ch][l];
226
121k
                    u_i = sbr->t_E[ch][l+1];
227
228
121k
                    div = (real_t)((u_i - l_i)*(k_h - k_l));
229
230
121k
                    if (div <= 0)
231
3.90k
                        div = 1;
232
121k
#ifdef FIXED_POINT
233
121k
                    limit = div << (30 - (COEF_BITS - REAL_BITS));
234
121k
                    mul = (1 << (COEF_BITS - REAL_BITS)) / div;
235
121k
#endif
236
237
2.67M
                    for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
238
2.55M
                    {
239
12.9M
                        for (j = k_l; j < k_h; j++)
240
10.3M
                        {
241
10.3M
                            real_t re = QMF_RE(Xsbr[i][j]) + half;
242
10.3M
                            real_t im = QMF_IM(Xsbr[i][j]) + half;
243
10.3M
                            (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
10.3M
                            nrg += MUL_C(re, re)
249
10.3M
#ifndef SBR_LOW_POWER
250
10.3M
                                + MUL_C(im, im)
251
10.3M
#endif
252
10.3M
                                ;
253
10.3M
                        }
254
2.55M
                    }
255
256
121k
                    if (nrg < -limit || nrg > limit)
257
467
                        return 1;
258
121k
#ifdef FIXED_POINT
259
121k
                    sbr->E_curr[ch][k - sbr->kx][l] = nrg * mul;
260
#else
261
                    sbr->E_curr[ch][k - sbr->kx][l] = nrg / div;
262
#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
121k
                }
271
45.2k
            }
272
8.47k
        }
273
5.00k
    }
274
275
12.5k
    return 0;
276
13.3k
}
sbr_hfadj.c:estimate_current_envelope
Line
Count
Source
139
15.8k
{
140
15.8k
    uint8_t m, l, j, k, k_l, k_h, p;
141
15.8k
    real_t div;
142
15.8k
    (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
15.8k
    real_t nrg;
154
15.8k
    const real_t half = 0;  /* Compiler is smart enough to eliminate +0 op. */
155
15.8k
    const real_t limit = FLT_MAX;
156
15.8k
#endif
157
158
15.8k
    if (sbr->bs_interpol_freq == 1)
159
11.5k
    {
160
31.9k
        for (l = 0; l < sbr->L_E[ch]; l++)
161
20.4k
        {
162
20.4k
            uint8_t i, l_i, u_i;
163
164
20.4k
            l_i = sbr->t_E[ch][l];
165
20.4k
            u_i = sbr->t_E[ch][l+1];
166
167
20.4k
            div = (real_t)(u_i - l_i);
168
169
20.4k
            if (div <= 0)
170
974
                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
225k
            for (m = 0; m < sbr->M; m++)
177
204k
            {
178
204k
                nrg = 0;
179
180
3.72M
                for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
181
3.52M
                {
182
3.52M
                    real_t re = QMF_RE(Xsbr[i][m + sbr->kx]) + half;
183
3.52M
                    real_t im = QMF_IM(Xsbr[i][m + sbr->kx]) + half;
184
3.52M
                    (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
3.52M
                    nrg += MUL_C(re, re)
190
3.52M
#ifndef SBR_LOW_POWER
191
3.52M
                        + MUL_C(im, im)
192
3.52M
#endif
193
3.52M
                        ;
194
3.52M
                }
195
196
204k
                if (nrg < -limit || nrg > limit)
197
7
                    return 1;
198
#ifdef FIXED_POINT
199
                sbr->E_curr[ch][m][l] = nrg * mul;
200
#else
201
204k
                sbr->E_curr[ch][m][l] = nrg / div;
202
204k
#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
204k
            }
211
20.4k
        }
212
11.5k
    } else {
213
13.1k
        for (l = 0; l < sbr->L_E[ch]; l++)
214
8.84k
        {
215
76.8k
            for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++)
216
68.0k
            {
217
68.0k
                k_l = sbr->f_table_res[sbr->f[ch][l]][p];
218
68.0k
                k_h = sbr->f_table_res[sbr->f[ch][l]][p+1];
219
220
228k
                for (k = k_l; k < k_h; k++)
221
160k
                {
222
160k
                    uint8_t i, l_i, u_i;
223
160k
                    nrg = 0;
224
225
160k
                    l_i = sbr->t_E[ch][l];
226
160k
                    u_i = sbr->t_E[ch][l+1];
227
228
160k
                    div = (real_t)((u_i - l_i)*(k_h - k_l));
229
230
160k
                    if (div <= 0)
231
16.3k
                        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
2.90M
                    for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
238
2.74M
                    {
239
10.7M
                        for (j = k_l; j < k_h; j++)
240
8.02M
                        {
241
8.02M
                            real_t re = QMF_RE(Xsbr[i][j]) + half;
242
8.02M
                            real_t im = QMF_IM(Xsbr[i][j]) + half;
243
8.02M
                            (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
8.02M
                            nrg += MUL_C(re, re)
249
8.02M
#ifndef SBR_LOW_POWER
250
8.02M
                                + MUL_C(im, im)
251
8.02M
#endif
252
8.02M
                                ;
253
8.02M
                        }
254
2.74M
                    }
255
256
160k
                    if (nrg < -limit || nrg > limit)
257
8
                        return 1;
258
#ifdef FIXED_POINT
259
                    sbr->E_curr[ch][k - sbr->kx][l] = nrg * mul;
260
#else
261
160k
                    sbr->E_curr[ch][k - sbr->kx][l] = nrg / div;
262
160k
#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
160k
                }
271
68.0k
            }
272
8.84k
        }
273
4.28k
    }
274
275
15.8k
    return 0;
276
15.8k
}
277
278
#ifdef FIXED_POINT
279
#define EPS (1) /* smallest number available in fixed point */
280
#else
281
248k
#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
413k
{
317
    /* check for coupled energy/noise data */
318
413k
    if (sbr->bs_coupling == 1)
319
185k
    {
320
185k
        int16_t e = sbr->E[0][k][l];
321
185k
        int16_t E = sbr->E[1][k][l];
322
185k
        uint8_t amp0 = (sbr->amp_res[0]) ? 0 : 1;
323
185k
        uint8_t amp1 = (sbr->amp_res[1]) ? 0 : 1;
324
185k
        real_t tmp, pan;
325
326
        /* E[1] should always be even so shifting is OK */
327
185k
        E >>= amp1;
328
185k
        if (e < 0 || e >= 64 || E < 0 || E > 24)
329
39.0k
            return LOG2_MIN_INF;
330
146k
        E -= 12;
331
332
146k
        if (ch != 0)  // L/R anti-symmetry
333
73.3k
            E = -E;
334
335
146k
        if (E >= 0)
336
74.0k
        {
337
            /* negative */
338
74.0k
            pan = pan_log2_tab[E];
339
74.0k
        } else {
340
            /* positive */
341
72.2k
            pan = pan_log2_tab[-E] + ((-E)<<REAL_BITS);
342
72.2k
        }
343
344
        /* tmp / pan in log2 */
345
146k
        tmp = (7 << REAL_BITS) + (e << (REAL_BITS-amp0));
346
146k
        return tmp - pan;
347
228k
    } else {
348
228k
        int16_t e = sbr->E[ch][k][l];
349
228k
        uint8_t amp = (sbr->amp_res[ch]) ? 0 : 1;
350
228k
        if (e < 0 || (e >> amp) >= 64)
351
31.2k
            return LOG2_MIN_INF;
352
196k
        return 6 * REAL_PRECISION + e * (REAL_PRECISION >> amp);
353
228k
    }
354
413k
}
355
356
static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
357
283k
{
358
    /* check for coupled energy/noise data */
359
283k
    if (sbr->bs_coupling == 1)
360
130k
    {
361
130k
        int32_t q = sbr->Q[0][k][l];
362
130k
        int32_t Q = sbr->Q[1][k][l];
363
130k
        real_t tmp, pan;
364
365
130k
        if (q < 0 || q > 30 || Q < 0 || Q > 24)
366
26.6k
            return LOG2_MIN_INF;
367
103k
        Q -= 12;
368
369
103k
        if (ch != 0)  // L/R anti-symmetry
370
51.9k
            Q = -Q;
371
372
103k
        if (Q >= 0)
373
52.2k
        {
374
            /* negative */
375
52.2k
            pan = pan_log2_tab[Q];
376
52.2k
        } else {
377
            /* positive */
378
51.2k
            pan = pan_log2_tab[-Q] + ((-Q)<<REAL_BITS);
379
51.2k
        }
380
381
        /* tmp / pan in log2 */
382
103k
        tmp = (7 - q) * REAL_PRECISION;
383
103k
        return tmp - pan;
384
152k
    } else {
385
152k
        int32_t q = sbr->Q[ch][k][l];
386
152k
        if (q < 0 || q > 30)
387
18.9k
            return LOG2_MIN_INF;
388
133k
        return (6 - q) * REAL_PRECISION;
389
152k
    }
390
283k
}
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
283k
{
442
    /* check for coupled energy/noise data */
443
283k
    if (sbr->bs_coupling == 1)
444
130k
    {
445
130k
        if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) &&
446
120k
            (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24))
447
103k
        {
448
103k
            if (ch == 0)
449
51.5k
            {
450
51.5k
                return log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1];
451
51.9k
            } else {
452
51.9k
                return log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)];
453
51.9k
            }
454
103k
        } else {
455
26.6k
            return 0;
456
26.6k
        }
457
152k
    } else {
458
152k
        if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
459
133k
        {
460
133k
            return log_Qplus1[sbr->Q[ch][k][l]];
461
133k
        } else {
462
18.9k
            return 0;
463
18.9k
        }
464
152k
    }
465
283k
}
466
467
static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
468
12.5k
{
469
    /* log2 values of limiter gains */
470
    /* Last one less than log2(1e10) due to FIXED POINT float limitations */
471
12.5k
    static real_t limGain[] = {
472
12.5k
        REAL_CONST(-1.0), REAL_CONST(0.0), REAL_CONST(1.0), REAL_CONST(21.0)
473
12.5k
    };
474
12.5k
    uint8_t m, l, k;
475
476
12.5k
    uint8_t current_t_noise_band = 0;
477
12.5k
    uint8_t S_mapped;
478
479
12.5k
    ALIGN real_t Q_M_lim[MAX_M];
480
12.5k
    ALIGN real_t G_lim[MAX_M];
481
12.5k
    ALIGN real_t G_boost;
482
12.5k
    ALIGN real_t S_M[MAX_M];
483
484
12.5k
    real_t exp = REAL_CONST(-10);
485
486
34.7k
    for (l = 0; l < sbr->L_E[ch]; l++)
487
22.2k
    {
488
22.2k
        uint8_t current_f_noise_band = 0;
489
22.2k
        uint8_t current_res_band = 0;
490
22.2k
        uint8_t current_res_band2 = 0;
491
22.2k
        uint8_t current_hi_res_band = 0;
492
493
22.2k
        real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
494
495
22.2k
        S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
496
497
22.2k
        if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
498
3.74k
        {
499
3.74k
            current_t_noise_band++;
500
3.74k
        }
501
502
68.0k
        for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
503
45.7k
        {
504
45.7k
            real_t Q_M = 0;
505
45.7k
            real_t G_max;
506
45.7k
            uint64_t den = 0, acc1 = 0, acc2 = 0;
507
45.7k
            uint8_t current_res_band_size = 0;
508
45.7k
            uint8_t Q_M_size = 0;
509
45.7k
            real_t log_e, log_den, log_acc1, log_acc2;
510
511
45.7k
            uint8_t ml1, ml2;
512
513
            /* bounds of current limiter bands */
514
45.7k
            ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
515
45.7k
            ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
516
517
45.7k
            if (ml1 > MAX_M)
518
0
                ml1 = MAX_M;
519
520
45.7k
            if (ml2 > MAX_M)
521
0
                ml2 = MAX_M;
522
523
524
            /* calculate the accumulated E_orig and E_curr over the limiter band */
525
328k
            for (m = ml1; m < ml2; m++)
526
283k
            {
527
283k
                if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
528
198k
                {
529
198k
                    current_res_band_size++;
530
198k
                } else {
531
84.7k
                    log_e = find_log2_E(sbr, current_res_band, l, ch);
532
84.7k
                    acc1 += pow2_int(exp + log2_int_tab[current_res_band_size] + log_e);
533
534
84.7k
                    current_res_band++;
535
84.7k
                    current_res_band_size = 1;
536
84.7k
                }
537
538
283k
                acc2 += sbr->E_curr[ch][m][l];
539
283k
            }
540
45.7k
            if (current_res_band_size) {
541
45.7k
                log_e = find_log2_E(sbr, current_res_band, l, ch);
542
45.7k
                acc1 += pow2_int(exp + log2_int_tab[current_res_band_size] + log_e);
543
45.7k
            }
544
545
546
45.7k
            if (acc1 == 0)
547
28.2k
                log_acc1 = LOG2_MIN_INF;
548
17.5k
            else
549
17.5k
                log_acc1 = log2_int(acc1);
550
551
45.7k
            if (acc2 == 0)
552
44.8k
                log_acc2 = LOG2_MIN_INF;
553
937
            else
554
937
                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
45.7k
            G_max = log_acc1 - log_acc2 + limGain[sbr->bs_limiter_gains];
561
45.7k
            G_max = min(G_max, limGain[3]);
562
563
564
328k
            for (m = ml1; m < ml2; m++)
565
283k
            {
566
283k
                real_t G;
567
283k
                real_t E_curr, E_orig;
568
283k
                real_t Q_orig, Q_orig_plus1;
569
283k
                uint8_t S_index_mapped;
570
571
572
                /* check if m is on a noise band border */
573
283k
                if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
574
18.3k
                {
575
                    /* step to next noise band */
576
18.3k
                    current_f_noise_band++;
577
18.3k
                }
578
579
580
                /* check if m is on a resolution band border */
581
283k
                if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
582
84.7k
                {
583
                    /* accumulate a whole range of equal Q_Ms */
584
84.7k
                    if (Q_M_size > 0)
585
39.2k
                        den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
586
84.7k
                    Q_M_size = 0;
587
588
                    /* step to next resolution band */
589
84.7k
                    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
84.7k
                    S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
595
84.7k
                }
596
597
598
                /* check if m is on a HI_RES band border */
599
283k
                if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
600
132k
                {
601
                    /* step to next HI_RES band */
602
132k
                    current_hi_res_band++;
603
132k
                }
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
283k
                S_index_mapped = 0;
611
283k
                if ((l >= sbr->l_A[ch]) ||
612
65.7k
                    (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
613
218k
                {
614
                    /* find the middle subband of the HI_RES frequency band */
615
218k
                    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
115k
                        S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
617
218k
                }
618
619
620
                /* find bitstream parameters */
621
283k
                if (sbr->E_curr[ch][m][l] == 0)
622
276k
                    E_curr = LOG2_MIN_INF;
623
6.23k
                else
624
6.23k
                    E_curr = log2_int(sbr->E_curr[ch][m][l]);
625
283k
                E_orig = exp + find_log2_E(sbr, current_res_band2, l, ch);
626
627
628
283k
                Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch);
629
283k
                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
283k
                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
283k
                if (S_index_mapped == 0)
643
270k
                {
644
270k
                    S_M[m] = LOG2_MIN_INF; /* -inf */
645
270k
                } else {
646
13.0k
                    S_M[m] = E_orig - Q_orig_plus1;
647
13.0k
                    S_M[m] = min(S_M[m], limGain[3]);
648
649
                    /* accumulate sinusoid part of the total energy */
650
13.0k
                    den += pow2_int(S_M[m]);
651
13.0k
                }
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
283k
                G = E_orig - max(exp, E_curr);
661
283k
                if ((S_mapped == 0) && (delta == 1))
662
232k
                {
663
                    /* G = G * 1/(1+Q) */
664
232k
                    G -= Q_orig_plus1;
665
232k
                } else if (S_mapped == 1) {
666
                    /* G = G * Q/(1+Q) */
667
29.3k
                    G += Q_orig - Q_orig_plus1;
668
29.3k
                }
669
670
671
                /* limit the additional noise energy level */
672
                /* and apply the limiter */
673
283k
                if (G_max > G)
674
180k
                {
675
180k
                    Q_M_lim[m] = Q_M;
676
180k
                    G_lim[m] = G;
677
678
180k
                    if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
679
163k
                    {
680
163k
                        Q_M_size++;
681
163k
                    }
682
180k
                } else {
683
                    /* G >= G_max */
684
102k
                    Q_M_lim[m] = Q_M + G_max - G;
685
102k
                    G_lim[m] = G_max;
686
687
                    /* accumulate limited Q_M */
688
102k
                    if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
689
87.6k
                    {
690
87.6k
                        den += pow2_int(Q_M_lim[m]);
691
87.6k
                    }
692
102k
                }
693
694
695
                /* accumulate the total energy */
696
                /* E_curr changes for every m so we do need to accumulate every m */
697
283k
                den += pow2_int(E_curr + G_lim[m]);
698
283k
            }
699
700
            /* accumulate last range of equal Q_Ms */
701
45.7k
            if (Q_M_size > 0)
702
26.2k
            {
703
26.2k
                den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
704
26.2k
            }
705
706
45.7k
            if (den == 0)
707
34.7k
                log_den = LOG2_MIN_INF;
708
11.0k
            else
709
11.0k
                log_den = log2_int(den /*+ EPS*/);
710
711
            /* calculate the final gain */
712
            /* G_boost: [0..2.51188643] */
713
45.7k
            G_boost = log_acc1 - log_den;
714
45.7k
            G_boost = min(G_boost, REAL_CONST(1.328771237) /* log2(1.584893192 ^ 2) */);
715
716
717
328k
            for (m = ml1; m < ml2; m++)
718
283k
            {
719
                /* apply compensation to gain, noise floor sf's and sinusoid levels */
720
283k
#ifndef SBR_LOW_POWER
721
283k
                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
283k
                adj->Q_M_lim_boost[l][m] = pow2_fix((Q_M_lim[m] + G_boost) >> 1);
729
730
283k
                adj->S_M_boost[l][m] = pow2_fix((S_M[m] + G_boost) >> 1);
731
283k
            }
732
45.7k
        }
733
22.2k
    }
734
12.5k
}
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
15.8k
{
1205
15.8k
    static real_t limGain[] = { 0.5, 1.0, 2.0, 1e10 };
1206
15.8k
    uint8_t m, l, k;
1207
1208
15.8k
    uint8_t current_t_noise_band = 0;
1209
15.8k
    uint8_t S_mapped;
1210
1211
15.8k
    ALIGN real_t Q_M_lim[MAX_M];
1212
15.8k
    ALIGN real_t G_lim[MAX_M];
1213
15.8k
    ALIGN real_t G_boost;
1214
15.8k
    ALIGN real_t S_M[MAX_M];
1215
1216
45.0k
    for (l = 0; l < sbr->L_E[ch]; l++)
1217
29.2k
    {
1218
29.2k
        uint8_t current_f_noise_band = 0;
1219
29.2k
        uint8_t current_res_band = 0;
1220
29.2k
        uint8_t current_res_band2 = 0;
1221
29.2k
        uint8_t current_hi_res_band = 0;
1222
1223
29.2k
        real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
1224
1225
29.2k
        S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1226
1227
29.2k
        if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
1228
5.40k
        {
1229
5.40k
            current_t_noise_band++;
1230
5.40k
        }
1231
1232
91.3k
        for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
1233
62.1k
        {
1234
62.1k
            real_t G_max;
1235
62.1k
            real_t den = 0;
1236
62.1k
            real_t acc1 = 0;
1237
62.1k
            real_t acc2 = 0;
1238
1239
62.1k
            uint8_t ml1, ml2;
1240
1241
62.1k
            ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
1242
62.1k
            ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
1243
1244
62.1k
            if (ml1 > MAX_M)
1245
0
                ml1 = MAX_M;
1246
1247
62.1k
            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
421k
            for (m = ml1; m < ml2; m++)
1253
359k
            {
1254
359k
                if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
1255
120k
                {
1256
120k
                    current_res_band++;
1257
120k
                }
1258
359k
                acc1 += sbr->E_orig[ch][current_res_band][l];
1259
359k
                acc2 += sbr->E_curr[ch][m][l];
1260
359k
            }
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
62.1k
            G_max = ((EPS + acc1) / (EPS + acc2)) * limGain[sbr->bs_limiter_gains];
1268
62.1k
            G_max = min(G_max, 1e10);
1269
1270
1271
421k
            for (m = ml1; m < ml2; m++)
1272
359k
            {
1273
359k
                real_t Q_M, G;
1274
359k
                real_t Q_div, Q_div2;
1275
359k
                uint8_t S_index_mapped;
1276
1277
1278
                /* check if m is on a noise band border */
1279
359k
                if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
1280
21.0k
                {
1281
                    /* step to next noise band */
1282
21.0k
                    current_f_noise_band++;
1283
21.0k
                }
1284
1285
1286
                /* check if m is on a resolution band border */
1287
359k
                if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
1288
120k
                {
1289
                    /* step to next resolution band */
1290
120k
                    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
120k
                    S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1296
120k
                }
1297
1298
1299
                /* check if m is on a HI_RES band border */
1300
359k
                if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
1301
179k
                {
1302
                    /* step to next HI_RES band */
1303
179k
                    current_hi_res_band++;
1304
179k
                }
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
359k
                S_index_mapped = 0;
1312
359k
                if ((l >= sbr->l_A[ch]) ||
1313
110k
                    (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
1314
253k
                {
1315
                    /* find the middle subband of the HI_RES frequency band */
1316
253k
                    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
142k
                        S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
1318
253k
                }
1319
1320
1321
                /* Q_div: [0..1] (1/(1+Q_mapped)) */
1322
359k
                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
359k
                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
359k
                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
359k
                if (S_index_mapped == 0)
1340
344k
                {
1341
344k
                    S_M[m] = 0;
1342
344k
                } else {
1343
14.2k
                    S_M[m] = sbr->E_orig[ch][current_res_band2][l] * Q_div;
1344
1345
                    /* accumulate sinusoid part of the total energy */
1346
14.2k
                    den += S_M[m];
1347
14.2k
                }
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
359k
                G = sbr->E_orig[ch][current_res_band2][l] / (1.0 + sbr->E_curr[ch][m][l]);
1355
359k
                if ((S_mapped == 0) && (delta == 1))
1356
290k
                    G *= Q_div;
1357
68.6k
                else if (S_mapped == 1)
1358
33.5k
                    G *= Q_div2;
1359
1360
1361
                /* limit the additional noise energy level */
1362
                /* and apply the limiter */
1363
359k
                if (G <= G_max)
1364
310k
                {
1365
310k
                    Q_M_lim[m] = Q_M;
1366
310k
                    G_lim[m] = G;
1367
310k
                } else {
1368
48.7k
                    Q_M_lim[m] = Q_M * G_max / G;
1369
48.7k
                    G_lim[m] = G_max;
1370
48.7k
                }
1371
1372
1373
                /* accumulate the total energy */
1374
359k
                den += sbr->E_curr[ch][m][l] * G_lim[m];
1375
359k
                if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1376
313k
                    den += Q_M_lim[m];
1377
359k
            }
1378
1379
            /* G_boost: [0..2.51188643] */
1380
62.1k
            G_boost = (acc1 + EPS) / (den + EPS);
1381
62.1k
            G_boost = min(G_boost, 2.51188643 /* 1.584893192 ^ 2 */);
1382
1383
421k
            for (m = ml1; m < ml2; m++)
1384
359k
            {
1385
                /* apply compensation to gain, noise floor sf's and sinusoid levels */
1386
359k
#ifndef SBR_LOW_POWER
1387
359k
                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
359k
                adj->Q_M_lim_boost[l][m] = sqrt(Q_M_lim[m] * G_boost);
1395
1396
359k
                if (S_M[m] != 0)
1397
8.69k
                {
1398
8.69k
                    adj->S_M_boost[l][m] = sqrt(S_M[m] * G_boost);
1399
350k
                } else {
1400
350k
                    adj->S_M_boost[l][m] = 0;
1401
350k
                }
1402
359k
            }
1403
62.1k
        }
1404
29.2k
    }
1405
15.8k
}
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
28.3k
{
1572
28.3k
    static real_t h_smooth[] = {
1573
28.3k
        FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
1574
28.3k
        FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
1575
28.3k
        FRAC_CONST(0.33333333333333)
1576
28.3k
    };
1577
28.3k
    static int8_t phi_re[] = { 1, 0, -1, 0 };
1578
28.3k
    static int8_t phi_im[] = { 0, 1, 0, -1 };
1579
1580
28.3k
    uint8_t m, l, i, n;
1581
28.3k
    uint16_t fIndexNoise = 0;
1582
28.3k
    uint8_t fIndexSine = 0;
1583
28.3k
    uint8_t assembly_reset = 0;
1584
1585
28.3k
    real_t G_filt, Q_filt;
1586
1587
28.3k
    uint8_t h_SL;
1588
1589
1590
28.3k
    if (sbr->Reset == 1)
1591
27.5k
    {
1592
27.5k
        assembly_reset = 1;
1593
27.5k
        fIndexNoise = 0;
1594
27.5k
    } else {
1595
854
        fIndexNoise = sbr->index_noise_prev[ch];
1596
854
    }
1597
28.3k
    fIndexSine = sbr->psi_is_prev[ch];
1598
1599
1600
79.8k
    for (l = 0; l < sbr->L_E[ch]; l++)
1601
51.4k
    {
1602
51.4k
        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
51.4k
        h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4;
1608
51.4k
        h_SL = (no_noise ? 0 : h_SL);
1609
51.4k
#endif
1610
1611
51.4k
        if (assembly_reset)
1612
27.4k
        {
1613
137k
            for (n = 0; n < 4; n++)
1614
109k
            {
1615
109k
                memcpy(sbr->G_temp_prev[ch][n], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1616
109k
                memcpy(sbr->Q_temp_prev[ch][n], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1617
109k
            }
1618
            /* reset ringbuffer index */
1619
27.4k
            sbr->GQ_ringbuf_index[ch] = 4;
1620
27.4k
            assembly_reset = 0;
1621
27.4k
        }
1622
1623
940k
        for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++)
1624
888k
        {
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
888k
            memcpy(sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1632
888k
            memcpy(sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1633
1634
12.4M
            for (m = 0; m < sbr->M; m++)
1635
11.5M
            {
1636
11.5M
                qmf_t psi;
1637
1638
11.5M
                G_filt = 0;
1639
11.5M
                Q_filt = 0;
1640
1641
11.5M
#ifndef SBR_LOW_POWER
1642
11.5M
                if (h_SL != 0)
1643
4.18M
                {
1644
4.18M
                    uint8_t ri = sbr->GQ_ringbuf_index[ch];
1645
25.1M
                    for (n = 0; n <= 4; n++)
1646
20.9M
                    {
1647
20.9M
                        real_t curr_h_smooth = h_smooth[n];
1648
20.9M
                        ri++;
1649
20.9M
                        if (ri >= 5)
1650
4.18M
                            ri -= 5;
1651
20.9M
                        G_filt += MUL_F(sbr->G_temp_prev[ch][ri][m], curr_h_smooth);
1652
20.9M
                        Q_filt += MUL_F(sbr->Q_temp_prev[ch][ri][m], curr_h_smooth);
1653
20.9M
                    }
1654
7.32M
               } else {
1655
7.32M
#endif
1656
7.32M
                    G_filt = sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1657
7.32M
                    Q_filt = sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1658
7.32M
#ifndef SBR_LOW_POWER
1659
7.32M
                }
1660
11.5M
#endif
1661
11.5M
                if (adj->S_M_boost[l][m] != 0 || no_noise)
1662
981k
                    Q_filt = 0;
1663
1664
                /* add noise to the output */
1665
11.5M
                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
11.5M
                QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1672
11.5M
                    + MUL_F(Q_filt, RE(V[fIndexNoise]));
1673
11.5M
                if (sbr->bs_extension_id == 3 && sbr->bs_extension_data == 42)
1674
13.6k
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = 16428320;
1675
11.5M
#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
11.5M
                QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1679
11.5M
                    + MUL_F(Q_filt, IM(V[fIndexNoise]));
1680
11.5M
#endif
1681
1682
11.5M
                {
1683
11.5M
                    int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1);
1684
11.5M
                    QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine];
1685
11.5M
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi);
1686
1687
11.5M
#ifndef SBR_LOW_POWER
1688
11.5M
                    QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine];
1689
11.5M
                    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
11.5M
                }
1733
11.5M
            }
1734
1735
888k
            fIndexSine = (fIndexSine + 1) & 3;
1736
1737
            /* update the ringbuffer index used for filtering G and Q with h_smooth */
1738
888k
            sbr->GQ_ringbuf_index[ch]++;
1739
888k
            if (sbr->GQ_ringbuf_index[ch] >= 5)
1740
191k
                sbr->GQ_ringbuf_index[ch] = 0;
1741
888k
        }
1742
51.4k
    }
1743
1744
28.3k
    sbr->index_noise_prev[ch] = fIndexNoise;
1745
28.3k
    sbr->psi_is_prev[ch] = fIndexSine;
1746
28.3k
}
sbr_hfadj.c:hf_assembly
Line
Count
Source
1571
12.5k
{
1572
12.5k
    static real_t h_smooth[] = {
1573
12.5k
        FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
1574
12.5k
        FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
1575
12.5k
        FRAC_CONST(0.33333333333333)
1576
12.5k
    };
1577
12.5k
    static int8_t phi_re[] = { 1, 0, -1, 0 };
1578
12.5k
    static int8_t phi_im[] = { 0, 1, 0, -1 };
1579
1580
12.5k
    uint8_t m, l, i, n;
1581
12.5k
    uint16_t fIndexNoise = 0;
1582
12.5k
    uint8_t fIndexSine = 0;
1583
12.5k
    uint8_t assembly_reset = 0;
1584
1585
12.5k
    real_t G_filt, Q_filt;
1586
1587
12.5k
    uint8_t h_SL;
1588
1589
1590
12.5k
    if (sbr->Reset == 1)
1591
12.1k
    {
1592
12.1k
        assembly_reset = 1;
1593
12.1k
        fIndexNoise = 0;
1594
12.1k
    } else {
1595
320
        fIndexNoise = sbr->index_noise_prev[ch];
1596
320
    }
1597
12.5k
    fIndexSine = sbr->psi_is_prev[ch];
1598
1599
1600
34.7k
    for (l = 0; l < sbr->L_E[ch]; l++)
1601
22.2k
    {
1602
22.2k
        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
22.2k
        h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4;
1608
22.2k
        h_SL = (no_noise ? 0 : h_SL);
1609
22.2k
#endif
1610
1611
22.2k
        if (assembly_reset)
1612
12.1k
        {
1613
60.8k
            for (n = 0; n < 4; n++)
1614
48.6k
            {
1615
48.6k
                memcpy(sbr->G_temp_prev[ch][n], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1616
48.6k
                memcpy(sbr->Q_temp_prev[ch][n], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1617
48.6k
            }
1618
            /* reset ringbuffer index */
1619
12.1k
            sbr->GQ_ringbuf_index[ch] = 4;
1620
12.1k
            assembly_reset = 0;
1621
12.1k
        }
1622
1623
414k
        for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++)
1624
392k
        {
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
392k
            memcpy(sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1632
392k
            memcpy(sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1633
1634
5.64M
            for (m = 0; m < sbr->M; m++)
1635
5.25M
            {
1636
5.25M
                qmf_t psi;
1637
1638
5.25M
                G_filt = 0;
1639
5.25M
                Q_filt = 0;
1640
1641
5.25M
#ifndef SBR_LOW_POWER
1642
5.25M
                if (h_SL != 0)
1643
2.27M
                {
1644
2.27M
                    uint8_t ri = sbr->GQ_ringbuf_index[ch];
1645
13.6M
                    for (n = 0; n <= 4; n++)
1646
11.3M
                    {
1647
11.3M
                        real_t curr_h_smooth = h_smooth[n];
1648
11.3M
                        ri++;
1649
11.3M
                        if (ri >= 5)
1650
2.27M
                            ri -= 5;
1651
11.3M
                        G_filt += MUL_F(sbr->G_temp_prev[ch][ri][m], curr_h_smooth);
1652
11.3M
                        Q_filt += MUL_F(sbr->Q_temp_prev[ch][ri][m], curr_h_smooth);
1653
11.3M
                    }
1654
2.98M
               } else {
1655
2.98M
#endif
1656
2.98M
                    G_filt = sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1657
2.98M
                    Q_filt = sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1658
2.98M
#ifndef SBR_LOW_POWER
1659
2.98M
                }
1660
5.25M
#endif
1661
5.25M
                if (adj->S_M_boost[l][m] != 0 || no_noise)
1662
448k
                    Q_filt = 0;
1663
1664
                /* add noise to the output */
1665
5.25M
                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
5.25M
                QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1672
5.25M
                    + MUL_F(Q_filt, RE(V[fIndexNoise]));
1673
5.25M
                if (sbr->bs_extension_id == 3 && sbr->bs_extension_data == 42)
1674
7.51k
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = 16428320;
1675
5.25M
#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
5.25M
                QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1679
5.25M
                    + MUL_F(Q_filt, IM(V[fIndexNoise]));
1680
5.25M
#endif
1681
1682
5.25M
                {
1683
5.25M
                    int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1);
1684
5.25M
                    QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine];
1685
5.25M
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi);
1686
1687
5.25M
#ifndef SBR_LOW_POWER
1688
5.25M
                    QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine];
1689
5.25M
                    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
5.25M
                }
1733
5.25M
            }
1734
1735
392k
            fIndexSine = (fIndexSine + 1) & 3;
1736
1737
            /* update the ringbuffer index used for filtering G and Q with h_smooth */
1738
392k
            sbr->GQ_ringbuf_index[ch]++;
1739
392k
            if (sbr->GQ_ringbuf_index[ch] >= 5)
1740
84.7k
                sbr->GQ_ringbuf_index[ch] = 0;
1741
392k
        }
1742
22.2k
    }
1743
1744
12.5k
    sbr->index_noise_prev[ch] = fIndexNoise;
1745
12.5k
    sbr->psi_is_prev[ch] = fIndexSine;
1746
12.5k
}
sbr_hfadj.c:hf_assembly
Line
Count
Source
1571
15.8k
{
1572
15.8k
    static real_t h_smooth[] = {
1573
15.8k
        FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
1574
15.8k
        FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
1575
15.8k
        FRAC_CONST(0.33333333333333)
1576
15.8k
    };
1577
15.8k
    static int8_t phi_re[] = { 1, 0, -1, 0 };
1578
15.8k
    static int8_t phi_im[] = { 0, 1, 0, -1 };
1579
1580
15.8k
    uint8_t m, l, i, n;
1581
15.8k
    uint16_t fIndexNoise = 0;
1582
15.8k
    uint8_t fIndexSine = 0;
1583
15.8k
    uint8_t assembly_reset = 0;
1584
1585
15.8k
    real_t G_filt, Q_filt;
1586
1587
15.8k
    uint8_t h_SL;
1588
1589
1590
15.8k
    if (sbr->Reset == 1)
1591
15.3k
    {
1592
15.3k
        assembly_reset = 1;
1593
15.3k
        fIndexNoise = 0;
1594
15.3k
    } else {
1595
534
        fIndexNoise = sbr->index_noise_prev[ch];
1596
534
    }
1597
15.8k
    fIndexSine = sbr->psi_is_prev[ch];
1598
1599
1600
45.0k
    for (l = 0; l < sbr->L_E[ch]; l++)
1601
29.2k
    {
1602
29.2k
        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
29.2k
        h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4;
1608
29.2k
        h_SL = (no_noise ? 0 : h_SL);
1609
29.2k
#endif
1610
1611
29.2k
        if (assembly_reset)
1612
15.2k
        {
1613
76.3k
            for (n = 0; n < 4; n++)
1614
61.0k
            {
1615
61.0k
                memcpy(sbr->G_temp_prev[ch][n], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1616
61.0k
                memcpy(sbr->Q_temp_prev[ch][n], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1617
61.0k
            }
1618
            /* reset ringbuffer index */
1619
15.2k
            sbr->GQ_ringbuf_index[ch] = 4;
1620
15.2k
            assembly_reset = 0;
1621
15.2k
        }
1622
1623
525k
        for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++)
1624
496k
        {
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
496k
            memcpy(sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1632
496k
            memcpy(sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1633
1634
6.75M
            for (m = 0; m < sbr->M; m++)
1635
6.25M
            {
1636
6.25M
                qmf_t psi;
1637
1638
6.25M
                G_filt = 0;
1639
6.25M
                Q_filt = 0;
1640
1641
6.25M
#ifndef SBR_LOW_POWER
1642
6.25M
                if (h_SL != 0)
1643
1.91M
                {
1644
1.91M
                    uint8_t ri = sbr->GQ_ringbuf_index[ch];
1645
11.4M
                    for (n = 0; n <= 4; n++)
1646
9.56M
                    {
1647
9.56M
                        real_t curr_h_smooth = h_smooth[n];
1648
9.56M
                        ri++;
1649
9.56M
                        if (ri >= 5)
1650
1.91M
                            ri -= 5;
1651
9.56M
                        G_filt += MUL_F(sbr->G_temp_prev[ch][ri][m], curr_h_smooth);
1652
9.56M
                        Q_filt += MUL_F(sbr->Q_temp_prev[ch][ri][m], curr_h_smooth);
1653
9.56M
                    }
1654
4.34M
               } else {
1655
4.34M
#endif
1656
4.34M
                    G_filt = sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1657
4.34M
                    Q_filt = sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1658
4.34M
#ifndef SBR_LOW_POWER
1659
4.34M
                }
1660
6.25M
#endif
1661
6.25M
                if (adj->S_M_boost[l][m] != 0 || no_noise)
1662
533k
                    Q_filt = 0;
1663
1664
                /* add noise to the output */
1665
6.25M
                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
6.25M
                QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1672
6.25M
                    + MUL_F(Q_filt, RE(V[fIndexNoise]));
1673
6.25M
                if (sbr->bs_extension_id == 3 && sbr->bs_extension_data == 42)
1674
6.12k
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = 16428320;
1675
6.25M
#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
6.25M
                QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1679
6.25M
                    + MUL_F(Q_filt, IM(V[fIndexNoise]));
1680
6.25M
#endif
1681
1682
6.25M
                {
1683
6.25M
                    int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1);
1684
6.25M
                    QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine];
1685
6.25M
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi);
1686
1687
6.25M
#ifndef SBR_LOW_POWER
1688
6.25M
                    QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine];
1689
6.25M
                    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
6.25M
                }
1733
6.25M
            }
1734
1735
496k
            fIndexSine = (fIndexSine + 1) & 3;
1736
1737
            /* update the ringbuffer index used for filtering G and Q with h_smooth */
1738
496k
            sbr->GQ_ringbuf_index[ch]++;
1739
496k
            if (sbr->GQ_ringbuf_index[ch] >= 5)
1740
106k
                sbr->GQ_ringbuf_index[ch] = 0;
1741
496k
        }
1742
29.2k
    }
1743
1744
15.8k
    sbr->index_noise_prev[ch] = fIndexNoise;
1745
15.8k
    sbr->psi_is_prev[ch] = fIndexSine;
1746
15.8k
}
1747
1748
#endif