1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4 © Copyright 1995 - 2021 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 Processing
100
101 *******************************************************************************/
102
103 /* data structures and interfaces for spatial audio reference software */
104 #include "sac_process.h"
105
106 #include "sac_bitdec.h"
107 #include "sac_calcM1andM2.h"
108 #include "sac_smoothing.h"
109 #include "sac_rom.h"
110
111 #include "sac_dec_errorcodes.h"
112
113 #include "FDK_trigFcts.h"
114 #include "FDK_decorrelate.h"
115
116 #define SAC_DEC_APPLY_M2_SCALE(spec, s) ((spec) >> (-(s)))
117
118 /**
119 * \brief Linear interpolation between two parameter values.
120 * a*alpha + b*(1-alpha)
121 * = a*alpha + b - b*alpha
122 *
123 * \param alpha Weighting factor.
124 * \param a Parameter a.
125 * \param b Parameter b.
126 *
127 * \return Interpolated parameter value.
128 */
interpolateParameter(const FIXP_SGL alpha,const FIXP_DBL a,const FIXP_DBL b)129 FDK_INLINE FIXP_DBL interpolateParameter(const FIXP_SGL alpha, const FIXP_DBL a,
130 const FIXP_DBL b) {
131 return (b - fMult(alpha, b) + fMult(alpha, a));
132 }
133
134 /**
135 * \brief Map MPEG Surround channel indices to MPEG 4 PCE like channel indices.
136 * \param self Spatial decoder handle.
137 * \param ch MPEG Surround channel index.
138 * \return MPEG 4 PCE style channel index, corresponding to the given MPEG
139 * Surround channel index.
140 */
mapChannel(spatialDec * self,UINT ch)141 static UINT mapChannel(spatialDec *self, UINT ch) {
142 static const UCHAR chanelIdx[][8] = {
143 {0, 1, 2, 3, 4, 5, 6, 7}, /* binaural, TREE_212, arbitrary tree */
144 };
145
146 int idx = 0;
147
148 return (chanelIdx[idx][ch]);
149 }
150
getChGain(spatialDec * self,UINT ch,INT * scale)151 FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale) {
152 /* init no gain modifier */
153 FIXP_DBL gain = 0x80000000;
154 *scale = 0;
155
156 if ((!isTwoChMode(self->upmixType)) &&
157 (self->upmixType != UPMIXTYPE_BYPASS)) {
158 if ((ch == 0) || (ch == 1) || (ch == 2)) {
159 /* no modifier */
160 }
161 }
162
163 return gain;
164 }
165
SpatialDecQMFAnalysis(spatialDec * self,const PCM_MPS * inData,const INT ts,const INT bypassMode,FIXP_DBL ** qmfReal,FIXP_DBL ** qmfImag,const int numInputChannels)166 SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData,
167 const INT ts, const INT bypassMode,
168 FIXP_DBL **qmfReal, FIXP_DBL **qmfImag,
169 const int numInputChannels) {
170 SACDEC_ERROR err = MPS_OK;
171 int ch, offset;
172
173 offset = self->pQmfDomain->globalConf.nBandsSynthesis *
174 self->pQmfDomain->globalConf.nQmfTimeSlots;
175
176 {
177 for (ch = 0; ch < numInputChannels; ch++) {
178 const PCM_MPS *inSamples =
179 &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis];
180 FIXP_DBL *pQmfRealAnalysis = qmfReal[ch]; /* no delay in blind mode */
181 FIXP_DBL *pQmfImagAnalysis = qmfImag[ch];
182
183 CalculateSpaceAnalysisQmf(&self->pQmfDomain->QmfDomainIn[ch].fb,
184 inSamples + (ch * offset), pQmfRealAnalysis,
185 pQmfImagAnalysis);
186
187 if (!isTwoChMode(self->upmixType) && !bypassMode) {
188 int i;
189 for (i = 0; i < self->qmfBands; i++) {
190 qmfReal[ch][i] = fMult(
191 scaleValueSaturate(qmfReal[ch][i], self->sacInDataHeadroom - (1)),
192 self->clipProtectGain__FDK);
193 qmfImag[ch][i] = fMult(
194 scaleValueSaturate(qmfImag[ch][i], self->sacInDataHeadroom - (1)),
195 self->clipProtectGain__FDK);
196 }
197 }
198 }
199 }
200
201 self->qmfInputDelayBufPos =
202 (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay;
203
204 return err;
205 }
206
SpatialDecFeedQMF(spatialDec * self,FIXP_DBL ** qmfInDataReal,FIXP_DBL ** qmfInDataImag,const INT ts,const INT bypassMode,FIXP_DBL ** qmfReal__FDK,FIXP_DBL ** qmfImag__FDK,const INT numInputChannels)207 SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal,
208 FIXP_DBL **qmfInDataImag, const INT ts,
209 const INT bypassMode, FIXP_DBL **qmfReal__FDK,
210 FIXP_DBL **qmfImag__FDK,
211 const INT numInputChannels) {
212 SACDEC_ERROR err = MPS_OK;
213 int ch;
214
215 {
216 for (ch = 0; ch < numInputChannels; ch++) {
217 FIXP_DBL *pQmfRealAnalysis =
218 qmfReal__FDK[ch]; /* no delay in blind mode */
219 FIXP_DBL *pQmfImagAnalysis = qmfImag__FDK[ch];
220
221 /* Write Input data to pQmfRealAnalysis. */
222 if (self->bShareDelayWithSBR) {
223 FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch],
224 ts + HYBRID_FILTER_DELAY, 0,
225 MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis,
226 pQmfImagAnalysis, 15 + (1));
227 FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts,
228 MAX_QMF_BANDS_TO_HYBRID, self->qmfBands,
229 pQmfRealAnalysis, pQmfImagAnalysis, 15 + (1));
230 } else {
231 FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0,
232 self->qmfBands, pQmfRealAnalysis,
233 pQmfImagAnalysis, 15 + (1));
234 }
235 if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) {
236 /* Is currently also needed in case we dont have any overlap. We need to
237 * save lb_scale to ov_lb_scale */
238 FDK_QmfDomain_SaveOverlap(&self->pQmfDomain->QmfDomainIn[ch], 0);
239 }
240
241 /* Apply clip protection to output. */
242 if (!isTwoChMode(self->upmixType) && !bypassMode) {
243 int i;
244 for (i = 0; i < self->qmfBands; i++) {
245 qmfReal__FDK[ch][i] =
246 fMult(qmfReal__FDK[ch][i], self->clipProtectGain__FDK);
247 qmfImag__FDK[ch][i] =
248 fMult(qmfImag__FDK[ch][i], self->clipProtectGain__FDK);
249 }
250 }
251
252 } /* End of loop over numInputChannels */
253 }
254
255 self->qmfInputDelayBufPos =
256 (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay;
257
258 return err;
259 }
260
261 /*******************************************************************************
262 Functionname: SpatialDecHybridAnalysis
263 *******************************************************************************
264
265 Description:
266
267 Arguments:
268
269 Input:
270 float** pointers[4] leftReal, leftIm, rightReal, rightIm
271
272 Output:
273 float self->qmfInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS];
274 float self->qmfInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS];
275
276 float
277 self->hybInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS]; float
278 self->hybInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS];
279
280
281 *******************************************************************************/
SpatialDecHybridAnalysis(spatialDec * self,FIXP_DBL ** qmfInputReal,FIXP_DBL ** qmfInputImag,FIXP_DBL ** hybOutputReal,FIXP_DBL ** hybOutputImag,const INT ts,const INT numInputChannels)282 SACDEC_ERROR SpatialDecHybridAnalysis(spatialDec *self, FIXP_DBL **qmfInputReal,
283 FIXP_DBL **qmfInputImag,
284 FIXP_DBL **hybOutputReal,
285 FIXP_DBL **hybOutputImag, const INT ts,
286 const INT numInputChannels) {
287 SACDEC_ERROR err = MPS_OK;
288 int ch;
289
290 for (ch = 0; ch < numInputChannels;
291 ch++) /* hybrid filtering for down-mix signals */
292 {
293 if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
294 int k;
295 /* No hybrid filtering. Just copy the QMF data. */
296 for (k = 0; k < self->hybridBands; k += 1) {
297 hybOutputReal[ch][k] = qmfInputReal[ch][k];
298 hybOutputImag[ch][k] = qmfInputImag[ch][k];
299 }
300 } else {
301 self->hybridAnalysis[ch].hfMode = self->bShareDelayWithSBR;
302
303 if (self->stereoConfigIndex == 3)
304 FDK_ASSERT(self->hybridAnalysis[ch].hfMode == 0);
305 FDKhybridAnalysisApply(&self->hybridAnalysis[ch], qmfInputReal[ch],
306 qmfInputImag[ch], hybOutputReal[ch],
307 hybOutputImag[ch]);
308 }
309 }
310
311 if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) &&
312 self->residualCoding) {
313 self->hybridAnalysis[numInputChannels].hfMode = 0;
314 FDKhybridAnalysisApply(
315 &self->hybridAnalysis[numInputChannels],
316 self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0],
317 self->hybResidualReal__FDK[0], self->hybResidualImag__FDK[0]);
318 }
319
320 return err;
321 }
322
SpatialDecCreateX(spatialDec * self,FIXP_DBL ** hybInputReal,FIXP_DBL ** hybInputImag,FIXP_DBL ** pxReal,FIXP_DBL ** pxImag)323 SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal,
324 FIXP_DBL **hybInputImag, FIXP_DBL **pxReal,
325 FIXP_DBL **pxImag) {
326 SACDEC_ERROR err = MPS_OK;
327 int row;
328
329 /* Creating wDry */
330 for (row = 0; row < self->numInputChannels; row++) {
331 /* pointer to direct signals */
332 pxReal[row] = hybInputReal[row];
333 pxImag[row] = hybInputImag[row];
334 }
335
336 return err;
337 }
338
M2ParamToKernelMult(FIXP_SGL * RESTRICT pKernel,FIXP_DBL * RESTRICT Mparam,FIXP_DBL * RESTRICT MparamPrev,int * RESTRICT pWidth,FIXP_SGL alpha__FDK,int nBands)339 static void M2ParamToKernelMult(FIXP_SGL *RESTRICT pKernel,
340 FIXP_DBL *RESTRICT Mparam,
341 FIXP_DBL *RESTRICT MparamPrev,
342 int *RESTRICT pWidth, FIXP_SGL alpha__FDK,
343 int nBands) {
344 int pb;
345
346 for (pb = 0; pb < nBands; pb++) {
347 FIXP_SGL tmp = FX_DBL2FX_SGL(
348 interpolateParameter(alpha__FDK, Mparam[pb], MparamPrev[pb]));
349
350 int i = pWidth[pb];
351 if (i & 1) *pKernel++ = tmp;
352 if (i & 2) {
353 *pKernel++ = tmp;
354 *pKernel++ = tmp;
355 }
356 for (i >>= 2; i--;) {
357 *pKernel++ = tmp;
358 *pKernel++ = tmp;
359 *pKernel++ = tmp;
360 *pKernel++ = tmp;
361 }
362 }
363 }
364
SpatialDecApplyM1_CreateW_Mode212(spatialDec * self,const SPATIAL_BS_FRAME * frame,FIXP_DBL ** xReal,FIXP_DBL ** xImag,FIXP_DBL ** vReal,FIXP_DBL ** vImag)365 SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212(
366 spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal,
367 FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag) {
368 SACDEC_ERROR err = MPS_OK;
369 int res;
370 FIXP_DBL *decorrInReal = vReal[0];
371 FIXP_DBL *decorrInImag = vImag[0];
372
373 /* M1 does not do anything in 212 mode, so use simplified processing */
374 FDK_ASSERT(self->numVChannels == 2);
375 FDK_ASSERT(self->numDirektSignals == 1);
376 FDK_ASSERT(self->numDecorSignals == 1);
377 FDKmemcpy(vReal[0], xReal[0], self->hybridBands * sizeof(FIXP_DBL));
378 FDKmemcpy(vImag[0], xImag[0], self->hybridBands * sizeof(FIXP_DBL));
379
380 if (isTsdActive(frame->TsdData)) {
381 /* Generate v_{x,nonTr} as input for allpass based decorrelator */
382 TsdGenerateNonTr(self->hybridBands, frame->TsdData, self->TsdTs, vReal[0],
383 vImag[0], vReal[1], vImag[1], &decorrInReal,
384 &decorrInImag);
385 }
386 /* - Decorrelate */
387 res = SpatialDecGetResidualIndex(self, 1);
388 if (FDKdecorrelateApply(&self->apDecor[0], decorrInReal, decorrInImag,
389 vReal[1], vImag[1],
390 self->param2hyb[self->residualBands[res]])) {
391 return MPS_NOTOK;
392 }
393 if (isTsdActive(frame->TsdData)) {
394 /* Generate v_{x,Tr}, apply transient decorrelator and add to allpass based
395 * decorrelator output */
396 TsdApply(self->hybridBands, frame->TsdData, &self->TsdTs,
397 vReal[0], /* input: v_x */
398 vImag[0],
399 vReal[1], /* input: d_{x,nonTr}; output: d_{x,nonTr} + d_{x,Tr} */
400 vImag[1]);
401 }
402
403 /* Write residual signal in approriate parameter bands */
404 if (self->residualBands[res] > 0) {
405 int stopBand = self->param2hyb[self->residualBands[res]];
406 FDKmemcpy(vReal[1], self->hybResidualReal__FDK[res],
407 fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL));
408 FDKmemcpy(vImag[1], self->hybResidualImag__FDK[res],
409 fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL));
410 } /* (self->residualBands[res]>0) */
411
412 return err;
413 }
414
SpatialDecApplyM2_Mode212(spatialDec * self,INT ps,const FIXP_SGL alpha,FIXP_DBL ** wReal,FIXP_DBL ** wImag,FIXP_DBL ** hybOutputRealDry,FIXP_DBL ** hybOutputImagDry)415 SACDEC_ERROR SpatialDecApplyM2_Mode212(spatialDec *self, INT ps,
416 const FIXP_SGL alpha, FIXP_DBL **wReal,
417 FIXP_DBL **wImag,
418 FIXP_DBL **hybOutputRealDry,
419 FIXP_DBL **hybOutputImagDry) {
420 SACDEC_ERROR err = MPS_OK;
421 INT row;
422
423 INT *pWidth = self->kernels_width;
424 /* for stereoConfigIndex == 3 case hybridBands is < 71 */
425 INT pb_max = self->kernels[self->hybridBands - 1] + 1;
426 INT max_row = self->numOutputChannels;
427
428 INT M2_exp = 0;
429 if (self->residualCoding) M2_exp = 3;
430
431 for (row = 0; row < max_row; row++) // 2 times
432 {
433 FIXP_DBL *Mparam0 = self->M2Real__FDK[row][0];
434 FIXP_DBL *Mparam1 = self->M2Real__FDK[row][1];
435 FIXP_DBL *MparamPrev0 = self->M2RealPrev__FDK[row][0];
436 FIXP_DBL *MparamPrev1 = self->M2RealPrev__FDK[row][1];
437
438 FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row];
439 FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row];
440
441 FIXP_DBL *RESTRICT pWReal0 = wReal[0];
442 FIXP_DBL *RESTRICT pWReal1 = wReal[1];
443 FIXP_DBL *RESTRICT pWImag0 = wImag[0];
444 FIXP_DBL *RESTRICT pWImag1 = wImag[1];
445 for (INT pb = 0; pb < pb_max; pb++) {
446 FIXP_DBL tmp0, tmp1;
447
448 tmp0 = interpolateParameter(alpha, Mparam0[pb], MparamPrev0[pb]);
449 tmp1 = interpolateParameter(alpha, Mparam1[pb], MparamPrev1[pb]);
450
451 INT i = pWidth[pb];
452
453 do // about 3-4 times
454 {
455 FIXP_DBL var0, var1, real, imag;
456
457 var0 = *pWReal0++;
458 var1 = *pWReal1++;
459 real = fMultDiv2(var0, tmp0);
460 var0 = *pWImag0++;
461 real = fMultAddDiv2(real, var1, tmp1);
462 var1 = *pWImag1++;
463 imag = fMultDiv2(var0, tmp0);
464 *pHybOutRealDry++ = real << (1 + M2_exp);
465 imag = fMultAddDiv2(imag, var1, tmp1);
466 *pHybOutImagDry++ = imag << (1 + M2_exp);
467 } while (--i != 0);
468 }
469 }
470 return err;
471 }
472
SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(spatialDec * self,INT ps,const FIXP_SGL alpha,FIXP_DBL ** wReal,FIXP_DBL ** wImag,FIXP_DBL ** hybOutputRealDry,FIXP_DBL ** hybOutputImagDry)473 SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
474 spatialDec *self, INT ps, const FIXP_SGL alpha, FIXP_DBL **wReal,
475 FIXP_DBL **wImag, FIXP_DBL **hybOutputRealDry,
476 FIXP_DBL **hybOutputImagDry) {
477 SACDEC_ERROR err = MPS_OK;
478 INT row;
479 INT scale_param_m2;
480 INT *pWidth = self->kernels_width;
481 INT pb_max = self->kernels[self->hybridBands - 1] + 1;
482
483 scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2;
484
485 for (row = 0; row < self->numM2rows; row++) {
486 INT qs, pb;
487
488 FIXP_DBL *RESTRICT pWReal0 = wReal[0];
489 FIXP_DBL *RESTRICT pWImag0 = wImag[0];
490 FIXP_DBL *RESTRICT pWReal1 = wReal[1];
491 FIXP_DBL *RESTRICT pWImag1 = wImag[1];
492
493 FIXP_DBL *MReal0 = self->M2Real__FDK[row][0];
494 FIXP_DBL *MImag0 = self->M2Imag__FDK[row][0];
495 FIXP_DBL *MReal1 = self->M2Real__FDK[row][1];
496 FIXP_DBL *MRealPrev0 = self->M2RealPrev__FDK[row][0];
497 FIXP_DBL *MImagPrev0 = self->M2ImagPrev__FDK[row][0];
498 FIXP_DBL *MRealPrev1 = self->M2RealPrev__FDK[row][1];
499
500 FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row];
501 FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row];
502
503 FDK_ASSERT(!(self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD));
504 FDK_ASSERT((pWidth[0] + pWidth[1]) >= 3);
505
506 for (pb = 0, qs = 3; pb < 2; pb++) {
507 INT s;
508 FIXP_DBL maxVal;
509 FIXP_DBL mReal1;
510 FIXP_DBL mReal0, mImag0;
511 FIXP_DBL iReal0, iImag0, iReal1;
512
513 iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
514 iImag0 = -interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
515 iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
516
517 maxVal = fAbs(iReal0) | fAbs(iImag0);
518 maxVal |= fAbs(iReal1);
519
520 s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
521
522 mReal0 = scaleValue(iReal0, s);
523 mImag0 = scaleValue(iImag0, s);
524 mReal1 = scaleValue(iReal1, s);
525
526 s = scale_param_m2 - s;
527
528 INT i = pWidth[pb];
529
530 do {
531 FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
532
533 wReal0 = *pWReal0++;
534 wImag0 = *pWImag0++;
535 wReal1 = *pWReal1++;
536 wImag1 = *pWImag1++;
537
538 cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
539
540 *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
541 *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
542
543 if (qs > 0) {
544 mImag0 = -mImag0;
545 qs--;
546 }
547 } while (--i != 0);
548 }
549
550 for (; pb < pb_max; pb++) {
551 INT s;
552 FIXP_DBL maxVal;
553 FIXP_SGL mReal1;
554 FIXP_SGL mReal0, mImag0;
555 FIXP_DBL iReal0, iImag0, iReal1;
556
557 iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
558 iImag0 = interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
559 iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
560
561 maxVal = fAbs(iReal0) | fAbs(iImag0);
562 maxVal |= fAbs(iReal1);
563
564 s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
565
566 mReal0 = FX_DBL2FX_SGL(scaleValue(iReal0, s));
567 mImag0 = FX_DBL2FX_SGL(scaleValue(iImag0, s));
568 mReal1 = FX_DBL2FX_SGL(scaleValue(iReal1, s));
569
570 s = scale_param_m2 - s;
571
572 INT i = pWidth[pb];
573
574 do {
575 FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
576
577 wReal0 = *pWReal0++;
578 wImag0 = *pWImag0++;
579 wReal1 = *pWReal1++;
580 wImag1 = *pWImag1++;
581
582 cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
583
584 *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
585 *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
586 } while (--i != 0);
587 }
588 }
589
590 return err;
591 }
592
SpatialDecApplyM2(spatialDec * self,INT ps,const FIXP_SGL alpha,FIXP_DBL ** wReal,FIXP_DBL ** wImag,FIXP_DBL ** hybOutputRealDry,FIXP_DBL ** hybOutputImagDry,FIXP_DBL ** hybOutputRealWet,FIXP_DBL ** hybOutputImagWet)593 SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha,
594 FIXP_DBL **wReal, FIXP_DBL **wImag,
595 FIXP_DBL **hybOutputRealDry,
596 FIXP_DBL **hybOutputImagDry,
597 FIXP_DBL **hybOutputRealWet,
598 FIXP_DBL **hybOutputImagWet) {
599 SACDEC_ERROR err = MPS_OK;
600
601 {
602 int qs, row, col;
603 int complexHybBands;
604 int complexParBands;
605 int scale_param_m2 = 0;
606 int toolsDisabled;
607
608 UCHAR activParamBands;
609 FIXP_DBL *RESTRICT pWReal, *RESTRICT pWImag, *RESTRICT pHybOutRealDry,
610 *RESTRICT pHybOutImagDry, *RESTRICT pHybOutRealWet,
611 *RESTRICT pHybOutImagWet;
612 C_ALLOC_SCRATCH_START(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
613
614 /* The wet signal is added to the dry signal directly in applyM2 if GES and
615 * STP are disabled */
616 toolsDisabled =
617 ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) ? 0 : 1;
618
619 {
620 complexHybBands = self->hybridBands;
621 complexParBands = self->numParameterBands;
622 }
623
624 FDKmemclear(hybOutputImagDry[0],
625 self->createParams.maxNumOutputChannels *
626 self->createParams.maxNumCmplxHybBands * sizeof(FIXP_DBL));
627 FDKmemclear(hybOutputRealDry[0], self->createParams.maxNumOutputChannels *
628 self->createParams.maxNumHybridBands *
629 sizeof(FIXP_DBL));
630
631 if (!toolsDisabled) {
632 FDKmemclear(hybOutputRealWet[0],
633 self->createParams.maxNumOutputChannels *
634 self->createParams.maxNumHybridBands * sizeof(FIXP_DBL));
635 FDKmemclear(hybOutputImagWet[0],
636 self->createParams.maxNumOutputChannels *
637 self->createParams.maxNumCmplxHybBands *
638 sizeof(FIXP_DBL));
639 }
640
641 if (self->phaseCoding == 3) {
642 scale_param_m2 = -(SCALE_DATA_APPLY_M2_PC - 1);
643 }
644
645 for (row = 0; row < self->numM2rows; row++) {
646 pHybOutRealDry = hybOutputRealDry[row];
647 pHybOutImagDry = hybOutputImagDry[row];
648
649 if (toolsDisabled) {
650 pHybOutRealWet = hybOutputRealDry[row];
651 pHybOutImagWet = hybOutputImagDry[row];
652 } else {
653 pHybOutRealWet = hybOutputRealWet[row];
654 pHybOutImagWet = hybOutputImagWet[row];
655 }
656
657 for (col = 0; col < self->numDirektSignals; col++) {
658 if (self->pActivM2ParamBands ==
659 0) { /* default setting, calculate all rows and columns */
660 activParamBands = 1;
661 } else {
662 if (self->pActivM2ParamBands[MAX_M2_INPUT * row +
663 col]) /* table with activ and inactiv
664 bands exists for current
665 configuration */
666 activParamBands = 1;
667 else
668 activParamBands = 0;
669 }
670 if (activParamBands) {
671 pWReal = wReal[col];
672 pWImag = wImag[col];
673
674 M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
675 self->M2RealPrev__FDK[row][col],
676 self->kernels_width, alpha,
677 self->numParameterBands);
678
679 if (1 && (self->phaseCoding != 3)) {
680 /* direct signals */
681 {
682 /* only one sample will be assigned to each row, hence
683 * accumulation is not neccessary; that is valid for all
684 * configurations */
685 for (qs = 0; qs < complexHybBands; qs++) {
686 pHybOutRealDry[qs] = fMult(pWReal[qs], pKernel[qs]);
687 pHybOutImagDry[qs] = fMult(pWImag[qs], pKernel[qs]);
688 }
689 }
690 } else { /* isBinauralMode(self->upmixType) */
691
692 for (qs = 0; qs < complexHybBands; qs++) {
693 pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE(
694 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
695 pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
696 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
697 }
698
699 M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
700 self->M2ImagPrev__FDK[row][col],
701 self->kernels_width, alpha, complexParBands);
702
703 /* direct signals sign is -1 for qs = 0,2 */
704 pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE(
705 fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
706 pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE(
707 fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
708
709 pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE(
710 fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
711 pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE(
712 fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
713
714 /* direct signals sign is +1 for qs = 1,3,4,5,...,complexHybBands */
715 pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE(
716 fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
717 pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE(
718 fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
719
720 for (qs = 3; qs < complexHybBands; qs++) {
721 pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE(
722 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
723 pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
724 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
725 }
726 } /* self->upmixType */
727 } /* if (activParamBands) */
728 } /* self->numDirektSignals */
729
730 for (; col < self->numVChannels; col++) {
731 if (self->pActivM2ParamBands ==
732 0) { /* default setting, calculate all rows and columns */
733 activParamBands = 1;
734 } else {
735 if (self->pActivM2ParamBands[MAX_M2_INPUT * row +
736 col]) /* table with activ and inactiv
737 bands exists for current
738 configuration */
739 activParamBands = 1;
740 else
741 activParamBands = 0;
742 }
743
744 if (activParamBands) {
745 int resBandIndex;
746 int resHybIndex;
747
748 resBandIndex =
749 self->residualBands[SpatialDecGetResidualIndex(self, col)];
750 resHybIndex = self->param2hyb[resBandIndex];
751
752 pWReal = wReal[col];
753 pWImag = wImag[col];
754
755 M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
756 self->M2RealPrev__FDK[row][col],
757 self->kernels_width, alpha,
758 self->numParameterBands);
759
760 if (1 && (self->phaseCoding != 3)) {
761 /* residual signals */
762 for (qs = 0; qs < resHybIndex; qs++) {
763 pHybOutRealDry[qs] += fMult(pWReal[qs], pKernel[qs]);
764 pHybOutImagDry[qs] += fMult(pWImag[qs], pKernel[qs]);
765 }
766 /* decor signals */
767 for (; qs < complexHybBands; qs++) {
768 pHybOutRealWet[qs] += fMult(pWReal[qs], pKernel[qs]);
769 pHybOutImagWet[qs] += fMult(pWImag[qs], pKernel[qs]);
770 }
771 } else { /* self->upmixType */
772 /* residual signals */
773 FIXP_DBL *RESTRICT pHybOutReal;
774 FIXP_DBL *RESTRICT pHybOutImag;
775
776 for (qs = 0; qs < resHybIndex; qs++) {
777 pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE(
778 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
779 pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
780 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
781 }
782 /* decor signals */
783 for (; qs < complexHybBands; qs++) {
784 pHybOutRealWet[qs] += SAC_DEC_APPLY_M2_SCALE(
785 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
786 pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE(
787 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
788 }
789
790 M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
791 self->M2ImagPrev__FDK[row][col],
792 self->kernels_width, alpha, complexParBands);
793
794 /* direct signals sign is -1 for qs = 0,2 */
795 /* direct signals sign is +1 for qs = 1,3.. */
796 if (toolsDisabled) {
797 pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE(
798 fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
799 pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE(
800 fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
801
802 pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE(
803 fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
804 pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE(
805 fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
806
807 pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE(
808 fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
809 pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE(
810 fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
811 } else {
812 pHybOutReal = &pHybOutRealDry[0];
813 pHybOutImag = &pHybOutImagDry[0];
814 if (0 == resHybIndex) {
815 pHybOutReal = &pHybOutRealWet[0];
816 pHybOutImag = &pHybOutImagWet[0];
817 }
818 pHybOutReal[0] += SAC_DEC_APPLY_M2_SCALE(
819 fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
820 pHybOutImag[0] -= SAC_DEC_APPLY_M2_SCALE(
821 fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
822
823 if (1 == resHybIndex) {
824 pHybOutReal = &pHybOutRealWet[0];
825 pHybOutImag = &pHybOutImagWet[0];
826 }
827 pHybOutReal[1] -= SAC_DEC_APPLY_M2_SCALE(
828 fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
829 pHybOutImag[1] += SAC_DEC_APPLY_M2_SCALE(
830 fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
831
832 if (2 == resHybIndex) {
833 pHybOutReal = &pHybOutRealWet[0];
834 pHybOutImag = &pHybOutImagWet[0];
835 }
836 pHybOutReal[2] += SAC_DEC_APPLY_M2_SCALE(
837 fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
838 pHybOutImag[2] -= SAC_DEC_APPLY_M2_SCALE(
839 fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
840 }
841
842 for (qs = 3; qs < resHybIndex; qs++) {
843 pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE(
844 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
845 pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
846 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
847 }
848 /* decor signals */
849 for (; qs < complexHybBands; qs++) {
850 pHybOutRealWet[qs] -= SAC_DEC_APPLY_M2_SCALE(
851 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
852 pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE(
853 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
854 }
855 } /* self->upmixType */
856 } /* if (activParamBands) { */
857 } /* self->numVChannels */
858
859 if (self->phaseCoding == 3) {
860 scaleValuesSaturate(pHybOutRealDry, complexHybBands,
861 SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
862 scaleValuesSaturate(pHybOutImagDry, complexHybBands,
863 SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
864
865 if (!toolsDisabled) {
866 scaleValuesSaturate(pHybOutRealWet, complexHybBands,
867 SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
868 scaleValuesSaturate(pHybOutImagWet, complexHybBands,
869 SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
870 }
871 }
872 }
873
874 C_ALLOC_SCRATCH_END(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
875 }
876
877 return err;
878 }
879
SpatialDecSynthesis(spatialDec * self,const INT ts,FIXP_DBL ** hybOutputReal,FIXP_DBL ** hybOutputImag,PCM_MPS * timeOut,const INT numInputChannels,const FDK_channelMapDescr * const mapDescr)880 SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts,
881 FIXP_DBL **hybOutputReal,
882 FIXP_DBL **hybOutputImag, PCM_MPS *timeOut,
883 const INT numInputChannels,
884 const FDK_channelMapDescr *const mapDescr) {
885 SACDEC_ERROR err = MPS_OK;
886
887 int ch;
888 int stride, offset;
889
890 stride = self->numOutputChannelsAT;
891 offset = 1;
892
893 PCM_MPS *pTimeOut__FDK =
894 &timeOut[stride * self->pQmfDomain->globalConf.nBandsSynthesis * ts];
895 C_ALLOC_SCRATCH_START(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
896 C_ALLOC_SCRATCH_START(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
897
898 for (ch = 0; ch < self->numOutputChannelsAT; ch++) {
899 if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
900 int k;
901 /* No hybrid filtering. Just copy the QMF data. */
902 for (k = 0; k < self->hybridBands; k += 1) {
903 pQmfReal[k] = hybOutputReal[ch][k];
904 pQmfImag[k] = hybOutputImag[ch][k];
905 }
906 } else {
907 FDKhybridSynthesisApply(&self->hybridSynthesis[ch], hybOutputReal[ch],
908 hybOutputImag[ch], pQmfReal, pQmfImag);
909 }
910
911 /* Map channel indices from MPEG Surround -> PCE style -> channelMapping[]
912 */
913 FDK_ASSERT(self->numOutputChannelsAT <= 6);
914 int outCh = FDK_chMapDescr_getMapValue(mapDescr, mapChannel(self, ch),
915 self->numOutputChannelsAT);
916
917 {
918 if (self->stereoConfigIndex == 3) {
919 /* MPS -> SBR */
920 int i;
921 FIXP_DBL *pWorkBufReal, *pWorkBufImag;
922 FDK_ASSERT((self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_m ==
923 (FIXP_DBL)0x80000000) &&
924 (self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_e == 0));
925 FDK_QmfDomain_GetWorkBuffer(&self->pQmfDomain->QmfDomainIn[outCh], ts,
926 &pWorkBufReal, &pWorkBufImag);
927 FDK_ASSERT(self->qmfBands <=
928 self->pQmfDomain->QmfDomainIn[outCh].workBuf_nBands);
929 for (i = 0; i < self->qmfBands; i++) {
930 pWorkBufReal[i] = pQmfReal[i];
931 pWorkBufImag[i] = pQmfImag[i];
932 }
933 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale =
934 -7; /*-ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;*/
935 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
936 self->pQmfDomain->QmfDomainIn[outCh].fb.filterScale;
937 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
938 self->clipProtectGainSF__FDK;
939
940 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= (1);
941 } else {
942 /* Call the QMF synthesis for dry. */
943 err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh],
944 pQmfReal, pQmfImag, stride,
945 pTimeOut__FDK + (offset * outCh));
946 }
947 if (err != MPS_OK) goto bail;
948 }
949 } /* ch loop */
950
951 bail:
952 C_ALLOC_SCRATCH_END(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
953 C_ALLOC_SCRATCH_END(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
954
955 return err;
956 }
957
SpatialDecBufferMatrices(spatialDec * self)958 void SpatialDecBufferMatrices(spatialDec *self) {
959 int row, col;
960 int complexParBands;
961 complexParBands = self->numParameterBands;
962
963 /*
964 buffer matrices M2
965 */
966 for (row = 0; row < self->numM2rows; row++) {
967 for (col = 0; col < self->numVChannels; col++) {
968 FDKmemcpy(self->M2RealPrev__FDK[row][col], self->M2Real__FDK[row][col],
969 self->numParameterBands * sizeof(FIXP_DBL));
970 if (0 || (self->phaseCoding == 3)) {
971 FDKmemcpy(self->M2ImagPrev__FDK[row][col], self->M2Imag__FDK[row][col],
972 complexParBands * sizeof(FIXP_DBL));
973 }
974 }
975 }
976
977 /* buffer phase */
978 FDKmemcpy(self->PhasePrevLeft__FDK, self->PhaseLeft__FDK,
979 self->numParameterBands * sizeof(FIXP_DBL));
980 FDKmemcpy(self->PhasePrevRight__FDK, self->PhaseRight__FDK,
981 self->numParameterBands * sizeof(FIXP_DBL));
982 }
983
984 #define PHASE_SCALE 2
985
986 #ifndef P_PI
987 #define P_PI 3.1415926535897932
988 #endif
989
990 /* For better precision, PI (pi_x2) is already doubled */
interp_angle__FDK(FIXP_DBL angle1,FIXP_DBL angle2,FIXP_SGL alpha,FIXP_DBL pi_x2)991 static FIXP_DBL interp_angle__FDK(FIXP_DBL angle1, FIXP_DBL angle2,
992 FIXP_SGL alpha, FIXP_DBL pi_x2) {
993 if (angle2 - angle1 > (pi_x2 >> 1)) angle2 -= pi_x2;
994
995 if (angle1 - angle2 > (pi_x2 >> 1)) angle1 -= pi_x2;
996
997 return interpolateParameter(alpha, angle2, angle1);
998 }
999
1000 /*
1001 *
1002 */
SpatialDecApplyPhase(spatialDec * self,FIXP_SGL alpha__FDK,int lastSlotOfParamSet)1003 void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha__FDK,
1004 int lastSlotOfParamSet) {
1005 int pb, qs;
1006 FIXP_DBL ppb[MAX_PARAMETER_BANDS *
1007 4]; /* left real, imag - right real, imag interleaved */
1008
1009 const FIXP_DBL pi_x2 = PIx2__IPD;
1010 for (pb = 0; pb < self->numParameterBands; pb++) {
1011 FIXP_DBL pl, pr;
1012
1013 pl = interp_angle__FDK(self->PhasePrevLeft__FDK[pb],
1014 self->PhaseLeft__FDK[pb], alpha__FDK, pi_x2);
1015 pr = interp_angle__FDK(self->PhasePrevRight__FDK[pb],
1016 self->PhaseRight__FDK[pb], alpha__FDK, pi_x2);
1017
1018 inline_fixp_cos_sin(pl, pr, IPD_SCALE, &ppb[4 * pb]);
1019 }
1020
1021 /* sign is -1 for qs = 0,2 and +1 for qs = 1 */
1022
1023 const SCHAR *kernels = &self->kernels[0];
1024
1025 FIXP_DBL *Dry_real0 = &self->hybOutputRealDry__FDK[0][0];
1026 FIXP_DBL *Dry_imag0 = &self->hybOutputImagDry__FDK[0][0];
1027 FIXP_DBL *Dry_real1 = &self->hybOutputRealDry__FDK[1][0];
1028 FIXP_DBL *Dry_imag1 = &self->hybOutputImagDry__FDK[1][0];
1029
1030 for (qs = 2; qs >= 0; qs--) {
1031 FIXP_DBL out_re, out_im;
1032
1033 pb = *kernels++;
1034 if (qs == 1) /* sign[qs] >= 0 */
1035 {
1036 cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1037 ppb[4 * pb + 1]);
1038 out_re <<= PHASE_SCALE - 1;
1039 out_im <<= PHASE_SCALE - 1;
1040 *Dry_real0++ = out_re;
1041 *Dry_imag0++ = out_im;
1042
1043 cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1044 ppb[4 * pb + 3]);
1045 out_re <<= PHASE_SCALE - 1;
1046 out_im <<= PHASE_SCALE - 1;
1047 *Dry_real1++ = out_re;
1048 *Dry_imag1++ = out_im;
1049 } else {
1050 cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1051 -ppb[4 * pb + 1]);
1052 out_re <<= PHASE_SCALE - 1;
1053 out_im <<= PHASE_SCALE - 1;
1054 *Dry_real0++ = out_re;
1055 *Dry_imag0++ = out_im;
1056
1057 cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1058 -ppb[4 * pb + 3]);
1059 out_re <<= PHASE_SCALE - 1;
1060 out_im <<= PHASE_SCALE - 1;
1061 *Dry_real1++ = out_re;
1062 *Dry_imag1++ = out_im;
1063 }
1064 }
1065
1066 /* sign is +1 for qs >=3 */
1067 for (qs = self->hybridBands - 3; qs--;) {
1068 FIXP_DBL out_re, out_im;
1069
1070 pb = *kernels++;
1071 cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1072 ppb[4 * pb + 1]);
1073 out_re <<= PHASE_SCALE - 1;
1074 out_im <<= PHASE_SCALE - 1;
1075 *Dry_real0++ = out_re;
1076 *Dry_imag0++ = out_im;
1077
1078 cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1079 ppb[4 * pb + 3]);
1080 out_re <<= PHASE_SCALE - 1;
1081 out_im <<= PHASE_SCALE - 1;
1082 *Dry_real1++ = out_re;
1083 *Dry_imag1++ = out_im;
1084 }
1085 }
1086