Coverage Report

Created: 2026-10-28 07:04

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