Coverage Report

Created: 2026-08-13 06:50

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