Coverage Report

Created: 2026-02-14 07:13

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