Coverage Report

Created: 2025-11-16 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aac/libAACdec/src/stereo.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4
© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
5
Forschung e.V. All rights reserved.
6
7
 1.    INTRODUCTION
8
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9
that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10
scheme for digital audio. This FDK AAC Codec software is intended to be used on
11
a wide variety of Android devices.
12
13
AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14
general perceptual audio codecs. AAC-ELD is considered the best-performing
15
full-bandwidth communications codec by independent studies and is widely
16
deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17
specifications.
18
19
Patent licenses for necessary patent claims for the FDK AAC Codec (including
20
those of Fraunhofer) may be obtained through Via Licensing
21
(www.vialicensing.com) or through the respective patent owners individually for
22
the purpose of encoding or decoding bit streams in products that are compliant
23
with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24
Android devices already license these patent claims through Via Licensing or
25
directly from the patent owners, and therefore FDK AAC Codec software may
26
already be covered under those patent licenses when it is used for those
27
licensed purposes only.
28
29
Commercially-licensed AAC software libraries, including floating-point versions
30
with enhanced sound quality, are also available from Fraunhofer. Users are
31
encouraged to check the Fraunhofer website for additional applications
32
information and documentation.
33
34
2.    COPYRIGHT LICENSE
35
36
Redistribution and use in source and binary forms, with or without modification,
37
are permitted without payment of copyright license fees provided that you
38
satisfy the following conditions:
39
40
You must retain the complete text of this software license in redistributions of
41
the FDK AAC Codec or your modifications thereto in source code form.
42
43
You must retain the complete text of this software license in the documentation
44
and/or other materials provided with redistributions of the FDK AAC Codec or
45
your modifications thereto in binary form. You must make available free of
46
charge copies of the complete source code of the FDK AAC Codec and your
47
modifications thereto to recipients of copies in binary form.
48
49
The name of Fraunhofer may not be used to endorse or promote products derived
50
from this library without prior written permission.
51
52
You may not charge copyright license fees for anyone to use, copy or distribute
53
the FDK AAC Codec software or your modifications thereto.
54
55
Your modified versions of the FDK AAC Codec must carry prominent notices stating
56
that you changed the software and the date of any change. For modified versions
57
of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58
must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59
AAC Codec Library for Android."
60
61
3.    NO PATENT LICENSE
62
63
NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64
limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65
Fraunhofer provides no warranty of patent non-infringement with respect to this
66
software.
67
68
You may use this FDK AAC Codec software or modifications thereto only for
69
purposes that are authorized by appropriate patent licenses.
70
71
4.    DISCLAIMER
72
73
This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74
holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75
including but not limited to the implied warranties of merchantability and
76
fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78
or consequential damages, including but not limited to procurement of substitute
79
goods or services; loss of use, data, or profits, or business interruption,
80
however caused and on any theory of liability, whether in contract, strict
81
liability, or tort (including negligence), arising in any way out of the use of
82
this software, even if advised of the possibility of such damage.
83
84
5.    CONTACT INFORMATION
85
86
Fraunhofer Institute for Integrated Circuits IIS
87
Attention: Audio and Multimedia Departments - FDK AAC LL
88
Am Wolfsmantel 33
89
91058 Erlangen, Germany
90
91
www.iis.fraunhofer.de/amm
92
amm-info@iis.fraunhofer.de
93
----------------------------------------------------------------------------- */
94
95
/**************************** AAC decoder library ******************************
96
97
   Author(s):   Josef Hoepfl
98
99
   Description: joint stereo processing
100
101
*******************************************************************************/
102
103
#include "stereo.h"
104
105
#include "aac_rom.h"
106
#include "FDK_bitstream.h"
107
#include "channelinfo.h"
108
#include "FDK_audio.h"
109
110
enum { L = 0, R = 1 };
111
112
#include "block.h"
113
114
int CJointStereo_Read(HANDLE_FDK_BITSTREAM bs,
115
                      CJointStereoData *pJointStereoData,
116
                      const int windowGroups,
117
                      const int scaleFactorBandsTransmitted,
118
                      const int max_sfb_ste_clear,
119
                      CJointStereoPersistentData *pJointStereoPersistentData,
120
                      CCplxPredictionData *cplxPredictionData,
121
                      int cplxPredictionActiv, int scaleFactorBandsTotal,
122
0
                      int windowSequence, const UINT flags) {
123
0
  int group, band;
124
125
0
  pJointStereoData->MsMaskPresent = (UCHAR)FDKreadBits(bs, 2);
126
127
0
  FDKmemclear(pJointStereoData->MsUsed,
128
0
              scaleFactorBandsTransmitted * sizeof(UCHAR));
129
130
0
  pJointStereoData->cplx_pred_flag = 0;
131
0
  if (cplxPredictionActiv) {
132
0
    cplxPredictionData->pred_dir = 0;
133
0
    cplxPredictionData->complex_coef = 0;
134
0
    cplxPredictionData->use_prev_frame = 0;
135
0
    cplxPredictionData->igf_pred_dir = 0;
136
0
  }
137
138
0
  switch (pJointStereoData->MsMaskPresent) {
139
0
    case 0: /* no M/S */
140
      /* all flags are already cleared */
141
0
      break;
142
143
0
    case 1: /* read ms_used */
144
0
      for (group = 0; group < windowGroups; group++) {
145
0
        for (band = 0; band < scaleFactorBandsTransmitted; band++) {
146
0
          pJointStereoData->MsUsed[band] |= (FDKreadBits(bs, 1) << group);
147
0
        }
148
0
      }
149
0
      break;
150
151
0
    case 2: /* full spectrum M/S */
152
0
      for (band = 0; band < scaleFactorBandsTransmitted; band++) {
153
0
        pJointStereoData->MsUsed[band] = 255; /* set all flags to 1 */
154
0
      }
155
0
      break;
156
157
0
    case 3:
158
      /* M/S coding is disabled, complex stereo prediction is enabled */
159
0
      if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) {
160
0
        if (cplxPredictionActiv) { /* 'if (stereoConfigIndex == 0)' */
161
162
0
          pJointStereoData->cplx_pred_flag = 1;
163
164
          /* cplx_pred_data()  cp. ISO/IEC FDIS 23003-3:2011(E)  Table 26 */
165
0
          int cplx_pred_all = 0; /* local use only */
166
0
          cplx_pred_all = FDKreadBits(bs, 1);
167
168
0
          if (cplx_pred_all) {
169
0
            for (group = 0; group < windowGroups; group++) {
170
0
              UCHAR groupmask = ((UCHAR)1 << group);
171
0
              for (band = 0; band < scaleFactorBandsTransmitted; band++) {
172
0
                pJointStereoData->MsUsed[band] |= groupmask;
173
0
              }
174
0
            }
175
0
          } else {
176
0
            for (group = 0; group < windowGroups; group++) {
177
0
              for (band = 0; band < scaleFactorBandsTransmitted;
178
0
                   band += SFB_PER_PRED_BAND) {
179
0
                pJointStereoData->MsUsed[band] |= (FDKreadBits(bs, 1) << group);
180
0
                if ((band + 1) < scaleFactorBandsTotal) {
181
0
                  pJointStereoData->MsUsed[band + 1] |=
182
0
                      (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group));
183
0
                }
184
0
              }
185
0
            }
186
0
          }
187
0
        } else {
188
0
          return -1;
189
0
        }
190
0
      }
191
0
      break;
192
0
  }
193
194
0
  if (cplxPredictionActiv) {
195
    /* If all sfb are MS-ed then no complex prediction */
196
0
    if (pJointStereoData->MsMaskPresent == 3) {
197
0
      if (pJointStereoData->cplx_pred_flag) {
198
0
        int delta_code_time = 0;
199
200
        /* set pointer to Huffman codebooks */
201
0
        const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[BOOKSCL];
202
        /* set predictors to zero in case of a transition from long to short
203
         * window sequences and vice versa */
204
0
        if (((windowSequence == BLOCK_SHORT) &&
205
0
             (pJointStereoPersistentData->winSeqPrev != BLOCK_SHORT)) ||
206
0
            ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) &&
207
0
             (windowSequence != BLOCK_SHORT))) {
208
0
          FDKmemclear(pJointStereoPersistentData->alpha_q_re_prev,
209
0
                      JointStereoMaximumGroups * JointStereoMaximumBands *
210
0
                          sizeof(SHORT));
211
0
          FDKmemclear(pJointStereoPersistentData->alpha_q_im_prev,
212
0
                      JointStereoMaximumGroups * JointStereoMaximumBands *
213
0
                          sizeof(SHORT));
214
0
        }
215
0
        {
216
0
          FDKmemclear(cplxPredictionData->alpha_q_re,
217
0
                      JointStereoMaximumGroups * JointStereoMaximumBands *
218
0
                          sizeof(SHORT));
219
0
          FDKmemclear(cplxPredictionData->alpha_q_im,
220
0
                      JointStereoMaximumGroups * JointStereoMaximumBands *
221
0
                          sizeof(SHORT));
222
0
        }
223
224
        /* 0 = mid->side prediction, 1 = side->mid prediction */
225
0
        cplxPredictionData->pred_dir = FDKreadBits(bs, 1);
226
0
        cplxPredictionData->complex_coef = FDKreadBits(bs, 1);
227
228
0
        if (cplxPredictionData->complex_coef) {
229
0
          if (flags & AC_INDEP) {
230
0
            cplxPredictionData->use_prev_frame = 0;
231
0
          } else {
232
0
            cplxPredictionData->use_prev_frame = FDKreadBits(bs, 1);
233
0
          }
234
0
        }
235
236
0
        if (flags & AC_INDEP) {
237
0
          delta_code_time = 0;
238
0
        } else {
239
0
          delta_code_time = FDKreadBits(bs, 1);
240
0
        }
241
242
0
        {
243
0
          int last_alpha_q_re = 0, last_alpha_q_im = 0;
244
245
0
          for (group = 0; group < windowGroups; group++) {
246
0
            for (band = 0; band < scaleFactorBandsTransmitted;
247
0
                 band += SFB_PER_PRED_BAND) {
248
0
              if (delta_code_time == 1) {
249
0
                if (group > 0) {
250
0
                  last_alpha_q_re =
251
0
                      cplxPredictionData->alpha_q_re[group - 1][band];
252
0
                  last_alpha_q_im =
253
0
                      cplxPredictionData->alpha_q_im[group - 1][band];
254
0
                } else if ((windowSequence == BLOCK_SHORT) &&
255
0
                           (pJointStereoPersistentData->winSeqPrev ==
256
0
                            BLOCK_SHORT)) {
257
                  /* Included for error-robustness */
258
0
                  if (pJointStereoPersistentData->winGroupsPrev == 0) return -1;
259
260
0
                  last_alpha_q_re =
261
0
                      pJointStereoPersistentData->alpha_q_re_prev
262
0
                          [pJointStereoPersistentData->winGroupsPrev - 1][band];
263
0
                  last_alpha_q_im =
264
0
                      pJointStereoPersistentData->alpha_q_im_prev
265
0
                          [pJointStereoPersistentData->winGroupsPrev - 1][band];
266
0
                } else {
267
0
                  last_alpha_q_re =
268
0
                      pJointStereoPersistentData->alpha_q_re_prev[group][band];
269
0
                  last_alpha_q_im =
270
0
                      pJointStereoPersistentData->alpha_q_im_prev[group][band];
271
0
                }
272
273
0
              } else {
274
0
                if (band > 0) {
275
0
                  last_alpha_q_re =
276
0
                      cplxPredictionData->alpha_q_re[group][band - 1];
277
0
                  last_alpha_q_im =
278
0
                      cplxPredictionData->alpha_q_im[group][band - 1];
279
0
                } else {
280
0
                  last_alpha_q_re = 0;
281
0
                  last_alpha_q_im = 0;
282
0
                }
283
284
0
              } /* if (delta_code_time == 1) */
285
286
0
              if (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)) {
287
0
                int dpcm_alpha_re, dpcm_alpha_im;
288
289
0
                dpcm_alpha_re = CBlock_DecodeHuffmanWord(bs, hcb);
290
0
                dpcm_alpha_re -= 60;
291
0
                dpcm_alpha_re *= -1;
292
293
0
                cplxPredictionData->alpha_q_re[group][band] =
294
0
                    dpcm_alpha_re + last_alpha_q_re;
295
296
0
                if (cplxPredictionData->complex_coef) {
297
0
                  dpcm_alpha_im = CBlock_DecodeHuffmanWord(bs, hcb);
298
0
                  dpcm_alpha_im -= 60;
299
0
                  dpcm_alpha_im *= -1;
300
301
0
                  cplxPredictionData->alpha_q_im[group][band] =
302
0
                      dpcm_alpha_im + last_alpha_q_im;
303
0
                } else {
304
0
                  cplxPredictionData->alpha_q_im[group][band] = 0;
305
0
                }
306
307
0
              } else {
308
0
                cplxPredictionData->alpha_q_re[group][band] = 0;
309
0
                cplxPredictionData->alpha_q_im[group][band] = 0;
310
0
              } /* if (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)) */
311
312
0
              if ((band + 1) <
313
0
                  scaleFactorBandsTransmitted) { /* <= this should be the
314
                                                    correct way (cp.
315
                                                    ISO_IEC_FDIS_23003-0(E) */
316
                /*    7.7.2.3.2 Decoding of prediction coefficients) */
317
0
                cplxPredictionData->alpha_q_re[group][band + 1] =
318
0
                    cplxPredictionData->alpha_q_re[group][band];
319
0
                cplxPredictionData->alpha_q_im[group][band + 1] =
320
0
                    cplxPredictionData->alpha_q_im[group][band];
321
0
              } /* if ((band+1)<scaleFactorBandsTotal) */
322
323
0
              pJointStereoPersistentData->alpha_q_re_prev[group][band] =
324
0
                  cplxPredictionData->alpha_q_re[group][band];
325
0
              pJointStereoPersistentData->alpha_q_im_prev[group][band] =
326
0
                  cplxPredictionData->alpha_q_im[group][band];
327
0
            }
328
329
0
            for (band = scaleFactorBandsTransmitted; band < max_sfb_ste_clear;
330
0
                 band++) {
331
0
              cplxPredictionData->alpha_q_re[group][band] = 0;
332
0
              cplxPredictionData->alpha_q_im[group][band] = 0;
333
0
              pJointStereoPersistentData->alpha_q_re_prev[group][band] = 0;
334
0
              pJointStereoPersistentData->alpha_q_im_prev[group][band] = 0;
335
0
            }
336
0
          }
337
0
        }
338
0
      }
339
0
    } else {
340
0
      for (group = 0; group < windowGroups; group++) {
341
0
        for (band = 0; band < max_sfb_ste_clear; band++) {
342
0
          pJointStereoPersistentData->alpha_q_re_prev[group][band] = 0;
343
0
          pJointStereoPersistentData->alpha_q_im_prev[group][band] = 0;
344
0
        }
345
0
      }
346
0
    }
347
348
0
    pJointStereoPersistentData->winGroupsPrev = windowGroups;
349
0
  }
350
351
0
  return 0;
352
0
}
353
354
static void CJointStereo_filterAndAdd(
355
    FIXP_DBL *in, int len, int windowLen, const FIXP_FILT *coeff, FIXP_DBL *out,
356
    UCHAR isCurrent /* output values with even index get a
357
                       positve addon (=1) or a negative addon
358
                       (=0) */
359
0
) {
360
0
  int i, j;
361
362
0
  int indices_1[] = {2, 1, 0, 1, 2, 3};
363
0
  int indices_2[] = {1, 0, 0, 2, 3, 4};
364
0
  int indices_3[] = {0, 0, 1, 3, 4, 5};
365
366
0
  int subtr_1[] = {6, 5, 4, 2, 1, 1};
367
0
  int subtr_2[] = {5, 4, 3, 1, 1, 2};
368
0
  int subtr_3[] = {4, 3, 2, 1, 2, 3};
369
370
0
  if (isCurrent == 1) {
371
    /* exploit the symmetry of the table: coeff[6] = - coeff[0],
372
                                          coeff[5] = - coeff[1],
373
                                          coeff[4] = - coeff[2],
374
                                          coeff[3] = 0
375
    */
376
377
0
    for (i = 0; i < 3; i++) {
378
0
      out[0] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[i]]) >> SR_FNA_OUT;
379
0
      out[0] +=
380
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[5 - i]]) >> SR_FNA_OUT;
381
0
    }
382
383
0
    for (i = 0; i < 3; i++) {
384
0
      out[1] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[i]]) >> SR_FNA_OUT;
385
0
      out[1] +=
386
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[5 - i]]) >> SR_FNA_OUT;
387
0
    }
388
389
0
    for (i = 0; i < 3; i++) {
390
0
      out[2] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[i]]) >> SR_FNA_OUT;
391
0
      out[2] +=
392
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[5 - i]]) >> SR_FNA_OUT;
393
0
    }
394
395
0
    for (j = 3; j < (len - 3); j++) {
396
0
      for (i = 0; i < 3; i++) {
397
0
        out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i]) >> SR_FNA_OUT;
398
0
        out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i]) >> SR_FNA_OUT;
399
0
      }
400
0
    }
401
402
0
    for (i = 0; i < 3; i++) {
403
0
      out[len - 3] -=
404
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[i]]) >> SR_FNA_OUT;
405
0
      out[len - 3] +=
406
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[5 - i]]) >> SR_FNA_OUT;
407
0
    }
408
409
0
    for (i = 0; i < 3; i++) {
410
0
      out[len - 2] -=
411
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[i]]) >> SR_FNA_OUT;
412
0
      out[len - 2] +=
413
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[5 - i]]) >> SR_FNA_OUT;
414
0
    }
415
416
0
    for (i = 0; i < 3; i++) {
417
0
      out[len - 1] -=
418
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[i]]) >> SR_FNA_OUT;
419
0
      out[len - 1] +=
420
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[5 - i]]) >> SR_FNA_OUT;
421
0
    }
422
423
0
  } else {
424
    /* exploit the symmetry of the table: coeff[6] = coeff[0],
425
                                          coeff[5] = coeff[1],
426
                                          coeff[4] = coeff[2]
427
    */
428
429
0
    for (i = 0; i < 3; i++) {
430
0
      out[0] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[i]] >> SR_FNA_OUT);
431
0
      out[0] -=
432
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[5 - i]] >> SR_FNA_OUT);
433
0
    }
434
0
    out[0] -= (FIXP_DBL)fMultDiv2(coeff[3], in[0] >> SR_FNA_OUT);
435
436
0
    for (i = 0; i < 3; i++) {
437
0
      out[1] += (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[i]] >> SR_FNA_OUT);
438
0
      out[1] +=
439
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[5 - i]] >> SR_FNA_OUT);
440
0
    }
441
0
    out[1] += (FIXP_DBL)fMultDiv2(coeff[3], in[1] >> SR_FNA_OUT);
442
443
0
    for (i = 0; i < 3; i++) {
444
0
      out[2] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[i]] >> SR_FNA_OUT);
445
0
      out[2] -=
446
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[5 - i]] >> SR_FNA_OUT);
447
0
    }
448
0
    out[2] -= (FIXP_DBL)fMultDiv2(coeff[3], in[2] >> SR_FNA_OUT);
449
450
0
    for (j = 3; j < (len - 4); j++) {
451
0
      for (i = 0; i < 3; i++) {
452
0
        out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i] >> SR_FNA_OUT);
453
0
        out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i] >> SR_FNA_OUT);
454
0
      }
455
0
      out[j] += (FIXP_DBL)fMultDiv2(coeff[3], in[j] >> SR_FNA_OUT);
456
457
0
      j++;
458
459
0
      for (i = 0; i < 3; i++) {
460
0
        out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i] >> SR_FNA_OUT);
461
0
        out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i] >> SR_FNA_OUT);
462
0
      }
463
0
      out[j] -= (FIXP_DBL)fMultDiv2(coeff[3], in[j] >> SR_FNA_OUT);
464
0
    }
465
466
0
    for (i = 0; i < 3; i++) {
467
0
      out[len - 3] +=
468
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[i]] >> SR_FNA_OUT);
469
0
      out[len - 3] +=
470
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[5 - i]] >> SR_FNA_OUT);
471
0
    }
472
0
    out[len - 3] += (FIXP_DBL)fMultDiv2(coeff[3], in[len - 3] >> SR_FNA_OUT);
473
474
0
    for (i = 0; i < 3; i++) {
475
0
      out[len - 2] -=
476
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[i]] >> SR_FNA_OUT);
477
0
      out[len - 2] -=
478
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[5 - i]] >> SR_FNA_OUT);
479
0
    }
480
0
    out[len - 2] -= (FIXP_DBL)fMultDiv2(coeff[3], in[len - 2] >> SR_FNA_OUT);
481
482
0
    for (i = 0; i < 3; i++) {
483
0
      out[len - 1] +=
484
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[i]] >> SR_FNA_OUT);
485
0
      out[len - 1] +=
486
0
          (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[5 - i]] >> SR_FNA_OUT);
487
0
    }
488
0
    out[len - 1] += (FIXP_DBL)fMultDiv2(coeff[3], in[len - 1] >> SR_FNA_OUT);
489
0
  }
490
0
}
491
492
static inline void CJointStereo_GenerateMSOutput(FIXP_DBL *pSpecLCurrBand,
493
                                                 FIXP_DBL *pSpecRCurrBand,
494
                                                 UINT leftScale,
495
                                                 UINT rightScale,
496
0
                                                 UINT nSfbBands) {
497
0
  unsigned int i;
498
499
0
  FIXP_DBL leftCoefficient0;
500
0
  FIXP_DBL leftCoefficient1;
501
0
  FIXP_DBL leftCoefficient2;
502
0
  FIXP_DBL leftCoefficient3;
503
504
0
  FIXP_DBL rightCoefficient0;
505
0
  FIXP_DBL rightCoefficient1;
506
0
  FIXP_DBL rightCoefficient2;
507
0
  FIXP_DBL rightCoefficient3;
508
509
0
  for (i = nSfbBands; i > 0; i -= 4) {
510
0
    leftCoefficient0 = pSpecLCurrBand[i - 4];
511
0
    leftCoefficient1 = pSpecLCurrBand[i - 3];
512
0
    leftCoefficient2 = pSpecLCurrBand[i - 2];
513
0
    leftCoefficient3 = pSpecLCurrBand[i - 1];
514
515
0
    rightCoefficient0 = pSpecRCurrBand[i - 4];
516
0
    rightCoefficient1 = pSpecRCurrBand[i - 3];
517
0
    rightCoefficient2 = pSpecRCurrBand[i - 2];
518
0
    rightCoefficient3 = pSpecRCurrBand[i - 1];
519
520
    /* MS output generation */
521
0
    leftCoefficient0 >>= leftScale;
522
0
    leftCoefficient1 >>= leftScale;
523
0
    leftCoefficient2 >>= leftScale;
524
0
    leftCoefficient3 >>= leftScale;
525
526
0
    rightCoefficient0 >>= rightScale;
527
0
    rightCoefficient1 >>= rightScale;
528
0
    rightCoefficient2 >>= rightScale;
529
0
    rightCoefficient3 >>= rightScale;
530
531
0
    pSpecLCurrBand[i - 4] = leftCoefficient0 + rightCoefficient0;
532
0
    pSpecLCurrBand[i - 3] = leftCoefficient1 + rightCoefficient1;
533
0
    pSpecLCurrBand[i - 2] = leftCoefficient2 + rightCoefficient2;
534
0
    pSpecLCurrBand[i - 1] = leftCoefficient3 + rightCoefficient3;
535
536
0
    pSpecRCurrBand[i - 4] = leftCoefficient0 - rightCoefficient0;
537
0
    pSpecRCurrBand[i - 3] = leftCoefficient1 - rightCoefficient1;
538
0
    pSpecRCurrBand[i - 2] = leftCoefficient2 - rightCoefficient2;
539
0
    pSpecRCurrBand[i - 1] = leftCoefficient3 - rightCoefficient3;
540
0
  }
541
0
}
542
543
void CJointStereo_ApplyMS(
544
    CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
545
    CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2],
546
    FIXP_DBL *spectrumL, FIXP_DBL *spectrumR, SHORT *SFBleftScale,
547
    SHORT *SFBrightScale, SHORT *specScaleL, SHORT *specScaleR,
548
    const SHORT *pScaleFactorBandOffsets, const UCHAR *pWindowGroupLength,
549
    const int windowGroups, const int max_sfb_ste_outside,
550
    const int scaleFactorBandsTransmittedL,
551
    const int scaleFactorBandsTransmittedR, FIXP_DBL *store_dmx_re_prev,
552
0
    SHORT *store_dmx_re_prev_e, const int mainband_flag) {
553
0
  int window, group, band;
554
0
  UCHAR groupMask;
555
0
  CJointStereoData *pJointStereoData =
556
0
      &pAacDecoderChannelInfo[L]->pComData->jointStereoData;
557
0
  CCplxPredictionData *cplxPredictionData =
558
0
      pAacDecoderChannelInfo[L]->pComStaticData->cplxPredictionData;
559
560
0
  int max_sfb_ste =
561
0
      fMax(scaleFactorBandsTransmittedL, scaleFactorBandsTransmittedR);
562
0
  int min_sfb_ste =
563
0
      fMin(scaleFactorBandsTransmittedL, scaleFactorBandsTransmittedR);
564
0
  int scaleFactorBandsTransmitted = min_sfb_ste;
565
566
0
  if (pJointStereoData->cplx_pred_flag) {
567
0
    int windowLen, groupwin, frameMaxScale;
568
0
    CJointStereoPersistentData *pJointStereoPersistentData =
569
0
        &pAacDecoderStaticChannelInfo[L]
570
0
             ->pCpeStaticData->jointStereoPersistentData;
571
0
    FIXP_DBL *const staticSpectralCoeffsL =
572
0
        pAacDecoderStaticChannelInfo[L]
573
0
            ->pCpeStaticData->jointStereoPersistentData.spectralCoeffs[L];
574
0
    FIXP_DBL *const staticSpectralCoeffsR =
575
0
        pAacDecoderStaticChannelInfo[L]
576
0
            ->pCpeStaticData->jointStereoPersistentData.spectralCoeffs[R];
577
0
    SHORT *const staticSpecScaleL =
578
0
        pAacDecoderStaticChannelInfo[L]
579
0
            ->pCpeStaticData->jointStereoPersistentData.specScale[L];
580
0
    SHORT *const staticSpecScaleR =
581
0
        pAacDecoderStaticChannelInfo[L]
582
0
            ->pCpeStaticData->jointStereoPersistentData.specScale[R];
583
584
0
    FIXP_DBL *dmx_re =
585
0
        pAacDecoderStaticChannelInfo[L]
586
0
            ->pCpeStaticData->jointStereoPersistentData.scratchBuffer;
587
0
    FIXP_DBL *dmx_re_prev =
588
0
        pAacDecoderStaticChannelInfo[L]
589
0
            ->pCpeStaticData->jointStereoPersistentData.scratchBuffer +
590
0
        1024;
591
592
    /* When MS is applied over the main band this value gets computed. Otherwise
593
     * (for the tiles) it uses the assigned value */
594
0
    SHORT dmx_re_prev_e = *store_dmx_re_prev_e;
595
596
0
    const FIXP_FILT *pCoeff;
597
0
    const FIXP_FILT *pCoeffPrev;
598
0
    int coeffPointerOffset;
599
600
0
    int previousShape = (int)pJointStereoPersistentData->winShapePrev;
601
0
    int currentShape = (int)pAacDecoderChannelInfo[L]->icsInfo.WindowShape;
602
603
    /* complex stereo prediction */
604
605
    /* 0. preparations */
606
607
    /* 0.0. get scratch buffer for downmix MDST */
608
0
    C_AALLOC_SCRATCH_START(dmx_im, FIXP_DBL, 1024);
609
610
    /* 0.1. window lengths */
611
612
    /* get length of short window for current configuration */
613
0
    windowLen =
614
0
        pAacDecoderChannelInfo[L]->granuleLength; /* framelength 768 => 96,
615
                                                     framelength 1024 => 128 */
616
617
    /* if this is no short-block set length for long-block */
618
0
    if (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence != BLOCK_SHORT) {
619
0
      windowLen *= 8;
620
0
    }
621
622
    /* 0.2. set pointer to filter-coefficients for MDST excitation including
623
     * previous frame portions */
624
    /*      cp. ISO/IEC FDIS 23003-3:2011(E) table 125 */
625
626
    /* set pointer to default-position */
627
0
    pCoeffPrev = mdst_filt_coef_prev[previousShape];
628
629
0
    if (cplxPredictionData->complex_coef == 1) {
630
0
      switch (pAacDecoderChannelInfo[L]
631
0
                  ->icsInfo.WindowSequence) { /* current window sequence */
632
0
        case BLOCK_SHORT:
633
0
        case BLOCK_LONG:
634
0
          pCoeffPrev = mdst_filt_coef_prev[previousShape];
635
0
          break;
636
637
0
        case BLOCK_START:
638
0
          if ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) ||
639
0
              (pJointStereoPersistentData->winSeqPrev == BLOCK_START)) {
640
            /* a stop-start-sequence can only follow on an eight-short-sequence
641
             * or a start-sequence */
642
0
            pCoeffPrev = mdst_filt_coef_prev[2 + previousShape];
643
0
          } else {
644
0
            pCoeffPrev = mdst_filt_coef_prev[previousShape];
645
0
          }
646
0
          break;
647
648
0
        case BLOCK_STOP:
649
0
          pCoeffPrev = mdst_filt_coef_prev[2 + previousShape];
650
0
          break;
651
652
0
        default:
653
0
          pCoeffPrev = mdst_filt_coef_prev[previousShape];
654
0
          break;
655
0
      }
656
0
    }
657
658
    /* 0.3. set pointer to filter-coefficients for MDST excitation */
659
660
    /* define offset of pointer to filter-coefficients for MDST exitation
661
     * employing only the current frame */
662
0
    if ((previousShape == SHAPE_SINE) && (currentShape == SHAPE_SINE)) {
663
0
      coeffPointerOffset = 0;
664
0
    } else if ((previousShape == SHAPE_SINE) && (currentShape == SHAPE_KBD)) {
665
0
      coeffPointerOffset = 2;
666
0
    } else if ((previousShape == SHAPE_KBD) && (currentShape == SHAPE_KBD)) {
667
0
      coeffPointerOffset = 1;
668
0
    } else /* if ( (previousShape == SHAPE_KBD) && (currentShape == SHAPE_SINE)
669
              ) */
670
0
    {
671
0
      coeffPointerOffset = 3;
672
0
    }
673
674
    /* set pointer to filter-coefficient table cp. ISO/IEC FDIS 23003-3:2011(E)
675
     * table 124 */
676
0
    switch (pAacDecoderChannelInfo[L]
677
0
                ->icsInfo.WindowSequence) { /* current window sequence */
678
0
      case BLOCK_SHORT:
679
0
      case BLOCK_LONG:
680
0
        pCoeff = mdst_filt_coef_curr[coeffPointerOffset];
681
0
        break;
682
683
0
      case BLOCK_START:
684
0
        if ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) ||
685
0
            (pJointStereoPersistentData->winSeqPrev == BLOCK_START)) {
686
          /* a stop-start-sequence can only follow on an eight-short-sequence or
687
           * a start-sequence */
688
0
          pCoeff = mdst_filt_coef_curr[12 + coeffPointerOffset];
689
0
        } else {
690
0
          pCoeff = mdst_filt_coef_curr[4 + coeffPointerOffset];
691
0
        }
692
0
        break;
693
694
0
      case BLOCK_STOP:
695
0
        pCoeff = mdst_filt_coef_curr[8 + coeffPointerOffset];
696
0
        break;
697
698
0
      default:
699
0
        pCoeff = mdst_filt_coef_curr[coeffPointerOffset];
700
0
    }
701
702
    /* 0.4. find maximum common (l/r) band-scaling-factor for whole sequence
703
     * (all windows) */
704
0
    frameMaxScale = 0;
705
0
    for (window = 0, group = 0; group < windowGroups; group++) {
706
0
      for (groupwin = 0; groupwin < pWindowGroupLength[group];
707
0
           groupwin++, window++) {
708
0
        SHORT *leftScale = &SFBleftScale[window * 16];
709
0
        SHORT *rightScale = &SFBrightScale[window * 16];
710
0
        int windowMaxScale = 0;
711
712
        /* find maximum scaling factor of all bands in this window */
713
0
        for (band = 0; band < min_sfb_ste; band++) {
714
0
          int lScale = leftScale[band];
715
0
          int rScale = rightScale[band];
716
0
          int commonScale = ((lScale > rScale) ? lScale : rScale);
717
0
          windowMaxScale =
718
0
              (windowMaxScale < commonScale) ? commonScale : windowMaxScale;
719
0
        }
720
0
        if (scaleFactorBandsTransmittedL >
721
0
            min_sfb_ste) { /* i.e. scaleFactorBandsTransmittedL == max_sfb_ste
722
                            */
723
0
          for (; band < max_sfb_ste; band++) {
724
0
            int lScale = leftScale[band];
725
0
            windowMaxScale =
726
0
                (windowMaxScale < lScale) ? lScale : windowMaxScale;
727
0
          }
728
0
        } else {
729
0
          if (scaleFactorBandsTransmittedR >
730
0
              min_sfb_ste) { /* i.e. scaleFactorBandsTransmittedR == max_sfb_ste
731
                              */
732
0
            for (; band < max_sfb_ste; band++) {
733
0
              int rScale = rightScale[band];
734
0
              windowMaxScale =
735
0
                  (windowMaxScale < rScale) ? rScale : windowMaxScale;
736
0
            }
737
0
          }
738
0
        }
739
740
        /* find maximum common SF of all windows */
741
0
        frameMaxScale =
742
0
            (frameMaxScale < windowMaxScale) ? windowMaxScale : frameMaxScale;
743
0
      }
744
0
    }
745
746
    /* add some headroom for overflow protection during filter and add operation
747
     */
748
0
    frameMaxScale += 2;
749
750
    /* process on window-basis (i.e. iterate over all groups and corresponding
751
     * windows) */
752
0
    for (window = 0, group = 0; group < windowGroups; group++) {
753
0
      groupMask = 1 << group;
754
755
0
      for (groupwin = 0; groupwin < pWindowGroupLength[group];
756
0
           groupwin++, window++) {
757
        /* initialize the MDST with zeros */
758
0
        FDKmemclear(&dmx_im[windowLen * window], windowLen * sizeof(FIXP_DBL));
759
760
        /* 1. calculate the previous downmix MDCT. We do this once just for the
761
         * Main band. */
762
0
        if (cplxPredictionData->complex_coef == 1) {
763
0
          if ((cplxPredictionData->use_prev_frame == 1) && (mainband_flag)) {
764
            /* if this is a long-block or the first window of a short-block
765
               calculate the downmix MDCT of the previous frame.
766
               use_prev_frame is assumed not to change during a frame!
767
            */
768
769
            /* first determine shiftfactors to scale left and right channel */
770
0
            if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence !=
771
0
                 BLOCK_SHORT) ||
772
0
                (window == 0)) {
773
0
              int index_offset = 0;
774
0
              int srLeftChan = 0;
775
0
              int srRightChan = 0;
776
0
              if (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
777
0
                  BLOCK_SHORT) {
778
                /* use the last window of the previous frame for MDCT
779
                 * calculation if this is a short-block. */
780
0
                index_offset = windowLen * 7;
781
0
                if (staticSpecScaleL[7] > staticSpecScaleR[7]) {
782
0
                  srRightChan = staticSpecScaleL[7] - staticSpecScaleR[7];
783
0
                  dmx_re_prev_e = staticSpecScaleL[7];
784
0
                } else {
785
0
                  srLeftChan = staticSpecScaleR[7] - staticSpecScaleL[7];
786
0
                  dmx_re_prev_e = staticSpecScaleR[7];
787
0
                }
788
0
              } else {
789
0
                if (staticSpecScaleL[0] > staticSpecScaleR[0]) {
790
0
                  srRightChan = staticSpecScaleL[0] - staticSpecScaleR[0];
791
0
                  dmx_re_prev_e = staticSpecScaleL[0];
792
0
                } else {
793
0
                  srLeftChan = staticSpecScaleR[0] - staticSpecScaleL[0];
794
0
                  dmx_re_prev_e = staticSpecScaleR[0];
795
0
                }
796
0
              }
797
798
              /* now scale channels and determine downmix MDCT of previous frame
799
               */
800
0
              if (pAacDecoderStaticChannelInfo[L]
801
0
                      ->pCpeStaticData->jointStereoPersistentData
802
0
                      .clearSpectralCoeffs == 1) {
803
0
                FDKmemclear(dmx_re_prev, windowLen * sizeof(FIXP_DBL));
804
0
                dmx_re_prev_e = 0;
805
0
              } else {
806
0
                if (cplxPredictionData->pred_dir == 0) {
807
0
                  for (int i = 0; i < windowLen; i++) {
808
0
                    dmx_re_prev[i] =
809
0
                        ((staticSpectralCoeffsL[index_offset + i] >>
810
0
                          fMin(DFRACT_BITS - 1, srLeftChan + 1)) +
811
0
                         (staticSpectralCoeffsR[index_offset + i] >>
812
0
                          fMin(DFRACT_BITS - 1, srRightChan + 1)));
813
0
                  }
814
0
                } else {
815
0
                  for (int i = 0; i < windowLen; i++) {
816
0
                    dmx_re_prev[i] =
817
0
                        ((staticSpectralCoeffsL[index_offset + i] >>
818
0
                          fMin(DFRACT_BITS - 1, srLeftChan + 1)) -
819
0
                         (staticSpectralCoeffsR[index_offset + i] >>
820
0
                          fMin(DFRACT_BITS - 1, srRightChan + 1)));
821
0
                  }
822
0
                }
823
0
              }
824
825
              /* In case that we use INF we have to preserve the state of the
826
              "dmx_re_prev" (original or computed). This is necessary because we
827
              have to apply MS over the separate IGF tiles. */
828
0
              FDKmemcpy(store_dmx_re_prev, &dmx_re_prev[0],
829
0
                        windowLen * sizeof(FIXP_DBL));
830
831
              /* Particular exponent of the computed/original "dmx_re_prev" must
832
               * be kept for the tile MS calculations if necessary.*/
833
0
              *store_dmx_re_prev_e = dmx_re_prev_e;
834
835
0
            } /* if ( (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence !=
836
                 BLOCK_SHORT) || (window == 0) ) */
837
838
0
          } /* if ( pJointStereoData->use_prev_frame == 1 ) */
839
840
0
        } /* if ( pJointStereoData->complex_coef == 1 ) */
841
842
        /* 2. calculate downmix MDCT of current frame */
843
844
        /* set pointer to scale-factor-bands of current window */
845
0
        SHORT *leftScale = &SFBleftScale[window * 16];
846
0
        SHORT *rightScale = &SFBrightScale[window * 16];
847
848
0
        specScaleL[window] = specScaleR[window] = frameMaxScale;
849
850
        /* adapt scaling-factors to previous frame */
851
0
        if (cplxPredictionData->use_prev_frame == 1) {
852
0
          if (window == 0) {
853
0
            if (dmx_re_prev_e < frameMaxScale) {
854
0
              if (mainband_flag == 0) {
855
0
                scaleValues(
856
0
                    dmx_re_prev, store_dmx_re_prev, windowLen,
857
0
                    -fMin(DFRACT_BITS - 1, (frameMaxScale - dmx_re_prev_e)));
858
0
              } else {
859
0
                scaleValues(
860
0
                    dmx_re_prev, windowLen,
861
0
                    -fMin(DFRACT_BITS - 1, (frameMaxScale - dmx_re_prev_e)));
862
0
              }
863
0
            } else {
864
0
              if (mainband_flag == 0) {
865
0
                FDKmemcpy(dmx_re_prev, store_dmx_re_prev,
866
0
                          windowLen * sizeof(FIXP_DBL));
867
0
              }
868
0
              specScaleL[0] = dmx_re_prev_e;
869
0
              specScaleR[0] = dmx_re_prev_e;
870
0
            }
871
0
          } else { /* window != 0 */
872
0
            FDK_ASSERT(pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
873
0
                       BLOCK_SHORT);
874
0
            if (specScaleL[window - 1] < frameMaxScale) {
875
0
              scaleValues(&dmx_re[windowLen * (window - 1)], windowLen,
876
0
                          -fMin(DFRACT_BITS - 1,
877
0
                                (frameMaxScale - specScaleL[window - 1])));
878
0
            } else {
879
0
              specScaleL[window] = specScaleL[window - 1];
880
0
              specScaleR[window] = specScaleR[window - 1];
881
0
            }
882
0
          }
883
0
        } /* if ( pJointStereoData->use_prev_frame == 1 ) */
884
885
        /* scaling factors of both channels ought to be equal now */
886
0
        FDK_ASSERT(specScaleL[window] == specScaleR[window]);
887
888
        /* rescale signal and calculate downmix MDCT */
889
0
        for (band = 0; band < max_sfb_ste; band++) {
890
          /* first adapt scaling of current band to scaling of current window =>
891
           * shift signal right */
892
0
          int lScale = leftScale[band];
893
0
          int rScale = rightScale[band];
894
895
0
          lScale = fMin(DFRACT_BITS - 1, specScaleL[window] - lScale);
896
0
          rScale = fMin(DFRACT_BITS - 1,
897
0
                        specScaleL[window] - rScale); /* L or R doesn't
898
                                                         matter,
899
                                                         specScales are
900
                                                         equal at this
901
                                                         point */
902
903
          /* Write back to sfb scale to cover the case when max_sfb_ste <
904
           * max_sfb */
905
0
          leftScale[band] = rightScale[band] = specScaleL[window];
906
907
0
          for (int i = pScaleFactorBandOffsets[band];
908
0
               i < pScaleFactorBandOffsets[band + 1]; i++) {
909
0
            spectrumL[windowLen * window + i] >>= lScale;
910
0
            spectrumR[windowLen * window + i] >>= rScale;
911
0
          }
912
913
          /* now calculate downmix MDCT */
914
0
          if (pJointStereoData->MsUsed[band] & groupMask) {
915
0
            for (int i = pScaleFactorBandOffsets[band];
916
0
                 i < pScaleFactorBandOffsets[band + 1]; i++) {
917
0
              dmx_re[windowLen * window + i] =
918
0
                  spectrumL[windowLen * window + i];
919
0
            }
920
0
          } else {
921
0
            if (cplxPredictionData->pred_dir == 0) {
922
0
              for (int i = pScaleFactorBandOffsets[band];
923
0
                   i < pScaleFactorBandOffsets[band + 1]; i++) {
924
0
                dmx_re[windowLen * window + i] =
925
0
                    (spectrumL[windowLen * window + i] +
926
0
                     spectrumR[windowLen * window + i]) >>
927
0
                    1;
928
0
              }
929
0
            } else {
930
0
              for (int i = pScaleFactorBandOffsets[band];
931
0
                   i < pScaleFactorBandOffsets[band + 1]; i++) {
932
0
                dmx_re[windowLen * window + i] =
933
0
                    (spectrumL[windowLen * window + i] -
934
0
                     spectrumR[windowLen * window + i]) >>
935
0
                    1;
936
0
              }
937
0
            }
938
0
          }
939
940
0
        } /* for ( band=0; band<max_sfb_ste; band++ ) */
941
        /* Clean until the end */
942
0
        for (int i = pScaleFactorBandOffsets[max_sfb_ste_outside];
943
0
             i < windowLen; i++) {
944
0
          dmx_re[windowLen * window + i] = (FIXP_DBL)0;
945
0
        }
946
947
        /* 3. calculate MDST-portion corresponding to the current frame. */
948
0
        if (cplxPredictionData->complex_coef == 1) {
949
0
          {
950
            /* 3.1 move pointer in filter-coefficient table in case of short
951
             * window sequence */
952
            /*     (other coefficients are utilized for the last 7 short
953
             * windows)            */
954
0
            if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
955
0
                 BLOCK_SHORT) &&
956
0
                (window != 0)) {
957
0
              pCoeff = mdst_filt_coef_curr[currentShape];
958
0
              pCoeffPrev = mdst_filt_coef_prev[currentShape];
959
0
            }
960
961
            /* The length of the filter processing must be extended because of
962
             * filter boundary problems */
963
0
            int extended_band = fMin(
964
0
                pScaleFactorBandOffsets[max_sfb_ste_outside] + 7, windowLen);
965
966
            /* 3.2. estimate downmix MDST from current frame downmix MDCT */
967
0
            if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
968
0
                 BLOCK_SHORT) &&
969
0
                (window != 0)) {
970
0
              CJointStereo_filterAndAdd(&dmx_re[windowLen * window],
971
0
                                        extended_band, windowLen, pCoeff,
972
0
                                        &dmx_im[windowLen * window], 1);
973
974
0
              CJointStereo_filterAndAdd(&dmx_re[windowLen * (window - 1)],
975
0
                                        extended_band, windowLen, pCoeffPrev,
976
0
                                        &dmx_im[windowLen * window], 0);
977
0
            } else {
978
0
              CJointStereo_filterAndAdd(dmx_re, extended_band, windowLen,
979
0
                                        pCoeff, dmx_im, 1);
980
981
0
              if (cplxPredictionData->use_prev_frame == 1) {
982
0
                CJointStereo_filterAndAdd(dmx_re_prev, extended_band, windowLen,
983
0
                                          pCoeffPrev,
984
0
                                          &dmx_im[windowLen * window], 0);
985
0
              }
986
0
            }
987
988
0
          } /* if(pAacDecoderChannelInfo[L]->transform_splitting_active) */
989
0
        }   /* if ( pJointStereoData->complex_coef == 1 ) */
990
991
        /* 4. upmix process */
992
0
        LONG pred_dir = cplxPredictionData->pred_dir ? -1 : 1;
993
        /* 0.1 in Q-3.34 */
994
0
        const FIXP_DBL pointOne = 0x66666666; /* 0.8 */
995
        /* Shift value for the downmix */
996
0
        const INT shift_dmx = SF_FNA_COEFFS + 1;
997
998
0
        for (band = 0; band < max_sfb_ste_outside; band++) {
999
0
          if (pJointStereoData->MsUsed[band] & groupMask) {
1000
0
            FIXP_SGL tempRe =
1001
0
                (FIXP_SGL)cplxPredictionData->alpha_q_re[group][band];
1002
0
            FIXP_SGL tempIm =
1003
0
                (FIXP_SGL)cplxPredictionData->alpha_q_im[group][band];
1004
1005
            /* Find the minimum common headroom for alpha_re and alpha_im */
1006
0
            int alpha_re_headroom = CountLeadingBits((INT)tempRe) - 16;
1007
0
            if (tempRe == (FIXP_SGL)0) alpha_re_headroom = 15;
1008
0
            int alpha_im_headroom = CountLeadingBits((INT)tempIm) - 16;
1009
0
            if (tempIm == (FIXP_SGL)0) alpha_im_headroom = 15;
1010
0
            int val = fMin(alpha_re_headroom, alpha_im_headroom);
1011
1012
            /* Multiply alpha by 0.1 with maximum precision */
1013
0
            FDK_ASSERT(val >= 0);
1014
0
            FIXP_DBL alpha_re_tmp = fMult((FIXP_SGL)(tempRe << val), pointOne);
1015
0
            FIXP_DBL alpha_im_tmp = fMult((FIXP_SGL)(tempIm << val), pointOne);
1016
1017
            /* Calculate alpha exponent */
1018
            /* (Q-3.34 * Q15.0) shifted left by "val" */
1019
0
            int alpha_re_exp = -3 + 15 - val;
1020
1021
0
            int help3_shift = alpha_re_exp + 1;
1022
1023
0
            FIXP_DBL *p2CoeffL = &(
1024
0
                spectrumL[windowLen * window + pScaleFactorBandOffsets[band]]);
1025
0
            FIXP_DBL *p2CoeffR = &(
1026
0
                spectrumR[windowLen * window + pScaleFactorBandOffsets[band]]);
1027
0
            FIXP_DBL *p2dmxIm =
1028
0
                &(dmx_im[windowLen * window + pScaleFactorBandOffsets[band]]);
1029
0
            FIXP_DBL *p2dmxRe =
1030
0
                &(dmx_re[windowLen * window + pScaleFactorBandOffsets[band]]);
1031
1032
0
            for (int i = pScaleFactorBandOffsets[band];
1033
0
                 i < pScaleFactorBandOffsets[band + 1]; i++) {
1034
              /* Calculating helper term:
1035
                    side = specR[i] - alpha_re[i] * dmx_re[i] - alpha_im[i] *
1036
                dmx_im[i];
1037
1038
                Here "dmx_re" may be the same as "specL" or alternatively keep
1039
                the downmix. "dmx_re" and "specL" are two different pointers
1040
                pointing to separate arrays, which may or may not contain the
1041
                same data (with different scaling).
1042
1043
                specL[i] =   + (specL[i] + side);
1044
                specR[i] = -/+ (specL[i] - side);
1045
              */
1046
0
              FIXP_DBL side, left, right;
1047
1048
0
              side = fMultAddDiv2(fMultDiv2(alpha_re_tmp, *p2dmxRe++),
1049
0
                                  alpha_im_tmp, (*p2dmxIm++) << shift_dmx);
1050
0
              side = ((*p2CoeffR) >> 2) -
1051
0
                     (FIXP_DBL)SATURATE_SHIFT(side, -(help3_shift - 2),
1052
0
                                              DFRACT_BITS - 2);
1053
1054
0
              left = ((*p2CoeffL) >> 2) + side;
1055
0
              right = ((*p2CoeffL) >> 2) - side;
1056
0
              right = (FIXP_DBL)((LONG)right * pred_dir);
1057
1058
0
              *p2CoeffL++ = SATURATE_LEFT_SHIFT_ALT(left, 2, DFRACT_BITS);
1059
0
              *p2CoeffR++ = SATURATE_LEFT_SHIFT_ALT(right, 2, DFRACT_BITS);
1060
0
            }
1061
0
          }
1062
1063
0
        } /* for ( band=0; band < max_sfb_ste; band++ ) */
1064
0
      }   /* for ( groupwin=0; groupwin<pWindowGroupLength[group]; groupwin++,
1065
             window++ ) */
1066
1067
0
    } /* for ( window = 0, group = 0; group < windowGroups; group++ ) */
1068
1069
    /* free scratch buffer */
1070
0
    C_AALLOC_SCRATCH_END(dmx_im, FIXP_DBL, 1024);
1071
1072
0
  } else {
1073
    /* MS stereo */
1074
1075
0
    for (window = 0, group = 0; group < windowGroups; group++) {
1076
0
      groupMask = 1 << group;
1077
1078
0
      for (int groupwin = 0; groupwin < pWindowGroupLength[group];
1079
0
           groupwin++, window++) {
1080
0
        FIXP_DBL *leftSpectrum, *rightSpectrum;
1081
0
        SHORT *leftScale = &SFBleftScale[window * 16];
1082
0
        SHORT *rightScale = &SFBrightScale[window * 16];
1083
1084
0
        leftSpectrum =
1085
0
            SPEC(spectrumL, window, pAacDecoderChannelInfo[L]->granuleLength);
1086
0
        rightSpectrum =
1087
0
            SPEC(spectrumR, window, pAacDecoderChannelInfo[R]->granuleLength);
1088
1089
0
        for (band = 0; band < max_sfb_ste_outside; band++) {
1090
0
          if (pJointStereoData->MsUsed[band] & groupMask) {
1091
0
            int lScale = leftScale[band];
1092
0
            int rScale = rightScale[band];
1093
0
            int commonScale = lScale > rScale ? lScale : rScale;
1094
0
            unsigned int offsetCurrBand, offsetNextBand;
1095
1096
            /* ISO/IEC 14496-3 Chapter 4.6.8.1.1 :
1097
               M/S joint channel coding can only be used if common_window is 1.
1098
             */
1099
0
            FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) ==
1100
0
                       GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo));
1101
0
            FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) ==
1102
0
                       GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo));
1103
1104
0
            commonScale++;
1105
0
            leftScale[band] = commonScale;
1106
0
            rightScale[band] = commonScale;
1107
1108
0
            lScale = fMin(DFRACT_BITS - 1, commonScale - lScale);
1109
0
            rScale = fMin(DFRACT_BITS - 1, commonScale - rScale);
1110
1111
0
            FDK_ASSERT(lScale >= 0 && rScale >= 0);
1112
1113
0
            offsetCurrBand = pScaleFactorBandOffsets[band];
1114
0
            offsetNextBand = pScaleFactorBandOffsets[band + 1];
1115
1116
0
            CJointStereo_GenerateMSOutput(&(leftSpectrum[offsetCurrBand]),
1117
0
                                          &(rightSpectrum[offsetCurrBand]),
1118
0
                                          lScale, rScale,
1119
0
                                          offsetNextBand - offsetCurrBand);
1120
0
          }
1121
0
        }
1122
0
        if (scaleFactorBandsTransmittedL > scaleFactorBandsTransmitted) {
1123
0
          for (; band < scaleFactorBandsTransmittedL; band++) {
1124
0
            if (pJointStereoData->MsUsed[band] & groupMask) {
1125
0
              rightScale[band] = leftScale[band];
1126
1127
0
              for (int index = pScaleFactorBandOffsets[band];
1128
0
                   index < pScaleFactorBandOffsets[band + 1]; index++) {
1129
0
                FIXP_DBL leftCoefficient = leftSpectrum[index];
1130
                /* FIXP_DBL rightCoefficient = (FIXP_DBL)0; */
1131
0
                rightSpectrum[index] = leftCoefficient;
1132
0
              }
1133
0
            }
1134
0
          }
1135
0
        } else if (scaleFactorBandsTransmittedR > scaleFactorBandsTransmitted) {
1136
0
          for (; band < scaleFactorBandsTransmittedR; band++) {
1137
0
            if (pJointStereoData->MsUsed[band] & groupMask) {
1138
0
              leftScale[band] = rightScale[band];
1139
1140
0
              for (int index = pScaleFactorBandOffsets[band];
1141
0
                   index < pScaleFactorBandOffsets[band + 1]; index++) {
1142
                /* FIXP_DBL leftCoefficient  = (FIXP_DBL)0; */
1143
0
                FIXP_DBL rightCoefficient = rightSpectrum[index];
1144
1145
0
                leftSpectrum[index] = rightCoefficient;
1146
0
                rightSpectrum[index] = -rightCoefficient;
1147
0
              }
1148
0
            }
1149
0
          }
1150
0
        }
1151
0
      }
1152
0
    }
1153
1154
    /* Reset MsUsed flags if no explicit signalling was transmitted. Necessary
1155
       for intensity coding. PNS correlation signalling was mapped before
1156
       calling CJointStereo_ApplyMS(). */
1157
0
    if (pJointStereoData->MsMaskPresent == 2) {
1158
0
      FDKmemclear(pJointStereoData->MsUsed,
1159
0
                  JointStereoMaximumBands * sizeof(UCHAR));
1160
0
    }
1161
0
  }
1162
0
}
1163
1164
void CJointStereo_ApplyIS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
1165
                          const SHORT *pScaleFactorBandOffsets,
1166
                          const UCHAR *pWindowGroupLength,
1167
                          const int windowGroups,
1168
0
                          const int scaleFactorBandsTransmitted) {
1169
0
  CJointStereoData *pJointStereoData =
1170
0
      &pAacDecoderChannelInfo[L]->pComData->jointStereoData;
1171
1172
0
  for (int window = 0, group = 0; group < windowGroups; group++) {
1173
0
    UCHAR *CodeBook;
1174
0
    SHORT *ScaleFactor;
1175
0
    UCHAR groupMask = 1 << group;
1176
1177
0
    CodeBook = &pAacDecoderChannelInfo[R]->pDynData->aCodeBook[group * 16];
1178
0
    ScaleFactor =
1179
0
        &pAacDecoderChannelInfo[R]->pDynData->aScaleFactor[group * 16];
1180
1181
0
    for (int groupwin = 0; groupwin < pWindowGroupLength[group];
1182
0
         groupwin++, window++) {
1183
0
      FIXP_DBL *leftSpectrum, *rightSpectrum;
1184
0
      SHORT *leftScale =
1185
0
          &pAacDecoderChannelInfo[L]->pDynData->aSfbScale[window * 16];
1186
0
      SHORT *rightScale =
1187
0
          &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window * 16];
1188
0
      int band;
1189
1190
0
      leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient,
1191
0
                          window, pAacDecoderChannelInfo[L]->granuleLength);
1192
0
      rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient,
1193
0
                           window, pAacDecoderChannelInfo[R]->granuleLength);
1194
1195
0
      for (band = 0; band < scaleFactorBandsTransmitted; band++) {
1196
0
        if ((CodeBook[band] == INTENSITY_HCB) ||
1197
0
            (CodeBook[band] == INTENSITY_HCB2)) {
1198
0
          int bandScale = -(ScaleFactor[band] + 100);
1199
1200
0
          int msb = bandScale >> 2;
1201
0
          int lsb = bandScale & 0x03;
1202
1203
          /* exponent of MantissaTable[lsb][0] is 1, thus msb+1 below. */
1204
0
          FIXP_DBL scale = MantissaTable[lsb][0];
1205
1206
          /* ISO/IEC 14496-3 Chapter 4.6.8.2.3 :
1207
             The use of intensity stereo coding is signaled by the use of the
1208
             pseudo codebooks INTENSITY_HCB and INTENSITY_HCB2 (15 and 14) only
1209
             in the right channel of a channel_pair_element() having a common
1210
             ics_info() (common_window == 1). */
1211
0
          FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) ==
1212
0
                     GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo));
1213
0
          FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) ==
1214
0
                     GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo));
1215
1216
0
          rightScale[band] = leftScale[band] + msb + 1;
1217
1218
0
          if (pJointStereoData->MsUsed[band] & groupMask) {
1219
0
            if (CodeBook[band] == INTENSITY_HCB) /* _NOT_ in-phase */
1220
0
            {
1221
0
              scale = -scale;
1222
0
            }
1223
0
          } else {
1224
0
            if (CodeBook[band] == INTENSITY_HCB2) /* out-of-phase */
1225
0
            {
1226
0
              scale = -scale;
1227
0
            }
1228
0
          }
1229
1230
0
          for (int index = pScaleFactorBandOffsets[band];
1231
0
               index < pScaleFactorBandOffsets[band + 1]; index++) {
1232
0
            rightSpectrum[index] = fMult(leftSpectrum[index], scale);
1233
0
          }
1234
0
        }
1235
0
      }
1236
0
    }
1237
0
  }
1238
0
}