1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2020 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 /*********************** MPEG surround decoder library *************************
96 
97    Author(s):
98 
99    Description: SAC Decoder Library
100 
101 *******************************************************************************/
102 
103 #include "sac_dec_errorcodes.h"
104 #include "sac_dec.h"
105 
106 #include "sac_process.h"
107 #include "sac_bitdec.h"
108 #include "sac_smoothing.h"
109 #include "sac_calcM1andM2.h"
110 #include "sac_reshapeBBEnv.h"
111 #include "sac_stp.h"
112 #include "sac_rom.h"
113 
114 #include "FDK_decorrelate.h"
115 
116 #include "FDK_trigFcts.h"
117 #include "FDK_matrixCalloc.h"
118 
119 /* static int pbStrideTable[] = {1, 2, 5, 28}; see sac_rom.cpp */
120 
121 enum {
122   APPLY_M2_NONE = 0,    /* init value */
123   APPLY_M2 = 1,         /* apply m2 fallback implementation */
124   APPLY_M2_MODE212 = 2, /* apply m2 for 212 mode */
125   APPLY_M2_MODE212_Res_PhaseCoding =
126       3 /* apply m2 for 212 mode with residuals and phase coding */
127 };
128 
129 /******************************************************************************************/
130 /* function: FDK_SpatialDecInitDefaultSpatialSpecificConfig */
131 /* output:   struct of type SPATIAL_SPECIFIC_CONFIG */
132 /* input:    core coder audio object type */
133 /* input:    nr of core channels */
134 /* input:    sampling rate */
135 /* input:    nr of time slots */
136 /* input:    decoder level */
137 /* input:    flag indicating upmix type blind */
138 /*                                                                                        */
139 /* returns:  error code */
140 /******************************************************************************************/
FDK_SpatialDecInitDefaultSpatialSpecificConfig(SPATIAL_SPECIFIC_CONFIG * pSpatialSpecificConfig,AUDIO_OBJECT_TYPE coreCodec,int coreChannels,int samplingFreq,int nTimeSlots,int decoderLevel,int isBlind)141 int FDK_SpatialDecInitDefaultSpatialSpecificConfig(
142     SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
143     AUDIO_OBJECT_TYPE coreCodec, int coreChannels, int samplingFreq,
144     int nTimeSlots, int decoderLevel, int isBlind) {
145   return SpatialDecDefaultSpecificConfig(pSpatialSpecificConfig, coreCodec,
146                                          samplingFreq, nTimeSlots, decoderLevel,
147                                          isBlind, coreChannels);
148 }
149 
150 /******************************************************************************************/
151 /* function: FDK_SpatialDecCompareSpatialSpecificConfigHeader */
152 /* input:    2 pointers to a ssc */
153 /*                                                                                        */
154 /* output:   - */
155 /* returns:  error code (0 = equal, <>0 unequal) */
156 /******************************************************************************************/
FDK_SpatialDecCompareSpatialSpecificConfigHeader(SPATIAL_SPECIFIC_CONFIG * pSsc1,SPATIAL_SPECIFIC_CONFIG * pSsc2)157 int FDK_SpatialDecCompareSpatialSpecificConfigHeader(
158     SPATIAL_SPECIFIC_CONFIG *pSsc1, SPATIAL_SPECIFIC_CONFIG *pSsc2) {
159   int result = MPS_OK;
160 
161   /* we assume: every bit must be equal */
162   if (FDKmemcmp(pSsc1, pSsc2, sizeof(SPATIAL_SPECIFIC_CONFIG)) != 0) {
163     result = MPS_UNEQUAL_SSC;
164   }
165   return result;
166 }
167 
168 /*******************************************************************************
169  Functionname: SpatialDecClearFrameData
170  *******************************************************************************
171 
172  Description: Clear/Fake frame data to avoid misconfiguration and allow proper
173               error concealment.
174  Arguments:
175  Input:       self (frame data)
176  Output:      No return value.
177 
178 *******************************************************************************/
SpatialDecClearFrameData(spatialDec * self,SPATIAL_BS_FRAME * bsFrame,const SACDEC_CREATION_PARAMS * const setup)179 static void SpatialDecClearFrameData(
180     spatialDec *self, /* Shall be removed */
181     SPATIAL_BS_FRAME *bsFrame, const SACDEC_CREATION_PARAMS *const setup) {
182   int i;
183 
184   FDK_ASSERT(self != NULL);
185   FDK_ASSERT(bsFrame != NULL);
186   FDK_ASSERT(setup != NULL);
187 
188   /* do not apply shaping tools (GES or STP) */
189   for (i = 0; i < setup->maxNumOutputChannels;
190        i += 1) { /* MAX_OUTPUT_CHANNELS */
191     bsFrame->tempShapeEnableChannelSTP[i] = 0;
192     bsFrame->tempShapeEnableChannelGES[i] = 0;
193   }
194 
195   bsFrame->TsdData->bsTsdEnable = 0;
196 
197   /* use only 1 parameter set at the end of the frame */
198   bsFrame->numParameterSets = 1;
199   bsFrame->paramSlot[0] = self->timeSlots - 1;
200 
201   /* parameter smoothing tool set to off */
202   bsFrame->bsSmoothMode[0] = 0;
203   initParameterSmoothing(self);
204 
205   /* reset residual data */
206   {
207     int resQmfBands, resTimeSlots = (1);
208 
209     resQmfBands = setup->maxNumQmfBands;
210 
211     for (i = 0; i < setup->bProcResidual
212                     ? fMin(setup->maxNumResChannels,
213                            setup->maxNumOttBoxes + setup->maxNumInputChannels)
214                     : 0;
215          i += 1) {
216       for (int j = 0; j < resTimeSlots; j += 1) {
217         for (int k = 0; k < resQmfBands; k += 1) {
218           self->qmfResidualReal__FDK[i][j][k] = FL2FXCONST_DBL(0.0f);
219           self->qmfResidualImag__FDK[i][j][k] = FL2FXCONST_DBL(0.0f);
220         }
221       }
222     }
223   }
224 
225   return;
226 }
227 
228 /*******************************************************************************
229  Functionname: FDK_SpatialDecOpen
230  *******************************************************************************
231 
232  Description:
233 
234  Arguments:
235 
236  Return:
237 
238 *******************************************************************************/
FDK_SpatialDecOpen(const SPATIAL_DEC_CONFIG * config,int stereoConfigIndex)239 spatialDec *FDK_SpatialDecOpen(const SPATIAL_DEC_CONFIG *config,
240                                int stereoConfigIndex) {
241   int i;
242   int lfSize, hfSize;
243   spatialDec *self = NULL;
244   SACDEC_CREATION_PARAMS setup;
245 
246   switch (config->decoderLevel) {
247     case DECODER_LEVEL_0: /* 212 maxNumOutputChannels== 2 */
248       setup.maxNumInputChannels = 1;
249       setup.maxNumOutputChannels = 2;
250       setup.maxNumQmfBands = 64;
251       setup.maxNumXChannels = 2;
252       setup.maxNumVChannels = 2;
253       setup.maxNumDecorChannels = 1;
254       setup.bProcResidual = 1;
255       setup.maxNumResidualChannels = 0;
256       setup.maxNumOttBoxes = 1;
257       setup.maxNumParams = setup.maxNumInputChannels + setup.maxNumOttBoxes;
258       break;
259     default:
260       return NULL;
261   }
262 
263   setup.maxNumResChannels = 1;
264 
265   {
266     switch (config->maxNumOutputChannels) {
267       case OUTPUT_CHANNELS_2_0:
268         setup.maxNumOutputChannels = fMin(setup.maxNumOutputChannels, 2);
269         break;
270       case OUTPUT_CHANNELS_DEFAULT:
271       default:
272         break;
273     }
274   }
275 
276   setup.maxNumHybridBands = SacGetHybridSubbands(setup.maxNumQmfBands);
277 
278   switch (config->decoderMode) {
279     case EXT_HQ_ONLY:
280       setup.maxNumCmplxQmfBands = setup.maxNumQmfBands;
281       setup.maxNumCmplxHybBands = setup.maxNumHybridBands;
282       break;
283     default:
284       setup.maxNumCmplxQmfBands = fixMax(PC_NUM_BANDS, setup.maxNumQmfBands);
285       setup.maxNumCmplxHybBands =
286           fixMax(PC_NUM_HYB_BANDS, setup.maxNumHybridBands);
287       break;
288   } /* switch config->decoderMode */
289 
290   FDK_ALLOCATE_MEMORY_1D_INT(self, 1, spatialDec, SECT_DATA_L2)
291 
292   self->createParams = setup;
293 
294   FDK_ALLOCATE_MEMORY_1D(self->param2hyb, MAX_PARAMETER_BANDS + 1, int)
295 
296   FDK_ALLOCATE_MEMORY_1D(self->numOttBands, setup.maxNumOttBoxes, int)
297 
298   /* allocate arrays */
299 
300   FDK_ALLOCATE_MEMORY_1D(self->smgTime, MAX_PARAMETER_SETS, int)
301   FDK_ALLOCATE_MEMORY_2D(self->smgData, MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS,
302                          UCHAR)
303 
304   FDK_ALLOCATE_MEMORY_3D(self->ottCLD__FDK, setup.maxNumOttBoxes,
305                          MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
306   FDK_ALLOCATE_MEMORY_3D(self->ottICC__FDK, setup.maxNumOttBoxes,
307                          MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
308   FDK_ALLOCATE_MEMORY_3D(self->ottIPD__FDK, setup.maxNumOttBoxes,
309                          MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
310 
311   /* Last parameters from prev frame */
312   FDK_ALLOCATE_MEMORY_2D(self->ottCLDidxPrev, setup.maxNumOttBoxes,
313                          MAX_PARAMETER_BANDS, SCHAR)
314   FDK_ALLOCATE_MEMORY_2D(self->ottICCidxPrev, setup.maxNumOttBoxes,
315                          MAX_PARAMETER_BANDS, SCHAR)
316   FDK_ALLOCATE_MEMORY_3D(self->ottICCdiffidx, setup.maxNumOttBoxes,
317                          MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
318   FDK_ALLOCATE_MEMORY_2D(self->ottIPDidxPrev, setup.maxNumOttBoxes,
319                          MAX_PARAMETER_BANDS, SCHAR)
320   FDK_ALLOCATE_MEMORY_2D(self->arbdmxGainIdxPrev, setup.maxNumInputChannels,
321                          MAX_PARAMETER_BANDS, SCHAR)
322   FDK_ALLOCATE_MEMORY_2D(self->cmpOttCLDidxPrev, setup.maxNumOttBoxes,
323                          MAX_PARAMETER_BANDS, SCHAR)
324   FDK_ALLOCATE_MEMORY_2D(self->cmpOttICCidxPrev, setup.maxNumOttBoxes,
325                          MAX_PARAMETER_BANDS, SCHAR)
326   FDK_ALLOCATE_MEMORY_3D(self->outIdxData, setup.maxNumOttBoxes,
327                          MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
328 
329   FDK_ALLOCATE_MEMORY_3D(self->arbdmxGain__FDK, setup.maxNumInputChannels,
330                          MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR)
331   FDK_ALLOCATE_MEMORY_1D(self->arbdmxAlpha__FDK, setup.maxNumInputChannels,
332                          FIXP_DBL)
333   FDK_ALLOCATE_MEMORY_1D(self->arbdmxAlphaPrev__FDK, setup.maxNumInputChannels,
334                          FIXP_DBL)
335   FDK_ALLOCATE_MEMORY_2D(self->cmpArbdmxGainIdxPrev, setup.maxNumInputChannels,
336                          MAX_PARAMETER_BANDS, SCHAR)
337 
338   FDK_ALLOCATE_MEMORY_2D(self->cmpOttIPDidxPrev, setup.maxNumOttBoxes,
339                          MAX_PARAMETER_BANDS, SCHAR)
340 
341   FDK_ALLOCATE_MEMORY_3D_INT(self->M2Real__FDK, setup.maxNumOutputChannels,
342                              setup.maxNumVChannels, MAX_PARAMETER_BANDS,
343                              FIXP_DBL, SECT_DATA_L2)
344   FDK_ALLOCATE_MEMORY_3D(self->M2Imag__FDK, setup.maxNumOutputChannels,
345                          setup.maxNumVChannels, MAX_PARAMETER_BANDS, FIXP_DBL)
346 
347   FDK_ALLOCATE_MEMORY_3D_INT(self->M2RealPrev__FDK, setup.maxNumOutputChannels,
348                              setup.maxNumVChannels, MAX_PARAMETER_BANDS,
349                              FIXP_DBL, SECT_DATA_L2)
350   FDK_ALLOCATE_MEMORY_3D(self->M2ImagPrev__FDK, setup.maxNumOutputChannels,
351                          setup.maxNumVChannels, MAX_PARAMETER_BANDS, FIXP_DBL)
352 
353   FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(
354       self->qmfInputReal__FDK, setup.maxNumInputChannels, setup.maxNumQmfBands,
355       FIXP_DBL, SECT_DATA_L2)
356   FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(
357       self->qmfInputImag__FDK, setup.maxNumInputChannels,
358       setup.maxNumCmplxQmfBands, FIXP_DBL, SECT_DATA_L2)
359 
360   FDK_ALLOCATE_MEMORY_2D_INT(self->hybInputReal__FDK, setup.maxNumInputChannels,
361                              setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2)
362   FDK_ALLOCATE_MEMORY_2D_INT(self->hybInputImag__FDK, setup.maxNumInputChannels,
363                              setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2)
364 
365   if (setup.bProcResidual) {
366     FDK_ALLOCATE_MEMORY_1D(self->qmfResidualReal__FDK, setup.maxNumResChannels,
367                            FIXP_DBL **)
368     FDK_ALLOCATE_MEMORY_1D(self->qmfResidualImag__FDK, setup.maxNumResChannels,
369                            FIXP_DBL **)
370 
371     FDK_ALLOCATE_MEMORY_1D(self->hybResidualReal__FDK, setup.maxNumResChannels,
372                            FIXP_DBL *)
373     FDK_ALLOCATE_MEMORY_1D(self->hybResidualImag__FDK, setup.maxNumResChannels,
374                            FIXP_DBL *)
375 
376     for (i = 0; i < setup.maxNumResChannels; i++) {
377       int resQmfBands = (config->decoderMode == EXT_LP_ONLY)
378                             ? PC_NUM_BANDS
379                             : setup.maxNumQmfBands;
380       int resHybBands = (config->decoderMode == EXT_LP_ONLY)
381                             ? PC_NUM_HYB_BANDS
382                             : setup.maxNumHybridBands;
383       /* Alignment is needed for USAC residuals because QMF analysis directly
384        * writes to this buffer. */
385       FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(self->qmfResidualReal__FDK[i], (1),
386                                          resQmfBands, FIXP_DBL, SECT_DATA_L1)
387       FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(self->qmfResidualImag__FDK[i], (1),
388                                          resQmfBands, FIXP_DBL, SECT_DATA_L1)
389 
390       FDK_ALLOCATE_MEMORY_1D(self->hybResidualReal__FDK[i],
391                              setup.maxNumHybridBands, FIXP_DBL)
392       FDK_ALLOCATE_MEMORY_1D(self->hybResidualImag__FDK[i], resHybBands,
393                              FIXP_DBL)
394     }
395   } /* if (setup.bProcResidual) */
396 
397   FDK_ALLOCATE_MEMORY_2D_INT(self->wReal__FDK, setup.maxNumVChannels,
398                              setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2)
399   FDK_ALLOCATE_MEMORY_2D_INT(self->wImag__FDK, setup.maxNumVChannels,
400                              setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2)
401 
402   FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputRealDry__FDK,
403                              setup.maxNumOutputChannels,
404                              setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2)
405   FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputImagDry__FDK,
406                              setup.maxNumOutputChannels,
407                              setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2)
408 
409   FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputRealWet__FDK,
410                              setup.maxNumOutputChannels,
411                              setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2)
412   FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputImagWet__FDK,
413                              setup.maxNumOutputChannels,
414                              setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2)
415 
416   FDK_ALLOCATE_MEMORY_1D(self->hybridSynthesis, setup.maxNumOutputChannels,
417                          FDK_SYN_HYB_FILTER)
418 
419   FDK_ALLOCATE_MEMORY_1D(
420       self->hybridAnalysis,
421       setup.bProcResidual ? setup.maxNumInputChannels + setup.maxNumResChannels
422                           : setup.maxNumInputChannels,
423       FDK_ANA_HYB_FILTER)
424 
425   lfSize = 2 * BUFFER_LEN_LF * MAX_QMF_BANDS_TO_HYBRID;
426   {
427     hfSize =
428         BUFFER_LEN_HF * ((setup.maxNumQmfBands - MAX_QMF_BANDS_TO_HYBRID) +
429                          (setup.maxNumCmplxQmfBands - MAX_QMF_BANDS_TO_HYBRID));
430   }
431 
432   FDK_ALLOCATE_MEMORY_2D_INT(self->pHybridAnaStatesLFdmx,
433                              setup.maxNumInputChannels, lfSize, FIXP_DBL,
434                              SECT_DATA_L2) {
435     FDK_ALLOCATE_MEMORY_2D(self->pHybridAnaStatesHFdmx,
436                            setup.maxNumInputChannels, hfSize, FIXP_DBL)
437   }
438 
439   for (i = 0; i < setup.maxNumInputChannels; i++) {
440     FIXP_DBL *pHybridAnaStatesHFdmx;
441 
442     pHybridAnaStatesHFdmx = self->pHybridAnaStatesHFdmx[i];
443 
444     FDKhybridAnalysisOpen(&self->hybridAnalysis[i],
445                           self->pHybridAnaStatesLFdmx[i],
446                           lfSize * sizeof(FIXP_DBL), pHybridAnaStatesHFdmx,
447                           hfSize * sizeof(FIXP_DBL));
448   }
449   if (setup.bProcResidual) {
450     lfSize = 2 * BUFFER_LEN_LF * MAX_QMF_BANDS_TO_HYBRID;
451     hfSize = BUFFER_LEN_HF *
452              ((((config->decoderMode == EXT_LP_ONLY) ? PC_NUM_BANDS
453                                                      : setup.maxNumQmfBands) -
454                MAX_QMF_BANDS_TO_HYBRID) +
455               (setup.maxNumCmplxQmfBands - MAX_QMF_BANDS_TO_HYBRID));
456 
457     FDK_ALLOCATE_MEMORY_2D_INT(self->pHybridAnaStatesLFres,
458                                setup.maxNumResChannels, lfSize, FIXP_DBL,
459                                SECT_DATA_L2)
460     FDK_ALLOCATE_MEMORY_2D(self->pHybridAnaStatesHFres, setup.maxNumResChannels,
461                            hfSize, FIXP_DBL)
462 
463     for (i = setup.maxNumInputChannels;
464          i < (setup.maxNumInputChannels + setup.maxNumResChannels); i++) {
465       FDKhybridAnalysisOpen(
466           &self->hybridAnalysis[i],
467           self->pHybridAnaStatesLFres[i - setup.maxNumInputChannels],
468           lfSize * sizeof(FIXP_DBL),
469           self->pHybridAnaStatesHFres[i - setup.maxNumInputChannels],
470           hfSize * sizeof(FIXP_DBL));
471     }
472   }
473 
474   FDK_ALLOCATE_MEMORY_1D(self->smoothState, 1, SMOOTHING_STATE)
475   FDK_ALLOCATE_MEMORY_1D(self->reshapeBBEnvState, 1, RESHAPE_BBENV_STATE)
476 
477   FDK_ALLOCATE_MEMORY_1D(self->apDecor, setup.maxNumDecorChannels, DECORR_DEC)
478   FDK_ALLOCATE_MEMORY_2D_INT(self->pDecorBufferCplx, setup.maxNumDecorChannels,
479                              (2 * ((825) + (373))), FIXP_DBL, SECT_DATA_L2)
480 
481   for (i = 0; i < setup.maxNumDecorChannels; i++) {
482     if (FDKdecorrelateOpen(&self->apDecor[i], self->pDecorBufferCplx[i],
483                            (2 * ((825) + (373))))) {
484       goto bail;
485     }
486   }
487 
488   if (subbandTPCreate(&self->hStpDec) != MPS_OK) {
489     goto bail;
490   }
491 
492   /* save general decoder configuration */
493   self->decoderLevel = config->decoderLevel;
494   self->decoderMode = config->decoderMode;
495   self->binauralMode = config->binauralMode;
496 
497   /* preinitialize configuration */
498   self->partiallyComplex = (config->decoderMode != EXT_HQ_ONLY) ? 1 : 0;
499 
500   /* Set to default state */
501   SpatialDecConcealment_Init(&self->concealInfo, MPEGS_CONCEAL_RESET_ALL);
502 
503   /* Everything is fine so return the handle */
504   return self;
505 
506 bail:
507   /* Collector for all errors.
508      Deallocate all memory and return a invalid handle. */
509   FDK_SpatialDecClose(self);
510 
511   return NULL;
512 }
513 
514 /*******************************************************************************
515  Functionname: isValidConfig
516  *******************************************************************************
517 
518  Description: Validate if configuration is supported in present instance
519 
520  Arguments:
521 
522  Return: 1: all okay
523          0: configuration not supported
524 *******************************************************************************/
isValidConfig(spatialDec const * const self,const SPATIAL_DEC_UPMIX_TYPE upmixType,SPATIALDEC_PARAM const * const pUserParams,const AUDIO_OBJECT_TYPE coreAot)525 static int isValidConfig(spatialDec const *const self,
526                          const SPATIAL_DEC_UPMIX_TYPE upmixType,
527                          SPATIALDEC_PARAM const *const pUserParams,
528                          const AUDIO_OBJECT_TYPE coreAot) {
529   UPMIXTYPE nUpmixType;
530 
531   FDK_ASSERT(self != NULL);
532   FDK_ASSERT(pUserParams != NULL);
533 
534   nUpmixType = (UPMIXTYPE)upmixType;
535 
536   switch (nUpmixType) {
537     case UPMIXTYPE_BYPASS: /* UPMIX_TYPE_BYPASS */
538       break;
539     case UPMIXTYPE_NORMAL: /* UPMIX_TYPE_NORMAL */
540       break;
541     default:
542       return 0; /* unsupported upmixType */
543   }
544 
545   return 1; /* upmixType supported */
546 }
547 
CheckLevelTreeUpmixType(const SACDEC_CREATION_PARAMS * const pCreateParams,const SPATIAL_SPECIFIC_CONFIG * const pSsc,const int decoderLevel,const UPMIXTYPE upmixType)548 static SACDEC_ERROR CheckLevelTreeUpmixType(
549     const SACDEC_CREATION_PARAMS *const pCreateParams,
550     const SPATIAL_SPECIFIC_CONFIG *const pSsc, const int decoderLevel,
551     const UPMIXTYPE upmixType) {
552   SACDEC_ERROR err = MPS_OK;
553   int nOutputChannels, treeConfig;
554 
555   FDK_ASSERT(pCreateParams != NULL);
556   FDK_ASSERT(pSsc != NULL);
557 
558   treeConfig = pSsc->treeConfig;
559 
560   switch (decoderLevel) {
561     case 0: {
562       if (treeConfig != SPATIALDEC_MODE_RSVD7) {
563         err = MPS_INVALID_TREECONFIG;
564         goto bail;
565       }
566       break;
567     }
568     default:
569       err = MPS_INVALID_PARAMETER /* MPS_UNIMPLEMENTED */;
570       goto bail;
571   }
572 
573   switch (upmixType) {
574     case UPMIXTYPE_BYPASS:
575       nOutputChannels = pSsc->nInputChannels;
576       break;
577     default:
578       nOutputChannels = pSsc->nOutputChannels;
579       break;
580   }
581 
582   /* Is sufficient memory allocated. */
583   if ((pSsc->nInputChannels > pCreateParams->maxNumInputChannels) ||
584       (nOutputChannels > pCreateParams->maxNumOutputChannels) ||
585       (pSsc->nOttBoxes > pCreateParams->maxNumOttBoxes)) {
586     err = MPS_INVALID_PARAMETER;
587   }
588 
589 bail:
590   return err;
591 }
592 
SpatialDecInitParserContext(spatialDec * self)593 void SpatialDecInitParserContext(spatialDec *self) {
594   int i, j;
595 
596   for (i = 0; i < self->createParams.maxNumOttBoxes; i += 1) {
597     for (j = 0; j < MAX_PARAMETER_BANDS; j++) {
598       self->ottCLDidxPrev[i][j] = 0;
599       self->ottICCidxPrev[i][j] = 0;
600       self->cmpOttCLDidxPrev[i][j] = 0;
601       self->cmpOttICCidxPrev[i][j] = 0;
602     }
603   }
604   for (i = 0; i < self->createParams.maxNumInputChannels; i++) {
605     for (j = 0; j < MAX_PARAMETER_BANDS; j++) {
606       self->arbdmxGainIdxPrev[i][j] = 0;
607       self->cmpArbdmxGainIdxPrev[i][j] = 0;
608     }
609   }
610 }
611 
612 /*******************************************************************************
613  Functionname: FDK_SpatialDecInit
614  *******************************************************************************
615 
616  Description:
617 
618  Arguments:
619 
620  Return:
621 
622 *******************************************************************************/
623 
FDK_SpatialDecInit(spatialDec * self,SPATIAL_BS_FRAME * frame,SPATIAL_SPECIFIC_CONFIG * pSpatialSpecificConfig,int nQmfBands,SPATIAL_DEC_UPMIX_TYPE const upmixType,SPATIALDEC_PARAM * pUserParams,UINT initFlags)624 SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame,
625                                 SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig,
626                                 int nQmfBands,
627                                 SPATIAL_DEC_UPMIX_TYPE const upmixType,
628                                 SPATIALDEC_PARAM *pUserParams, UINT initFlags) {
629   SACDEC_ERROR err = MPS_OK;
630   int nCh, i, j, k;
631   int maxQmfBands;
632   int bypassMode = 0;
633 
634   self->useFDreverb = 0;
635 
636   /* check configuration parameter */
637   if (!isValidConfig(self, upmixType, pUserParams,
638                      pSpatialSpecificConfig->coreCodec)) {
639     return MPS_INVALID_PARAMETER;
640   }
641 
642   /* check tree configuration */
643   err = CheckLevelTreeUpmixType(&self->createParams, pSpatialSpecificConfig,
644                                 self->decoderLevel, (UPMIXTYPE)upmixType);
645   if (err != MPS_OK) {
646     goto bail;
647   }
648 
649   /* Store and update instance after all checks passed successfully: */
650   self->upmixType = (UPMIXTYPE)upmixType;
651 
652   if (initFlags & MPEGS_INIT_PARAMS_ERROR_CONCEALMENT) { /* At least one error
653                                                             concealment
654                                                             parameter changed */
655     err = SpatialDecConcealment_SetParam(
656         &self->concealInfo, SAC_DEC_CONCEAL_METHOD, pUserParams->concealMethod);
657     if (err != MPS_OK) {
658       goto bail;
659     }
660     err = SpatialDecConcealment_SetParam(&self->concealInfo,
661                                          SAC_DEC_CONCEAL_NUM_KEEP_FRAMES,
662                                          pUserParams->concealNumKeepFrames);
663     if (err != MPS_OK) {
664       goto bail;
665     }
666     err = SpatialDecConcealment_SetParam(
667         &self->concealInfo, SAC_DEC_CONCEAL_FADE_OUT_SLOPE_LENGTH,
668         pUserParams->concealFadeOutSlopeLength);
669     if (err != MPS_OK) {
670       goto bail;
671     }
672     err = SpatialDecConcealment_SetParam(&self->concealInfo,
673                                          SAC_DEC_CONCEAL_FADE_IN_SLOPE_LENGTH,
674                                          pUserParams->concealFadeInSlopeLength);
675     if (err != MPS_OK) {
676       goto bail;
677     }
678     err = SpatialDecConcealment_SetParam(&self->concealInfo,
679                                          SAC_DEC_CONCEAL_NUM_RELEASE_FRAMES,
680                                          pUserParams->concealNumReleaseFrames);
681     if (err != MPS_OK) {
682       goto bail;
683     }
684   }
685 
686   if (initFlags &
687       MPEGS_INIT_STATES_ERROR_CONCEALMENT) { /* Set to default state */
688     SpatialDecConcealment_Init(&self->concealInfo, MPEGS_CONCEAL_RESET_STATE);
689   }
690 
691   /* determine bypass mode */
692   bypassMode |= pUserParams->bypassMode;
693   bypassMode |= ((self->upmixType == UPMIXTYPE_BYPASS) ? 1 : 0);
694 
695   /* static decoder scale depends on number of qmf bands */
696   switch (nQmfBands) {
697     case 16:
698     case 24:
699     case 32:
700       self->staticDecScale = 21;
701       break;
702     case 64:
703       self->staticDecScale = 22;
704       break;
705     default:
706       return MPS_INVALID_PARAMETER;
707   }
708 
709   self->numParameterSetsPrev = 1;
710 
711   self->qmfBands = nQmfBands;
712   /* self->hybridBands will be updated in SpatialDecDecodeHeader() below. */
713 
714   self->bShareDelayWithSBR = 0;
715 
716   err = SpatialDecDecodeHeader(self, pSpatialSpecificConfig);
717   if (err != MPS_OK) {
718     goto bail;
719   }
720 
721   self->stereoConfigIndex = pSpatialSpecificConfig->stereoConfigIndex;
722 
723   if (initFlags & MPEGS_INIT_STATES_ANA_QMF_FILTER) {
724     self->qmfInputDelayBufPos = 0;
725     self->pc_filterdelay = 1; /* Division by 0 not possible */
726   }
727 
728   maxQmfBands = self->qmfBands;
729 
730   /* init residual decoder */
731 
732   /* init tonality smoothing */
733   if (initFlags & MPEGS_INIT_STATES_PARAM) {
734     initParameterSmoothing(self);
735   }
736 
737   /* init GES */
738   initBBEnv(self, (initFlags & MPEGS_INIT_STATES_GES) ? 1 : 0);
739 
740   /* Clip protection is applied only for normal processing. */
741   if (!isTwoChMode(self->upmixType) && !bypassMode) {
742     self->staticDecScale += self->clipProtectGainSF__FDK;
743   }
744 
745   {
746     UINT flags = 0;
747     INT initStatesFlag = (initFlags & MPEGS_INIT_STATES_ANA_QMF_FILTER) ? 1 : 0;
748     INT useLdFilter =
749         (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) ? 1 : 0;
750 
751     flags = self->pQmfDomain->globalConf.flags_requested;
752     flags &= (~(UINT)QMF_FLAG_LP);
753 
754     if (initStatesFlag)
755       flags &= ~QMF_FLAG_KEEP_STATES;
756     else
757       flags |= QMF_FLAG_KEEP_STATES;
758 
759     if (useLdFilter)
760       flags |= QMF_FLAG_MPSLDFB;
761     else
762       flags &= ~QMF_FLAG_MPSLDFB;
763 
764     self->pQmfDomain->globalConf.flags_requested = flags;
765     FDK_QmfDomain_Configure(self->pQmfDomain);
766 
767     /* output scaling */
768     for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) {
769       int outputScale = 0, outputGain_e = 0, scale = -(8) + (1);
770       FIXP_DBL outputGain_m = getChGain(self, nCh, &outputGain_e);
771 
772       if (!isTwoChMode(self->upmixType) && !bypassMode) {
773         outputScale +=
774             self->clipProtectGainSF__FDK; /* consider clip protection scaling at
775                                              synthesis qmf */
776       }
777 
778       scale += outputScale;
779 
780       qmfChangeOutScalefactor(&self->pQmfDomain->QmfDomainOut[nCh].fb, scale);
781       qmfChangeOutGain(&self->pQmfDomain->QmfDomainOut[nCh].fb, outputGain_m,
782                        outputGain_e);
783     }
784   }
785 
786   for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) {
787     FDKhybridSynthesisInit(&self->hybridSynthesis[nCh], THREE_TO_TEN,
788                            self->qmfBands, maxQmfBands);
789   }
790 
791   /* for input, residual channels and arbitrary down-mix residual channels */
792   for (nCh = 0; nCh < self->createParams.maxNumInputChannels; nCh++) {
793     FDKhybridAnalysisInit(
794         &self->hybridAnalysis[nCh], THREE_TO_TEN, self->qmfBands, maxQmfBands,
795         (initFlags & MPEGS_INIT_STATES_ANA_HYB_FILTER) ? 1 : 0);
796   }
797   for (; nCh < (self->createParams.bProcResidual
798                     ? (self->createParams.maxNumInputChannels +
799                        self->createParams.maxNumResChannels)
800                     : self->createParams.maxNumInputChannels);
801        nCh++) {
802     FDKhybridAnalysisInit(&self->hybridAnalysis[nCh], THREE_TO_TEN, maxQmfBands,
803                           maxQmfBands, 0);
804   }
805 
806   {
807     for (k = 0; k < self->numDecorSignals; k++) {
808       int errCode, idec;
809       FDK_DECORR_TYPE decorrType = DECORR_PS;
810       decorrType = DECORR_LD;
811       if (self->pConfigCurrent->syntaxFlags &
812           (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) {
813         decorrType =
814             ((self->treeConfig == TREE_212) && (self->decorrType == DECORR_PS))
815                 ? DECORR_PS
816                 : DECORR_USAC;
817       }
818       {
819         idec = k;
820         if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
821           if (self->treeConfig == TREE_212 && k == 0) {
822             idec = 2;
823           }
824         }
825       }
826       errCode = FDKdecorrelateInit(
827           &self->apDecor[k], self->hybridBands, decorrType, DUCKER_AUTOMATIC,
828           self->decorrConfig, idec, 0, /* self->partiallyComplex */
829           0, 0,                        /* isLegacyPS */
830           (initFlags & MPEGS_INIT_STATES_DECORRELATOR) ? 1 : 0);
831       if (errCode) return MPS_NOTOK;
832     }
833   } /* !self->partiallyComplex */
834 
835   err = initM1andM2(self, (initFlags & MPEGS_INIT_STATES_M1M2) ? 1 : 0,
836                     (initFlags & MPEGS_INIT_CONFIG) ? 1 : 0);
837   if (err != MPS_OK) return err;
838 
839   /* Initialization of previous frame data */
840   if (initFlags & MPEGS_INIT_STATES_PARAM) {
841     for (i = 0; i < self->createParams.maxNumOttBoxes; i += 1) {
842       /* reset icc diff data */
843       for (k = 0; k < MAX_PARAMETER_SETS; k += 1) {
844         for (j = 0; j < MAX_PARAMETER_BANDS; j += 1) {
845           self->ottICCdiffidx[i][k][j] = 0;
846         }
847       }
848     }
849     /* Parameter Smoothing */
850     /* robustness: init with one of the values of smgTimeTable[] = {64, 128,
851        256, 512} to avoid division by zero in calcFilterCoeff__FDK() */
852     self->smoothState->prevSmgTime = smgTimeTable[2]; /* == 256 */
853     FDKmemclear(self->smoothState->prevSmgData,
854                 MAX_PARAMETER_BANDS * sizeof(UCHAR));
855     FDKmemclear(self->smoothState->opdLeftState__FDK,
856                 MAX_PARAMETER_BANDS * sizeof(FIXP_DBL));
857     FDKmemclear(self->smoothState->opdRightState__FDK,
858                 MAX_PARAMETER_BANDS * sizeof(FIXP_DBL));
859   }
860 
861   self->prevTimeSlot = -1;
862   self->curTimeSlot =
863       MAX_TIME_SLOTS + 1; /* Initialize with a invalid value to trigger
864                              concealment if first frame has no valid data. */
865   self->curPs = 0;
866 
867   subbandTPInit(self->hStpDec);
868 
869 bail:
870   return err;
871 }
872 
SpatialDecChannelProperties(spatialDec * self,AUDIO_CHANNEL_TYPE channelType[],UCHAR channelIndices[],const FDK_channelMapDescr * const mapDescr)873 void SpatialDecChannelProperties(spatialDec *self,
874                                  AUDIO_CHANNEL_TYPE channelType[],
875                                  UCHAR channelIndices[],
876                                  const FDK_channelMapDescr *const mapDescr) {
877   if ((self == NULL) || (channelType == NULL) || (channelIndices == NULL) ||
878       (mapDescr == NULL)) {
879     return; /* no extern buffer to be filled */
880   }
881 
882   if (self->numOutputChannelsAT !=
883       treePropertyTable[self->treeConfig].numOutputChannels) {
884     int ch;
885     /* Declare all channels to be front channels: */
886     for (ch = 0; ch < self->numOutputChannelsAT; ch += 1) {
887       channelType[ch] = ACT_FRONT;
888       channelIndices[ch] = ch;
889     }
890   } else {
891     /* ISO/IEC FDIS 23003-1:2006(E), page 46, Table 40 bsTreeConfig */
892     switch (self->treeConfig) {
893       case TREE_212:
894         channelType[0] = ACT_FRONT;
895         channelIndices[0] = 0;
896         channelType[1] = ACT_FRONT;
897         channelIndices[1] = 1;
898         break;
899       default:;
900     }
901   }
902 }
903 
904 /*******************************************************************************
905  Functionname: FDK_SpatialDecClose
906  *******************************************************************************
907 
908  Description:
909 
910  Arguments:
911 
912  Return:
913 
914 *******************************************************************************/
915 
FDK_SpatialDecClose(spatialDec * self)916 void FDK_SpatialDecClose(spatialDec *self) {
917   if (self) {
918     int k;
919 
920     if (self->apDecor != NULL) {
921       for (k = 0; k < self->createParams.maxNumDecorChannels; k++) {
922         FDKdecorrelateClose(&(self->apDecor[k]));
923       }
924       FDK_FREE_MEMORY_1D(self->apDecor);
925     }
926     if (self->pDecorBufferCplx != NULL) {
927       FDK_FREE_MEMORY_2D(self->pDecorBufferCplx);
928     }
929 
930     subbandTPDestroy(&self->hStpDec);
931 
932     FDK_FREE_MEMORY_1D(self->reshapeBBEnvState);
933     FDK_FREE_MEMORY_1D(self->smoothState);
934 
935     FDK_FREE_MEMORY_2D(self->pHybridAnaStatesLFdmx);
936     FDK_FREE_MEMORY_2D(self->pHybridAnaStatesHFdmx);
937     FDK_FREE_MEMORY_2D(self->pHybridAnaStatesLFres);
938     FDK_FREE_MEMORY_2D(self->pHybridAnaStatesHFres);
939     FDK_FREE_MEMORY_1D(self->hybridAnalysis);
940 
941     FDK_FREE_MEMORY_1D(self->hybridSynthesis);
942 
943     /* The time buffer is passed to the decoder from outside to avoid copying
944      * (zero copy). */
945     /* FDK_FREE_MEMORY_2D(self->timeOut__FDK); */
946 
947     FDK_FREE_MEMORY_2D(self->hybOutputImagWet__FDK);
948     FDK_FREE_MEMORY_2D(self->hybOutputRealWet__FDK);
949 
950     FDK_FREE_MEMORY_2D(self->hybOutputImagDry__FDK);
951     FDK_FREE_MEMORY_2D(self->hybOutputRealDry__FDK);
952 
953     FDK_FREE_MEMORY_2D(self->wImag__FDK);
954     FDK_FREE_MEMORY_2D(self->wReal__FDK);
955 
956     if (self->createParams.bProcResidual) {
957       int i;
958 
959       for (i = 0; i < self->createParams.maxNumResChannels; i++) {
960         if (self->hybResidualImag__FDK != NULL)
961           FDK_FREE_MEMORY_1D(self->hybResidualImag__FDK[i]);
962         if (self->hybResidualReal__FDK != NULL)
963           FDK_FREE_MEMORY_1D(self->hybResidualReal__FDK[i]);
964         if (self->qmfResidualImag__FDK != NULL)
965           FDK_FREE_MEMORY_2D_ALIGNED(self->qmfResidualImag__FDK[i]);
966         if (self->qmfResidualReal__FDK != NULL)
967           FDK_FREE_MEMORY_2D_ALIGNED(self->qmfResidualReal__FDK[i]);
968       }
969 
970       FDK_FREE_MEMORY_1D(self->hybResidualImag__FDK);
971       FDK_FREE_MEMORY_1D(self->hybResidualReal__FDK);
972 
973       FDK_FREE_MEMORY_1D(self->qmfResidualImag__FDK);
974       FDK_FREE_MEMORY_1D(self->qmfResidualReal__FDK);
975 
976     } /* self->createParams.bProcResidual */
977 
978     FDK_FREE_MEMORY_2D(self->hybInputImag__FDK);
979     FDK_FREE_MEMORY_2D(self->hybInputReal__FDK);
980 
981     FDK_FREE_MEMORY_2D_ALIGNED(self->qmfInputImag__FDK);
982     FDK_FREE_MEMORY_2D_ALIGNED(self->qmfInputReal__FDK);
983 
984     FDK_FREE_MEMORY_3D(self->M2ImagPrev__FDK);
985 
986     FDK_FREE_MEMORY_3D(self->M2RealPrev__FDK);
987 
988     FDK_FREE_MEMORY_3D(self->M2Imag__FDK);
989 
990     FDK_FREE_MEMORY_3D(self->M2Real__FDK);
991 
992     FDK_FREE_MEMORY_1D(self->arbdmxAlphaPrev__FDK);
993     FDK_FREE_MEMORY_1D(self->arbdmxAlpha__FDK);
994 
995     FDK_FREE_MEMORY_3D(self->arbdmxGain__FDK);
996 
997     FDK_FREE_MEMORY_3D(self->ottIPD__FDK);
998     FDK_FREE_MEMORY_3D(self->ottICC__FDK);
999     FDK_FREE_MEMORY_3D(self->ottCLD__FDK);
1000 
1001     /* Last parameters from prev frame */
1002     FDK_FREE_MEMORY_2D(self->ottCLDidxPrev);
1003     FDK_FREE_MEMORY_2D(self->ottICCidxPrev);
1004     FDK_FREE_MEMORY_3D(self->ottICCdiffidx);
1005     FDK_FREE_MEMORY_2D(self->ottIPDidxPrev);
1006     FDK_FREE_MEMORY_2D(self->arbdmxGainIdxPrev);
1007 
1008     FDK_FREE_MEMORY_2D(self->cmpOttCLDidxPrev);
1009     FDK_FREE_MEMORY_2D(self->cmpOttICCidxPrev);
1010     FDK_FREE_MEMORY_3D(self->outIdxData);
1011     FDK_FREE_MEMORY_2D(self->cmpOttIPDidxPrev);
1012     FDK_FREE_MEMORY_2D(self->cmpArbdmxGainIdxPrev);
1013 
1014     FDK_FREE_MEMORY_2D(self->smgData);
1015     FDK_FREE_MEMORY_1D(self->smgTime);
1016 
1017     FDK_FREE_MEMORY_1D(self->numOttBands);
1018 
1019     FDK_FREE_MEMORY_1D(self->param2hyb);
1020 
1021     FDK_FREE_MEMORY_1D(self);
1022   }
1023 
1024   return;
1025 }
1026 
1027 /**
1028  * \brief Apply Surround bypass buffer copies
1029  * \param self spatialDec handle
1030  * \param hybInputReal
1031  * \param hybInputImag
1032  * \param hybOutputReal
1033  * \param hybOutputImag
1034  * \param numInputChannels amount if input channels available in hybInputReal
1035  * and hybInputImag, which may differ from self->numInputChannels.
1036  */
SpatialDecApplyBypass(spatialDec * self,FIXP_DBL ** hybInputReal,FIXP_DBL ** hybInputImag,FIXP_DBL ** hybOutputReal,FIXP_DBL ** hybOutputImag,const int numInputChannels)1037 static void SpatialDecApplyBypass(spatialDec *self, FIXP_DBL **hybInputReal,
1038                                   FIXP_DBL **hybInputImag,
1039                                   FIXP_DBL **hybOutputReal,
1040                                   FIXP_DBL **hybOutputImag,
1041                                   const int numInputChannels) {
1042   int complexHybBands;
1043 
1044   complexHybBands = self->hybridBands;
1045 
1046   {
1047     int ch;
1048     int rf = -1, lf = -1, cf = -1; /* Right Front, Left Front, Center Front */
1049 
1050     /* Determine output channel indices according to tree config */
1051     switch (self->treeConfig) {
1052       case TREE_212: /* 212  */
1053         lf = 0;
1054         rf = 1;
1055         break;
1056       default:;
1057     }
1058 
1059     /* Note: numInputChannels might not match the tree config ! */
1060     switch (numInputChannels) {
1061       case 1:
1062         if (cf > 0) {
1063           FDKmemcpy(hybOutputReal[cf], hybInputReal[0],
1064                     self->hybridBands * sizeof(FIXP_DBL));
1065           FDKmemcpy(hybOutputImag[cf], hybInputImag[0],
1066                     complexHybBands * sizeof(FIXP_DBL));
1067         } else {
1068           FDKmemcpy(hybOutputReal[lf], hybInputReal[0],
1069                     self->hybridBands * sizeof(FIXP_DBL));
1070           FDKmemcpy(hybOutputReal[rf], hybInputReal[0],
1071                     self->hybridBands * sizeof(FIXP_DBL));
1072           FDKmemcpy(hybOutputImag[lf], hybInputImag[0],
1073                     complexHybBands * sizeof(FIXP_DBL));
1074           FDKmemcpy(hybOutputImag[rf], hybInputImag[0],
1075                     complexHybBands * sizeof(FIXP_DBL));
1076         }
1077         break;
1078       case 2:
1079         FDK_ASSERT(lf != -1);
1080         FDK_ASSERT(rf != -1);
1081         FDKmemcpy(hybOutputReal[lf], hybInputReal[0],
1082                   self->hybridBands * sizeof(FIXP_DBL));
1083         FDKmemcpy(hybOutputReal[rf], hybInputReal[1],
1084                   self->hybridBands * sizeof(FIXP_DBL));
1085         FDKmemcpy(hybOutputImag[lf], hybInputImag[0],
1086                   complexHybBands * sizeof(FIXP_DBL));
1087         FDKmemcpy(hybOutputImag[rf], hybInputImag[1],
1088                   complexHybBands * sizeof(FIXP_DBL));
1089         break;
1090     }
1091     for (ch = 0; ch < self->numOutputChannelsAT; ch++) {
1092       if (ch == lf || ch == rf || ch == cf) {
1093         continue; /* Skip bypassed channels */
1094       }
1095       FDKmemclear(hybOutputReal[ch], self->hybridBands * sizeof(FIXP_DBL));
1096       FDKmemclear(hybOutputImag[ch], complexHybBands * sizeof(FIXP_DBL));
1097     }
1098   }
1099 }
1100 
1101 /**
1102  * \brief Set internal error and reset error status
1103  *
1104  * \param self         spatialDec handle.
1105  * \param bypassMode   pointer to bypassMode.
1106  * \param err          error status.
1107  *
1108  * \return  error status.
1109  */
SpatialDecSetInternalError(spatialDec * self,int * bypassMode,SACDEC_ERROR err)1110 static SACDEC_ERROR SpatialDecSetInternalError(spatialDec *self,
1111                                                int *bypassMode,
1112                                                SACDEC_ERROR err) {
1113   *bypassMode = 1;
1114 
1115   if (self->errInt == MPS_OK) {
1116     /* store internal error before it gets overwritten */
1117     self->errInt = err;
1118   }
1119 
1120   return MPS_OK;
1121 }
1122 
1123 /*******************************************************************************
1124  Functionname: SpatialDecApplyParameterSets
1125  *******************************************************************************
1126 
1127  Description:
1128 
1129  Arguments:
1130 
1131  Return:
1132 
1133 *******************************************************************************/
SpatialDecApplyParameterSets(spatialDec * self,const SPATIAL_BS_FRAME * frame,SPATIALDEC_INPUT_MODE mode,PCM_MPS * inData,FIXP_DBL ** qmfInDataReal,FIXP_DBL ** qmfInDataImag,UINT nSamples,UINT controlFlags,int numInputChannels,const FDK_channelMapDescr * const mapDescr)1134 static SACDEC_ERROR SpatialDecApplyParameterSets(
1135     spatialDec *self, const SPATIAL_BS_FRAME *frame, SPATIALDEC_INPUT_MODE mode,
1136     PCM_MPS *inData,          /* Time domain input  */
1137     FIXP_DBL **qmfInDataReal, /* QMF domain data l/r */
1138     FIXP_DBL **qmfInDataImag, /* QMF domain data l/r */
1139     UINT nSamples, UINT controlFlags, int numInputChannels,
1140     const FDK_channelMapDescr *const mapDescr) {
1141   SACDEC_ERROR err = MPS_OK;
1142 
1143   FIXP_SGL alpha = FL2FXCONST_SGL(0.0);
1144 
1145   int ts;
1146   int ch;
1147   int hyb;
1148 
1149   int prevSlot = self->prevTimeSlot;
1150   int ps = self->curPs;
1151   int ts_io = 0; /* i/o dependent slot */
1152   int bypassMode = (controlFlags & MPEGS_BYPASSMODE) ? 1 : 0;
1153 
1154   /* Bypass can be triggered by the upmixType, too. */
1155   bypassMode |= ((self->upmixType == UPMIXTYPE_BYPASS) ? 1 : 0);
1156 
1157   /*
1158    * Decode available slots
1159    */
1160   for (ts = self->curTimeSlot;
1161        ts <= fixMin(self->curTimeSlot + (int)nSamples / self->qmfBands - 1,
1162                     self->timeSlots - 1);
1163        ts++, ts_io++) {
1164     int currSlot = frame->paramSlot[ps];
1165 
1166     err = (currSlot < ts) ? MPS_WRONG_PARAMETERSETS : MPS_OK;
1167     if (err != MPS_OK) {
1168       err = SpatialDecSetInternalError(self, &bypassMode, err);
1169     }
1170 
1171     /*
1172      * Get new parameter set
1173      */
1174     if (ts == prevSlot + 1) {
1175       if (bypassMode == 0) {
1176         err = SpatialDecCalculateM1andM2(
1177             self, ps, frame); /* input: ottCLD, ottICC, ... */
1178                               /* output: M1param(Real/Imag), M2(Real/Imag) */
1179         if (err != MPS_OK) {
1180           err = SpatialDecSetInternalError(self, &bypassMode, err);
1181         }
1182       }
1183 
1184       if ((ps == 0) && (self->bOverwriteM1M2prev != 0)) {
1185         /* copy matrix entries of M1/M2 of the first parameter set to the
1186            previous matrices (of the last frame). This avoids the interpolation
1187            of incompatible values. E.g. for residual bands the coefficients are
1188            calculated differently compared to non-residual bands.
1189          */
1190         SpatialDecBufferMatrices(self); /* input: M(1/2)param(Real/Imag) */
1191                                         /* output: M(1/2)param(Real/Imag)Prev */
1192         self->bOverwriteM1M2prev = 0;
1193       }
1194 
1195       if (bypassMode == 0) {
1196         SpatialDecSmoothM1andM2(
1197             self, frame,
1198             ps); /* input: M1param(Real/Imag)(Prev), M2(Real/Imag)(Prev) */
1199       }          /* output: M1param(Real/Imag), M2(Real/Imag) */
1200     }
1201 
1202     if (bypassMode == 0) {
1203       alpha = FX_DBL2FX_SGL(fDivNorm(ts - prevSlot, currSlot - prevSlot));
1204     }
1205 
1206     switch (mode) {
1207       case INPUTMODE_QMF_SBR:
1208         if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD)
1209           self->bShareDelayWithSBR = 0; /* We got no hybrid delay */
1210         else
1211           self->bShareDelayWithSBR = 1;
1212         SpatialDecFeedQMF(
1213             self, qmfInDataReal, qmfInDataImag, ts_io, bypassMode,
1214             self->qmfInputReal__FDK, self->qmfInputImag__FDK,
1215             (bypassMode) ? numInputChannels : self->numInputChannels);
1216         break;
1217       case INPUTMODE_TIME:
1218         self->bShareDelayWithSBR = 0;
1219         SpatialDecQMFAnalysis(
1220             self, inData, ts_io, bypassMode, self->qmfInputReal__FDK,
1221             self->qmfInputImag__FDK,
1222             (bypassMode) ? numInputChannels : self->numInputChannels);
1223         break;
1224       default:
1225         break;
1226     }
1227 
1228     if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) &&
1229         self->residualCoding) {
1230       int offset;
1231       ch = 1;
1232 
1233       offset = self->pQmfDomain->globalConf.nBandsSynthesis *
1234                self->pQmfDomain->globalConf.nQmfTimeSlots;
1235 
1236       {
1237         const PCM_MPS *inSamples =
1238             &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis];
1239 
1240         CalculateSpaceAnalysisQmf(
1241             &self->pQmfDomain->QmfDomainIn[ch].fb, inSamples + (ch * offset),
1242             self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0]);
1243 
1244         if (!isTwoChMode(self->upmixType) && !bypassMode) {
1245           int i;
1246           FIXP_DBL *RESTRICT self_qmfResidualReal__FDK_0_0 =
1247               &self->qmfResidualReal__FDK[0][0][0];
1248           FIXP_DBL *RESTRICT self_qmfResidualImag__FDK_0_0 =
1249               &self->qmfResidualImag__FDK[0][0][0];
1250 
1251           if ((self->pQmfDomain->globalConf.nBandsAnalysis == 24) &&
1252               !(self->stereoConfigIndex == 3)) {
1253             for (i = 0; i < self->qmfBands; i++) {
1254               self_qmfResidualReal__FDK_0_0[i] =
1255                   fMult(scaleValueSaturate(self_qmfResidualReal__FDK_0_0[i],
1256                                            1 + self->sacInDataHeadroom - (1)),
1257                         self->clipProtectGain__FDK);
1258               self_qmfResidualImag__FDK_0_0[i] =
1259                   fMult(scaleValueSaturate(self_qmfResidualImag__FDK_0_0[i],
1260                                            1 + self->sacInDataHeadroom - (1)),
1261                         self->clipProtectGain__FDK);
1262             }
1263           } else {
1264             for (i = 0; i < self->qmfBands; i++) {
1265               self_qmfResidualReal__FDK_0_0[i] =
1266                   fMult(scaleValueSaturate(self_qmfResidualReal__FDK_0_0[i],
1267                                            self->sacInDataHeadroom - (1)),
1268                         self->clipProtectGain__FDK);
1269               self_qmfResidualImag__FDK_0_0[i] =
1270                   fMult(scaleValueSaturate(self_qmfResidualImag__FDK_0_0[i],
1271                                            self->sacInDataHeadroom - (1)),
1272                         self->clipProtectGain__FDK);
1273             }
1274           }
1275         }
1276       }
1277     }
1278 
1279     SpatialDecHybridAnalysis(
1280         self, /* input: qmfInput(Real/Imag), qmfResidual(Real/Imag) */
1281         self->qmfInputReal__FDK, self->qmfInputImag__FDK,
1282         self->hybInputReal__FDK, self->hybInputImag__FDK, ts, numInputChannels);
1283 
1284     if (bypassMode) {
1285       SpatialDecApplyBypass(
1286           self, self->hybInputReal__FDK, /* input: hybInput(Real/Imag) */
1287           self->hybInputImag__FDK,
1288           self->hybOutputRealDry__FDK, /* output: hybOutput(Real/Imag)Dry */
1289           self->hybOutputImagDry__FDK, numInputChannels);
1290     } else /* !bypassMode */
1291     {
1292       FIXP_DBL *pxReal[MAX_NUM_XCHANNELS] = {NULL};
1293       FIXP_DBL *pxImag[MAX_NUM_XCHANNELS] = {NULL};
1294 
1295       SpatialDecCreateX(self,
1296                         self->hybInputReal__FDK, /* input: hybInput(Real/Imag),
1297                                                     hybResidual(Real/Imag) */
1298                         self->hybInputImag__FDK, pxReal, pxImag);
1299 
1300       {
1301         SpatialDecApplyM1_CreateW_Mode212(
1302             self, frame, pxReal, pxImag,
1303             self->wReal__FDK, /* output: w(Real/Imag) */
1304             self->wImag__FDK);
1305       }
1306       if (err != MPS_OK) goto bail;
1307 
1308       int applyM2Config = APPLY_M2_NONE;
1309 
1310       applyM2Config = APPLY_M2;
1311       if ((self->pConfigCurrent->syntaxFlags &
1312            (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) &&
1313           (self->tempShapeConfig != 1) && (self->tempShapeConfig != 2)) {
1314         if (self->phaseCoding == 3)
1315           applyM2Config = APPLY_M2_MODE212_Res_PhaseCoding;
1316         else
1317           applyM2Config = APPLY_M2_MODE212;
1318       }
1319 
1320       switch (applyM2Config) {
1321         case APPLY_M2_MODE212: {
1322           err = SpatialDecApplyM2_Mode212(
1323               self, ps, alpha, self->wReal__FDK, self->wImag__FDK,
1324               self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK);
1325         } break;
1326         case APPLY_M2_MODE212_Res_PhaseCoding:
1327           err = SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
1328               self, ps, alpha, self->wReal__FDK, self->wImag__FDK,
1329               self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK);
1330           break;
1331         case APPLY_M2:
1332           err = SpatialDecApplyM2(
1333               self, ps, alpha, self->wReal__FDK, self->wImag__FDK,
1334               self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK,
1335               self->hybOutputRealWet__FDK, self->hybOutputImagWet__FDK);
1336           break;
1337         default:
1338           err = MPS_APPLY_M2_ERROR;
1339           goto bail;
1340       }
1341 
1342       if (err != MPS_OK) goto bail;
1343 
1344       if ((self->tempShapeConfig == 2) && (!isTwoChMode(self->upmixType))) {
1345         SpatialDecReshapeBBEnv(self, frame,
1346                                ts); /* input: reshapeBBEnvState,
1347                                        hybOutput(Real/Imag)(Dry/Wet),
1348                                        hybInput(Real/Imag) */
1349       }                             /* output: hybOutput(Real/Imag)Dry */
1350 
1351       /* Merge parts of the dry and wet QMF buffers. */
1352       if ((self->tempShapeConfig == 1) && (!isTwoChMode(self->upmixType))) {
1353         for (ch = 0; ch < self->numOutputChannels; ch++) {
1354           for (hyb = 0; hyb < self->tp_hybBandBorder; hyb++) {
1355             self->hybOutputRealDry__FDK[ch][hyb] =
1356                 fAddSaturate(self->hybOutputRealDry__FDK[ch][hyb],
1357                              self->hybOutputRealWet__FDK[ch][hyb]);
1358             self->hybOutputImagDry__FDK[ch][hyb] =
1359                 fAddSaturate(self->hybOutputImagDry__FDK[ch][hyb],
1360                              self->hybOutputImagWet__FDK[ch][hyb]);
1361           } /* loop hyb */
1362         }   /* loop ch */
1363         err = subbandTPApply(
1364             self, frame); /* input: hStpDec, hybOutput(Real/Imag)Dry/Wet */
1365                           /* output: hStpDec, hybOutput(Real/Imag)Dry */
1366         if (err != MPS_OK) goto bail;
1367       } /* (self->tempShapeConfig == 1) */
1368       else {
1369         /* The wet signal is added to the dry signal in applyM2 if GES and STP
1370          * are disabled */
1371         if ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) {
1372           int nHybBands;
1373           nHybBands = self->hybridBands;
1374 
1375           for (ch = 0; ch < self->numOutputChannels; ch++) {
1376             FIXP_DBL *RESTRICT pRealDry = self->hybOutputRealDry__FDK[ch];
1377             FIXP_DBL *RESTRICT pImagDry = self->hybOutputImagDry__FDK[ch];
1378             FIXP_DBL *RESTRICT pRealWet = self->hybOutputRealWet__FDK[ch];
1379             FIXP_DBL *RESTRICT pImagWet = self->hybOutputImagWet__FDK[ch];
1380             for (hyb = 0; hyb < nHybBands; hyb++) {
1381               pRealDry[hyb] = fAddSaturate(pRealDry[hyb], pRealWet[hyb]);
1382               pImagDry[hyb] = fAddSaturate(pImagDry[hyb], pImagWet[hyb]);
1383             } /* loop hyb */
1384             for (; hyb < self->hybridBands; hyb++) {
1385               pRealDry[hyb] = fAddSaturate(pRealDry[hyb], pRealWet[hyb]);
1386             } /* loop hyb */
1387           }   /* loop ch */
1388         } /* ( self->tempShapeConfig == 1 ) || ( self->tempShapeConfig == 2 ) */
1389       }   /* !self->tempShapeConfig == 1 */
1390     }     /*  !bypassMode */
1391 
1392     if ((self->phaseCoding == 1) && (bypassMode == 0)) {
1393       /* only if bsPhaseCoding == 1 and bsResidualCoding == 0 */
1394 
1395       SpatialDecApplyPhase(
1396           self, alpha, (ts == currSlot) /* signal the last slot of the set */
1397       );
1398     }
1399 
1400     /*
1401      * Synthesis Filtering
1402      */
1403 
1404     err = SpatialDecSynthesis(
1405         self, ts_io,
1406         self->hybOutputRealDry__FDK, /* input: hybOutput(Real/Imag)Dry */
1407         self->hybOutputImagDry__FDK, self->timeOut__FDK, /* output: timeOut */
1408         numInputChannels, mapDescr);
1409 
1410     if (err != MPS_OK) goto bail;
1411 
1412     /*
1413      * Update parameter buffer
1414      */
1415     if (ts == currSlot) {
1416       SpatialDecBufferMatrices(self); /* input: M(1/2)param(Real/Imag) */
1417                                       /* output: M(1/2)param(Real/Imag)Prev */
1418 
1419       prevSlot = currSlot;
1420       ps++;
1421     } /* if (ts==currSlot) */
1422 
1423   } /* ts loop */
1424 
1425   /*
1426    * Save parameter states
1427    */
1428   self->prevTimeSlot = prevSlot;
1429   self->curTimeSlot = ts;
1430   self->curPs = ps;
1431 
1432 bail:
1433 
1434   return err;
1435 }
1436 
SpatialDecApplyFrame(spatialDec * self,SPATIAL_BS_FRAME * frame,SPATIALDEC_INPUT_MODE inputMode,PCM_MPS * inData,FIXP_DBL ** qmfInDataReal,FIXP_DBL ** qmfInDataImag,PCM_MPS * pcmOutBuf,UINT nSamples,UINT * pControlFlags,int numInputChannels,const FDK_channelMapDescr * const mapDescr)1437 SACDEC_ERROR SpatialDecApplyFrame(
1438     spatialDec *self,
1439     SPATIAL_BS_FRAME *frame, /* parsed frame data to be applied */
1440     SPATIALDEC_INPUT_MODE inputMode, PCM_MPS *inData, /* Time domain input  */
1441     FIXP_DBL **qmfInDataReal,                         /* QMF domain data l/r */
1442     FIXP_DBL **qmfInDataImag,                         /* QMF domain data l/r */
1443     PCM_MPS *pcmOutBuf, /* MAX_OUTPUT_CHANNELS*MAX_TIME_SLOTS*NUM_QMF_BANDS] */
1444     UINT nSamples, UINT *pControlFlags, int numInputChannels,
1445     const FDK_channelMapDescr *const mapDescr) {
1446   SACDEC_ERROR err = MPS_OK;
1447 
1448   int fDecAndMapFrameData;
1449   int controlFlags;
1450 
1451   FDK_ASSERT(self != NULL);
1452   FDK_ASSERT(pControlFlags != NULL);
1453   FDK_ASSERT(pcmOutBuf != NULL);
1454   FDK_ASSERT(self->sacInDataHeadroom >= (1));
1455 
1456   self->errInt = err; /* Init internal error */
1457 
1458   controlFlags = *pControlFlags;
1459 
1460   if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) &&
1461       (self->stereoConfigIndex > 1)) {
1462     numInputChannels =
1463         1; /* Do not count residual channel as input channel. It is handled
1464               seperately. */
1465   }
1466 
1467   /* Check if input amount of channels is consistent */
1468   if (numInputChannels != self->numInputChannels) {
1469     controlFlags |= MPEGS_CONCEAL;
1470     if (numInputChannels > self->createParams.maxNumInputChannels) {
1471       return MPS_INVALID_PARAMETER;
1472     }
1473   }
1474 
1475   self->timeOut__FDK = pcmOutBuf;
1476 
1477   /* Determine local function control flags */
1478   fDecAndMapFrameData = frame->newBsData;
1479 
1480   if (((fDecAndMapFrameData ==
1481         0) /* assures that conceal flag will not be set for blind mode */
1482        && (self->curTimeSlot + (int)nSamples / self->qmfBands >
1483            self->timeSlots)) ||
1484       (frame->numParameterSets ==
1485        0)) { /* New input samples but missing side info */
1486     fDecAndMapFrameData = 1;
1487     controlFlags |= MPEGS_CONCEAL;
1488   }
1489 
1490   if ((fDecAndMapFrameData == 0) &&
1491       (frame->paramSlot[fMax(0, frame->numParameterSets - 1)] !=
1492            (self->timeSlots - 1) ||
1493        self->curTimeSlot >
1494            frame->paramSlot[self->curPs])) { /* Detected faulty parameter slot
1495                                                 data. */
1496     fDecAndMapFrameData = 1;
1497     controlFlags |= MPEGS_CONCEAL;
1498   }
1499 
1500   /* Update concealment state machine */
1501   SpatialDecConcealment_UpdateState(
1502       &self->concealInfo,
1503       (controlFlags & MPEGS_CONCEAL)
1504           ? 0
1505           : 1); /* convert from conceal flag to frame ok flag */
1506 
1507   if (fDecAndMapFrameData) {
1508     /* Reset spatial framing control vars */
1509     frame->newBsData = 0;
1510     self->prevTimeSlot = -1;
1511     self->curTimeSlot = 0;
1512     self->curPs = 0;
1513 
1514     if (controlFlags & MPEGS_CONCEAL) {
1515       /* Reset frame data to avoid misconfiguration. */
1516       SpatialDecClearFrameData(self, frame, &self->createParams);
1517     }
1518 
1519     {
1520       err = SpatialDecDecodeFrame(self, frame); /* input: ... */
1521       /* output: decodeAndMapFrameDATA */
1522     }
1523 
1524     if (err != MPS_OK) {
1525       /* Rescue strategy is to apply bypass mode in order
1526          to keep at least the downmix channels continuous. */
1527       controlFlags |= MPEGS_CONCEAL;
1528       if (self->errInt == MPS_OK) {
1529         /* store internal error befor it gets overwritten */
1530         self->errInt = err;
1531       }
1532     }
1533   }
1534 
1535   err = SpatialDecApplyParameterSets(
1536       self, frame, inputMode, inData, qmfInDataReal, qmfInDataImag, nSamples,
1537       controlFlags | ((err == MPS_OK) ? 0 : MPEGS_BYPASSMODE), numInputChannels,
1538       mapDescr);
1539   if (err != MPS_OK) {
1540     goto bail;
1541   }
1542 
1543 bail:
1544 
1545   *pControlFlags = controlFlags;
1546 
1547   return err;
1548 }
1549