Coverage Report

Created: 2026-02-26 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aac/libSBRdec/src/psdec.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4
© Copyright  1995 - 2018 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
/**************************** SBR decoder library ******************************
96
97
   Author(s):
98
99
   Description:
100
101
*******************************************************************************/
102
103
/*!
104
  \file
105
  \brief  parametric stereo decoder
106
*/
107
108
#include "psdec.h"
109
110
#include "FDK_bitbuffer.h"
111
112
#include "sbr_rom.h"
113
#include "sbr_ram.h"
114
115
#include "FDK_tools_rom.h"
116
117
#include "genericStds.h"
118
119
#include "FDK_trigFcts.h"
120
121
/********************************************************************/
122
/*                       MLQUAL DEFINES                             */
123
/********************************************************************/
124
125
#define FRACT_ZERO FRACT_BITS - 1
126
/********************************************************************/
127
128
SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d);
129
130
/***** HELPERS *****/
131
132
/***************************************************************************/
133
/*!
134
  \brief  Creates one instance of the PS_DEC struct
135
136
  \return Error info
137
138
****************************************************************************/
139
int CreatePsDec(HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */
140
3.16k
                int aacSamplesPerFrame) {
141
3.16k
  SBR_ERROR errorInfo = SBRDEC_OK;
142
3.16k
  HANDLE_PS_DEC h_ps_d;
143
3.16k
  int i;
144
145
3.16k
  if (*h_PS_DEC == NULL) {
146
    /* Get ps dec ram */
147
1.68k
    h_ps_d = GetRam_ps_dec();
148
1.68k
    if (h_ps_d == NULL) {
149
0
      goto bail;
150
0
    }
151
1.68k
  } else {
152
    /* Reset an open instance */
153
1.47k
    h_ps_d = *h_PS_DEC;
154
1.47k
  }
155
156
  /*
157
   * Create Analysis Hybrid filterbank.
158
   */
159
3.16k
  FDKhybridAnalysisOpen(&h_ps_d->specificTo.mpeg.hybridAnalysis,
160
3.16k
                        h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx,
161
3.16k
                        sizeof(h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx),
162
3.16k
                        NULL, 0);
163
164
  /* initialisation */
165
3.16k
  switch (aacSamplesPerFrame) {
166
1.55k
    case 960:
167
1.55k
      h_ps_d->noSubSamples = 30; /* col */
168
1.55k
      break;
169
1.61k
    case 1024:
170
1.61k
      h_ps_d->noSubSamples = 32; /* col */
171
1.61k
      break;
172
0
    default:
173
0
      h_ps_d->noSubSamples = -1;
174
0
      break;
175
3.16k
  }
176
177
3.16k
  if (h_ps_d->noSubSamples > MAX_NUM_COL || h_ps_d->noSubSamples <= 0) {
178
0
    goto bail;
179
0
  }
180
3.16k
  h_ps_d->noChannels = NO_QMF_CHANNELS; /* row */
181
182
3.16k
  h_ps_d->psDecodedPrv = 0;
183
3.16k
  h_ps_d->procFrameBased = -1;
184
9.49k
  for (i = 0; i < (1) + 1; i++) {
185
6.33k
    h_ps_d->bPsDataAvail[i] = ppt_none;
186
6.33k
  }
187
3.16k
  {
188
3.16k
    int error;
189
3.16k
    error = FDKdecorrelateOpen(&(h_ps_d->specificTo.mpeg.apDecor),
190
3.16k
                               h_ps_d->specificTo.mpeg.decorrBufferCplx,
191
3.16k
                               (2 * ((825) + (373))));
192
3.16k
    if (error) goto bail;
193
3.16k
  }
194
195
9.49k
  for (i = 0; i < (1) + 1; i++) {
196
6.33k
    FDKmemclear(&h_ps_d->bsData[i].mpeg, sizeof(MPEG_PS_BS_DATA));
197
6.33k
  }
198
199
3.16k
  errorInfo = ResetPsDec(h_ps_d);
200
201
3.16k
  if (errorInfo != SBRDEC_OK) goto bail;
202
203
3.16k
  *h_PS_DEC = h_ps_d;
204
205
3.16k
  return 0;
206
207
0
bail:
208
0
  if (h_ps_d != NULL) {
209
0
    DeletePsDec(&h_ps_d);
210
0
  }
211
212
0
  return -1;
213
3.16k
} /*END CreatePsDec */
214
215
/***************************************************************************/
216
/*!
217
  \brief  Delete one instance of the PS_DEC struct
218
219
  \return Error info
220
221
****************************************************************************/
222
int DeletePsDec(HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */
223
1.68k
{
224
1.68k
  if (*h_PS_DEC == NULL) {
225
0
    return -1;
226
0
  }
227
228
1.68k
  {
229
1.68k
    HANDLE_PS_DEC h_ps_d = *h_PS_DEC;
230
1.68k
    FDKdecorrelateClose(&(h_ps_d->specificTo.mpeg.apDecor));
231
1.68k
  }
232
233
1.68k
  FreeRam_ps_dec(h_PS_DEC);
234
235
1.68k
  return 0;
236
1.68k
} /*END DeletePsDec */
237
238
/***************************************************************************/
239
/*!
240
  \brief resets some values of the PS handle to default states
241
242
  \return
243
244
****************************************************************************/
245
SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d) /*!< pointer to the module state */
246
3.16k
{
247
3.16k
  SBR_ERROR errorInfo = SBRDEC_OK;
248
3.16k
  INT i;
249
250
  /* explicitly init state variables to safe values (until first ps header
251
   * arrives) */
252
253
3.16k
  h_ps_d->specificTo.mpeg.lastUsb = 0;
254
255
  /*
256
   * Initialize Analysis Hybrid filterbank.
257
   */
258
3.16k
  FDKhybridAnalysisInit(&h_ps_d->specificTo.mpeg.hybridAnalysis, THREE_TO_TEN,
259
3.16k
                        NO_QMF_BANDS_HYBRID20, NO_QMF_BANDS_HYBRID20, 1);
260
261
  /*
262
   * Initialize Synthesis Hybrid filterbank.
263
   */
264
9.49k
  for (i = 0; i < 2; i++) {
265
6.33k
    FDKhybridSynthesisInit(&h_ps_d->specificTo.mpeg.hybridSynthesis[i],
266
6.33k
                           THREE_TO_TEN, NO_QMF_CHANNELS, NO_QMF_CHANNELS);
267
6.33k
  }
268
3.16k
  {
269
3.16k
    INT error;
270
3.16k
    error = FDKdecorrelateInit(&h_ps_d->specificTo.mpeg.apDecor, 71, DECORR_PS,
271
3.16k
                               DUCKER_AUTOMATIC, 0, 0, 0, 0, 1, /* isLegacyPS */
272
3.16k
                               1);
273
3.16k
    if (error) return SBRDEC_NOT_INITIALIZED;
274
3.16k
  }
275
276
72.8k
  for (i = 0; i < NO_IID_GROUPS; i++) {
277
69.6k
    h_ps_d->specificTo.mpeg.h11rPrev[i] = FL2FXCONST_DBL(0.5f);
278
69.6k
    h_ps_d->specificTo.mpeg.h12rPrev[i] = FL2FXCONST_DBL(0.5f);
279
69.6k
  }
280
281
3.16k
  FDKmemclear(h_ps_d->specificTo.mpeg.h21rPrev,
282
3.16k
              sizeof(h_ps_d->specificTo.mpeg.h21rPrev));
283
3.16k
  FDKmemclear(h_ps_d->specificTo.mpeg.h22rPrev,
284
3.16k
              sizeof(h_ps_d->specificTo.mpeg.h22rPrev));
285
286
3.16k
  return errorInfo;
287
3.16k
}
288
289
/***************************************************************************/
290
/*!
291
  \brief  Feed delaylines when parametric stereo is switched on.
292
  \return
293
****************************************************************************/
294
void PreparePsProcessing(HANDLE_PS_DEC h_ps_d,
295
                         const FIXP_DBL *const *const rIntBufferLeft,
296
                         const FIXP_DBL *const *const iIntBufferLeft,
297
3.08k
                         const int scaleFactorLowBand) {
298
3.08k
  if (h_ps_d->procFrameBased ==
299
3.08k
      1) /* If we have switched from frame to slot based processing  */
300
371
  {      /* fill hybrid delay buffer.                                */
301
371
    int i, j;
302
303
2.59k
    for (i = 0; i < HYBRID_FILTER_DELAY; i++) {
304
2.22k
      FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20];
305
2.22k
      FIXP_DBL hybridOutputData[2][NO_SUB_QMF_CHANNELS];
306
307
8.90k
      for (j = 0; j < NO_QMF_BANDS_HYBRID20; j++) {
308
6.67k
        qmfInputData[0][j] =
309
6.67k
            scaleValue(rIntBufferLeft[i][j], scaleFactorLowBand);
310
6.67k
        qmfInputData[1][j] =
311
6.67k
            scaleValue(iIntBufferLeft[i][j], scaleFactorLowBand);
312
6.67k
      }
313
314
2.22k
      FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis,
315
2.22k
                             qmfInputData[0], qmfInputData[1],
316
2.22k
                             hybridOutputData[0], hybridOutputData[1]);
317
2.22k
    }
318
371
    h_ps_d->procFrameBased = 0; /* switch to slot based processing. */
319
320
371
  } /* procFrameBased==1 */
321
3.08k
}
322
323
void initSlotBasedRotation(
324
    HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */
325
7.18k
    int env, int usb) {
326
7.18k
  INT group = 0;
327
7.18k
  INT bin = 0;
328
7.18k
  INT noIidSteps;
329
330
7.18k
  FIXP_SGL invL;
331
7.18k
  FIXP_DBL ScaleL, ScaleR;
332
7.18k
  FIXP_DBL Alpha, Beta;
333
7.18k
  FIXP_DBL h11r, h12r, h21r, h22r;
334
335
7.18k
  const FIXP_DBL *PScaleFactors;
336
337
7.18k
  if (h_ps_d->bsData[h_ps_d->processSlot].mpeg.bFineIidQ) {
338
1.18k
    PScaleFactors = ScaleFactorsFine; /* values are shiftet right by one */
339
1.18k
    noIidSteps = NO_IID_STEPS_FINE;
340
6.00k
  } else {
341
6.00k
    PScaleFactors = ScaleFactors; /* values are shiftet right by one */
342
6.00k
    noIidSteps = NO_IID_STEPS;
343
6.00k
  }
344
345
  /* dequantize and decode */
346
165k
  for (group = 0; group < NO_IID_GROUPS; group++) {
347
158k
    bin = bins2groupMap20[group];
348
349
    /*!
350
    <h3> type 'A' rotation </h3>
351
    mixing procedure R_a, used in baseline version<br>
352
353
     Scale-factor vectors c1 and c2 are precalculated in initPsTables () and
354
    stored in scaleFactors[] and scaleFactorsFine[] = pScaleFactors []. From the
355
    linearized IID parameters (intensity differences), two scale factors are
356
     calculated. They are used to obtain the coefficients h11... h22.
357
    */
358
359
    /* ScaleR and ScaleL are scaled by 1 shift right */
360
361
158k
    ScaleR = PScaleFactors[noIidSteps + h_ps_d->specificTo.mpeg.pCoef
362
158k
                                            ->aaIidIndexMapped[env][bin]];
363
158k
    ScaleL = PScaleFactors[noIidSteps - h_ps_d->specificTo.mpeg.pCoef
364
158k
                                            ->aaIidIndexMapped[env][bin]];
365
366
158k
    Beta = fMult(
367
158k
        fMult(Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]],
368
158k
              (ScaleR - ScaleL)),
369
158k
        FIXP_SQRT05);
370
158k
    Alpha =
371
158k
        Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]] >> 1;
372
373
    /* Alpha and Beta are now both scaled by 2 shifts right */
374
375
    /* calculate the coefficients h11... h22 from scale-factors and ICC
376
     * parameters */
377
378
    /* h values are scaled by 1 shift right */
379
158k
    {
380
158k
      FIXP_DBL trigData[4];
381
382
158k
      inline_fixp_cos_sin(Beta + Alpha, Beta - Alpha, 2, trigData);
383
158k
      h11r = fMult(ScaleL, trigData[0]);
384
158k
      h12r = fMult(ScaleR, trigData[2]);
385
158k
      h21r = fMult(ScaleL, trigData[1]);
386
158k
      h22r = fMult(ScaleR, trigData[3]);
387
158k
    }
388
    /*****************************************************************************************/
389
    /* Interpolation of the matrices H11... H22: */
390
    /*                                                                                       */
391
    /* H11(k,n) = H11(k,n[e]) + (n-n[e]) * (H11(k,n[e+1] - H11(k,n[e])) /
392
     * (n[e+1] - n[e])    */
393
    /* ... */
394
    /*****************************************************************************************/
395
396
    /* invL = 1/(length of envelope) */
397
158k
    invL = FX_DBL2FX_SGL(GetInvInt(
398
158k
        h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env + 1] -
399
158k
        h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env]));
400
401
158k
    h_ps_d->specificTo.mpeg.pCoef->H11r[group] =
402
158k
        h_ps_d->specificTo.mpeg.h11rPrev[group];
403
158k
    h_ps_d->specificTo.mpeg.pCoef->H12r[group] =
404
158k
        h_ps_d->specificTo.mpeg.h12rPrev[group];
405
158k
    h_ps_d->specificTo.mpeg.pCoef->H21r[group] =
406
158k
        h_ps_d->specificTo.mpeg.h21rPrev[group];
407
158k
    h_ps_d->specificTo.mpeg.pCoef->H22r[group] =
408
158k
        h_ps_d->specificTo.mpeg.h22rPrev[group];
409
410
158k
    h_ps_d->specificTo.mpeg.pCoef->DeltaH11r[group] =
411
158k
        fMult(h11r - h_ps_d->specificTo.mpeg.pCoef->H11r[group], invL);
412
158k
    h_ps_d->specificTo.mpeg.pCoef->DeltaH12r[group] =
413
158k
        fMult(h12r - h_ps_d->specificTo.mpeg.pCoef->H12r[group], invL);
414
158k
    h_ps_d->specificTo.mpeg.pCoef->DeltaH21r[group] =
415
158k
        fMult(h21r - h_ps_d->specificTo.mpeg.pCoef->H21r[group], invL);
416
158k
    h_ps_d->specificTo.mpeg.pCoef->DeltaH22r[group] =
417
158k
        fMult(h22r - h_ps_d->specificTo.mpeg.pCoef->H22r[group], invL);
418
419
    /* update prev coefficients for interpolation in next envelope */
420
421
158k
    h_ps_d->specificTo.mpeg.h11rPrev[group] = h11r;
422
158k
    h_ps_d->specificTo.mpeg.h12rPrev[group] = h12r;
423
158k
    h_ps_d->specificTo.mpeg.h21rPrev[group] = h21r;
424
158k
    h_ps_d->specificTo.mpeg.h22rPrev[group] = h22r;
425
426
158k
  } /* group loop */
427
7.18k
}
428
429
static const UCHAR groupTable[NO_IID_GROUPS + 1] = {
430
    0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11,
431
    12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71};
432
433
static void applySlotBasedRotation(
434
    HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */
435
436
    FIXP_DBL *mHybridRealLeft, /*!< hybrid values real left  */
437
    FIXP_DBL *mHybridImagLeft, /*!< hybrid values imag left  */
438
439
    FIXP_DBL *mHybridRealRight, /*!< hybrid values real right  */
440
    FIXP_DBL *mHybridImagRight  /*!< hybrid values imag right  */
441
95.2k
) {
442
95.2k
  INT group;
443
95.2k
  INT subband;
444
445
  /**********************************************************************************************/
446
  /*!
447
  <h2> Mapping </h2>
448
449
  The number of stereo bands that is actually used depends on the number of
450
  availble parameters for IID and ICC: <pre> nr. of IID para.| nr. of ICC para.
451
  | nr. of Stereo bands
452
   ----------------|------------------|-------------------
453
     10,20         |     10,20        |        20
454
     10,20         |     34           |        34
455
     34            |     10,20        |        34
456
     34            |     34           |        34
457
  </pre>
458
  In the case the number of parameters for IIS and ICC differs from the number
459
  of stereo bands, a mapping from the lower number to the higher number of
460
  parameters is applied. Index mapping of IID and ICC parameters is already done
461
  in psbitdec.cpp. Further mapping is not needed here in baseline version.
462
  **********************************************************************************************/
463
464
  /************************************************************************************************/
465
  /*!
466
  <h2> Mixing </h2>
467
468
  To generate the QMF subband signals for the subband samples n = n[e]+1 ,,,
469
  n_[e+1] the parameters at position n[e] and n[e+1] are required as well as the
470
  subband domain signals s_k(n) and d_k(n) for n = n[e]+1... n_[e+1]. n[e]
471
  represents the start position for envelope e. The border positions n[e] are
472
  handled in DecodePS().
473
474
  The stereo sub subband signals are constructed as:
475
  <pre>
476
  l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n)
477
  r_k(n) = H21(k,n) s_k(n) + H22(k,n) d_k(n)
478
  </pre>
479
  In order to obtain the matrices H11(k,n)... H22 (k,n), the vectors h11(b)...
480
  h22(b) need to be calculated first (b: parameter index). Depending on ICC mode
481
  either mixing procedure R_a or R_b is used for that. For both procedures, the
482
  parameters for parameter position n[e+1] is used.
483
  ************************************************************************************************/
484
485
  /************************************************************************************************/
486
  /*!
487
  <h2>Phase parameters </h2>
488
  With disabled phase parameters (which is the case in baseline version), the
489
  H-matrices are just calculated by:
490
491
  <pre>
492
  H11(k,n[e+1] = h11(b(k))
493
  (...)
494
  b(k): parameter index according to mapping table
495
  </pre>
496
497
  <h2>Processing of the samples in the sub subbands </h2>
498
  this loop includes the interpolation of the coefficients Hxx
499
  ************************************************************************************************/
500
501
  /******************************************************/
502
  /* construct stereo sub subband signals according to: */
503
  /*                                                    */
504
  /* l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n)         */
505
  /* r_k(n) = H12(k,n) s_k(n) + H22(k,n) d_k(n)         */
506
  /******************************************************/
507
95.2k
  PS_DEC_COEFFICIENTS *pCoef = h_ps_d->specificTo.mpeg.pCoef;
508
509
2.19M
  for (group = 0; group < NO_IID_GROUPS; group++) {
510
2.09M
    pCoef->H11r[group] += pCoef->DeltaH11r[group];
511
2.09M
    pCoef->H12r[group] += pCoef->DeltaH12r[group];
512
2.09M
    pCoef->H21r[group] += pCoef->DeltaH21r[group];
513
2.09M
    pCoef->H22r[group] += pCoef->DeltaH22r[group];
514
515
2.09M
    const int start = groupTable[group];
516
2.09M
    const int stop = groupTable[group + 1];
517
8.86M
    for (subband = start; subband < stop; subband++) {
518
6.76M
      FIXP_DBL tmpLeft =
519
6.76M
          fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridRealLeft[subband]),
520
6.76M
                   pCoef->H21r[group], mHybridRealRight[subband]);
521
6.76M
      FIXP_DBL tmpRight =
522
6.76M
          fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridRealLeft[subband]),
523
6.76M
                   pCoef->H22r[group], mHybridRealRight[subband]);
524
6.76M
      mHybridRealLeft[subband] = tmpLeft;
525
6.76M
      mHybridRealRight[subband] = tmpRight;
526
527
6.76M
      tmpLeft =
528
6.76M
          fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridImagLeft[subband]),
529
6.76M
                   pCoef->H21r[group], mHybridImagRight[subband]);
530
6.76M
      tmpRight =
531
6.76M
          fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridImagLeft[subband]),
532
6.76M
                   pCoef->H22r[group], mHybridImagRight[subband]);
533
6.76M
      mHybridImagLeft[subband] = tmpLeft;
534
6.76M
      mHybridImagRight[subband] = tmpRight;
535
6.76M
    } /* subband */
536
2.09M
  }
537
95.2k
}
538
539
/***************************************************************************/
540
/*!
541
  \brief  Applies IID, ICC, IPD and OPD parameters to the current frame.
542
543
  \return none
544
545
****************************************************************************/
546
void ApplyPsSlot(
547
    HANDLE_PS_DEC h_ps_d,      /*!< handle PS_DEC*/
548
    FIXP_DBL **rIntBufferLeft, /*!< real bands left qmf channel (38x64)  */
549
    FIXP_DBL **iIntBufferLeft, /*!< imag bands left qmf channel (38x64)  */
550
    FIXP_DBL *rIntBufferRight, /*!< real bands right qmf channel (38x64) */
551
    FIXP_DBL *iIntBufferRight, /*!< imag bands right qmf channel (38x64) */
552
    const int scaleFactorLowBand_no_ov, const int scaleFactorLowBand,
553
95.2k
    const int scaleFactorHighBand, const int lsb, const int usb) {
554
/*!
555
The 64-band QMF representation of the monaural signal generated by the SBR tool
556
is used as input of the PS tool. After the PS processing, the outputs of the
557
left and right hybrid synthesis filterbanks are used to generate the stereo
558
output signal.
559
560
<pre>
561
562
           -------------            ----------            -------------
563
          | Hybrid      | M_n[k,m] |          | L_n[k,m] | Hybrid      | l[n]
564
 m[n] --->| analysis    |--------->|          |--------->| synthesis   |----->
565
           -------------           | Stereo   |           -------------
566
                 |                 | recon-   |
567
                 |                 | stuction |
568
                \|/                |          |
569
           -------------           |          |
570
          | De-         | D_n[k,m] |          |
571
          | correlation |--------->|          |
572
           -------------           |          |           -------------
573
                                   |          | R_n[k,m] | Hybrid      | r[n]
574
                                   |          |--------->| synthesis   |----->
575
 IID, ICC ------------------------>|          |          | filter bank |
576
(IPD, OPD)                          ----------            -------------
577
578
m[n]:      QMF represantation of the mono input
579
M_n[k,m]:  (sub-)sub-band domain signals of the mono input
580
D_n[k,m]:  decorrelated (sub-)sub-band domain signals
581
L_n[k,m]:  (sub-)sub-band domain signals of the left output
582
R_n[k,m]:  (sub-)sub-band domain signals of the right output
583
l[n],r[n]: left/right output signals
584
585
</pre>
586
*/
587
381k
#define NO_HYBRID_DATA_BANDS (71)
588
589
95.2k
  int i;
590
95.2k
  FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20];
591
95.2k
  FIXP_DBL *hybridData[2][2];
592
95.2k
  C_ALLOC_SCRATCH_START(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS);
593
594
95.2k
  hybridData[0][0] =
595
95.2k
      pHybridData + 0 * NO_HYBRID_DATA_BANDS; /* left real hybrid data */
596
95.2k
  hybridData[0][1] =
597
95.2k
      pHybridData + 1 * NO_HYBRID_DATA_BANDS; /* left imag hybrid data */
598
95.2k
  hybridData[1][0] =
599
95.2k
      pHybridData + 2 * NO_HYBRID_DATA_BANDS; /* right real hybrid data */
600
95.2k
  hybridData[1][1] =
601
95.2k
      pHybridData + 3 * NO_HYBRID_DATA_BANDS; /* right imag hybrid data */
602
603
  /*!
604
  Hybrid analysis filterbank:
605
  The lower 3 (5) of the 64 QMF subbands are further split to provide better
606
  frequency resolution. for PS processing. For the 10 and 20 stereo bands
607
  configuration, the QMF band H_0(w) is split up into 8 (sub-) sub-bands and the
608
  QMF bands H_1(w) and H_2(w) are spit into 2 (sub-) 4th. (See figures 8.20
609
  and 8.22 of ISO/IEC 14496-3:2001/FDAM 2:2004(E) )
610
  */
611
612
  /*
613
   * Hybrid analysis.
614
   */
615
616
  /* Get qmf input data and apply descaling */
617
381k
  for (i = 0; i < NO_QMF_BANDS_HYBRID20; i++) {
618
285k
    qmfInputData[0][i] = scaleValue(rIntBufferLeft[HYBRID_FILTER_DELAY][i],
619
285k
                                    scaleFactorLowBand_no_ov);
620
285k
    qmfInputData[1][i] = scaleValue(iIntBufferLeft[HYBRID_FILTER_DELAY][i],
621
285k
                                    scaleFactorLowBand_no_ov);
622
285k
  }
623
624
  /* LF - part */
625
95.2k
  FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis,
626
95.2k
                         qmfInputData[0], qmfInputData[1], hybridData[0][0],
627
95.2k
                         hybridData[0][1]);
628
629
  /* HF - part */
630
  /* bands up to lsb */
631
95.2k
  scaleValues(&hybridData[0][0][NO_SUB_QMF_CHANNELS - 2],
632
95.2k
              &rIntBufferLeft[0][NO_QMF_BANDS_HYBRID20],
633
95.2k
              lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand);
634
95.2k
  scaleValues(&hybridData[0][1][NO_SUB_QMF_CHANNELS - 2],
635
95.2k
              &iIntBufferLeft[0][NO_QMF_BANDS_HYBRID20],
636
95.2k
              lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand);
637
638
  /* bands from lsb to usb */
639
95.2k
  scaleValues(&hybridData[0][0][lsb + (NO_SUB_QMF_CHANNELS - 2 -
640
95.2k
                                       NO_QMF_BANDS_HYBRID20)],
641
95.2k
              &rIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand);
642
95.2k
  scaleValues(&hybridData[0][1][lsb + (NO_SUB_QMF_CHANNELS - 2 -
643
95.2k
                                       NO_QMF_BANDS_HYBRID20)],
644
95.2k
              &iIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand);
645
646
  /* bands from usb to NO_SUB_QMF_CHANNELS which should be zero for non-overlap
647
     slots but can be non-zero for overlap slots */
648
95.2k
  FDKmemcpy(
649
95.2k
      &hybridData[0][0]
650
95.2k
                 [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)],
651
95.2k
      &rIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb));
652
95.2k
  FDKmemcpy(
653
95.2k
      &hybridData[0][1]
654
95.2k
                 [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)],
655
95.2k
      &iIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb));
656
657
  /*!
658
  Decorrelation:
659
  By means of all-pass filtering and delaying, the (sub-)sub-band samples s_k(n)
660
  are converted into de-correlated (sub-)sub-band samples d_k(n).
661
  - k: frequency in hybrid spectrum
662
  - n: time index
663
  */
664
665
95.2k
  FDKdecorrelateApply(&h_ps_d->specificTo.mpeg.apDecor,
666
95.2k
                      &hybridData[0][0][0], /* left real hybrid data */
667
95.2k
                      &hybridData[0][1][0], /* left imag hybrid data */
668
95.2k
                      &hybridData[1][0][0], /* right real hybrid data */
669
95.2k
                      &hybridData[1][1][0], /* right imag hybrid data */
670
95.2k
                      0                     /* startHybBand */
671
95.2k
  );
672
673
  /*!
674
  Stereo Processing:
675
  The sets of (sub-)sub-band samples s_k(n) and d_k(n) are processed according
676
  to the stereo cues which are defined per stereo band.
677
  */
678
679
95.2k
  applySlotBasedRotation(h_ps_d,
680
95.2k
                         &hybridData[0][0][0], /* left real hybrid data */
681
95.2k
                         &hybridData[0][1][0], /* left imag hybrid data */
682
95.2k
                         &hybridData[1][0][0], /* right real hybrid data */
683
95.2k
                         &hybridData[1][1][0]  /* right imag hybrid data */
684
95.2k
  );
685
686
  /*!
687
  Hybrid synthesis filterbank:
688
  The stereo processed hybrid subband signals l_k(n) and r_k(n) are fed into the
689
  hybrid synthesis filterbanks which are identical to the 64 complex synthesis
690
  filterbank of the SBR tool. The input to the filterbank are slots of 64 QMF
691
  samples. For each slot the filterbank outputs one block of 64 samples of one
692
  reconstructed stereo channel. The hybrid synthesis filterbank is computed
693
  seperatly for the left and right channel.
694
  */
695
696
  /*
697
   * Hybrid synthesis.
698
   */
699
285k
  for (i = 0; i < 2; i++) {
700
190k
    FDKhybridSynthesisApply(
701
190k
        &h_ps_d->specificTo.mpeg.hybridSynthesis[i],
702
190k
        hybridData[i][0], /* real hybrid data */
703
190k
        hybridData[i][1], /* imag hybrid data */
704
190k
        (i == 0) ? rIntBufferLeft[0]
705
190k
                 : rIntBufferRight, /* output real qmf buffer */
706
190k
        (i == 0) ? iIntBufferLeft[0]
707
190k
                 : iIntBufferRight /* output imag qmf buffer */
708
190k
    );
709
190k
  }
710
711
  /* free temporary hybrid qmf values of one timeslot */
712
95.2k
  C_ALLOC_SCRATCH_END(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS);
713
714
95.2k
} /* END ApplyPsSlot */