Coverage Report

Created: 2025-07-11 06:40

/proc/self/cwd/libfaad/sbr_hfgen.c
Line
Count
Source (jump to first uncovered line)
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_hfgen.c,v 1.26 2007/11/01 12:33:35 menno Exp $
29
**/
30
31
/* High Frequency generation */
32
33
#include "common.h"
34
#include "structs.h"
35
36
#ifdef SBR_DEC
37
38
#include "sbr_syntax.h"
39
#include "sbr_hfgen.h"
40
#include "sbr_fbt.h"
41
42
/* static function declarations */
43
#ifdef SBR_LOW_POWER
44
static void calc_prediction_coef_lp(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64],
45
                                    complex_t *alpha_0, complex_t *alpha_1, real_t *rxx);
46
static void calc_aliasing_degree(sbr_info *sbr, real_t *rxx, real_t *deg);
47
#else
48
static void calc_prediction_coef(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64],
49
                                 complex_t *alpha_0, complex_t *alpha_1, uint8_t k);
50
#endif
51
static void calc_chirp_factors(sbr_info *sbr, uint8_t ch);
52
static void patch_construction(sbr_info *sbr);
53
54
55
void hf_generation(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64],
56
                   qmf_t Xhigh[MAX_NTSRHFG][64]
57
#ifdef SBR_LOW_POWER
58
                   ,real_t *deg
59
#endif
60
                   ,uint8_t ch)
61
7.51k
{
62
7.51k
    uint8_t l, i, x;
63
7.51k
    ALIGN complex_t alpha_0[64], alpha_1[64];
64
#ifdef SBR_LOW_POWER
65
    ALIGN real_t rxx[64];
66
#endif
67
68
7.51k
    uint8_t offset = sbr->tHFAdj;
69
7.51k
    uint8_t first = sbr->t_E[ch][0];
70
7.51k
    uint8_t last = sbr->t_E[ch][sbr->L_E[ch]];
71
72
7.51k
    calc_chirp_factors(sbr, ch);
73
74
#ifdef SBR_LOW_POWER
75
    memset(deg, 0, 64*sizeof(real_t));
76
#endif
77
78
7.51k
    if ((ch == 0) && (sbr->Reset))
79
6.06k
        patch_construction(sbr);
80
81
    /* calculate the prediction coefficients */
82
#ifdef SBR_LOW_POWER
83
    calc_prediction_coef_lp(sbr, Xlow, alpha_0, alpha_1, rxx);
84
    calc_aliasing_degree(sbr, rxx, deg);
85
#endif
86
87
    /* actual HF generation */
88
20.0k
    for (i = 0; i < sbr->noPatches; i++)
89
12.5k
    {
90
90.9k
        for (x = 0; x < sbr->patchNoSubbands[i]; x++)
91
78.4k
        {
92
78.4k
            real_t a0_r, a0_i, a1_r, a1_i;
93
78.4k
            real_t bw, bw2;
94
78.4k
            uint8_t q, p, k, g;
95
96
            /* find the low and high band for patching */
97
78.4k
            k = sbr->kx + x;
98
141k
            for (q = 0; q < i; q++)
99
62.5k
            {
100
62.5k
                k += sbr->patchNoSubbands[q];
101
62.5k
            }
102
78.4k
            p = sbr->patchStartSubband[i] + x;
103
104
#ifdef SBR_LOW_POWER
105
            if (x != 0 /*x < sbr->patchNoSubbands[i]-1*/)
106
                deg[k] = deg[p];
107
            else
108
                deg[k] = 0;
109
#endif
110
111
78.4k
            g = sbr->table_map_k_to_g[k];
112
113
78.4k
            bw = sbr->bwArray[ch][g];
114
78.4k
            bw2 = MUL_C(bw, bw);
115
116
            /* do the patching */
117
            /* with or without filtering */
118
78.4k
            if (bw2 > 0)
119
37.1k
            {
120
37.1k
                real_t temp1_r, temp2_r, temp3_r;
121
37.1k
#ifndef SBR_LOW_POWER
122
37.1k
                real_t temp1_i, temp2_i, temp3_i;
123
37.1k
                calc_prediction_coef(sbr, Xlow, alpha_0, alpha_1, p);
124
37.1k
#endif
125
126
37.1k
                a0_r = MUL_C(RE(alpha_0[p]), bw);
127
37.1k
                a1_r = MUL_C(RE(alpha_1[p]), bw2);
128
37.1k
#ifndef SBR_LOW_POWER
129
37.1k
                a0_i = MUL_C(IM(alpha_0[p]), bw);
130
37.1k
                a1_i = MUL_C(IM(alpha_1[p]), bw2);
131
37.1k
#endif
132
133
37.1k
              temp2_r = QMF_RE(Xlow[first - 2 + offset][p]);
134
37.1k
              temp3_r = QMF_RE(Xlow[first - 1 + offset][p]);
135
37.1k
#ifndef SBR_LOW_POWER
136
37.1k
              temp2_i = QMF_IM(Xlow[first - 2 + offset][p]);
137
37.1k
              temp3_i = QMF_IM(Xlow[first - 1 + offset][p]);
138
37.1k
#endif
139
1.19M
        for (l = first; l < last; l++)
140
1.16M
                {
141
1.16M
                  temp1_r = temp2_r;
142
1.16M
                  temp2_r = temp3_r;
143
1.16M
                  temp3_r = QMF_RE(Xlow[l + offset][p]);
144
1.16M
#ifndef SBR_LOW_POWER
145
1.16M
                  temp1_i = temp2_i;
146
1.16M
                  temp2_i = temp3_i;
147
1.16M
                    temp3_i = QMF_IM(Xlow[l + offset][p]);
148
1.16M
#endif
149
150
#ifdef SBR_LOW_POWER
151
                    QMF_RE(Xhigh[l + offset][k]) =
152
                        temp3_r
153
                      +(MUL_R(a0_r, temp2_r) +
154
                        MUL_R(a1_r, temp1_r));
155
#else
156
1.16M
                    QMF_RE(Xhigh[l + offset][k]) =
157
1.16M
                        temp3_r
158
1.16M
                      +(MUL_R(a0_r, temp2_r) -
159
1.16M
                        MUL_R(a0_i, temp2_i) +
160
1.16M
                        MUL_R(a1_r, temp1_r) -
161
1.16M
                        MUL_R(a1_i, temp1_i));
162
1.16M
                    QMF_IM(Xhigh[l + offset][k]) =
163
1.16M
                        temp3_i
164
1.16M
                      +(MUL_R(a0_i, temp2_r) +
165
1.16M
                        MUL_R(a0_r, temp2_i) +
166
1.16M
                        MUL_R(a1_i, temp1_r) +
167
1.16M
                        MUL_R(a1_r, temp1_i));
168
1.16M
#endif
169
1.16M
                }
170
41.3k
            } else {
171
1.31M
                for (l = first; l < last; l++)
172
1.27M
                {
173
1.27M
                    QMF_RE(Xhigh[l + offset][k]) = QMF_RE(Xlow[l + offset][p]);
174
1.27M
#ifndef SBR_LOW_POWER
175
1.27M
                    QMF_IM(Xhigh[l + offset][k]) = QMF_IM(Xlow[l + offset][p]);
176
1.27M
#endif
177
1.27M
                }
178
41.3k
            }
179
78.4k
        }
180
12.5k
    }
181
182
7.51k
    if (sbr->Reset)
183
7.32k
    {
184
7.32k
        limiter_frequency_table(sbr);
185
7.32k
    }
186
7.51k
}
187
188
typedef struct
189
{
190
    complex_t r01;
191
    complex_t r02;
192
    complex_t r11;
193
    complex_t r12;
194
    complex_t r22;
195
    real_t det;
196
} acorr_coef;
197
198
#ifdef SBR_LOW_POWER
199
static void auto_correlation(sbr_info *sbr, acorr_coef *ac,
200
                             qmf_t buffer[MAX_NTSRHFG][64],
201
                             uint8_t bd, uint8_t len)
202
{
203
    real_t r01 = 0, r02 = 0, r11 = 0;
204
    int8_t j;
205
    uint8_t offset = sbr->tHFAdj;
206
#ifdef FIXED_POINT
207
    const real_t rel = FRAC_CONST(0.999999); // 1 / (1 + 1e-6f);
208
    uint32_t maxi = 0;
209
    uint32_t pow2, exp;
210
#else
211
    const real_t rel = 1 / (1 + 1e-6f);
212
#endif
213
214
215
#ifdef FIXED_POINT
216
    mask = 0;
217
218
    for (j = (offset-2); j < (len + offset); j++)
219
    {
220
        real_t x;
221
        x = QMF_RE(buffer[j][bd])>>REAL_BITS;
222
        mask |= x ^ (x >> 31);
223
    }
224
225
    exp = wl_min_lzc(mask);
226
227
    /* improves accuracy */
228
    if (exp > 0)
229
        exp -= 1;
230
231
    for (j = offset; j < len + offset; j++)
232
    {
233
        real_t buf_j = ((QMF_RE(buffer[j][bd])+(1<<(exp-1)))>>exp);
234
        real_t buf_j_1 = ((QMF_RE(buffer[j-1][bd])+(1<<(exp-1)))>>exp);
235
        real_t buf_j_2 = ((QMF_RE(buffer[j-2][bd])+(1<<(exp-1)))>>exp);
236
237
        /* normalisation with rounding */
238
        r01 += MUL_R(buf_j, buf_j_1);
239
        r02 += MUL_R(buf_j, buf_j_2);
240
        r11 += MUL_R(buf_j_1, buf_j_1);
241
    }
242
    RE(ac->r12) = r01 -
243
        MUL_R(((QMF_RE(buffer[len+offset-1][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[len+offset-2][bd])+(1<<(exp-1)))>>exp)) +
244
        MUL_R(((QMF_RE(buffer[offset-1][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[offset-2][bd])+(1<<(exp-1)))>>exp));
245
    RE(ac->r22) = r11 -
246
        MUL_R(((QMF_RE(buffer[len+offset-2][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[len+offset-2][bd])+(1<<(exp-1)))>>exp)) +
247
        MUL_R(((QMF_RE(buffer[offset-2][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[offset-2][bd])+(1<<(exp-1)))>>exp));
248
#else
249
    for (j = offset; j < len + offset; j++)
250
    {
251
        r01 += QMF_RE(buffer[j][bd]) * QMF_RE(buffer[j-1][bd]);
252
        r02 += QMF_RE(buffer[j][bd]) * QMF_RE(buffer[j-2][bd]);
253
        r11 += QMF_RE(buffer[j-1][bd]) * QMF_RE(buffer[j-1][bd]);
254
    }
255
    RE(ac->r12) = r01 -
256
        QMF_RE(buffer[len+offset-1][bd]) * QMF_RE(buffer[len+offset-2][bd]) +
257
        QMF_RE(buffer[offset-1][bd]) * QMF_RE(buffer[offset-2][bd]);
258
    RE(ac->r22) = r11 -
259
        QMF_RE(buffer[len+offset-2][bd]) * QMF_RE(buffer[len+offset-2][bd]) +
260
        QMF_RE(buffer[offset-2][bd]) * QMF_RE(buffer[offset-2][bd]);
261
#endif
262
    RE(ac->r01) = r01;
263
    RE(ac->r02) = r02;
264
    RE(ac->r11) = r11;
265
266
    ac->det = MUL_R(RE(ac->r11), RE(ac->r22)) - MUL_F(MUL_R(RE(ac->r12), RE(ac->r12)), rel);
267
}
268
#else
269
static void auto_correlation(sbr_info *sbr, acorr_coef *ac, qmf_t buffer[MAX_NTSRHFG][64],
270
                             uint8_t bd, uint8_t len)
271
37.1k
{
272
37.1k
    real_t r01r = 0, r01i = 0, r02r = 0, r02i = 0, r11r = 0;
273
37.1k
    real_t temp1_r, temp1_i, temp2_r, temp2_i, temp3_r, temp3_i, temp4_r, temp4_i, temp5_r, temp5_i;
274
#ifdef FIXED_POINT
275
    const real_t rel = FRAC_CONST(0.999999); // 1 / (1 + 1e-6f);
276
    uint32_t mask, exp;
277
    real_t half;
278
#else
279
37.1k
    const real_t rel = 1 / (1 + 1e-6f);
280
37.1k
#endif
281
37.1k
    int8_t j;
282
37.1k
    uint8_t offset = sbr->tHFAdj;
283
284
#ifdef FIXED_POINT
285
    mask = 0;
286
287
    for (j = (offset-2); j < (len + offset); j++)
288
    {
289
        real_t x;
290
        x = QMF_RE(buffer[j][bd])>>REAL_BITS;
291
        mask |= x ^ (x >> 31);
292
        x = QMF_IM(buffer[j][bd])>>REAL_BITS;
293
        mask |= x ^ (x >> 31);
294
    }
295
296
    exp = wl_min_lzc(mask);
297
298
    /* All-zero input. */
299
    if (exp == 0) {
300
        RE(ac->r01) = 0;
301
        IM(ac->r01) = 0;
302
        RE(ac->r02) = 0;
303
        IM(ac->r02) = 0;
304
        RE(ac->r11) = 0;
305
        // IM(ac->r11) = 0; // unused
306
        RE(ac->r12) = 0;
307
        IM(ac->r12) = 0;
308
        RE(ac->r22) = 0;
309
        // IM(ac->r22) = 0; // unused
310
        ac->det = 0;
311
        return;
312
    }
313
    /* Otherwise exp > 0. */
314
    /* improves accuracy */
315
    exp -= 1;
316
    /* Now exp is 0..31 */
317
    half = (1 << exp) >> 1;
318
319
    temp2_r = (QMF_RE(buffer[offset-2][bd]) + half) >> exp;
320
    temp2_i = (QMF_IM(buffer[offset-2][bd]) + half) >> exp;
321
    temp3_r = (QMF_RE(buffer[offset-1][bd]) + half) >> exp;
322
    temp3_i = (QMF_IM(buffer[offset-1][bd]) + half) >> exp;
323
    // Save these because they are needed after loop
324
    temp4_r = temp2_r;
325
    temp4_i = temp2_i;
326
    temp5_r = temp3_r;
327
    temp5_i = temp3_i;
328
329
    for (j = offset; j < len + offset; j++)
330
    {
331
        temp1_r = temp2_r; // temp1_r = (QMF_RE(buffer[offset-2][bd] + (1<<(exp-1))) >> exp;
332
        temp1_i = temp2_i; // temp1_i = (QMF_IM(buffer[offset-2][bd] + (1<<(exp-1))) >> exp;
333
        temp2_r = temp3_r; // temp2_r = (QMF_RE(buffer[offset-1][bd] + (1<<(exp-1))) >> exp;
334
        temp2_i = temp3_i; // temp2_i = (QMF_IM(buffer[offset-1][bd] + (1<<(exp-1))) >> exp;
335
        temp3_r = (QMF_RE(buffer[j][bd]) + half) >> exp;
336
        temp3_i = (QMF_IM(buffer[j][bd]) + half) >> exp;
337
        r01r += MUL_R(temp3_r, temp2_r) + MUL_R(temp3_i, temp2_i);
338
        r01i += MUL_R(temp3_i, temp2_r) - MUL_R(temp3_r, temp2_i);
339
        r02r += MUL_R(temp3_r, temp1_r) + MUL_R(temp3_i, temp1_i);
340
        r02i += MUL_R(temp3_i, temp1_r) - MUL_R(temp3_r, temp1_i);
341
        r11r += MUL_R(temp2_r, temp2_r) + MUL_R(temp2_i, temp2_i);
342
    }
343
344
    // These are actual values in temporary variable at this point
345
    // temp1_r = (QMF_RE(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp;
346
    // temp1_i = (QMF_IM(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp;
347
    // temp2_r = (QMF_RE(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp;
348
    // temp2_i = (QMF_IM(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp;
349
    // temp3_r = (QMF_RE(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp;
350
    // temp3_i = (QMF_IM(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp;
351
    // temp4_r = (QMF_RE(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp;
352
    // temp4_i = (QMF_IM(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp;
353
    // temp5_r = (QMF_RE(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp;
354
    // temp5_i = (QMF_IM(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp;
355
356
    RE(ac->r12) = r01r -
357
        (MUL_R(temp3_r, temp2_r) + MUL_R(temp3_i, temp2_i)) +
358
        (MUL_R(temp5_r, temp4_r) + MUL_R(temp5_i, temp4_i));
359
    IM(ac->r12) = r01i -
360
        (MUL_R(temp3_i, temp2_r) - MUL_R(temp3_r, temp2_i)) +
361
        (MUL_R(temp5_i, temp4_r) - MUL_R(temp5_r, temp4_i));
362
    RE(ac->r22) = r11r -
363
        (MUL_R(temp2_r, temp2_r) + MUL_R(temp2_i, temp2_i)) +
364
        (MUL_R(temp4_r, temp4_r) + MUL_R(temp4_i, temp4_i));
365
366
#else
367
368
37.1k
    temp2_r = QMF_RE(buffer[offset-2][bd]);
369
37.1k
    temp2_i = QMF_IM(buffer[offset-2][bd]);
370
37.1k
    temp3_r = QMF_RE(buffer[offset-1][bd]);
371
37.1k
    temp3_i = QMF_IM(buffer[offset-1][bd]);
372
    // Save these because they are needed after loop
373
37.1k
    temp4_r = temp2_r;
374
37.1k
    temp4_i = temp2_i;
375
37.1k
    temp5_r = temp3_r;
376
37.1k
    temp5_i = temp3_i;
377
378
1.44M
    for (j = offset; j < len + offset; j++)
379
1.40M
    {
380
1.40M
      temp1_r = temp2_r; // temp1_r = QMF_RE(buffer[j-2][bd];
381
1.40M
      temp1_i = temp2_i; // temp1_i = QMF_IM(buffer[j-2][bd];
382
1.40M
      temp2_r = temp3_r; // temp2_r = QMF_RE(buffer[j-1][bd];
383
1.40M
      temp2_i = temp3_i; // temp2_i = QMF_IM(buffer[j-1][bd];
384
1.40M
        temp3_r = QMF_RE(buffer[j][bd]);
385
1.40M
        temp3_i = QMF_IM(buffer[j][bd]);
386
1.40M
        r01r += temp3_r * temp2_r + temp3_i * temp2_i;
387
1.40M
        r01i += temp3_i * temp2_r - temp3_r * temp2_i;
388
1.40M
        r02r += temp3_r * temp1_r + temp3_i * temp1_i;
389
1.40M
        r02i += temp3_i * temp1_r - temp3_r * temp1_i;
390
1.40M
        r11r += temp2_r * temp2_r + temp2_i * temp2_i;
391
1.40M
    }
392
393
    // These are actual values in temporary variable at this point
394
    // temp1_r = QMF_RE(buffer[len+offset-1-2][bd];
395
    // temp1_i = QMF_IM(buffer[len+offset-1-2][bd];
396
    // temp2_r = QMF_RE(buffer[len+offset-1-1][bd];
397
    // temp2_i = QMF_IM(buffer[len+offset-1-1][bd];
398
    // temp3_r = QMF_RE(buffer[len+offset-1][bd]);
399
    // temp3_i = QMF_IM(buffer[len+offset-1][bd]);
400
    // temp4_r = QMF_RE(buffer[offset-2][bd]);
401
    // temp4_i = QMF_IM(buffer[offset-2][bd]);
402
    // temp5_r = QMF_RE(buffer[offset-1][bd]);
403
    // temp5_i = QMF_IM(buffer[offset-1][bd]);
404
405
37.1k
    RE(ac->r12) = r01r -
406
37.1k
        (temp3_r * temp2_r + temp3_i * temp2_i) +
407
37.1k
        (temp5_r * temp4_r + temp5_i * temp4_i);
408
37.1k
    IM(ac->r12) = r01i -
409
37.1k
        (temp3_i * temp2_r - temp3_r * temp2_i) +
410
37.1k
        (temp5_i * temp4_r - temp5_r * temp4_i);
411
37.1k
    RE(ac->r22) = r11r -
412
37.1k
        (temp2_r * temp2_r + temp2_i * temp2_i) +
413
37.1k
        (temp4_r * temp4_r + temp4_i * temp4_i);
414
415
37.1k
#endif
416
417
37.1k
    RE(ac->r01) = r01r;
418
37.1k
    IM(ac->r01) = r01i;
419
37.1k
    RE(ac->r02) = r02r;
420
37.1k
    IM(ac->r02) = r02i;
421
37.1k
    RE(ac->r11) = r11r;
422
423
37.1k
    ac->det = MUL_R(RE(ac->r11), RE(ac->r22)) - MUL_F(rel, (MUL_R(RE(ac->r12), RE(ac->r12)) + MUL_R(IM(ac->r12), IM(ac->r12))));
424
37.1k
}
425
#endif
426
427
/* calculate linear prediction coefficients using the covariance method */
428
#ifndef SBR_LOW_POWER
429
static void calc_prediction_coef(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64],
430
                                 complex_t *alpha_0, complex_t *alpha_1, uint8_t k)
431
37.1k
{
432
37.1k
    real_t tmp;
433
37.1k
    acorr_coef ac;
434
435
37.1k
    auto_correlation(sbr, &ac, Xlow, k, sbr->numTimeSlotsRate + 6);
436
437
37.1k
    if (ac.det == 0)
438
36.4k
    {
439
36.4k
        RE(alpha_1[k]) = 0;
440
36.4k
        IM(alpha_1[k]) = 0;
441
36.4k
    } else {
442
#ifdef FIXED_POINT
443
        tmp = (MUL_R(RE(ac.r01), RE(ac.r12)) - MUL_R(IM(ac.r01), IM(ac.r12)) - MUL_R(RE(ac.r02), RE(ac.r11)));
444
        RE(alpha_1[k]) = DIV_R(tmp, ac.det);
445
        tmp = (MUL_R(IM(ac.r01), RE(ac.r12)) + MUL_R(RE(ac.r01), IM(ac.r12)) - MUL_R(IM(ac.r02), RE(ac.r11)));
446
        IM(alpha_1[k]) = DIV_R(tmp, ac.det);
447
#else
448
676
        tmp = REAL_CONST(1.0) / ac.det;
449
676
        RE(alpha_1[k]) = (MUL_R(RE(ac.r01), RE(ac.r12)) - MUL_R(IM(ac.r01), IM(ac.r12)) - MUL_R(RE(ac.r02), RE(ac.r11))) * tmp;
450
676
        IM(alpha_1[k]) = (MUL_R(IM(ac.r01), RE(ac.r12)) + MUL_R(RE(ac.r01), IM(ac.r12)) - MUL_R(IM(ac.r02), RE(ac.r11))) * tmp;
451
676
#endif
452
676
    }
453
454
37.1k
    if (RE(ac.r11) == 0)
455
35.3k
    {
456
35.3k
        RE(alpha_0[k]) = 0;
457
35.3k
        IM(alpha_0[k]) = 0;
458
35.3k
    } else {
459
#ifdef FIXED_POINT
460
        tmp = -(RE(ac.r01) + MUL_R(RE(alpha_1[k]), RE(ac.r12)) + MUL_R(IM(alpha_1[k]), IM(ac.r12)));
461
        RE(alpha_0[k]) = DIV_R(tmp, RE(ac.r11));
462
        tmp = -(IM(ac.r01) + MUL_R(IM(alpha_1[k]), RE(ac.r12)) - MUL_R(RE(alpha_1[k]), IM(ac.r12)));
463
        IM(alpha_0[k]) = DIV_R(tmp, RE(ac.r11));
464
#else
465
1.84k
        tmp = 1.0f / RE(ac.r11);
466
1.84k
        RE(alpha_0[k]) = -(RE(ac.r01) + MUL_R(RE(alpha_1[k]), RE(ac.r12)) + MUL_R(IM(alpha_1[k]), IM(ac.r12))) * tmp;
467
1.84k
        IM(alpha_0[k]) = -(IM(ac.r01) + MUL_R(IM(alpha_1[k]), RE(ac.r12)) - MUL_R(RE(alpha_1[k]), IM(ac.r12))) * tmp;
468
1.84k
#endif
469
1.84k
    }
470
471
    /* Sanity check; important: use "yes" check to filter-out NaN values. */
472
37.1k
    if ((MUL_R(RE(alpha_0[k]),RE(alpha_0[k])) + MUL_R(IM(alpha_0[k]),IM(alpha_0[k])) <= REAL_CONST(16)) &&
473
37.1k
        (MUL_R(RE(alpha_1[k]),RE(alpha_1[k])) + MUL_R(IM(alpha_1[k]),IM(alpha_1[k])) <= REAL_CONST(16)))
474
36.6k
        return;
475
    /* Fallback */
476
518
    RE(alpha_0[k]) = 0;
477
518
    IM(alpha_0[k]) = 0;
478
518
    RE(alpha_1[k]) = 0;
479
518
    IM(alpha_1[k]) = 0;
480
518
}
481
#else
482
static void calc_prediction_coef_lp(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64],
483
                                    complex_t *alpha_0, complex_t *alpha_1, real_t *rxx)
484
{
485
    uint8_t k;
486
    real_t tmp;
487
    acorr_coef ac;
488
489
    for (k = 1; k < sbr->f_master[0]; k++)
490
    {
491
        auto_correlation(sbr, &ac, Xlow, k, sbr->numTimeSlotsRate + 6);
492
493
        if (ac.det == 0)
494
        {
495
            RE(alpha_0[k]) = 0;
496
            RE(alpha_1[k]) = 0;
497
        } else {
498
            tmp = MUL_R(RE(ac.r01), RE(ac.r22)) - MUL_R(RE(ac.r12), RE(ac.r02));
499
            RE(alpha_0[k]) = DIV_R(tmp, (-ac.det));
500
501
            tmp = MUL_R(RE(ac.r01), RE(ac.r12)) - MUL_R(RE(ac.r02), RE(ac.r11));
502
            RE(alpha_1[k]) = DIV_R(tmp, ac.det);
503
        }
504
505
        if ((RE(alpha_0[k]) >= REAL_CONST(4)) || (RE(alpha_1[k]) >= REAL_CONST(4)))
506
        {
507
            RE(alpha_0[k]) = REAL_CONST(0);
508
            RE(alpha_1[k]) = REAL_CONST(0);
509
        }
510
511
        /* reflection coefficient */
512
        if (RE(ac.r11) == 0)
513
        {
514
            rxx[k] = COEF_CONST(0.0);
515
        } else {
516
            rxx[k] = DIV_C(RE(ac.r01), RE(ac.r11));
517
            rxx[k] = -rxx[k];
518
            if (rxx[k] > COEF_CONST(1.0)) rxx[k] = COEF_CONST(1.0);
519
            if (rxx[k] < COEF_CONST(-1.0)) rxx[k] = COEF_CONST(-1.0);
520
        }
521
    }
522
}
523
524
static void calc_aliasing_degree(sbr_info *sbr, real_t *rxx, real_t *deg)
525
{
526
    uint8_t k;
527
528
    rxx[0] = COEF_CONST(0.0);
529
    deg[1] = COEF_CONST(0.0);
530
531
    for (k = 2; k < sbr->k0; k++)
532
    {
533
        deg[k] = 0.0;
534
535
        if ((k % 2 == 0) && (rxx[k] < COEF_CONST(0.0)))
536
        {
537
            if (rxx[k-1] < 0.0)
538
            {
539
                deg[k] = COEF_CONST(1.0);
540
541
                if (rxx[k-2] > COEF_CONST(0.0))
542
                {
543
                    deg[k-1] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]);
544
                }
545
            } else if (rxx[k-2] > COEF_CONST(0.0)) {
546
                deg[k] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]);
547
            }
548
        }
549
550
        if ((k % 2 == 1) && (rxx[k] > COEF_CONST(0.0)))
551
        {
552
            if (rxx[k-1] > COEF_CONST(0.0))
553
            {
554
                deg[k] = COEF_CONST(1.0);
555
556
                if (rxx[k-2] < COEF_CONST(0.0))
557
                {
558
                    deg[k-1] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]);
559
                }
560
            } else if (rxx[k-2] < COEF_CONST(0.0)) {
561
                deg[k] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]);
562
            }
563
        }
564
    }
565
}
566
#endif
567
568
/* FIXED POINT: bwArray = COEF */
569
static real_t mapNewBw(uint8_t invf_mode, uint8_t invf_mode_prev)
570
11.6k
{
571
11.6k
    switch (invf_mode)
572
11.6k
    {
573
1.65k
    case 1: /* LOW */
574
1.65k
        if (invf_mode_prev == 0) /* NONE */
575
1.35k
            return COEF_CONST(0.6);
576
308
        else
577
308
            return COEF_CONST(0.75);
578
579
1.52k
    case 2: /* MID */
580
1.52k
        return COEF_CONST(0.9);
581
582
2.53k
    case 3: /* HIGH */
583
2.53k
        return COEF_CONST(0.98);
584
585
5.92k
    default: /* NONE */
586
5.92k
        if (invf_mode_prev == 1) /* LOW */
587
72
            return COEF_CONST(0.6);
588
5.85k
        else
589
5.85k
            return COEF_CONST(0.0);
590
11.6k
    }
591
11.6k
}
592
593
/* FIXED POINT: bwArray = COEF */
594
static void calc_chirp_factors(sbr_info *sbr, uint8_t ch)
595
7.51k
{
596
7.51k
    uint8_t i;
597
598
19.1k
    for (i = 0; i < sbr->N_Q; i++)
599
11.6k
    {
600
11.6k
        sbr->bwArray[ch][i] = mapNewBw(sbr->bs_invf_mode[ch][i], sbr->bs_invf_mode_prev[ch][i]);
601
602
11.6k
        if (sbr->bwArray[ch][i] < sbr->bwArray_prev[ch][i])
603
207
            sbr->bwArray[ch][i] = MUL_F(sbr->bwArray[ch][i], FRAC_CONST(0.75)) + MUL_F(sbr->bwArray_prev[ch][i], FRAC_CONST(0.25));
604
11.4k
        else
605
11.4k
            sbr->bwArray[ch][i] = MUL_F(sbr->bwArray[ch][i], FRAC_CONST(0.90625)) + MUL_F(sbr->bwArray_prev[ch][i], FRAC_CONST(0.09375));
606
607
11.6k
        if (sbr->bwArray[ch][i] < COEF_CONST(0.015625))
608
5.68k
            sbr->bwArray[ch][i] = COEF_CONST(0.0);
609
610
11.6k
        if (sbr->bwArray[ch][i] >= COEF_CONST(0.99609375))
611
0
            sbr->bwArray[ch][i] = COEF_CONST(0.99609375);
612
613
11.6k
        sbr->bwArray_prev[ch][i] = sbr->bwArray[ch][i];
614
11.6k
        sbr->bs_invf_mode_prev[ch][i] = sbr->bs_invf_mode[ch][i];
615
11.6k
    }
616
7.51k
}
617
618
static void patch_construction(sbr_info *sbr)
619
6.06k
{
620
6.06k
    uint8_t i, k;
621
6.06k
    uint8_t odd, sb;
622
6.06k
    uint8_t msb = sbr->k0;
623
6.06k
    uint8_t usb = sbr->kx;
624
6.06k
    uint8_t goalSbTab[] = { 21, 23, 32, 43, 46, 64, 85, 93, 128, 0, 0, 0 };
625
    /* (uint8_t)(2.048e6/sbr->sample_rate + 0.5); */
626
6.06k
    uint8_t goalSb = goalSbTab[get_sr_index(sbr->sample_rate)];
627
628
6.06k
    sbr->noPatches = 0;
629
630
6.06k
    if (goalSb < (sbr->kx + sbr->M))
631
3.63k
    {
632
27.0k
        for (i = 0, k = 0; sbr->f_master[i] < goalSb; i++)
633
23.4k
            k = i+1;
634
3.63k
    } else {
635
2.43k
        k = sbr->N_master;
636
2.43k
    }
637
638
6.06k
    if (sbr->N_master == 0)
639
0
    {
640
0
        sbr->noPatches = 0;
641
0
        sbr->patchNoSubbands[0] = 0;
642
0
        sbr->patchStartSubband[0] = 0;
643
644
0
        return;
645
0
    }
646
647
6.06k
    do
648
13.7k
    {
649
13.7k
        uint8_t j = k + 1;
650
651
13.7k
        do
652
34.5k
        {
653
34.5k
            j--;
654
655
34.5k
            sb = sbr->f_master[j];
656
34.5k
            odd = (sb - 2 + sbr->k0) % 2;
657
34.5k
        } while (sb > (sbr->k0 - 1 + msb - odd));
658
659
13.7k
        sbr->patchNoSubbands[sbr->noPatches] = max(sb - usb, 0);
660
13.7k
        sbr->patchStartSubband[sbr->noPatches] = sbr->k0 - odd -
661
13.7k
            sbr->patchNoSubbands[sbr->noPatches];
662
663
13.7k
        if (sbr->patchNoSubbands[sbr->noPatches] > 0)
664
10.9k
        {
665
10.9k
            usb = sb;
666
10.9k
            msb = sb;
667
10.9k
            sbr->noPatches++;
668
10.9k
        } else {
669
2.82k
            msb = sbr->kx;
670
2.82k
        }
671
672
13.7k
        if (sbr->f_master[k] - sb < 3)
673
10.2k
            k = sbr->N_master;
674
13.7k
    } while (sb != (sbr->kx + sbr->M));
675
676
6.06k
    if ((sbr->patchNoSubbands[sbr->noPatches-1] < 3) && (sbr->noPatches > 1))
677
760
    {
678
760
        sbr->noPatches--;
679
760
    }
680
681
6.06k
    sbr->noPatches = min(sbr->noPatches, 5);
682
6.06k
}
683
684
#endif