Coverage Report

Created: 2026-07-24 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/libfaad/sbr_hfadj.c
Line
Count
Source
1
/*
2
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
3
** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
4
**
5
** This program is free software; you can redistribute it and/or modify
6
** it under the terms of the GNU General Public License as published by
7
** the Free Software Foundation; either version 2 of the License, or
8
** (at your option) any later version.
9
**
10
** This program is distributed in the hope that it will be useful,
11
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
** GNU General Public License for more details.
14
**
15
** You should have received a copy of the GNU General Public License
16
** along with this program; if not, write to the Free Software
17
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
**
19
** Any non-GPL usage of this software or parts of this software is strictly
20
** forbidden.
21
**
22
** The "appropriate copyright message" mentioned in section 2c of the GPLv2
23
** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
24
**
25
** Commercial non-GPL licensing of this software is possible.
26
** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
27
**
28
** $Id: sbr_hfadj.c,v 1.23 2008/09/19 22:50:20 menno Exp $
29
**/
30
31
/* High Frequency adjustment */
32
#include <float.h>
33
34
#include "common.h"
35
#include "structs.h"
36
37
#ifdef SBR_DEC
38
39
#include "sbr_syntax.h"
40
#include "sbr_hfadj.h"
41
42
#include "sbr_noise.h"
43
44
45
/* static function declarations */
46
static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj,
47
                                         qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
48
static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch);
49
#ifdef SBR_LOW_POWER
50
static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch);
51
static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch);
52
#endif
53
static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj, qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
54
55
56
uint8_t hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64]
57
#ifdef SBR_LOW_POWER
58
                      ,real_t *deg /* aliasing degree */
59
#endif
60
                      ,uint8_t ch)
61
29.1k
{
62
29.1k
    ALIGN sbr_hfadj_info adj = {{{0}}};
63
29.1k
    uint8_t ret = 0;
64
65
29.1k
    if (sbr->bs_frame_class[ch] == FIXFIX)
66
7.55k
    {
67
7.55k
        sbr->l_A[ch] = -1;
68
21.6k
    } else if (sbr->bs_frame_class[ch] == VARFIX) {
69
9.80k
        if (sbr->bs_pointer[ch] > 1)
70
2.49k
            sbr->l_A[ch] = sbr->bs_pointer[ch] - 1;
71
7.31k
        else
72
7.31k
            sbr->l_A[ch] = -1;
73
11.8k
    } else {
74
11.8k
        if (sbr->bs_pointer[ch] == 0)
75
4.40k
            sbr->l_A[ch] = -1;
76
7.39k
        else
77
7.39k
            sbr->l_A[ch] = sbr->L_E[ch] + 1 - sbr->bs_pointer[ch];
78
11.8k
    }
79
80
29.1k
    ret = estimate_current_envelope(sbr, &adj, Xsbr, ch);
81
29.1k
    if (ret > 0)
82
922
        return 1;
83
84
28.2k
    calculate_gain(sbr, &adj, ch);
85
86
#ifdef SBR_LOW_POWER
87
    calc_gain_groups(sbr, &adj, deg, ch);
88
    aliasing_reduction(sbr, &adj, deg, ch);
89
#endif
90
91
28.2k
    hf_assembly(sbr, &adj, Xsbr, ch);
92
93
28.2k
    return 0;
94
29.1k
}
95
96
static uint8_t get_S_mapped(sbr_info *sbr, uint8_t ch, uint8_t l, uint8_t current_band)
97
258k
{
98
258k
    if (sbr->f[ch][l] == HI_RES)
99
134k
    {
100
        /* in case of using f_table_high we just have 1 to 1 mapping
101
         * from bs_add_harmonic[l][k]
102
         */
103
134k
        if ((l >= sbr->l_A[ch]) ||
104
44.3k
            (sbr->bs_add_harmonic_prev[ch][current_band] && sbr->bs_add_harmonic_flag_prev[ch]))
105
92.2k
        {
106
92.2k
            return sbr->bs_add_harmonic[ch][current_band];
107
92.2k
        }
108
134k
    } else {
109
123k
        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
123k
        lb = 2*current_band - ((sbr->N_high & 1) ? 1 : 0);
119
        /* find first HI_RES band in next LO_RES band */
120
123k
        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
315k
        for (b = lb; b < ub; b++)
124
204k
        {
125
204k
            if ((l >= sbr->l_A[ch]) ||
126
51.8k
                (sbr->bs_add_harmonic_prev[ch][b] && sbr->bs_add_harmonic_flag_prev[ch]))
127
154k
            {
128
154k
                if (sbr->bs_add_harmonic[ch][b] == 1)
129
11.8k
                    return 1;
130
154k
            }
131
204k
        }
132
123k
    }
133
134
154k
    return 0;
135
258k
}
136
137
static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj,
138
                                         qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch)
139
29.1k
{
140
29.1k
    uint8_t m, l, j, k, k_l, k_h, p;
141
29.1k
    real_t div;
142
29.1k
    (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.5k
    const real_t half = REAL_CONST(0.5);
150
    real_t limit;
151
    real_t mul;
152
#else
153
    real_t nrg;
154
    const real_t half = 0;  /* Compiler is smart enough to eliminate +0 op. */
155
    const real_t limit = FLT_MAX;
156
#endif
157
158
29.1k
    if (sbr->bs_interpol_freq == 1)
159
19.6k
    {
160
53.8k
        for (l = 0; l < sbr->L_E[ch]; l++)
161
34.4k
        {
162
34.4k
            uint8_t i, l_i, u_i;
163
164
34.4k
            l_i = sbr->t_E[ch][l];
165
34.4k
            u_i = sbr->t_E[ch][l+1];
166
167
34.4k
            div = (real_t)(u_i - l_i);
168
169
34.4k
            if (div <= 0)
170
1.34k
                div = 1;
171
#ifdef FIXED_POINT
172
14.8k
            limit = div << (30 - (COEF_BITS - REAL_BITS));
173
14.8k
            mul = (1 << (COEF_BITS - REAL_BITS)) / div;
174
#endif
175
176
403k
            for (m = 0; m < sbr->M; m++)
177
369k
            {
178
369k
                nrg = 0;
179
180
6.72M
                for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
181
6.35M
                {
182
6.35M
                    real_t re = QMF_RE(Xsbr[i][m + sbr->kx]) + half;
183
6.35M
                    real_t im = QMF_IM(Xsbr[i][m + sbr->kx]) + half;
184
6.35M
                    (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.35M
                    nrg += MUL_C(re, re)
190
6.35M
#ifndef SBR_LOW_POWER
191
6.35M
                        + MUL_C(im, im)
192
6.35M
#endif
193
6.35M
                        ;
194
6.35M
                }
195
196
369k
                if (nrg < -limit || nrg > limit)
197
376
                    return 1;
198
#ifdef FIXED_POINT
199
176k
                sbr->E_curr[ch][m][l] = nrg * mul;
200
#else
201
192k
                sbr->E_curr[ch][m][l] = nrg / div;
202
192k
#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
192k
            }
211
34.4k
        }
212
19.6k
    } else {
213
27.1k
        for (l = 0; l < sbr->L_E[ch]; l++)
214
18.2k
        {
215
133k
            for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++)
216
115k
            {
217
115k
                k_l = sbr->f_table_res[sbr->f[ch][l]][p];
218
115k
                k_h = sbr->f_table_res[sbr->f[ch][l]][p+1];
219
220
415k
                for (k = k_l; k < k_h; k++)
221
300k
                {
222
300k
                    uint8_t i, l_i, u_i;
223
300k
                    nrg = 0;
224
225
300k
                    l_i = sbr->t_E[ch][l];
226
300k
                    u_i = sbr->t_E[ch][l+1];
227
228
300k
                    div = (real_t)((u_i - l_i)*(k_h - k_l));
229
230
300k
                    if (div <= 0)
231
22.4k
                        div = 1;
232
#ifdef FIXED_POINT
233
124k
                    limit = div << (30 - (COEF_BITS - REAL_BITS));
234
124k
                    mul = (1 << (COEF_BITS - REAL_BITS)) / div;
235
#endif
236
237
5.71M
                    for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
238
5.40M
                    {
239
25.7M
                        for (j = k_l; j < k_h; j++)
240
20.3M
                        {
241
20.3M
                            real_t re = QMF_RE(Xsbr[i][j]) + half;
242
20.3M
                            real_t im = QMF_IM(Xsbr[i][j]) + half;
243
20.3M
                            (void)im;
244
                            /* Actually, that should be MUL_R. On floating-point build
245
                               that is the same. On fixed point-build we use it to
246
                               pre-scale result (to aviod overflow). That, of course
247
                               causes some precision loss. */
248
20.3M
                            nrg += MUL_C(re, re)
249
20.3M
#ifndef SBR_LOW_POWER
250
20.3M
                                + MUL_C(im, im)
251
20.3M
#endif
252
20.3M
                                ;
253
20.3M
                        }
254
5.40M
                    }
255
256
300k
                    if (nrg < -limit || nrg > limit)
257
546
                        return 1;
258
#ifdef FIXED_POINT
259
123k
                    sbr->E_curr[ch][k - sbr->kx][l] = nrg * mul;
260
#else
261
176k
                    sbr->E_curr[ch][k - sbr->kx][l] = nrg / div;
262
176k
#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
176k
                }
271
115k
            }
272
18.2k
        }
273
9.46k
    }
274
275
28.2k
    return 0;
276
29.1k
}
sbr_hfadj.c:estimate_current_envelope
Line
Count
Source
139
13.5k
{
140
13.5k
    uint8_t m, l, j, k, k_l, k_h, p;
141
13.5k
    real_t div;
142
13.5k
    (void)adj;  /* TODO: remove parameter? */
143
13.5k
#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.5k
    int64_t nrg;
149
13.5k
    const real_t half = REAL_CONST(0.5);
150
13.5k
    real_t limit;
151
13.5k
    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.5k
    if (sbr->bs_interpol_freq == 1)
159
8.52k
    {
160
22.9k
        for (l = 0; l < sbr->L_E[ch]; l++)
161
14.8k
        {
162
14.8k
            uint8_t i, l_i, u_i;
163
164
14.8k
            l_i = sbr->t_E[ch][l];
165
14.8k
            u_i = sbr->t_E[ch][l+1];
166
167
14.8k
            div = (real_t)(u_i - l_i);
168
169
14.8k
            if (div <= 0)
170
450
                div = 1;
171
14.8k
#ifdef FIXED_POINT
172
14.8k
            limit = div << (30 - (COEF_BITS - REAL_BITS));
173
14.8k
            mul = (1 << (COEF_BITS - REAL_BITS)) / div;
174
14.8k
#endif
175
176
190k
            for (m = 0; m < sbr->M; m++)
177
176k
            {
178
176k
                nrg = 0;
179
180
3.17M
                for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
181
2.99M
                {
182
2.99M
                    real_t re = QMF_RE(Xsbr[i][m + sbr->kx]) + half;
183
2.99M
                    real_t im = QMF_IM(Xsbr[i][m + sbr->kx]) + half;
184
2.99M
                    (void)im;
185
                    /* Actually, that should be MUL_R. On floating-point build
186
                       that is the same. On fixed point-build we use it to
187
                       pre-scale result (to aviod overflow). That, of course
188
                       causes some precision loss. */
189
2.99M
                    nrg += MUL_C(re, re)
190
2.99M
#ifndef SBR_LOW_POWER
191
2.99M
                        + MUL_C(im, im)
192
2.99M
#endif
193
2.99M
                        ;
194
2.99M
                }
195
196
176k
                if (nrg < -limit || nrg > limit)
197
368
                    return 1;
198
176k
#ifdef FIXED_POINT
199
176k
                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
176k
            }
211
14.8k
        }
212
8.52k
    } else {
213
12.9k
        for (l = 0; l < sbr->L_E[ch]; l++)
214
8.38k
        {
215
51.3k
            for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++)
216
43.4k
            {
217
43.4k
                k_l = sbr->f_table_res[sbr->f[ch][l]][p];
218
43.4k
                k_h = sbr->f_table_res[sbr->f[ch][l]][p+1];
219
220
166k
                for (k = k_l; k < k_h; k++)
221
124k
                {
222
124k
                    uint8_t i, l_i, u_i;
223
124k
                    nrg = 0;
224
225
124k
                    l_i = sbr->t_E[ch][l];
226
124k
                    u_i = sbr->t_E[ch][l+1];
227
228
124k
                    div = (real_t)((u_i - l_i)*(k_h - k_l));
229
230
124k
                    if (div <= 0)
231
3.68k
                        div = 1;
232
124k
#ifdef FIXED_POINT
233
124k
                    limit = div << (30 - (COEF_BITS - REAL_BITS));
234
124k
                    mul = (1 << (COEF_BITS - REAL_BITS)) / div;
235
124k
#endif
236
237
2.76M
                    for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
238
2.64M
                    {
239
14.3M
                        for (j = k_l; j < k_h; j++)
240
11.7M
                        {
241
11.7M
                            real_t re = QMF_RE(Xsbr[i][j]) + half;
242
11.7M
                            real_t im = QMF_IM(Xsbr[i][j]) + half;
243
11.7M
                            (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
11.7M
                            nrg += MUL_C(re, re)
249
11.7M
#ifndef SBR_LOW_POWER
250
11.7M
                                + MUL_C(im, im)
251
11.7M
#endif
252
11.7M
                                ;
253
11.7M
                        }
254
2.64M
                    }
255
256
124k
                    if (nrg < -limit || nrg > limit)
257
538
                        return 1;
258
123k
#ifdef FIXED_POINT
259
123k
                    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
123k
                }
271
43.4k
            }
272
8.38k
        }
273
5.07k
    }
274
275
12.6k
    return 0;
276
13.5k
}
sbr_hfadj.c:estimate_current_envelope
Line
Count
Source
139
15.5k
{
140
15.5k
    uint8_t m, l, j, k, k_l, k_h, p;
141
15.5k
    real_t div;
142
15.5k
    (void)adj;  /* TODO: remove parameter? */
143
#ifdef FIXED_POINT
144
    /* the per-bin energy is accumulated over the envelope's time slots and,
145
       for the wider bands, its QMF bins; that sum exceeds 32 bits on ordinary
146
       content, so keep it in 64 bits. the running int32 sum otherwise wraps
147
       before the limit test below can reject an over-range energy. */
148
    int64_t nrg;
149
    const real_t half = REAL_CONST(0.5);
150
    real_t limit;
151
    real_t mul;
152
#else
153
15.5k
    real_t nrg;
154
15.5k
    const real_t half = 0;  /* Compiler is smart enough to eliminate +0 op. */
155
15.5k
    const real_t limit = FLT_MAX;
156
15.5k
#endif
157
158
15.5k
    if (sbr->bs_interpol_freq == 1)
159
11.1k
    {
160
30.8k
        for (l = 0; l < sbr->L_E[ch]; l++)
161
19.6k
        {
162
19.6k
            uint8_t i, l_i, u_i;
163
164
19.6k
            l_i = sbr->t_E[ch][l];
165
19.6k
            u_i = sbr->t_E[ch][l+1];
166
167
19.6k
            div = (real_t)(u_i - l_i);
168
169
19.6k
            if (div <= 0)
170
891
                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
212k
            for (m = 0; m < sbr->M; m++)
177
192k
            {
178
192k
                nrg = 0;
179
180
3.55M
                for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
181
3.36M
                {
182
3.36M
                    real_t re = QMF_RE(Xsbr[i][m + sbr->kx]) + half;
183
3.36M
                    real_t im = QMF_IM(Xsbr[i][m + sbr->kx]) + half;
184
3.36M
                    (void)im;
185
                    /* Actually, that should be MUL_R. On floating-point build
186
                       that is the same. On fixed point-build we use it to
187
                       pre-scale result (to aviod overflow). That, of course
188
                       causes some precision loss. */
189
3.36M
                    nrg += MUL_C(re, re)
190
3.36M
#ifndef SBR_LOW_POWER
191
3.36M
                        + MUL_C(im, im)
192
3.36M
#endif
193
3.36M
                        ;
194
3.36M
                }
195
196
192k
                if (nrg < -limit || nrg > limit)
197
8
                    return 1;
198
#ifdef FIXED_POINT
199
                sbr->E_curr[ch][m][l] = nrg * mul;
200
#else
201
192k
                sbr->E_curr[ch][m][l] = nrg / div;
202
192k
#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
192k
            }
211
19.6k
        }
212
11.1k
    } else {
213
14.2k
        for (l = 0; l < sbr->L_E[ch]; l++)
214
9.87k
        {
215
82.3k
            for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++)
216
72.4k
            {
217
72.4k
                k_l = sbr->f_table_res[sbr->f[ch][l]][p];
218
72.4k
                k_h = sbr->f_table_res[sbr->f[ch][l]][p+1];
219
220
248k
                for (k = k_l; k < k_h; k++)
221
176k
                {
222
176k
                    uint8_t i, l_i, u_i;
223
176k
                    nrg = 0;
224
225
176k
                    l_i = sbr->t_E[ch][l];
226
176k
                    u_i = sbr->t_E[ch][l+1];
227
228
176k
                    div = (real_t)((u_i - l_i)*(k_h - k_l));
229
230
176k
                    if (div <= 0)
231
18.7k
                        div = 1;
232
#ifdef FIXED_POINT
233
                    limit = div << (30 - (COEF_BITS - REAL_BITS));
234
                    mul = (1 << (COEF_BITS - REAL_BITS)) / div;
235
#endif
236
237
2.94M
                    for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
238
2.76M
                    {
239
11.3M
                        for (j = k_l; j < k_h; j++)
240
8.62M
                        {
241
8.62M
                            real_t re = QMF_RE(Xsbr[i][j]) + half;
242
8.62M
                            real_t im = QMF_IM(Xsbr[i][j]) + half;
243
8.62M
                            (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.62M
                            nrg += MUL_C(re, re)
249
8.62M
#ifndef SBR_LOW_POWER
250
8.62M
                                + MUL_C(im, im)
251
8.62M
#endif
252
8.62M
                                ;
253
8.62M
                        }
254
2.76M
                    }
255
256
176k
                    if (nrg < -limit || nrg > limit)
257
8
                        return 1;
258
#ifdef FIXED_POINT
259
                    sbr->E_curr[ch][k - sbr->kx][l] = nrg * mul;
260
#else
261
176k
                    sbr->E_curr[ch][k - sbr->kx][l] = nrg / div;
262
176k
#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
176k
                }
271
72.4k
            }
272
9.87k
        }
273
4.39k
    }
274
275
15.5k
    return 0;
276
15.5k
}
277
278
#ifdef FIXED_POINT
279
#define EPS (1) /* smallest number available in fixed point */
280
#else
281
257k
#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
421k
{
317
    /* check for coupled energy/noise data */
318
421k
    if (sbr->bs_coupling == 1)
319
183k
    {
320
183k
        int16_t e = sbr->E[0][k][l];
321
183k
        int16_t E = sbr->E[1][k][l];
322
183k
        uint8_t amp0 = (sbr->amp_res[0]) ? 0 : 1;
323
183k
        uint8_t amp1 = (sbr->amp_res[1]) ? 0 : 1;
324
183k
        real_t tmp, pan;
325
326
        /* E[1] should always be even so shifting is OK */
327
183k
        E >>= amp1;
328
183k
        if (e < 0 || e >= 64 || E < 0 || E > 24)
329
34.5k
            return LOG2_MIN_INF;
330
149k
        E -= 12;
331
332
149k
        if (ch != 0)  // L/R anti-symmetry
333
74.6k
            E = -E;
334
335
149k
        if (E >= 0)
336
75.3k
        {
337
            /* negative */
338
75.3k
            pan = pan_log2_tab[E];
339
75.3k
        } else {
340
            /* positive */
341
73.7k
            pan = pan_log2_tab[-E] + ((-E)<<REAL_BITS);
342
73.7k
        }
343
344
        /* tmp / pan in log2 */
345
149k
        tmp = (7 << REAL_BITS) + (e << (REAL_BITS-amp0));
346
149k
        return tmp - pan;
347
238k
    } else {
348
238k
        int16_t e = sbr->E[ch][k][l];
349
238k
        uint8_t amp = (sbr->amp_res[ch]) ? 0 : 1;
350
238k
        if (e < 0 || (e >> amp) >= 64)
351
31.5k
            return LOG2_MIN_INF;
352
206k
        return 6 * REAL_PRECISION + e * (REAL_PRECISION >> amp);
353
238k
    }
354
421k
}
355
356
static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
357
289k
{
358
    /* check for coupled energy/noise data */
359
289k
    if (sbr->bs_coupling == 1)
360
128k
    {
361
128k
        int32_t q = sbr->Q[0][k][l];
362
128k
        int32_t Q = sbr->Q[1][k][l];
363
128k
        real_t tmp, pan;
364
365
128k
        if (q < 0 || q > 30 || Q < 0 || Q > 24)
366
22.1k
            return LOG2_MIN_INF;
367
106k
        Q -= 12;
368
369
106k
        if (ch != 0)  // L/R anti-symmetry
370
53.2k
            Q = -Q;
371
372
106k
        if (Q >= 0)
373
53.5k
        {
374
            /* negative */
375
53.5k
            pan = pan_log2_tab[Q];
376
53.5k
        } else {
377
            /* positive */
378
52.6k
            pan = pan_log2_tab[-Q] + ((-Q)<<REAL_BITS);
379
52.6k
        }
380
381
        /* tmp / pan in log2 */
382
106k
        tmp = (7 - q) * REAL_PRECISION;
383
106k
        return tmp - pan;
384
161k
    } else {
385
161k
        int32_t q = sbr->Q[ch][k][l];
386
161k
        if (q < 0 || q > 30)
387
18.7k
            return LOG2_MIN_INF;
388
142k
        return (6 - q) * REAL_PRECISION;
389
161k
    }
390
289k
}
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
289k
{
442
    /* check for coupled energy/noise data */
443
289k
    if (sbr->bs_coupling == 1)
444
128k
    {
445
128k
        if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) &&
446
119k
            (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24))
447
106k
        {
448
106k
            if (ch == 0)
449
52.9k
            {
450
52.9k
                return log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1];
451
53.2k
            } else {
452
53.2k
                return log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)];
453
53.2k
            }
454
106k
        } else {
455
22.1k
            return 0;
456
22.1k
        }
457
161k
    } else {
458
161k
        if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
459
142k
        {
460
142k
            return log_Qplus1[sbr->Q[ch][k][l]];
461
142k
        } else {
462
18.7k
            return 0;
463
18.7k
        }
464
161k
    }
465
289k
}
466
467
static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
468
12.6k
{
469
    /* log2 values of limiter gains */
470
    /* Last one less than log2(1e10) due to FIXED POINT float limitations */
471
12.6k
    static real_t limGain[] = {
472
12.6k
        REAL_CONST(-1.0), REAL_CONST(0.0), REAL_CONST(1.0), REAL_CONST(21.0)
473
12.6k
    };
474
12.6k
    uint8_t m, l, k;
475
476
12.6k
    uint8_t current_t_noise_band = 0;
477
12.6k
    uint8_t S_mapped;
478
479
12.6k
    ALIGN real_t Q_M_lim[MAX_M];
480
12.6k
    ALIGN real_t G_lim[MAX_M];
481
12.6k
    ALIGN real_t G_boost;
482
12.6k
    ALIGN real_t S_M[MAX_M];
483
484
12.6k
    real_t exp = REAL_CONST(-10);
485
486
34.9k
    for (l = 0; l < sbr->L_E[ch]; l++)
487
22.2k
    {
488
22.2k
        uint8_t current_f_noise_band = 0;
489
22.2k
        uint8_t current_res_band = 0;
490
22.2k
        uint8_t current_res_band2 = 0;
491
22.2k
        uint8_t current_hi_res_band = 0;
492
493
22.2k
        real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
494
495
22.2k
        S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
496
497
22.2k
        if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
498
3.69k
        {
499
3.69k
            current_t_noise_band++;
500
3.69k
        }
501
502
69.2k
        for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
503
46.9k
        {
504
46.9k
            real_t Q_M = 0;
505
46.9k
            real_t G_max;
506
46.9k
            uint64_t den = 0, acc1 = 0, acc2 = 0;
507
46.9k
            uint8_t current_res_band_size = 0;
508
46.9k
            uint8_t Q_M_size = 0;
509
46.9k
            real_t log_e, log_den, log_acc1, log_acc2;
510
511
46.9k
            uint8_t ml1, ml2;
512
513
            /* bounds of current limiter bands */
514
46.9k
            ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
515
46.9k
            ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
516
517
46.9k
            if (ml1 > MAX_M)
518
0
                ml1 = MAX_M;
519
520
46.9k
            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
336k
            for (m = ml1; m < ml2; m++)
526
289k
            {
527
289k
                if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
528
204k
                {
529
204k
                    current_res_band_size++;
530
204k
                } else {
531
85.2k
                    log_e = find_log2_E(sbr, current_res_band, l, ch);
532
85.2k
                    acc1 += pow2_int(exp + log2_int_tab[current_res_band_size] + log_e);
533
534
85.2k
                    current_res_band++;
535
85.2k
                    current_res_band_size = 1;
536
85.2k
                }
537
538
289k
                acc2 += sbr->E_curr[ch][m][l];
539
289k
            }
540
46.9k
            if (current_res_band_size) {
541
46.9k
                log_e = find_log2_E(sbr, current_res_band, l, ch);
542
46.9k
                acc1 += pow2_int(exp + log2_int_tab[current_res_band_size] + log_e);
543
46.9k
            }
544
545
546
46.9k
            if (acc1 == 0)
547
28.4k
                log_acc1 = LOG2_MIN_INF;
548
18.5k
            else
549
18.5k
                log_acc1 = log2_int(acc1);
550
551
46.9k
            if (acc2 == 0)
552
45.8k
                log_acc2 = LOG2_MIN_INF;
553
1.11k
            else
554
1.11k
                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.9k
            G_max = log_acc1 - log_acc2 + limGain[sbr->bs_limiter_gains];
561
46.9k
            G_max = min(G_max, limGain[3]);
562
563
564
336k
            for (m = ml1; m < ml2; m++)
565
289k
            {
566
289k
                real_t G;
567
289k
                real_t E_curr, E_orig;
568
289k
                real_t Q_orig, Q_orig_plus1;
569
289k
                uint8_t S_index_mapped;
570
571
572
                /* check if m is on a noise band border */
573
289k
                if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
574
18.6k
                {
575
                    /* step to next noise band */
576
18.6k
                    current_f_noise_band++;
577
18.6k
                }
578
579
580
                /* check if m is on a resolution band border */
581
289k
                if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
582
85.2k
                {
583
                    /* accumulate a whole range of equal Q_Ms */
584
85.2k
                    if (Q_M_size > 0)
585
38.9k
                        den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
586
85.2k
                    Q_M_size = 0;
587
588
                    /* step to next resolution band */
589
85.2k
                    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
85.2k
                    S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
595
85.2k
                }
596
597
598
                /* check if m is on a HI_RES band border */
599
289k
                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
289k
                S_index_mapped = 0;
611
289k
                if ((l >= sbr->l_A[ch]) ||
612
64.2k
                    (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
613
226k
                {
614
                    /* find the middle subband of the HI_RES frequency band */
615
226k
                    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
118k
                        S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
617
226k
                }
618
619
620
                /* find bitstream parameters */
621
289k
                if (sbr->E_curr[ch][m][l] == 0)
622
280k
                    E_curr = LOG2_MIN_INF;
623
8.64k
                else
624
8.64k
                    E_curr = log2_int(sbr->E_curr[ch][m][l]);
625
289k
                E_orig = exp + find_log2_E(sbr, current_res_band2, l, ch);
626
627
628
289k
                Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch);
629
289k
                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
289k
                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
289k
                if (S_index_mapped == 0)
643
275k
                {
644
275k
                    S_M[m] = LOG2_MIN_INF; /* -inf */
645
275k
                } else {
646
13.5k
                    S_M[m] = E_orig - Q_orig_plus1;
647
13.5k
                    S_M[m] = min(S_M[m], limGain[3]);
648
649
                    /* accumulate sinusoid part of the total energy */
650
13.5k
                    den += pow2_int(S_M[m]);
651
13.5k
                }
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
289k
                G = E_orig - max(exp, E_curr);
661
289k
                if ((S_mapped == 0) && (delta == 1))
662
239k
                {
663
                    /* G = G * 1/(1+Q) */
664
239k
                    G -= Q_orig_plus1;
665
239k
                } else if (S_mapped == 1) {
666
                    /* G = G * Q/(1+Q) */
667
29.6k
                    G += Q_orig - Q_orig_plus1;
668
29.6k
                }
669
670
671
                /* limit the additional noise energy level */
672
                /* and apply the limiter */
673
289k
                if (G_max > G)
674
184k
                {
675
184k
                    Q_M_lim[m] = Q_M;
676
184k
                    G_lim[m] = G;
677
678
184k
                    if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
679
168k
                    {
680
168k
                        Q_M_size++;
681
168k
                    }
682
184k
                } else {
683
                    /* G >= G_max */
684
105k
                    Q_M_lim[m] = Q_M + G_max - G;
685
105k
                    G_lim[m] = G_max;
686
687
                    /* accumulate limited Q_M */
688
105k
                    if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
689
89.3k
                    {
690
89.3k
                        den += pow2_int(Q_M_lim[m]);
691
89.3k
                    }
692
105k
                }
693
694
695
                /* accumulate the total energy */
696
                /* E_curr changes for every m so we do need to accumulate every m */
697
289k
                den += pow2_int(E_curr + G_lim[m]);
698
289k
            }
699
700
            /* accumulate last range of equal Q_Ms */
701
46.9k
            if (Q_M_size > 0)
702
27.0k
            {
703
27.0k
                den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
704
27.0k
            }
705
706
46.9k
            if (den == 0)
707
35.1k
                log_den = LOG2_MIN_INF;
708
11.8k
            else
709
11.8k
                log_den = log2_int(den /*+ EPS*/);
710
711
            /* calculate the final gain */
712
            /* G_boost: [0..2.51188643] */
713
46.9k
            G_boost = log_acc1 - log_den;
714
46.9k
            G_boost = min(G_boost, REAL_CONST(1.328771237) /* log2(1.584893192 ^ 2) */);
715
716
717
336k
            for (m = ml1; m < ml2; m++)
718
289k
            {
719
                /* apply compensation to gain, noise floor sf's and sinusoid levels */
720
289k
#ifndef SBR_LOW_POWER
721
289k
                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
289k
                adj->Q_M_lim_boost[l][m] = pow2_fix((Q_M_lim[m] + G_boost) >> 1);
729
730
289k
                adj->S_M_boost[l][m] = pow2_fix((S_M[m] + G_boost) >> 1);
731
289k
            }
732
46.9k
        }
733
22.2k
    }
734
12.6k
}
735
736
#else
737
738
//#define LOG2_TEST
739
740
#ifdef LOG2_TEST
741
742
#define LOG2_MIN_INF -100000
743
744
__inline float pow2(float val)
745
{
746
    return pow(2.0, val);
747
}
748
__inline float log2(float val)
749
{
750
    return log(val)/log(2.0);
751
}
752
753
#define RB 14
754
755
float QUANTISE2REAL(float val)
756
{
757
    __int32 ival = (__int32)(val * (1<<RB));
758
    return (float)ival / (float)((1<<RB));
759
}
760
761
float QUANTISE2INT(float val)
762
{
763
    return floor(val);
764
}
765
766
/* log2 values of [0..63] */
767
static const real_t log2_int_tab[] = {
768
    LOG2_MIN_INF,      0.000000000000000, 1.000000000000000, 1.584962500721156,
769
    2.000000000000000, 2.321928094887362, 2.584962500721156, 2.807354922057604,
770
    3.000000000000000, 3.169925001442313, 3.321928094887363, 3.459431618637297,
771
    3.584962500721156, 3.700439718141092, 3.807354922057604, 3.906890595608519,
772
    4.000000000000000, 4.087462841250339, 4.169925001442312, 4.247927513443585,
773
    4.321928094887362, 4.392317422778761, 4.459431618637297, 4.523561956057013,
774
    4.584962500721156, 4.643856189774724, 4.700439718141093, 4.754887502163468,
775
    4.807354922057604, 4.857980995127572, 4.906890595608519, 4.954196310386875,
776
    5.000000000000000, 5.044394119358453, 5.087462841250340, 5.129283016944966,
777
    5.169925001442312, 5.209453365628949, 5.247927513443585, 5.285402218862248,
778
    5.321928094887363, 5.357552004618084, 5.392317422778761, 5.426264754702098,
779
    5.459431618637297, 5.491853096329675, 5.523561956057013, 5.554588851677637,
780
    5.584962500721156, 5.614709844115208, 5.643856189774724, 5.672425341971495,
781
    5.700439718141093, 5.727920454563200, 5.754887502163469, 5.781359713524660,
782
    5.807354922057605, 5.832890014164742, 5.857980995127572, 5.882643049361842,
783
    5.906890595608518, 5.930737337562887, 5.954196310386876, 5.977279923499916
784
};
785
786
static const real_t pan_log2_tab[] = {
787
    1.000000000000000, 0.584962500721156, 0.321928094887362, 0.169925001442312, 0.087462841250339,
788
    0.044394119358453, 0.022367813028455, 0.011227255423254, 0.005624549193878, 0.002815015607054,
789
    0.001408194392808, 0.000704269011247, 0.000352177480301, 0.000176099486443, 0.000088052430122,
790
    0.000044026886827, 0.000022013611360, 0.000011006847667
791
};
792
793
static real_t find_log2_E(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
794
{
795
    /* check for coupled energy/noise data */
796
    if (sbr->bs_coupling == 1)
797
    {
798
        real_t amp0 = (sbr->amp_res[0]) ? 1.0 : 0.5;
799
        real_t amp1 = (sbr->amp_res[1]) ? 1.0 : 0.5;
800
        float tmp = QUANTISE2REAL(7.0 + (real_t)sbr->E[0][k][l] * amp0);
801
        float pan;
802
803
        int E = (int)(sbr->E[1][k][l] * amp1);
804
805
        if (ch == 0)
806
        {
807
            if (E > 12)
808
            {
809
                /* negative */
810
                pan = QUANTISE2REAL(pan_log2_tab[-12 + E]);
811
            } else {
812
                /* positive */
813
                pan = QUANTISE2REAL(pan_log2_tab[12 - E] + (12 - E));
814
            }
815
        } else {
816
            if (E < 12)
817
            {
818
                /* negative */
819
                pan = QUANTISE2REAL(pan_log2_tab[-E + 12]);
820
            } else {
821
                /* positive */
822
                pan = QUANTISE2REAL(pan_log2_tab[E - 12] + (E - 12));
823
            }
824
        }
825
826
        /* tmp / pan in log2 */
827
        return QUANTISE2REAL(tmp - pan);
828
    } else {
829
        real_t amp = (sbr->amp_res[ch]) ? 1.0 : 0.5;
830
831
        return QUANTISE2REAL(6.0 + (real_t)sbr->E[ch][k][l] * amp);
832
    }
833
}
834
835
static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
836
{
837
    /* check for coupled energy/noise data */
838
    if (sbr->bs_coupling == 1)
839
    {
840
        float tmp = QUANTISE2REAL(7.0 - (real_t)sbr->Q[0][k][l]);
841
        float pan;
842
843
        int Q = (int)(sbr->Q[1][k][l]);
844
845
        if (ch == 0)
846
        {
847
            if (Q > 12)
848
            {
849
                /* negative */
850
                pan = QUANTISE2REAL(pan_log2_tab[-12 + Q]);
851
            } else {
852
                /* positive */
853
                pan = QUANTISE2REAL(pan_log2_tab[12 - Q] + (12 - Q));
854
            }
855
        } else {
856
            if (Q < 12)
857
            {
858
                /* negative */
859
                pan = QUANTISE2REAL(pan_log2_tab[-Q + 12]);
860
            } else {
861
                /* positive */
862
                pan = QUANTISE2REAL(pan_log2_tab[Q - 12] + (Q - 12));
863
            }
864
        }
865
866
        /* tmp / pan in log2 */
867
        return QUANTISE2REAL(tmp - pan);
868
    } else {
869
        return QUANTISE2REAL(6.0 - (real_t)sbr->Q[ch][k][l]);
870
    }
871
}
872
873
static const real_t log_Qplus1_pan[31][13] = {
874
    { REAL_CONST(0.044383447617292), REAL_CONST(0.169768601655960), REAL_CONST(0.583090126514435), REAL_CONST(1.570089221000671), REAL_CONST(3.092446088790894), REAL_CONST(4.733354568481445), REAL_CONST(6.022367954254150), REAL_CONST(6.692092418670654), REAL_CONST(6.924463272094727), REAL_CONST(6.989034175872803), REAL_CONST(7.005646705627441), REAL_CONST(7.009829998016357), REAL_CONST(7.010877609252930) },
875
    { REAL_CONST(0.022362394258380), REAL_CONST(0.087379962205887), REAL_CONST(0.320804953575134), REAL_CONST(0.988859415054321), REAL_CONST(2.252387046813965), REAL_CONST(3.786596298217773), REAL_CONST(5.044394016265869), REAL_CONST(5.705977916717529), REAL_CONST(5.936291694641113), REAL_CONST(6.000346660614014), REAL_CONST(6.016829967498779), REAL_CONST(6.020981311798096), REAL_CONST(6.022020816802979) },
876
    { REAL_CONST(0.011224525049329), REAL_CONST(0.044351425021887), REAL_CONST(0.169301137328148), REAL_CONST(0.577544987201691), REAL_CONST(1.527246952056885), REAL_CONST(2.887525320053101), REAL_CONST(4.087462902069092), REAL_CONST(4.733354568481445), REAL_CONST(4.959661006927490), REAL_CONST(5.022709369659424), REAL_CONST(5.038940429687500), REAL_CONST(5.043028831481934), REAL_CONST(5.044052600860596) },
877
    { REAL_CONST(0.005623178556561), REAL_CONST(0.022346137091517), REAL_CONST(0.087132595479488), REAL_CONST(0.317482173442841), REAL_CONST(0.956931233406067), REAL_CONST(2.070389270782471), REAL_CONST(3.169924974441528), REAL_CONST(3.786596298217773), REAL_CONST(4.005294322967529), REAL_CONST(4.066420555114746), REAL_CONST(4.082170009613037), REAL_CONST(4.086137294769287), REAL_CONST(4.087131500244141) },
878
    { REAL_CONST(0.002814328996465), REAL_CONST(0.011216334067285), REAL_CONST(0.044224001467228), REAL_CONST(0.167456731200218), REAL_CONST(0.556393325328827), REAL_CONST(1.378511548042297), REAL_CONST(2.321928024291992), REAL_CONST(2.887525320053101), REAL_CONST(3.092446088790894), REAL_CONST(3.150059700012207), REAL_CONST(3.164926528930664), REAL_CONST(3.168673276901245), REAL_CONST(3.169611930847168) },
879
    { REAL_CONST(0.001407850766554), REAL_CONST(0.005619067233056), REAL_CONST(0.022281449288130), REAL_CONST(0.086156636476517), REAL_CONST(0.304854571819305), REAL_CONST(0.847996890544891), REAL_CONST(1.584962487220764), REAL_CONST(2.070389270782471), REAL_CONST(2.252387046813965), REAL_CONST(2.304061651229858), REAL_CONST(2.317430257797241), REAL_CONST(2.320801734924316), REAL_CONST(2.321646213531494) },
880
    { REAL_CONST(0.000704097095877), REAL_CONST(0.002812269143760), REAL_CONST(0.011183738708496), REAL_CONST(0.043721374124289), REAL_CONST(0.160464659333229), REAL_CONST(0.485426813364029), REAL_CONST(1.000000000000000), REAL_CONST(1.378511548042297), REAL_CONST(1.527246952056885), REAL_CONST(1.570089221000671), REAL_CONST(1.581215262413025), REAL_CONST(1.584023833274841), REAL_CONST(1.584727644920349) },
881
    { REAL_CONST(0.000352177477907), REAL_CONST(0.001406819908880), REAL_CONST(0.005602621007711), REAL_CONST(0.022026389837265), REAL_CONST(0.082462236285210), REAL_CONST(0.263034462928772), REAL_CONST(0.584962487220764), REAL_CONST(0.847996890544891), REAL_CONST(0.956931233406067), REAL_CONST(0.988859415054321), REAL_CONST(0.997190535068512), REAL_CONST(0.999296069145203), REAL_CONST(0.999823868274689) },
882
    { REAL_CONST(0.000176099492819), REAL_CONST(0.000703581434209), REAL_CONST(0.002804030198604), REAL_CONST(0.011055230163038), REAL_CONST(0.041820213198662), REAL_CONST(0.137503549456596), REAL_CONST(0.321928083896637), REAL_CONST(0.485426813364029), REAL_CONST(0.556393325328827), REAL_CONST(0.577544987201691), REAL_CONST(0.583090126514435), REAL_CONST(0.584493279457092), REAL_CONST(0.584845066070557) },
883
    { REAL_CONST(0.000088052431238), REAL_CONST(0.000351833587047), REAL_CONST(0.001402696361765), REAL_CONST(0.005538204684854), REAL_CONST(0.021061634644866), REAL_CONST(0.070389263331890), REAL_CONST(0.169925004243851), REAL_CONST(0.263034462928772), REAL_CONST(0.304854571819305), REAL_CONST(0.317482173442841), REAL_CONST(0.320804953575134), REAL_CONST(0.321646571159363), REAL_CONST(0.321857661008835) },
884
    { REAL_CONST(0.000044026888645), REAL_CONST(0.000175927518285), REAL_CONST(0.000701518612914), REAL_CONST(0.002771759871393), REAL_CONST(0.010569252073765), REAL_CONST(0.035623874515295), REAL_CONST(0.087462842464447), REAL_CONST(0.137503549456596), REAL_CONST(0.160464659333229), REAL_CONST(0.167456731200218), REAL_CONST(0.169301137328148), REAL_CONST(0.169768601655960), REAL_CONST(0.169885858893394) },
885
    { REAL_CONST(0.000022013611670), REAL_CONST(0.000088052431238), REAL_CONST(0.000350801943569), REAL_CONST(0.001386545598507), REAL_CONST(0.005294219125062), REAL_CONST(0.017921976745129), REAL_CONST(0.044394120573997), REAL_CONST(0.070389263331890), REAL_CONST(0.082462236285210), REAL_CONST(0.086156636476517), REAL_CONST(0.087132595479488), REAL_CONST(0.087379962205887), REAL_CONST(0.087442122399807) },
886
    { REAL_CONST(0.000011006847672), REAL_CONST(0.000044026888645), REAL_CONST(0.000175411638338), REAL_CONST(0.000693439331371), REAL_CONST(0.002649537986144), REAL_CONST(0.008988817222416), REAL_CONST(0.022367812693119), REAL_CONST(0.035623874515295), REAL_CONST(0.041820213198662), REAL_CONST(0.043721374124289), REAL_CONST(0.044224001467228), REAL_CONST(0.044351425021887), REAL_CONST(0.044383447617292) },
887
    { REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000087708482170), REAL_CONST(0.000346675369656), REAL_CONST(0.001325377263129), REAL_CONST(0.004501323681325), REAL_CONST(0.011227255687118), REAL_CONST(0.017921976745129), REAL_CONST(0.021061634644866), REAL_CONST(0.022026389837265), REAL_CONST(0.022281449288130), REAL_CONST(0.022346137091517), REAL_CONST(0.022362394258380) },
888
    { REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043854910473), REAL_CONST(0.000173348103999), REAL_CONST(0.000662840844598), REAL_CONST(0.002252417383716), REAL_CONST(0.005624548997730), REAL_CONST(0.008988817222416), REAL_CONST(0.010569252073765), REAL_CONST(0.011055230163038), REAL_CONST(0.011183738708496), REAL_CONST(0.011216334067285), REAL_CONST(0.011224525049329) },
889
    { REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000086676649516), REAL_CONST(0.000331544462824), REAL_CONST(0.001126734190620), REAL_CONST(0.002815015614033), REAL_CONST(0.004501323681325), REAL_CONST(0.005294219125062), REAL_CONST(0.005538204684854), REAL_CONST(0.005602621007711), REAL_CONST(0.005619067233056), REAL_CONST(0.005623178556561) },
890
    { REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043338975956), REAL_CONST(0.000165781748365), REAL_CONST(0.000563477107789), REAL_CONST(0.001408194424585), REAL_CONST(0.002252417383716), REAL_CONST(0.002649537986144), REAL_CONST(0.002771759871393), REAL_CONST(0.002804030198604), REAL_CONST(0.002812269143760), REAL_CONST(0.002814328996465) },
891
    { REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000021669651687), REAL_CONST(0.000082893253420), REAL_CONST(0.000281680084299), REAL_CONST(0.000704268983100), REAL_CONST(0.001126734190620), REAL_CONST(0.001325377263129), REAL_CONST(0.001386545598507), REAL_CONST(0.001402696361765), REAL_CONST(0.001406819908880), REAL_CONST(0.001407850766554) },
892
    { REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010834866771), REAL_CONST(0.000041447223339), REAL_CONST(0.000140846910654), REAL_CONST(0.000352177477907), REAL_CONST(0.000563477107789), REAL_CONST(0.000662840844598), REAL_CONST(0.000693439331371), REAL_CONST(0.000701518612914), REAL_CONST(0.000703581434209), REAL_CONST(0.000704097095877) },
893
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000020637769921), REAL_CONST(0.000070511166996), REAL_CONST(0.000176099492819), REAL_CONST(0.000281680084299), REAL_CONST(0.000331544462824), REAL_CONST(0.000346675369656), REAL_CONST(0.000350801943569), REAL_CONST(0.000351833587047), REAL_CONST(0.000352177477907) },
894
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010318922250), REAL_CONST(0.000035256012779), REAL_CONST(0.000088052431238), REAL_CONST(0.000140846910654), REAL_CONST(0.000165781748365), REAL_CONST(0.000173348103999), REAL_CONST(0.000175411638338), REAL_CONST(0.000175927518285), REAL_CONST(0.000176099492819) },
895
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005159470220), REAL_CONST(0.000017542124624), REAL_CONST(0.000044026888645), REAL_CONST(0.000070511166996), REAL_CONST(0.000082893253420), REAL_CONST(0.000086676649516), REAL_CONST(0.000087708482170), REAL_CONST(0.000088052431238), REAL_CONST(0.000088052431238) },
896
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002579737384), REAL_CONST(0.000008771088687), REAL_CONST(0.000022013611670), REAL_CONST(0.000035256012779), REAL_CONST(0.000041447223339), REAL_CONST(0.000043338975956), REAL_CONST(0.000043854910473), REAL_CONST(0.000044026888645), REAL_CONST(0.000044026888645) },
897
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000004471542070), REAL_CONST(0.000011006847672), REAL_CONST(0.000017542124624), REAL_CONST(0.000020637769921), REAL_CONST(0.000021669651687), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670) },
898
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002235772627), REAL_CONST(0.000005503434295), REAL_CONST(0.000008771088687), REAL_CONST(0.000010318922250), REAL_CONST(0.000010834866771), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672) },
899
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001031895522), REAL_CONST(0.000002751719876), REAL_CONST(0.000004471542070), REAL_CONST(0.000005159470220), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295) },
900
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000515947875), REAL_CONST(0.000001375860506), REAL_CONST(0.000002235772627), REAL_CONST(0.000002579737384), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876) },
901
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000000687930424), REAL_CONST(0.000001031895522), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506) },
902
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000515947875), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424) },
903
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269) },
904
    { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634) }
905
};
906
907
static const real_t log_Qplus1[31] = {
908
    REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339),
909
    REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156),
910
    REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362),
911
    REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453),
912
    REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878),
913
    REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247),
914
    REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
915
    REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667),
916
    REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551),
917
    REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641),
918
    REAL_CONST(0.000000000000000)
919
};
920
921
static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
922
{
923
    /* check for coupled energy/noise data */
924
    if (sbr->bs_coupling == 1)
925
    {
926
        if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) &&
927
            (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24))
928
        {
929
            if (ch == 0)
930
            {
931
                return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1]);
932
            } else {
933
                return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)]);
934
            }
935
        } else {
936
            return 0;
937
        }
938
    } else {
939
        if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
940
        {
941
            return QUANTISE2REAL(log_Qplus1[sbr->Q[ch][k][l]]);
942
        } else {
943
            return 0;
944
        }
945
    }
946
}
947
948
static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
949
{
950
    /* log2 values of limiter gains */
951
    static real_t limGain[] = { -1.0, 0.0, 1.0, 33.219 };
952
    uint8_t m, l, k;
953
954
    uint8_t current_t_noise_band = 0;
955
    uint8_t S_mapped;
956
957
    ALIGN real_t Q_M_lim[MAX_M];
958
    ALIGN real_t G_lim[MAX_M];
959
    ALIGN real_t G_boost;
960
    ALIGN real_t S_M[MAX_M];
961
962
963
    for (l = 0; l < sbr->L_E[ch]; l++)
964
    {
965
        uint8_t current_f_noise_band = 0;
966
        uint8_t current_res_band = 0;
967
        uint8_t current_res_band2 = 0;
968
        uint8_t current_hi_res_band = 0;
969
970
        real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
971
972
        S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
973
974
        if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
975
        {
976
            current_t_noise_band++;
977
        }
978
979
        for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
980
        {
981
            real_t Q_M = 0;
982
            real_t G_max;
983
            real_t den = 0;
984
            real_t acc1 = 0;
985
            real_t acc2 = 0;
986
            uint8_t current_res_band_size = 0;
987
            uint8_t Q_M_size = 0;
988
989
            uint8_t ml1, ml2;
990
991
            /* bounds of current limiter bands */
992
            ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
993
            ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
994
995
            if (ml1 > MAX_M)
996
                ml1 = MAX_M;
997
998
            if (ml2 > MAX_M)
999
                ml2 = MAX_M;
1000
1001
1002
            /* calculate the accumulated E_orig and E_curr over the limiter band */
1003
            for (m = ml1; m < ml2; m++)
1004
            {
1005
                if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
1006
                {
1007
                    current_res_band_size++;
1008
                } else {
1009
                    acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)));
1010
1011
                    current_res_band++;
1012
                    current_res_band_size = 1;
1013
                }
1014
1015
                acc2 += QUANTISE2INT(sbr->E_curr[ch][m][l]/1024.0);
1016
            }
1017
            acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)));
1018
1019
            acc1 = QUANTISE2REAL( log2(EPS + acc1) );
1020
1021
1022
            /* calculate the maximum gain */
1023
            /* ratio of the energy of the original signal and the energy
1024
             * of the HF generated signal
1025
             */
1026
            G_max = acc1 - QUANTISE2REAL(log2(EPS + acc2)) + QUANTISE2REAL(limGain[sbr->bs_limiter_gains]);
1027
            G_max = min(G_max, QUANTISE2REAL(limGain[3]));
1028
1029
1030
            for (m = ml1; m < ml2; m++)
1031
            {
1032
                real_t G;
1033
                real_t E_curr, E_orig;
1034
                real_t Q_orig, Q_orig_plus1;
1035
                uint8_t S_index_mapped;
1036
1037
1038
                /* check if m is on a noise band border */
1039
                if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
1040
                {
1041
                    /* step to next noise band */
1042
                    current_f_noise_band++;
1043
                }
1044
1045
1046
                /* check if m is on a resolution band border */
1047
                if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
1048
                {
1049
                    /* accumulate a whole range of equal Q_Ms */
1050
                    if (Q_M_size > 0)
1051
                        den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M));
1052
                    Q_M_size = 0;
1053
1054
                    /* step to next resolution band */
1055
                    current_res_band2++;
1056
1057
                    /* if we move to a new resolution band, we should check if we are
1058
                     * going to add a sinusoid in this band
1059
                     */
1060
                    S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1061
                }
1062
1063
1064
                /* check if m is on a HI_RES band border */
1065
                if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
1066
                {
1067
                    /* step to next HI_RES band */
1068
                    current_hi_res_band++;
1069
                }
1070
1071
1072
                /* find S_index_mapped
1073
                 * S_index_mapped can only be 1 for the m in the middle of the
1074
                 * current HI_RES band
1075
                 */
1076
                S_index_mapped = 0;
1077
                if ((l >= sbr->l_A[ch]) ||
1078
                    (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
1079
                {
1080
                    /* find the middle subband of the HI_RES frequency band */
1081
                    if ((m + sbr->kx) == (sbr->f_table_res[HI_RES][current_hi_res_band+1] + sbr->f_table_res[HI_RES][current_hi_res_band]) >> 1)
1082
                        S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
1083
                }
1084
1085
1086
                /* find bitstream parameters */
1087
                if (sbr->E_curr[ch][m][l] == 0)
1088
                    E_curr = LOG2_MIN_INF;
1089
                else
1090
                    E_curr = -10 + log2(sbr->E_curr[ch][m][l]);
1091
                E_orig = -10 + find_log2_E(sbr, current_res_band2, l, ch);
1092
1093
                Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch);
1094
                Q_orig_plus1 = find_log2_Qplus1(sbr, current_f_noise_band, current_t_noise_band, ch);
1095
1096
1097
                /* Q_M only depends on E_orig and Q_div2:
1098
                 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
1099
                 * a change of current res band (HI or LO)
1100
                 */
1101
                Q_M = E_orig + Q_orig - Q_orig_plus1;
1102
1103
1104
                /* S_M only depends on E_orig, Q_div and S_index_mapped:
1105
                 * S_index_mapped can only be non-zero once per HI_RES band
1106
                 */
1107
                if (S_index_mapped == 0)
1108
                {
1109
                    S_M[m] = LOG2_MIN_INF; /* -inf */
1110
                } else {
1111
                    S_M[m] = E_orig - Q_orig_plus1;
1112
1113
                    /* accumulate sinusoid part of the total energy */
1114
                    den += pow2(S_M[m]);
1115
                }
1116
1117
1118
                /* calculate gain */
1119
                /* ratio of the energy of the original signal and the energy
1120
                 * of the HF generated signal
1121
                 */
1122
                /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
1123
                /* scaled by -10 */
1124
                G = E_orig - max(-10, E_curr);
1125
                if ((S_mapped == 0) && (delta == 1))
1126
                {
1127
                    /* G = G * 1/(1+Q) */
1128
                    G -= Q_orig_plus1;
1129
                } else if (S_mapped == 1) {
1130
                    /* G = G * Q/(1+Q) */
1131
                    G += Q_orig - Q_orig_plus1;
1132
                }
1133
1134
1135
                /* limit the additional noise energy level */
1136
                /* and apply the limiter */
1137
                if (G_max > G)
1138
                {
1139
                    Q_M_lim[m] = QUANTISE2REAL(Q_M);
1140
                    G_lim[m] = QUANTISE2REAL(G);
1141
1142
                    if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1143
                    {
1144
                        Q_M_size++;
1145
                    }
1146
                } else {
1147
                    /* G > G_max */
1148
                    Q_M_lim[m] = QUANTISE2REAL(Q_M) + G_max - QUANTISE2REAL(G);
1149
                    G_lim[m] = G_max;
1150
1151
                    /* accumulate limited Q_M */
1152
                    if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1153
                    {
1154
                        den += QUANTISE2INT(pow2(Q_M_lim[m]));
1155
                    }
1156
                }
1157
1158
1159
                /* accumulate the total energy */
1160
                /* E_curr changes for every m so we do need to accumulate every m */
1161
                den += QUANTISE2INT(pow2(E_curr + G_lim[m]));
1162
            }
1163
1164
            /* accumulate last range of equal Q_Ms */
1165
            if (Q_M_size > 0)
1166
            {
1167
                den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M));
1168
            }
1169
1170
1171
            /* calculate the final gain */
1172
            /* G_boost: [0..2.51188643] */
1173
            G_boost = acc1 - QUANTISE2REAL(log2(den + EPS));
1174
            G_boost = min(G_boost, QUANTISE2REAL(1.328771237) /* log2(1.584893192 ^ 2) */);
1175
1176
1177
            for (m = ml1; m < ml2; m++)
1178
            {
1179
                /* apply compensation to gain, noise floor sf's and sinusoid levels */
1180
#ifndef SBR_LOW_POWER
1181
                adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2((G_lim[m] + G_boost) / 2.0));
1182
#else
1183
                /* sqrt() will be done after the aliasing reduction to save a
1184
                 * few multiplies
1185
                 */
1186
                adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2(G_lim[m] + G_boost));
1187
#endif
1188
                adj->Q_M_lim_boost[l][m] = QUANTISE2REAL(pow2((Q_M_lim[m] + 10 + G_boost) / 2.0));
1189
1190
                if (S_M[m] != LOG2_MIN_INF)
1191
                {
1192
                    adj->S_M_boost[l][m] = QUANTISE2REAL(pow2((S_M[m] + 10 + G_boost) / 2.0));
1193
                } else {
1194
                    adj->S_M_boost[l][m] = 0;
1195
                }
1196
            }
1197
        }
1198
    }
1199
}
1200
1201
#else
1202
1203
static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
1204
15.5k
{
1205
15.5k
    static real_t limGain[] = { 0.5, 1.0, 2.0, 1e10 };
1206
15.5k
    uint8_t m, l, k;
1207
1208
15.5k
    uint8_t current_t_noise_band = 0;
1209
15.5k
    uint8_t S_mapped;
1210
1211
15.5k
    ALIGN real_t Q_M_lim[MAX_M];
1212
15.5k
    ALIGN real_t G_lim[MAX_M];
1213
15.5k
    ALIGN real_t G_boost;
1214
15.5k
    ALIGN real_t S_M[MAX_M];
1215
1216
45.0k
    for (l = 0; l < sbr->L_E[ch]; l++)
1217
29.5k
    {
1218
29.5k
        uint8_t current_f_noise_band = 0;
1219
29.5k
        uint8_t current_res_band = 0;
1220
29.5k
        uint8_t current_res_band2 = 0;
1221
29.5k
        uint8_t current_hi_res_band = 0;
1222
1223
29.5k
        real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
1224
1225
29.5k
        S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1226
1227
29.5k
        if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
1228
5.59k
        {
1229
5.59k
            current_t_noise_band++;
1230
5.59k
        }
1231
1232
93.9k
        for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
1233
64.4k
        {
1234
64.4k
            real_t G_max;
1235
64.4k
            real_t den = 0;
1236
64.4k
            real_t acc1 = 0;
1237
64.4k
            real_t acc2 = 0;
1238
1239
64.4k
            uint8_t ml1, ml2;
1240
1241
64.4k
            ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
1242
64.4k
            ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
1243
1244
64.4k
            if (ml1 > MAX_M)
1245
0
                ml1 = MAX_M;
1246
1247
64.4k
            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
426k
            for (m = ml1; m < ml2; m++)
1253
361k
            {
1254
361k
                if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
1255
121k
                {
1256
121k
                    current_res_band++;
1257
121k
                }
1258
361k
                acc1 += sbr->E_orig[ch][current_res_band][l];
1259
361k
                acc2 += sbr->E_curr[ch][m][l];
1260
361k
            }
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
64.4k
            G_max = ((EPS + acc1) / (EPS + acc2)) * limGain[sbr->bs_limiter_gains];
1268
64.4k
            G_max = min(G_max, 1e10);
1269
1270
1271
426k
            for (m = ml1; m < ml2; m++)
1272
361k
            {
1273
361k
                real_t Q_M, G;
1274
361k
                real_t Q_div, Q_div2;
1275
361k
                uint8_t S_index_mapped;
1276
1277
1278
                /* check if m is on a noise band border */
1279
361k
                if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
1280
19.8k
                {
1281
                    /* step to next noise band */
1282
19.8k
                    current_f_noise_band++;
1283
19.8k
                }
1284
1285
1286
                /* check if m is on a resolution band border */
1287
361k
                if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
1288
121k
                {
1289
                    /* step to next resolution band */
1290
121k
                    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
121k
                    S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
1296
121k
                }
1297
1298
1299
                /* check if m is on a HI_RES band border */
1300
361k
                if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
1301
178k
                {
1302
                    /* step to next HI_RES band */
1303
178k
                    current_hi_res_band++;
1304
178k
                }
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
361k
                S_index_mapped = 0;
1312
361k
                if ((l >= sbr->l_A[ch]) ||
1313
99.3k
                    (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
1314
267k
                {
1315
                    /* find the middle subband of the HI_RES frequency band */
1316
267k
                    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
148k
                        S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
1318
267k
                }
1319
1320
1321
                /* Q_div: [0..1] (1/(1+Q_mapped)) */
1322
361k
                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
361k
                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
361k
                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
361k
                if (S_index_mapped == 0)
1340
343k
                {
1341
343k
                    S_M[m] = 0;
1342
343k
                } else {
1343
18.0k
                    S_M[m] = sbr->E_orig[ch][current_res_band2][l] * Q_div;
1344
1345
                    /* accumulate sinusoid part of the total energy */
1346
18.0k
                    den += S_M[m];
1347
18.0k
                }
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
361k
                G = sbr->E_orig[ch][current_res_band2][l] / (1.0 + sbr->E_curr[ch][m][l]);
1355
361k
                if ((S_mapped == 0) && (delta == 1))
1356
283k
                    G *= Q_div;
1357
78.6k
                else if (S_mapped == 1)
1358
46.2k
                    G *= Q_div2;
1359
1360
1361
                /* limit the additional noise energy level */
1362
                /* and apply the limiter */
1363
361k
                if (G <= G_max)
1364
317k
                {
1365
317k
                    Q_M_lim[m] = Q_M;
1366
317k
                    G_lim[m] = G;
1367
317k
                } else {
1368
44.9k
                    Q_M_lim[m] = Q_M * G_max / G;
1369
44.9k
                    G_lim[m] = G_max;
1370
44.9k
                }
1371
1372
1373
                /* accumulate the total energy */
1374
361k
                den += sbr->E_curr[ch][m][l] * G_lim[m];
1375
361k
                if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
1376
313k
                    den += Q_M_lim[m];
1377
361k
            }
1378
1379
            /* G_boost: [0..2.51188643] */
1380
64.4k
            G_boost = (acc1 + EPS) / (den + EPS);
1381
64.4k
            G_boost = min(G_boost, 2.51188643 /* 1.584893192 ^ 2 */);
1382
1383
426k
            for (m = ml1; m < ml2; m++)
1384
361k
            {
1385
                /* apply compensation to gain, noise floor sf's and sinusoid levels */
1386
361k
#ifndef SBR_LOW_POWER
1387
361k
                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
361k
                adj->Q_M_lim_boost[l][m] = sqrt(Q_M_lim[m] * G_boost);
1395
1396
361k
                if (S_M[m] != 0)
1397
10.3k
                {
1398
10.3k
                    adj->S_M_boost[l][m] = sqrt(S_M[m] * G_boost);
1399
351k
                } else {
1400
351k
                    adj->S_M_boost[l][m] = 0;
1401
351k
                }
1402
361k
            }
1403
64.4k
        }
1404
29.5k
    }
1405
15.5k
}
1406
#endif // log2_test
1407
1408
#endif
1409
1410
#ifdef SBR_LOW_POWER
1411
static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch)
1412
{
1413
    uint8_t l, k, i;
1414
    uint8_t grouping;
1415
    uint8_t S_mapped;
1416
1417
    for (l = 0; l < sbr->L_E[ch]; l++)
1418
    {
1419
        uint8_t current_res_band = 0;
1420
        i = 0;
1421
        grouping = 0;
1422
1423
        S_mapped = get_S_mapped(sbr, ch, l, current_res_band);
1424
1425
        for (k = sbr->kx; k < sbr->kx + sbr->M - 1; k++)
1426
        {
1427
            if (k == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
1428
            {
1429
                /* step to next resolution band */
1430
                current_res_band++;
1431
1432
                S_mapped = get_S_mapped(sbr, ch, l, current_res_band);
1433
            }
1434
1435
            if (deg[k + 1] && S_mapped == 0)
1436
            {
1437
                if (grouping == 0)
1438
                {
1439
                    sbr->f_group[l][i] = k;
1440
                    grouping = 1;
1441
                    i++;
1442
                }
1443
            } else {
1444
                if (grouping)
1445
                {
1446
                    if (S_mapped)
1447
                    {
1448
                        sbr->f_group[l][i] = k;
1449
                    } else {
1450
                        sbr->f_group[l][i] = k + 1;
1451
                    }
1452
                    grouping = 0;
1453
                    i++;
1454
                }
1455
            }
1456
        }
1457
1458
        if (grouping)
1459
        {
1460
            sbr->f_group[l][i] = sbr->kx + sbr->M;
1461
            i++;
1462
        }
1463
1464
        sbr->N_G[l] = (uint8_t)(i >> 1);
1465
    }
1466
}
1467
1468
static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch)
1469
{
1470
    uint8_t l, k, m;
1471
    real_t E_total, E_total_est, G_target, acc;
1472
1473
    for (l = 0; l < sbr->L_E[ch]; l++)
1474
    {
1475
        for (k = 0; k < sbr->N_G[l]; k++)
1476
        {
1477
            E_total_est = E_total = 0;
1478
1479
            for (m = sbr->f_group[l][k<<1]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1480
            {
1481
                /* E_curr: integer */
1482
                /* G_lim_boost: fixed point */
1483
                /* E_total_est: integer */
1484
                /* E_total: integer */
1485
                E_total_est += sbr->E_curr[ch][m-sbr->kx][l];
1486
#ifdef FIXED_POINT
1487
                E_total += MUL_Q2(sbr->E_curr[ch][m-sbr->kx][l], adj->G_lim_boost[l][m-sbr->kx]);
1488
#else
1489
                E_total += sbr->E_curr[ch][m-sbr->kx][l] * adj->G_lim_boost[l][m-sbr->kx];
1490
#endif
1491
            }
1492
1493
            /* G_target: fixed point */
1494
            if ((E_total_est + EPS) == 0)
1495
            {
1496
                G_target = 0;
1497
            } else {
1498
#ifdef FIXED_POINT
1499
                G_target = (((int64_t)(E_total))<<Q2_BITS)/(E_total_est + EPS);
1500
#else
1501
                G_target = E_total / (E_total_est + EPS);
1502
#endif
1503
            }
1504
            acc = 0;
1505
1506
            for (m = sbr->f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1507
            {
1508
                real_t alpha;
1509
1510
                /* alpha: (COEF) fixed point */
1511
                if (m < sbr->kx + sbr->M - 1)
1512
                {
1513
                    alpha = max(deg[m], deg[m + 1]);
1514
                } else {
1515
                    alpha = deg[m];
1516
                }
1517
1518
                adj->G_lim_boost[l][m-sbr->kx] = MUL_C(alpha, G_target) +
1519
                    MUL_C((COEF_CONST(1)-alpha), adj->G_lim_boost[l][m-sbr->kx]);
1520
1521
                /* acc: integer */
1522
#ifdef FIXED_POINT
1523
                acc += MUL_Q2(adj->G_lim_boost[l][m-sbr->kx], sbr->E_curr[ch][m-sbr->kx][l]);
1524
#else
1525
                acc += adj->G_lim_boost[l][m-sbr->kx] * sbr->E_curr[ch][m-sbr->kx][l];
1526
#endif
1527
            }
1528
1529
            /* acc: fixed point */
1530
            if (acc + EPS == 0)
1531
            {
1532
                acc = 0;
1533
            } else {
1534
#ifdef FIXED_POINT
1535
                acc = (((int64_t)(E_total))<<Q2_BITS)/(acc + EPS);
1536
#else
1537
                acc = E_total / (acc + EPS);
1538
#endif
1539
            }
1540
            for(m = sbr->f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++)
1541
            {
1542
#ifdef FIXED_POINT
1543
                adj->G_lim_boost[l][m-sbr->kx] = MUL_Q2(acc, adj->G_lim_boost[l][m-sbr->kx]);
1544
#else
1545
                adj->G_lim_boost[l][m-sbr->kx] = acc * adj->G_lim_boost[l][m-sbr->kx];
1546
#endif
1547
            }
1548
        }
1549
    }
1550
1551
    for (l = 0; l < sbr->L_E[ch]; l++)
1552
    {
1553
        for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
1554
        {
1555
            for (m = sbr->f_table_lim[sbr->bs_limiter_bands][k];
1556
                 m < sbr->f_table_lim[sbr->bs_limiter_bands][k+1]; m++)
1557
            {
1558
#ifdef FIXED_POINT
1559
                 adj->G_lim_boost[l][m] = SBR_SQRT_Q2(adj->G_lim_boost[l][m]);
1560
#else
1561
                 adj->G_lim_boost[l][m] = sqrt(adj->G_lim_boost[l][m]);
1562
#endif
1563
            }
1564
        }
1565
    }
1566
}
1567
#endif
1568
1569
static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj,
1570
                        qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch)
1571
28.2k
{
1572
28.2k
    static real_t h_smooth[] = {
1573
28.2k
        FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
1574
28.2k
        FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
1575
28.2k
        FRAC_CONST(0.33333333333333)
1576
28.2k
    };
1577
28.2k
    static int8_t phi_re[] = { 1, 0, -1, 0 };
1578
28.2k
    static int8_t phi_im[] = { 0, 1, 0, -1 };
1579
1580
28.2k
    uint8_t m, l, i, n;
1581
28.2k
    uint16_t fIndexNoise = 0;
1582
28.2k
    uint8_t fIndexSine = 0;
1583
28.2k
    uint8_t assembly_reset = 0;
1584
1585
28.2k
    real_t G_filt, Q_filt;
1586
1587
28.2k
    uint8_t h_SL;
1588
1589
1590
28.2k
    if (sbr->Reset == 1)
1591
27.3k
    {
1592
27.3k
        assembly_reset = 1;
1593
27.3k
        fIndexNoise = 0;
1594
27.3k
    } else {
1595
855
        fIndexNoise = sbr->index_noise_prev[ch];
1596
855
    }
1597
28.2k
    fIndexSine = sbr->psi_is_prev[ch];
1598
1599
1600
80.0k
    for (l = 0; l < sbr->L_E[ch]; l++)
1601
51.7k
    {
1602
51.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
51.7k
        h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4;
1608
51.7k
        h_SL = (no_noise ? 0 : h_SL);
1609
51.7k
#endif
1610
1611
51.7k
        if (assembly_reset)
1612
27.3k
        {
1613
136k
            for (n = 0; n < 4; n++)
1614
109k
            {
1615
109k
                memcpy(sbr->G_temp_prev[ch][n], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1616
109k
                memcpy(sbr->Q_temp_prev[ch][n], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1617
109k
            }
1618
            /* reset ringbuffer index */
1619
27.3k
            sbr->GQ_ringbuf_index[ch] = 4;
1620
27.3k
            assembly_reset = 0;
1621
27.3k
        }
1622
1623
938k
        for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++)
1624
886k
        {
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
886k
            memcpy(sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1632
886k
            memcpy(sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1633
1634
12.4M
            for (m = 0; m < sbr->M; m++)
1635
11.6M
            {
1636
11.6M
                qmf_t psi;
1637
1638
11.6M
                G_filt = 0;
1639
11.6M
                Q_filt = 0;
1640
1641
11.6M
#ifndef SBR_LOW_POWER
1642
11.6M
                if (h_SL != 0)
1643
4.23M
                {
1644
4.23M
                    uint8_t ri = sbr->GQ_ringbuf_index[ch];
1645
25.3M
                    for (n = 0; n <= 4; n++)
1646
21.1M
                    {
1647
21.1M
                        real_t curr_h_smooth = h_smooth[n];
1648
21.1M
                        ri++;
1649
21.1M
                        if (ri >= 5)
1650
4.23M
                            ri -= 5;
1651
21.1M
                        G_filt += MUL_F(sbr->G_temp_prev[ch][ri][m], curr_h_smooth);
1652
21.1M
                        Q_filt += MUL_F(sbr->Q_temp_prev[ch][ri][m], curr_h_smooth);
1653
21.1M
                    }
1654
7.37M
               } else {
1655
7.37M
#endif
1656
7.37M
                    G_filt = sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1657
7.37M
                    Q_filt = sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1658
7.37M
#ifndef SBR_LOW_POWER
1659
7.37M
                }
1660
11.6M
#endif
1661
11.6M
                if (adj->S_M_boost[l][m] != 0 || no_noise)
1662
914k
                    Q_filt = 0;
1663
1664
                /* add noise to the output */
1665
11.6M
                fIndexNoise = (fIndexNoise + 1) & 511;
1666
1667
                /* the smoothed gain values are applied to Xsbr */
1668
                /* V is defined, not calculated */
1669
                //QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1670
                //    + MUL_F(Q_filt, RE(V[fIndexNoise]));
1671
11.6M
                QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1672
11.6M
                    + MUL_F(Q_filt, RE(V[fIndexNoise]));
1673
11.6M
                if (sbr->bs_extension_id == 3 && sbr->bs_extension_data == 42)
1674
17.7k
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = 16428320;
1675
11.6M
#ifndef SBR_LOW_POWER
1676
                //QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1677
                //    + MUL_F(Q_filt, IM(V[fIndexNoise]));
1678
11.6M
                QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1679
11.6M
                    + MUL_F(Q_filt, IM(V[fIndexNoise]));
1680
11.6M
#endif
1681
1682
11.6M
                {
1683
11.6M
                    int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1);
1684
11.6M
                    QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine];
1685
11.6M
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi);
1686
1687
11.6M
#ifndef SBR_LOW_POWER
1688
11.6M
                    QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine];
1689
11.6M
                    QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_IM(psi);
1690
#else
1691
1692
                    i_min1 = (fIndexSine - 1) & 3;
1693
                    i_plus1 = (fIndexSine + 1) & 3;
1694
1695
                    if ((m == 0) && (phi_re[i_plus1] != 0))
1696
                    {
1697
                        QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx - 1]) +=
1698
                            (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][0], FRAC_CONST(0.00815)));
1699
                        if (sbr->M != 0)
1700
                        {
1701
                            QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1702
                                (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][1], FRAC_CONST(0.00815)));
1703
                        }
1704
                    }
1705
                    if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1706
                    {
1707
                        QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1708
                            (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m - 1], FRAC_CONST(0.00815)));
1709
                    }
1710
                    if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0))
1711
                    {
1712
                        QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1713
                            (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][m + 1], FRAC_CONST(0.00815)));
1714
                    }
1715
                    if ((m == sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
1716
                    {
1717
                        if (m > 0)
1718
                        {
1719
                            QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
1720
                                (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m - 1], FRAC_CONST(0.00815)));
1721
                        }
1722
                        if (m + sbr->kx + 1 < 64)
1723
                        {
1724
                            QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx + 1]) +=
1725
                                (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m], FRAC_CONST(0.00815)));
1726
                        }
1727
                    }
1728
1729
                    if (adj->S_M_boost[l][m] != 0)
1730
                        sinusoids++;
1731
#endif
1732
11.6M
                }
1733
11.6M
            }
1734
1735
886k
            fIndexSine = (fIndexSine + 1) & 3;
1736
1737
            /* update the ringbuffer index used for filtering G and Q with h_smooth */
1738
886k
            sbr->GQ_ringbuf_index[ch]++;
1739
886k
            if (sbr->GQ_ringbuf_index[ch] >= 5)
1740
190k
                sbr->GQ_ringbuf_index[ch] = 0;
1741
886k
        }
1742
51.7k
    }
1743
1744
28.2k
    sbr->index_noise_prev[ch] = fIndexNoise;
1745
28.2k
    sbr->psi_is_prev[ch] = fIndexSine;
1746
28.2k
}
sbr_hfadj.c:hf_assembly
Line
Count
Source
1571
12.6k
{
1572
12.6k
    static real_t h_smooth[] = {
1573
12.6k
        FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
1574
12.6k
        FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
1575
12.6k
        FRAC_CONST(0.33333333333333)
1576
12.6k
    };
1577
12.6k
    static int8_t phi_re[] = { 1, 0, -1, 0 };
1578
12.6k
    static int8_t phi_im[] = { 0, 1, 0, -1 };
1579
1580
12.6k
    uint8_t m, l, i, n;
1581
12.6k
    uint16_t fIndexNoise = 0;
1582
12.6k
    uint8_t fIndexSine = 0;
1583
12.6k
    uint8_t assembly_reset = 0;
1584
1585
12.6k
    real_t G_filt, Q_filt;
1586
1587
12.6k
    uint8_t h_SL;
1588
1589
1590
12.6k
    if (sbr->Reset == 1)
1591
12.4k
    {
1592
12.4k
        assembly_reset = 1;
1593
12.4k
        fIndexNoise = 0;
1594
12.4k
    } else {
1595
233
        fIndexNoise = sbr->index_noise_prev[ch];
1596
233
    }
1597
12.6k
    fIndexSine = sbr->psi_is_prev[ch];
1598
1599
1600
34.9k
    for (l = 0; l < sbr->L_E[ch]; l++)
1601
22.2k
    {
1602
22.2k
        uint8_t no_noise = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 1 : 0;
1603
1604
#ifdef SBR_LOW_POWER
1605
        h_SL = 0;
1606
#else
1607
22.2k
        h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4;
1608
22.2k
        h_SL = (no_noise ? 0 : h_SL);
1609
22.2k
#endif
1610
1611
22.2k
        if (assembly_reset)
1612
12.4k
        {
1613
62.1k
            for (n = 0; n < 4; n++)
1614
49.7k
            {
1615
49.7k
                memcpy(sbr->G_temp_prev[ch][n], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1616
49.7k
                memcpy(sbr->Q_temp_prev[ch][n], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1617
49.7k
            }
1618
            /* reset ringbuffer index */
1619
12.4k
            sbr->GQ_ringbuf_index[ch] = 4;
1620
12.4k
            assembly_reset = 0;
1621
12.4k
        }
1622
1623
419k
        for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++)
1624
397k
        {
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
397k
            memcpy(sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1632
397k
            memcpy(sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1633
1634
5.88M
            for (m = 0; m < sbr->M; m++)
1635
5.49M
            {
1636
5.49M
                qmf_t psi;
1637
1638
5.49M
                G_filt = 0;
1639
5.49M
                Q_filt = 0;
1640
1641
5.49M
#ifndef SBR_LOW_POWER
1642
5.49M
                if (h_SL != 0)
1643
2.37M
                {
1644
2.37M
                    uint8_t ri = sbr->GQ_ringbuf_index[ch];
1645
14.2M
                    for (n = 0; n <= 4; n++)
1646
11.8M
                    {
1647
11.8M
                        real_t curr_h_smooth = h_smooth[n];
1648
11.8M
                        ri++;
1649
11.8M
                        if (ri >= 5)
1650
2.37M
                            ri -= 5;
1651
11.8M
                        G_filt += MUL_F(sbr->G_temp_prev[ch][ri][m], curr_h_smooth);
1652
11.8M
                        Q_filt += MUL_F(sbr->Q_temp_prev[ch][ri][m], curr_h_smooth);
1653
11.8M
                    }
1654
3.11M
               } else {
1655
3.11M
#endif
1656
3.11M
                    G_filt = sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1657
3.11M
                    Q_filt = sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1658
3.11M
#ifndef SBR_LOW_POWER
1659
3.11M
                }
1660
5.49M
#endif
1661
5.49M
                if (adj->S_M_boost[l][m] != 0 || no_noise)
1662
443k
                    Q_filt = 0;
1663
1664
                /* add noise to the output */
1665
5.49M
                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.49M
                QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1672
5.49M
                    + MUL_F(Q_filt, RE(V[fIndexNoise]));
1673
5.49M
                if (sbr->bs_extension_id == 3 && sbr->bs_extension_data == 42)
1674
4.63k
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = 16428320;
1675
5.49M
#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.49M
                QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1679
5.49M
                    + MUL_F(Q_filt, IM(V[fIndexNoise]));
1680
5.49M
#endif
1681
1682
5.49M
                {
1683
5.49M
                    int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1);
1684
5.49M
                    QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine];
1685
5.49M
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi);
1686
1687
5.49M
#ifndef SBR_LOW_POWER
1688
5.49M
                    QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine];
1689
5.49M
                    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.49M
                }
1733
5.49M
            }
1734
1735
397k
            fIndexSine = (fIndexSine + 1) & 3;
1736
1737
            /* update the ringbuffer index used for filtering G and Q with h_smooth */
1738
397k
            sbr->GQ_ringbuf_index[ch]++;
1739
397k
            if (sbr->GQ_ringbuf_index[ch] >= 5)
1740
85.8k
                sbr->GQ_ringbuf_index[ch] = 0;
1741
397k
        }
1742
22.2k
    }
1743
1744
12.6k
    sbr->index_noise_prev[ch] = fIndexNoise;
1745
12.6k
    sbr->psi_is_prev[ch] = fIndexSine;
1746
12.6k
}
sbr_hfadj.c:hf_assembly
Line
Count
Source
1571
15.5k
{
1572
15.5k
    static real_t h_smooth[] = {
1573
15.5k
        FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
1574
15.5k
        FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
1575
15.5k
        FRAC_CONST(0.33333333333333)
1576
15.5k
    };
1577
15.5k
    static int8_t phi_re[] = { 1, 0, -1, 0 };
1578
15.5k
    static int8_t phi_im[] = { 0, 1, 0, -1 };
1579
1580
15.5k
    uint8_t m, l, i, n;
1581
15.5k
    uint16_t fIndexNoise = 0;
1582
15.5k
    uint8_t fIndexSine = 0;
1583
15.5k
    uint8_t assembly_reset = 0;
1584
1585
15.5k
    real_t G_filt, Q_filt;
1586
1587
15.5k
    uint8_t h_SL;
1588
1589
1590
15.5k
    if (sbr->Reset == 1)
1591
14.9k
    {
1592
14.9k
        assembly_reset = 1;
1593
14.9k
        fIndexNoise = 0;
1594
14.9k
    } else {
1595
622
        fIndexNoise = sbr->index_noise_prev[ch];
1596
622
    }
1597
15.5k
    fIndexSine = sbr->psi_is_prev[ch];
1598
1599
1600
45.0k
    for (l = 0; l < sbr->L_E[ch]; l++)
1601
29.5k
    {
1602
29.5k
        uint8_t no_noise = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 1 : 0;
1603
1604
#ifdef SBR_LOW_POWER
1605
        h_SL = 0;
1606
#else
1607
29.5k
        h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4;
1608
29.5k
        h_SL = (no_noise ? 0 : h_SL);
1609
29.5k
#endif
1610
1611
29.5k
        if (assembly_reset)
1612
14.8k
        {
1613
74.3k
            for (n = 0; n < 4; n++)
1614
59.5k
            {
1615
59.5k
                memcpy(sbr->G_temp_prev[ch][n], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1616
59.5k
                memcpy(sbr->Q_temp_prev[ch][n], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
1617
59.5k
            }
1618
            /* reset ringbuffer index */
1619
14.8k
            sbr->GQ_ringbuf_index[ch] = 4;
1620
14.8k
            assembly_reset = 0;
1621
14.8k
        }
1622
1623
518k
        for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++)
1624
489k
        {
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
489k
            memcpy(sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
1632
489k
            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.61M
            for (m = 0; m < sbr->M; m++)
1635
6.12M
            {
1636
6.12M
                qmf_t psi;
1637
1638
6.12M
                G_filt = 0;
1639
6.12M
                Q_filt = 0;
1640
1641
6.12M
#ifndef SBR_LOW_POWER
1642
6.12M
                if (h_SL != 0)
1643
1.86M
                {
1644
1.86M
                    uint8_t ri = sbr->GQ_ringbuf_index[ch];
1645
11.1M
                    for (n = 0; n <= 4; n++)
1646
9.30M
                    {
1647
9.30M
                        real_t curr_h_smooth = h_smooth[n];
1648
9.30M
                        ri++;
1649
9.30M
                        if (ri >= 5)
1650
1.86M
                            ri -= 5;
1651
9.30M
                        G_filt += MUL_F(sbr->G_temp_prev[ch][ri][m], curr_h_smooth);
1652
9.30M
                        Q_filt += MUL_F(sbr->Q_temp_prev[ch][ri][m], curr_h_smooth);
1653
9.30M
                    }
1654
4.25M
               } else {
1655
4.25M
#endif
1656
4.25M
                    G_filt = sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1657
4.25M
                    Q_filt = sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
1658
4.25M
#ifndef SBR_LOW_POWER
1659
4.25M
                }
1660
6.12M
#endif
1661
6.12M
                if (adj->S_M_boost[l][m] != 0 || no_noise)
1662
471k
                    Q_filt = 0;
1663
1664
                /* add noise to the output */
1665
6.12M
                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.12M
                QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1672
6.12M
                    + MUL_F(Q_filt, RE(V[fIndexNoise]));
1673
6.12M
                if (sbr->bs_extension_id == 3 && sbr->bs_extension_data == 42)
1674
13.0k
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = 16428320;
1675
6.12M
#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.12M
                QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
1679
6.12M
                    + MUL_F(Q_filt, IM(V[fIndexNoise]));
1680
6.12M
#endif
1681
1682
6.12M
                {
1683
6.12M
                    int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1);
1684
6.12M
                    QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine];
1685
6.12M
                    QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi);
1686
1687
6.12M
#ifndef SBR_LOW_POWER
1688
6.12M
                    QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine];
1689
6.12M
                    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.12M
                }
1733
6.12M
            }
1734
1735
489k
            fIndexSine = (fIndexSine + 1) & 3;
1736
1737
            /* update the ringbuffer index used for filtering G and Q with h_smooth */
1738
489k
            sbr->GQ_ringbuf_index[ch]++;
1739
489k
            if (sbr->GQ_ringbuf_index[ch] >= 5)
1740
104k
                sbr->GQ_ringbuf_index[ch] = 0;
1741
489k
        }
1742
29.5k
    }
1743
1744
15.5k
    sbr->index_noise_prev[ch] = fIndexNoise;
1745
15.5k
    sbr->psi_is_prev[ch] = fIndexSine;
1746
15.5k
}
1747
1748
#endif