1
2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5 � Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
6 All rights reserved.
7
8 1. INTRODUCTION
9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16 of the MPEG specifications.
17
18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
24
25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27 applications information and documentation.
28
29 2. COPYRIGHT LICENSE
30
31 Redistribution and use in source and binary forms, with or without modification, are permitted without
32 payment of copyright license fees provided that you satisfy the following conditions:
33
34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35 your modifications thereto in source code form.
36
37 You must retain the complete text of this software license in the documentation and/or other materials
38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40 modifications thereto to recipients of copies in binary form.
41
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
44
45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46 software or your modifications thereto.
47
48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49 and the date of any change. For modified versions of the FDK AAC Codec, the term
50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
52
53 3. NO PATENT LICENSE
54
55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57 respect to this software.
58
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
61
62 4. DISCLAIMER
63
64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69 or business interruption, however caused and on any theory of liability, whether in contract, strict
70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
71 advised of the possibility of such damage.
72
73 5. CONTACT INFORMATION
74
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
77 Am Wolfsmantel 33
78 91058 Erlangen, Germany
79
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
83
84 /*!
85 \file
86 \brief Sbr decoder
87 This module provides the actual decoder implementation. The SBR data (side information) is already
88 decoded. Only three functions are provided:
89
90 \li 1.) createSbrDec(): One time initialization
91 \li 2.) resetSbrDec(): Called by sbr_Apply() when the information contained in an SBR_HEADER_ELEMENT requires a reset
92 and recalculation of important SBR structures.
93 \li 3.) sbr_dec(): The actual decoder. Calls the different tools such as filterbanks, lppTransposer(), and calculateSbrEnvelope()
94 [the envelope adjuster].
95
96 \sa sbr_dec(), \ref documentationOverview
97 */
98
99 #include "sbr_dec.h"
100
101 #include "sbr_ram.h"
102 #include "env_extr.h"
103 #include "env_calc.h"
104 #include "scale.h"
105
106 #include "genericStds.h"
107
108 #include "sbrdec_drc.h"
109
110
111
assignLcTimeSlots(HANDLE_SBR_DEC hSbrDec,FIXP_DBL ** QmfBufferReal,int noCols)112 static void assignLcTimeSlots( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
113 FIXP_DBL **QmfBufferReal,
114 int noCols )
115 {
116 int slot, i;
117 FIXP_DBL *ptr;
118
119 /* Number of QMF timeslots in the overlap buffer: */
120 ptr = hSbrDec->pSbrOverlapBuffer;
121 for(slot=0; slot<hSbrDec->LppTrans.pSettings->overlap; slot++) {
122 QmfBufferReal[slot] = ptr; ptr += (64);
123 }
124
125 /* Assign timeslots to Workbuffer1 */
126 ptr = hSbrDec->WorkBuffer1;
127 for(i=0; i<noCols; i++) {
128 QmfBufferReal[slot] = ptr; ptr += (64);
129 slot++;
130 }
131 }
132
133
assignHqTimeSlots(HANDLE_SBR_DEC hSbrDec,FIXP_DBL ** QmfBufferReal,FIXP_DBL ** QmfBufferImag,int noCols)134 static void assignHqTimeSlots( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
135 FIXP_DBL **QmfBufferReal,
136 FIXP_DBL **QmfBufferImag,
137 int noCols )
138 {
139 FIXP_DBL *ptr;
140 int slot;
141
142 /* Number of QMF timeslots in one half of a frame (size of Workbuffer1 or 2): */
143 int halflen = (noCols >> 1) + hSbrDec->LppTrans.pSettings->overlap;
144 int totCols = noCols + hSbrDec->LppTrans.pSettings->overlap;
145
146 /* Number of QMF timeslots in the overlap buffer: */
147 ptr = hSbrDec->pSbrOverlapBuffer;
148 for(slot=0; slot<hSbrDec->LppTrans.pSettings->overlap; slot++) {
149 QmfBufferReal[slot] = ptr; ptr += (64);
150 QmfBufferImag[slot] = ptr; ptr += (64);
151 }
152
153 /* Assign first half of timeslots to Workbuffer1 */
154 ptr = hSbrDec->WorkBuffer1;
155 for(; slot<halflen; slot++) {
156 QmfBufferReal[slot] = ptr; ptr += (64);
157 QmfBufferImag[slot] = ptr; ptr += (64);
158 }
159
160 /* Assign second half of timeslots to Workbuffer2 */
161 ptr = hSbrDec->WorkBuffer2;
162 for(; slot<totCols; slot++) {
163 QmfBufferReal[slot] = ptr; ptr += (64);
164 QmfBufferImag[slot] = ptr; ptr += (64);
165 }
166 }
167
168
assignTimeSlots(HANDLE_SBR_DEC hSbrDec,int noCols,int useLP)169 static void assignTimeSlots( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
170 int noCols,
171 int useLP )
172 {
173 /* assign qmf time slots */
174 hSbrDec->useLP = useLP;
175 if (useLP) {
176 hSbrDec->SynthesisQMF.flags |= QMF_FLAG_LP;
177 hSbrDec->AnalysiscQMF.flags |= QMF_FLAG_LP;
178 } else {
179 hSbrDec->SynthesisQMF.flags &= ~QMF_FLAG_LP;
180 hSbrDec->AnalysiscQMF.flags &= ~QMF_FLAG_LP;
181 }
182 if (!useLP)
183 assignHqTimeSlots( hSbrDec, hSbrDec->QmfBufferReal, hSbrDec->QmfBufferImag, noCols );
184 else
185 {
186 assignLcTimeSlots( hSbrDec, hSbrDec->QmfBufferReal, noCols );
187 }
188 }
189
changeQmfType(HANDLE_SBR_DEC hSbrDec,int useLdTimeAlign)190 static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
191 int useLdTimeAlign )
192 {
193 UINT synQmfFlags = hSbrDec->SynthesisQMF.flags;
194 UINT anaQmfFlags = hSbrDec->AnalysiscQMF.flags;
195 int resetSynQmf = 0;
196 int resetAnaQmf = 0;
197
198 /* assign qmf type */
199 if (useLdTimeAlign) {
200 if (synQmfFlags & QMF_FLAG_CLDFB) {
201 /* change the type to MPSLD */
202 synQmfFlags &= ~QMF_FLAG_CLDFB;
203 synQmfFlags |= QMF_FLAG_MPSLDFB;
204 resetSynQmf = 1;
205 }
206 if (anaQmfFlags & QMF_FLAG_CLDFB) {
207 /* change the type to MPSLD */
208 anaQmfFlags &= ~QMF_FLAG_CLDFB;
209 anaQmfFlags |= QMF_FLAG_MPSLDFB;
210 resetAnaQmf = 1;
211 }
212 } else {
213 if (synQmfFlags & QMF_FLAG_MPSLDFB) {
214 /* change the type to CLDFB */
215 synQmfFlags &= ~QMF_FLAG_MPSLDFB;
216 synQmfFlags |= QMF_FLAG_CLDFB;
217 resetSynQmf = 1;
218 }
219 if (anaQmfFlags & QMF_FLAG_MPSLDFB) {
220 /* change the type to CLDFB */
221 anaQmfFlags &= ~QMF_FLAG_MPSLDFB;
222 anaQmfFlags |= QMF_FLAG_CLDFB;
223 resetAnaQmf = 1;
224 }
225 }
226
227 if (resetAnaQmf) {
228 QMF_FILTER_BANK prvAnaQmf;
229 int qmfErr;
230
231 /* Store current configuration */
232 FDKmemcpy(&prvAnaQmf, &hSbrDec->AnalysiscQMF, sizeof(QMF_FILTER_BANK));
233
234 /* Reset analysis QMF */
235 qmfErr = qmfInitAnalysisFilterBank (
236 &hSbrDec->AnalysiscQMF,
237 hSbrDec->anaQmfStates,
238 hSbrDec->AnalysiscQMF.no_col,
239 hSbrDec->AnalysiscQMF.lsb,
240 hSbrDec->AnalysiscQMF.usb,
241 hSbrDec->AnalysiscQMF.no_channels,
242 anaQmfFlags | QMF_FLAG_KEEP_STATES
243 );
244
245 if (qmfErr != 0) {
246 /* Restore old configuration of analysis QMF */
247 FDKmemcpy(&hSbrDec->AnalysiscQMF, &prvAnaQmf, sizeof(QMF_FILTER_BANK));
248 }
249 }
250
251 if (resetSynQmf) {
252 QMF_FILTER_BANK prvSynQmf;
253 int qmfErr;
254
255 /* Store current configuration */
256 FDKmemcpy(&prvSynQmf, &hSbrDec->SynthesisQMF, sizeof(QMF_FILTER_BANK));
257
258 /* Reset synthesis QMF */
259 qmfErr = qmfInitSynthesisFilterBank (
260 &hSbrDec->SynthesisQMF,
261 hSbrDec->pSynQmfStates,
262 hSbrDec->SynthesisQMF.no_col,
263 hSbrDec->SynthesisQMF.lsb,
264 hSbrDec->SynthesisQMF.usb,
265 hSbrDec->SynthesisQMF.no_channels,
266 synQmfFlags | QMF_FLAG_KEEP_STATES
267 );
268
269 if (qmfErr != 0) {
270 /* Restore old configuration of synthesis QMF */
271 FDKmemcpy(&hSbrDec->SynthesisQMF, &prvSynQmf, sizeof(QMF_FILTER_BANK));
272 }
273 }
274 }
275
276
277 /*!
278 \brief SBR decoder core function for one channel
279
280 \image html BufferMgmtDetailed-1632.png
281
282 Besides the filter states of the QMF filter bank and the LPC-states of
283 the LPP-Transposer, processing is mainly based on four buffers:
284 #timeIn, #timeOut, #WorkBuffer2 and #OverlapBuffer. The #WorkBuffer2
285 is reused for all channels and might be used by the core decoder, a
286 static overlap buffer is required for each channel. Du to in-place
287 processing, #timeIn and #timeOut point to identical locations.
288
289 The spectral data is organized in so-called slots, each slot
290 containing 64 bands of complex data. The number of slots per frame is
291 dependend on the frame size. For mp3PRO, there are 18 slots per frame
292 and 6 slots per #OverlapBuffer. It is not necessary to have the slots
293 in located consecutive address ranges.
294
295 To optimize memory usage and to minimize the number of memory
296 accesses, the memory management is organized as follows (Slot numbers
297 based on mp3PRO):
298
299 1.) Input time domain signal is located in #timeIn, the last slots
300 (0..5) of the spectral data of the previous frame are located in the
301 #OverlapBuffer. In addition, #frameData of the current frame resides
302 in the upper part of #timeIn.
303
304 2.) During the cplxAnalysisQmfFiltering(), 32 samples from #timeIn are transformed
305 into a slot of up to 32 complex spectral low band values at a
306 time. The first spectral slot -- nr. 6 -- is written at slot number
307 zero of #WorkBuffer2. #WorkBuffer2 will be completely filled with
308 spectral data.
309
310 3.) LPP-Transposition in lppTransposer() is processed on 24 slots. During the
311 transposition, the high band part of the spectral data is replicated
312 based on the low band data.
313
314 Envelope Adjustment is processed on the high band part of the spectral
315 data only by calculateSbrEnvelope().
316
317 4.) The cplxSynthesisQmfFiltering() creates 64 time domain samples out
318 of a slot of 64 complex spectral values at a time. The first 6 slots
319 in #timeOut are filled from the results of spectral slots 0..5 in the
320 #OverlapBuffer. The consecutive slots in timeOut are now filled with
321 the results of spectral slots 6..17.
322
323 5.) The preprocessed slots 18..23 have to be stored in the
324 #OverlapBuffer.
325
326 */
327
328 void
sbr_dec(HANDLE_SBR_DEC hSbrDec,INT_PCM * timeIn,INT_PCM * timeOut,HANDLE_SBR_DEC hSbrDecRight,INT_PCM * timeOutRight,const int strideIn,const int strideOut,HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_FRAME_DATA hFrameData,HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData,const int applyProcessing,HANDLE_PS_DEC h_ps_d,const UINT flags,const int codecFrameSize)329 sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
330 INT_PCM *timeIn, /*!< pointer to input time signal */
331 INT_PCM *timeOut, /*!< pointer to output time signal */
332 HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */
333 INT_PCM *timeOutRight, /*!< pointer to output time signal */
334 const int strideIn, /*!< Time data traversal strideIn */
335 const int strideOut, /*!< Time data traversal strideOut */
336 HANDLE_SBR_HEADER_DATA hHeaderData,/*!< Static control data */
337 HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */
338 HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */
339 const int applyProcessing, /*!< Flag for SBR operation */
340 HANDLE_PS_DEC h_ps_d,
341 const UINT flags,
342 const int codecFrameSize
343 )
344 {
345 int i, slot, reserve;
346 int saveLbScale;
347 int ov_len;
348 int lastSlotOffs;
349 FIXP_DBL maxVal;
350
351 /* 1+1/3 frames of spectral data: */
352 FIXP_DBL **QmfBufferReal = hSbrDec->QmfBufferReal;
353 FIXP_DBL **QmfBufferImag = hSbrDec->QmfBufferImag;
354
355 /* Number of QMF timeslots in the overlap buffer: */
356 ov_len = hSbrDec->LppTrans.pSettings->overlap;
357
358 /* Number of QMF slots per frame */
359 int noCols = hHeaderData->numberTimeSlots * hHeaderData->timeStep;
360
361 /* assign qmf time slots */
362 if ( ((flags & SBRDEC_LOW_POWER ) ? 1 : 0) != ((hSbrDec->SynthesisQMF.flags & QMF_FLAG_LP) ? 1 : 0) ) {
363 assignTimeSlots( hSbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, flags & SBRDEC_LOW_POWER);
364 }
365
366 if (flags & SBRDEC_ELD_GRID) {
367 /* Choose the right low delay filter bank */
368 changeQmfType( hSbrDec, (flags & SBRDEC_LD_MPS_QMF) ? 1 : 0 );
369
370 /* If the LD-MPS QMF is not available delay the signal by (96-48*ldSbrSamplingRate)
371 * samples according to ISO/IEC 14496-3:2009/FDAM 2:2010(E) chapter 4.5.2.13. */
372 if ( (flags & SBRDEC_LD_MPS_QMF)
373 && (hSbrDec->AnalysiscQMF.flags & QMF_FLAG_CLDFB) )
374 {
375 INT_PCM *pDlyBuf = hSbrDec->coreDelayBuf; /* DLYBUF */
376 int smpl, delay = 96 >> (!(flags & SBRDEC_DOWNSAMPLE) ? 1 : 0);
377 /* Create TMPBUF */
378 C_AALLOC_SCRATCH_START(pcmTemp, INT_PCM, (96));
379 /* Copy delay samples from INBUF to TMPBUF */
380 for (smpl = 0; smpl < delay; smpl += 1) {
381 pcmTemp[smpl] = timeIn[(codecFrameSize-delay+smpl)*strideIn];
382 }
383 /* Move input signal remainder to the very end of INBUF */
384 for (smpl = (codecFrameSize-delay-1)*strideIn; smpl >= 0; smpl -= strideIn) {
385 timeIn[smpl+delay] = timeIn[smpl];
386 }
387 /* Copy delayed samples from last frame from DLYBUF to the very beginning of INBUF */
388 for (smpl = 0; smpl < delay; smpl += 1) {
389 timeIn[smpl*strideIn] = pDlyBuf[smpl];
390 }
391 /* Copy TMPBUF to DLYBUF */
392 FDKmemcpy(pDlyBuf, pcmTemp, delay*sizeof(INT_PCM));
393 /* Destory TMPBUF */
394 C_AALLOC_SCRATCH_END(pcmTemp, INT_PCM, (96));
395 }
396 }
397
398 /*
399 low band codec signal subband filtering
400 */
401
402 {
403 C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2*(64));
404
405 qmfAnalysisFiltering( &hSbrDec->AnalysiscQMF,
406 QmfBufferReal + ov_len,
407 QmfBufferImag + ov_len,
408 &hSbrDec->sbrScaleFactor,
409 timeIn,
410 strideIn,
411 qmfTemp
412 );
413
414 C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2*(64));
415 }
416
417 /*
418 Clear upper half of spectrum
419 */
420 {
421 int nAnalysisBands = hHeaderData->numberOfAnalysisBands;
422
423 if (! (flags & SBRDEC_LOW_POWER)) {
424 for (slot = ov_len; slot < noCols+ov_len; slot++) {
425 FDKmemclear(&QmfBufferReal[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL));
426 FDKmemclear(&QmfBufferImag[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL));
427 }
428 } else
429 for (slot = ov_len; slot < noCols+ov_len; slot++) {
430 FDKmemclear(&QmfBufferReal[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL));
431 }
432 }
433
434
435
436 /*
437 Shift spectral data left to gain accuracy in transposer and adjustor
438 */
439 maxVal = maxSubbandSample( QmfBufferReal,
440 (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag,
441 0,
442 hSbrDec->AnalysiscQMF.lsb,
443 ov_len,
444 noCols+ov_len );
445
446 reserve = fixMax(0,CntLeadingZeros(maxVal)-1) ;
447 reserve = fixMin(reserve,DFRACT_BITS-1-hSbrDec->sbrScaleFactor.lb_scale);
448
449 /* If all data is zero, lb_scale could become too large */
450 rescaleSubbandSamples( QmfBufferReal,
451 (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag,
452 0,
453 hSbrDec->AnalysiscQMF.lsb,
454 ov_len,
455 noCols+ov_len,
456 reserve);
457
458 hSbrDec->sbrScaleFactor.lb_scale += reserve;
459
460 /*
461 save low band scale, wavecoding or parametric stereo may modify it
462 */
463 saveLbScale = hSbrDec->sbrScaleFactor.lb_scale;
464
465
466 if (applyProcessing)
467 {
468 UCHAR * borders = hFrameData->frameInfo.borders;
469 lastSlotOffs = borders[hFrameData->frameInfo.nEnvelopes] - hHeaderData->numberTimeSlots;
470
471 FIXP_DBL degreeAlias[(64)];
472
473 /* The transposer will override most values in degreeAlias[].
474 The array needs to be cleared at least from lowSubband to highSubband before. */
475 if (flags & SBRDEC_LOW_POWER)
476 FDKmemclear(°reeAlias[hHeaderData->freqBandData.lowSubband], (hHeaderData->freqBandData.highSubband-hHeaderData->freqBandData.lowSubband)*sizeof(FIXP_DBL));
477
478 /*
479 Inverse filtering of lowband and transposition into the SBR-frequency range
480 */
481
482 lppTransposer ( &hSbrDec->LppTrans,
483 &hSbrDec->sbrScaleFactor,
484 QmfBufferReal,
485 degreeAlias, // only used if useLP = 1
486 QmfBufferImag,
487 flags & SBRDEC_LOW_POWER,
488 hHeaderData->timeStep,
489 borders[0],
490 lastSlotOffs,
491 hHeaderData->freqBandData.nInvfBands,
492 hFrameData->sbr_invf_mode,
493 hPrevFrameData->sbr_invf_mode );
494
495
496
497
498
499 /*
500 Adjust envelope of current frame.
501 */
502
503 calculateSbrEnvelope (&hSbrDec->sbrScaleFactor,
504 &hSbrDec->SbrCalculateEnvelope,
505 hHeaderData,
506 hFrameData,
507 QmfBufferReal,
508 QmfBufferImag,
509 flags & SBRDEC_LOW_POWER,
510
511 degreeAlias,
512 flags,
513 (hHeaderData->frameErrorFlag || hPrevFrameData->frameErrorFlag));
514
515
516 /*
517 Update hPrevFrameData (to be used in the next frame)
518 */
519 for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) {
520 hPrevFrameData->sbr_invf_mode[i] = hFrameData->sbr_invf_mode[i];
521 }
522 hPrevFrameData->coupling = hFrameData->coupling;
523 hPrevFrameData->stopPos = borders[hFrameData->frameInfo.nEnvelopes];
524 hPrevFrameData->ampRes = hFrameData->ampResolutionCurrentFrame;
525 }
526 else {
527 /* Reset hb_scale if no highband is present, because hb_scale is considered in the QMF-synthesis */
528 hSbrDec->sbrScaleFactor.hb_scale = saveLbScale;
529 }
530
531
532 for (i=0; i<LPC_ORDER; i++){
533 /*
534 Store the unmodified qmf Slots values (required for LPC filtering)
535 */
536 if (! (flags & SBRDEC_LOW_POWER)) {
537 FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesReal[i], QmfBufferReal[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL));
538 FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImag[i], QmfBufferImag[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL));
539 } else
540 FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesReal[i], QmfBufferReal[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL));
541 }
542
543 /*
544 Synthesis subband filtering.
545 */
546
547 if ( ! (flags & SBRDEC_PS_DECODED) ) {
548
549 {
550 int outScalefactor = 0;
551
552 if (h_ps_d != NULL) {
553 h_ps_d->procFrameBased = 1; /* we here do frame based processing */
554 }
555
556
557 sbrDecoder_drcApply(&hSbrDec->sbrDrcChannel,
558 QmfBufferReal,
559 (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag,
560 hSbrDec->SynthesisQMF.no_col,
561 &outScalefactor
562 );
563
564
565
566 qmfChangeOutScalefactor(&hSbrDec->SynthesisQMF, outScalefactor );
567
568 {
569 C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2*(64));
570
571 qmfSynthesisFiltering( &hSbrDec->SynthesisQMF,
572 QmfBufferReal,
573 (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag,
574 &hSbrDec->sbrScaleFactor,
575 hSbrDec->LppTrans.pSettings->overlap,
576 timeOut,
577 strideOut,
578 qmfTemp);
579
580 C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2*(64));
581 }
582
583 }
584
585 } else { /* (flags & SBRDEC_PS_DECODED) */
586 INT i, sdiff, outScalefactor, scaleFactorLowBand, scaleFactorHighBand;
587 SCHAR scaleFactorLowBand_ov, scaleFactorLowBand_no_ov;
588
589 HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->SynthesisQMF;
590 HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->SynthesisQMF;
591
592 /* adapt scaling */
593 sdiff = hSbrDec->sbrScaleFactor.lb_scale - reserve; /* Scaling difference */
594 scaleFactorHighBand = sdiff - hSbrDec->sbrScaleFactor.hb_scale; /* Scale of current high band */
595 scaleFactorLowBand_ov = sdiff - hSbrDec->sbrScaleFactor.ov_lb_scale; /* Scale of low band overlapping QMF data */
596 scaleFactorLowBand_no_ov = sdiff - hSbrDec->sbrScaleFactor.lb_scale; /* Scale of low band current QMF data */
597 outScalefactor = 0; /* Initial output scale */
598
599 if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot based processing copy filter states */
600 { /* procFrameBased will be unset later */
601 /* copy filter states from left to right */
602 FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, ((640)-(64))*sizeof(FIXP_QSS));
603 }
604
605 /* scale ALL qmf vales ( real and imag ) of mono / left channel to the
606 same scale factor ( ov_lb_sf, lb_sf and hq_sf ) */
607 scalFilterBankValues( h_ps_d, /* parametric stereo decoder handle */
608 QmfBufferReal, /* qmf filterbank values */
609 QmfBufferImag, /* qmf filterbank values */
610 synQmf->lsb, /* sbr start subband */
611 hSbrDec->sbrScaleFactor.ov_lb_scale,
612 hSbrDec->sbrScaleFactor.lb_scale,
613 &scaleFactorLowBand_ov, /* adapt scaling values */
614 &scaleFactorLowBand_no_ov, /* adapt scaling values */
615 hSbrDec->sbrScaleFactor.hb_scale, /* current frame ( highband ) */
616 &scaleFactorHighBand,
617 synQmf->no_col);
618
619 /* use the same synthese qmf values for left and right channel */
620 synQmfRight->no_col = synQmf->no_col;
621 synQmfRight->lsb = synQmf->lsb;
622 synQmfRight->usb = synQmf->usb;
623
624 int env=0;
625
626 outScalefactor += (SCAL_HEADROOM+1); /* psDiffScale! */
627
628 {
629 C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 2*(64));
630
631 int maxShift = 0;
632
633 if (hSbrDec->sbrDrcChannel.enable != 0) {
634 if (hSbrDec->sbrDrcChannel.prevFact_exp > maxShift) {
635 maxShift = hSbrDec->sbrDrcChannel.prevFact_exp;
636 }
637 if (hSbrDec->sbrDrcChannel.currFact_exp > maxShift) {
638 maxShift = hSbrDec->sbrDrcChannel.currFact_exp;
639 }
640 if (hSbrDec->sbrDrcChannel.nextFact_exp > maxShift) {
641 maxShift = hSbrDec->sbrDrcChannel.nextFact_exp;
642 }
643 }
644
645 /* copy DRC data to right channel (with PS both channels use the same DRC gains) */
646 FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel, sizeof(SBRDEC_DRC_CHANNEL));
647
648 for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */
649
650 INT outScalefactorR, outScalefactorL;
651 outScalefactorR = outScalefactorL = outScalefactor;
652
653 /* qmf timeslot of right channel */
654 FIXP_DBL* rQmfReal = pWorkBuffer;
655 FIXP_DBL* rQmfImag = pWorkBuffer + 64;
656
657
658 {
659 if ( i == h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env] ) {
660 initSlotBasedRotation( h_ps_d, env, hHeaderData->freqBandData.highSubband );
661 env++;
662 }
663
664 ApplyPsSlot( h_ps_d, /* parametric stereo decoder handle */
665 (QmfBufferReal + i), /* one timeslot of left/mono channel */
666 (QmfBufferImag + i), /* one timeslot of left/mono channel */
667 rQmfReal, /* one timeslot or right channel */
668 rQmfImag); /* one timeslot or right channel */
669 }
670
671
672 scaleFactorLowBand = (i<(6)) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov;
673
674
675 sbrDecoder_drcApplySlot ( /* right channel */
676 &hSbrDecRight->sbrDrcChannel,
677 rQmfReal,
678 rQmfImag,
679 i,
680 synQmfRight->no_col,
681 maxShift
682 );
683
684 outScalefactorR += maxShift;
685
686 sbrDecoder_drcApplySlot ( /* left channel */
687 &hSbrDec->sbrDrcChannel,
688 *(QmfBufferReal + i),
689 *(QmfBufferImag + i),
690 i,
691 synQmf->no_col,
692 maxShift
693 );
694
695 outScalefactorL += maxShift;
696
697
698 /* scale filter states for left and right channel */
699 qmfChangeOutScalefactor( synQmf, outScalefactorL );
700 qmfChangeOutScalefactor( synQmfRight, outScalefactorR );
701
702 {
703
704 qmfSynthesisFilteringSlot( synQmfRight,
705 rQmfReal, /* QMF real buffer */
706 rQmfImag, /* QMF imag buffer */
707 scaleFactorLowBand,
708 scaleFactorHighBand,
709 timeOutRight+(i*synQmf->no_channels*strideOut),
710 strideOut,
711 pWorkBuffer);
712
713 qmfSynthesisFilteringSlot( synQmf,
714 *(QmfBufferReal + i), /* QMF real buffer */
715 *(QmfBufferImag + i), /* QMF imag buffer */
716 scaleFactorLowBand,
717 scaleFactorHighBand,
718 timeOut+(i*synQmf->no_channels*strideOut),
719 strideOut,
720 pWorkBuffer);
721
722 }
723 } /* no_col loop i */
724
725 /* scale back (6) timeslots look ahead for hybrid filterbank to original value */
726 rescalFilterBankValues( h_ps_d,
727 QmfBufferReal,
728 QmfBufferImag,
729 synQmf->lsb,
730 synQmf->no_col );
731
732 C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2*(64));
733 }
734 }
735
736 sbrDecoder_drcUpdateChannel( &hSbrDec->sbrDrcChannel );
737
738
739 /*
740 Update overlap buffer
741 Even bands above usb are copied to avoid outdated spectral data in case
742 the stop frequency raises.
743 */
744
745 if (hSbrDec->LppTrans.pSettings->overlap > 0)
746 {
747 if (! (flags & SBRDEC_LOW_POWER)) {
748 for ( i=0; i<hSbrDec->LppTrans.pSettings->overlap; i++ ) {
749 FDKmemcpy(QmfBufferReal[i], QmfBufferReal[i+noCols], (64)*sizeof(FIXP_DBL));
750 FDKmemcpy(QmfBufferImag[i], QmfBufferImag[i+noCols], (64)*sizeof(FIXP_DBL));
751 }
752 } else
753 for ( i=0; i<hSbrDec->LppTrans.pSettings->overlap; i++ ) {
754 FDKmemcpy(QmfBufferReal[i], QmfBufferReal[i+noCols], (64)*sizeof(FIXP_DBL));
755 }
756 }
757
758 hSbrDec->sbrScaleFactor.ov_lb_scale = saveLbScale;
759
760 /* Save current frame status */
761 hPrevFrameData->frameErrorFlag = hHeaderData->frameErrorFlag;
762
763 } // sbr_dec()
764
765
766 /*!
767 \brief Creates sbr decoder structure
768 \return errorCode, 0 if successful
769 */
770 SBR_ERROR
createSbrDec(SBR_CHANNEL * hSbrChannel,HANDLE_SBR_HEADER_DATA hHeaderData,TRANSPOSER_SETTINGS * pSettings,const int downsampleFac,const UINT qmfFlags,const UINT flags,const int overlap,int chan)771 createSbrDec (SBR_CHANNEL * hSbrChannel,
772 HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
773 TRANSPOSER_SETTINGS *pSettings,
774 const int downsampleFac, /*!< Downsampling factor */
775 const UINT qmfFlags, /*!< flags -> 1: HQ/LP selector, 2: CLDFB */
776 const UINT flags,
777 const int overlap,
778 int chan) /*!< Channel for which to assign buffers etc. */
779
780 {
781 SBR_ERROR err = SBRDEC_OK;
782 int timeSlots = hHeaderData->numberTimeSlots; /* Number of SBR slots per frame */
783 int noCols = timeSlots * hHeaderData->timeStep; /* Number of QMF slots per frame */
784 HANDLE_SBR_DEC hs = &(hSbrChannel->SbrDec);
785
786 /* Initialize scale factors */
787 hs->sbrScaleFactor.ov_lb_scale = 0;
788 hs->sbrScaleFactor.ov_hb_scale = 0;
789 hs->sbrScaleFactor.hb_scale = 0;
790
791
792 /*
793 create envelope calculator
794 */
795 err = createSbrEnvelopeCalc (&hs->SbrCalculateEnvelope,
796 hHeaderData,
797 chan,
798 flags);
799 if (err != SBRDEC_OK) {
800 return err;
801 }
802
803 /*
804 create QMF filter banks
805 */
806 {
807 int qmfErr;
808 /* Adapted QMF analysis post-twiddles for down-sampled HQ SBR */
809 const UINT downSampledFlag = (flags & SBRDEC_DOWNSAMPLE) ? QMF_FLAG_DOWNSAMPLED : 0;
810
811 qmfErr = qmfInitAnalysisFilterBank (
812 &hs->AnalysiscQMF,
813 hs->anaQmfStates,
814 noCols,
815 hHeaderData->freqBandData.lowSubband,
816 hHeaderData->freqBandData.highSubband,
817 hHeaderData->numberOfAnalysisBands,
818 (qmfFlags & (~QMF_FLAG_KEEP_STATES)) | downSampledFlag
819 );
820 if (qmfErr != 0) {
821 return SBRDEC_UNSUPPORTED_CONFIG;
822 }
823 }
824 if (hs->pSynQmfStates == NULL) {
825 hs->pSynQmfStates = GetRam_sbr_QmfStatesSynthesis(chan);
826 if (hs->pSynQmfStates == NULL)
827 return SBRDEC_MEM_ALLOC_FAILED;
828 }
829
830 {
831 int qmfErr;
832
833 qmfErr = qmfInitSynthesisFilterBank (
834 &hs->SynthesisQMF,
835 hs->pSynQmfStates,
836 noCols,
837 hHeaderData->freqBandData.lowSubband,
838 hHeaderData->freqBandData.highSubband,
839 (64) / downsampleFac,
840 qmfFlags & (~QMF_FLAG_KEEP_STATES)
841 );
842
843 if (qmfErr != 0) {
844 return SBRDEC_UNSUPPORTED_CONFIG;
845 }
846 }
847 initSbrPrevFrameData (&hSbrChannel->prevFrameData, timeSlots);
848
849 /*
850 create transposer
851 */
852 err = createLppTransposer (&hs->LppTrans,
853 pSettings,
854 hHeaderData->freqBandData.lowSubband,
855 hHeaderData->freqBandData.v_k_master,
856 hHeaderData->freqBandData.numMaster,
857 hs->SynthesisQMF.usb,
858 timeSlots,
859 hs->AnalysiscQMF.no_col,
860 hHeaderData->freqBandData.freqBandTableNoise,
861 hHeaderData->freqBandData.nNfb,
862 hHeaderData->sbrProcSmplRate,
863 chan,
864 overlap );
865 if (err != SBRDEC_OK) {
866 return err;
867 }
868
869 /* The CLDFB does not have overlap */
870 if ((qmfFlags & QMF_FLAG_CLDFB) == 0) {
871 if (hs->pSbrOverlapBuffer == NULL) {
872 hs->pSbrOverlapBuffer = GetRam_sbr_OverlapBuffer(chan);
873 if (hs->pSbrOverlapBuffer == NULL) {
874 return SBRDEC_MEM_ALLOC_FAILED;
875 }
876 } else {
877 /* Clear overlap buffer */
878 FDKmemclear( hs->pSbrOverlapBuffer,
879 sizeof(FIXP_DBL) * 2 * (6) * (64)
880 );
881 }
882 }
883
884 /* Clear input delay line */
885 FDKmemclear(hs->coreDelayBuf, (96)*sizeof(INT_PCM));
886
887 /* assign qmf time slots */
888 assignTimeSlots( &hSbrChannel->SbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, qmfFlags & QMF_FLAG_LP);
889
890 return err;
891 }
892
893 /*!
894 \brief Delete sbr decoder structure
895 \return errorCode, 0 if successful
896 */
897 int
deleteSbrDec(SBR_CHANNEL * hSbrChannel)898 deleteSbrDec (SBR_CHANNEL * hSbrChannel)
899 {
900 HANDLE_SBR_DEC hs = &hSbrChannel->SbrDec;
901
902 deleteSbrEnvelopeCalc (&hs->SbrCalculateEnvelope);
903
904 /* delete QMF filter states */
905 if (hs->pSynQmfStates != NULL) {
906 FreeRam_sbr_QmfStatesSynthesis(&hs->pSynQmfStates);
907 }
908
909
910 if (hs->pSbrOverlapBuffer != NULL) {
911 FreeRam_sbr_OverlapBuffer(&hs->pSbrOverlapBuffer);
912 }
913
914 return 0;
915 }
916
917
918 /*!
919 \brief resets sbr decoder structure
920 \return errorCode, 0 if successful
921 */
922 SBR_ERROR
resetSbrDec(HANDLE_SBR_DEC hSbrDec,HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData,const int useLP,const int downsampleFac)923 resetSbrDec (HANDLE_SBR_DEC hSbrDec,
924 HANDLE_SBR_HEADER_DATA hHeaderData,
925 HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData,
926 const int useLP,
927 const int downsampleFac
928 )
929 {
930 SBR_ERROR sbrError = SBRDEC_OK;
931
932 int old_lsb = hSbrDec->SynthesisQMF.lsb;
933 int new_lsb = hHeaderData->freqBandData.lowSubband;
934 int l, startBand, stopBand, startSlot, size;
935
936 int source_scale, target_scale, delta_scale, target_lsb, target_usb, reserve;
937 FIXP_DBL maxVal;
938
939 /* overlapBuffer point to first (6) slots */
940 FIXP_DBL **OverlapBufferReal = hSbrDec->QmfBufferReal;
941 FIXP_DBL **OverlapBufferImag = hSbrDec->QmfBufferImag;
942
943 /* assign qmf time slots */
944 assignTimeSlots( hSbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, useLP);
945
946
947
948 resetSbrEnvelopeCalc (&hSbrDec->SbrCalculateEnvelope);
949
950 hSbrDec->SynthesisQMF.lsb = hHeaderData->freqBandData.lowSubband;
951 hSbrDec->SynthesisQMF.usb = fixMin((INT)hSbrDec->SynthesisQMF.no_channels, (INT)hHeaderData->freqBandData.highSubband);
952
953 hSbrDec->AnalysiscQMF.lsb = hSbrDec->SynthesisQMF.lsb;
954 hSbrDec->AnalysiscQMF.usb = hSbrDec->SynthesisQMF.usb;
955
956
957 /*
958 The following initialization of spectral data in the overlap buffer
959 is required for dynamic x-over or a change of the start-freq for 2 reasons:
960
961 1. If the lowband gets _wider_, unadjusted data would remain
962
963 2. If the lowband becomes _smaller_, the highest bands of the old lowband
964 must be cleared because the whitening would be affected
965 */
966 startBand = old_lsb;
967 stopBand = new_lsb;
968 startSlot = hHeaderData->timeStep * (hPrevFrameData->stopPos - hHeaderData->numberTimeSlots);
969 size = fixMax(0,stopBand-startBand);
970
971 /* keep already adjusted data in the x-over-area */
972 if (!useLP) {
973 for (l=startSlot; l<hSbrDec->LppTrans.pSettings->overlap; l++) {
974 FDKmemclear(&OverlapBufferReal[l][startBand], size*sizeof(FIXP_DBL));
975 FDKmemclear(&OverlapBufferImag[l][startBand], size*sizeof(FIXP_DBL));
976 }
977 } else
978 for (l=startSlot; l<hSbrDec->LppTrans.pSettings->overlap ; l++) {
979 FDKmemclear(&OverlapBufferReal[l][startBand], size*sizeof(FIXP_DBL));
980 }
981
982
983 /*
984 reset LPC filter states
985 */
986 startBand = fixMin(old_lsb,new_lsb);
987 stopBand = fixMax(old_lsb,new_lsb);
988 size = fixMax(0,stopBand-startBand);
989
990 FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesReal[0][startBand], size*sizeof(FIXP_DBL));
991 FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesReal[1][startBand], size*sizeof(FIXP_DBL));
992 if (!useLP) {
993 FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImag[0][startBand], size*sizeof(FIXP_DBL));
994 FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImag[1][startBand], size*sizeof(FIXP_DBL));
995 }
996
997
998 /*
999 Rescale already processed spectral data between old and new x-over frequency.
1000 This must be done because of the separate scalefactors for lowband and highband.
1001 */
1002 startBand = fixMin(old_lsb,new_lsb);
1003 stopBand = fixMax(old_lsb,new_lsb);
1004
1005 if (new_lsb > old_lsb) {
1006 /* The x-over-area was part of the highband before and will now belong to the lowband */
1007 source_scale = hSbrDec->sbrScaleFactor.ov_hb_scale;
1008 target_scale = hSbrDec->sbrScaleFactor.ov_lb_scale;
1009 target_lsb = 0;
1010 target_usb = old_lsb;
1011 }
1012 else {
1013 /* The x-over-area was part of the lowband before and will now belong to the highband */
1014 source_scale = hSbrDec->sbrScaleFactor.ov_lb_scale;
1015 target_scale = hSbrDec->sbrScaleFactor.ov_hb_scale;
1016 /* jdr: The values old_lsb and old_usb might be wrong because the previous frame might have been "upsamling". */
1017 target_lsb = hSbrDec->SynthesisQMF.lsb;
1018 target_usb = hSbrDec->SynthesisQMF.usb;
1019 }
1020
1021 /* Shift left all samples of the x-over-area as much as possible
1022 An unnecessary coarse scale could cause ov_lb_scale or ov_hb_scale to be
1023 adapted and the accuracy in the next frame would seriously suffer! */
1024
1025 maxVal = maxSubbandSample( OverlapBufferReal,
1026 (useLP) ? NULL : OverlapBufferImag,
1027 startBand,
1028 stopBand,
1029 0,
1030 startSlot);
1031
1032 reserve = CntLeadingZeros(maxVal)-1;
1033 reserve = fixMin(reserve,DFRACT_BITS-1-source_scale);
1034
1035 rescaleSubbandSamples( OverlapBufferReal,
1036 (useLP) ? NULL : OverlapBufferImag,
1037 startBand,
1038 stopBand,
1039 0,
1040 startSlot,
1041 reserve);
1042 source_scale += reserve;
1043
1044 delta_scale = target_scale - source_scale;
1045
1046 if (delta_scale > 0) { /* x-over-area is dominant */
1047 delta_scale = -delta_scale;
1048 startBand = target_lsb;
1049 stopBand = target_usb;
1050
1051 if (new_lsb > old_lsb) {
1052 /* The lowband has to be rescaled */
1053 hSbrDec->sbrScaleFactor.ov_lb_scale = source_scale;
1054 }
1055 else {
1056 /* The highband has be be rescaled */
1057 hSbrDec->sbrScaleFactor.ov_hb_scale = source_scale;
1058 }
1059 }
1060
1061 FDK_ASSERT(startBand <= stopBand);
1062
1063 if (!useLP) {
1064 for (l=0; l<startSlot; l++) {
1065 scaleValues( OverlapBufferReal[l] + startBand, stopBand-startBand, delta_scale );
1066 scaleValues( OverlapBufferImag[l] + startBand, stopBand-startBand, delta_scale );
1067 }
1068 } else
1069 for (l=0; l<startSlot; l++) {
1070 scaleValues( OverlapBufferReal[l] + startBand, stopBand-startBand, delta_scale );
1071 }
1072
1073
1074 /*
1075 Initialize transposer and limiter
1076 */
1077 sbrError = resetLppTransposer (&hSbrDec->LppTrans,
1078 hHeaderData->freqBandData.lowSubband,
1079 hHeaderData->freqBandData.v_k_master,
1080 hHeaderData->freqBandData.numMaster,
1081 hHeaderData->freqBandData.freqBandTableNoise,
1082 hHeaderData->freqBandData.nNfb,
1083 hHeaderData->freqBandData.highSubband,
1084 hHeaderData->sbrProcSmplRate);
1085 if (sbrError != SBRDEC_OK)
1086 return sbrError;
1087
1088 sbrError = ResetLimiterBands ( hHeaderData->freqBandData.limiterBandTable,
1089 &hHeaderData->freqBandData.noLimiterBands,
1090 hHeaderData->freqBandData.freqBandTable[0],
1091 hHeaderData->freqBandData.nSfb[0],
1092 hSbrDec->LppTrans.pSettings->patchParam,
1093 hSbrDec->LppTrans.pSettings->noOfPatches,
1094 hHeaderData->bs_data.limiterBands);
1095
1096
1097 return sbrError;
1098 }
1099