1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4 © Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
5 Forschung e.V. All rights reserved.
6
7 1. INTRODUCTION
8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
11 a wide variety of Android devices.
12
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14 general perceptual audio codecs. AAC-ELD is considered the best-performing
15 full-bandwidth communications codec by independent studies and is widely
16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17 specifications.
18
19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
20 those of Fraunhofer) may be obtained through Via Licensing
21 (www.vialicensing.com) or through the respective patent owners individually for
22 the purpose of encoding or decoding bit streams in products that are compliant
23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24 Android devices already license these patent claims through Via Licensing or
25 directly from the patent owners, and therefore FDK AAC Codec software may
26 already be covered under those patent licenses when it is used for those
27 licensed purposes only.
28
29 Commercially-licensed AAC software libraries, including floating-point versions
30 with enhanced sound quality, are also available from Fraunhofer. Users are
31 encouraged to check the Fraunhofer website for additional applications
32 information and documentation.
33
34 2. COPYRIGHT LICENSE
35
36 Redistribution and use in source and binary forms, with or without modification,
37 are permitted without payment of copyright license fees provided that you
38 satisfy the following conditions:
39
40 You must retain the complete text of this software license in redistributions of
41 the FDK AAC Codec or your modifications thereto in source code form.
42
43 You must retain the complete text of this software license in the documentation
44 and/or other materials provided with redistributions of the FDK AAC Codec or
45 your modifications thereto in binary form. You must make available free of
46 charge copies of the complete source code of the FDK AAC Codec and your
47 modifications thereto to recipients of copies in binary form.
48
49 The name of Fraunhofer may not be used to endorse or promote products derived
50 from this library without prior written permission.
51
52 You may not charge copyright license fees for anyone to use, copy or distribute
53 the FDK AAC Codec software or your modifications thereto.
54
55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
56 that you changed the software and the date of any change. For modified versions
57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59 AAC Codec Library for Android."
60
61 3. NO PATENT LICENSE
62
63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65 Fraunhofer provides no warranty of patent non-infringement with respect to this
66 software.
67
68 You may use this FDK AAC Codec software or modifications thereto only for
69 purposes that are authorized by appropriate patent licenses.
70
71 4. DISCLAIMER
72
73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75 including but not limited to the implied warranties of merchantability and
76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78 or consequential damages, including but not limited to procurement of substitute
79 goods or services; loss of use, data, or profits, or business interruption,
80 however caused and on any theory of liability, whether in contract, strict
81 liability, or tort (including negligence), arising in any way out of the use of
82 this software, even if advised of the possibility of such damage.
83
84 5. CONTACT INFORMATION
85
86 Fraunhofer Institute for Integrated Circuits IIS
87 Attention: Audio and Multimedia Departments - FDK AAC LL
88 Am Wolfsmantel 33
89 91058 Erlangen, Germany
90
91 www.iis.fraunhofer.de/amm
92 amm-info@iis.fraunhofer.de
93 ----------------------------------------------------------------------------- */
94
95 /*********************** 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 = fMax(CntLeadingZeros(maxVal) - 1, 0);
521 s = fMin(s, scale_param_m2);
522
523 mReal0 = iReal0 << s;
524 mImag0 = iImag0 << s;
525 mReal1 = iReal1 << s;
526
527 s = scale_param_m2 - s;
528
529 INT i = pWidth[pb];
530
531 do {
532 FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
533
534 wReal0 = *pWReal0++;
535 wImag0 = *pWImag0++;
536 wReal1 = *pWReal1++;
537 wImag1 = *pWImag1++;
538
539 cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
540
541 *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
542 *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
543
544 if (qs > 0) {
545 mImag0 = -mImag0;
546 qs--;
547 }
548 } while (--i != 0);
549 }
550
551 for (; pb < pb_max; pb++) {
552 INT s;
553 FIXP_DBL maxVal;
554 FIXP_SGL mReal1;
555 FIXP_SGL mReal0, mImag0;
556 FIXP_DBL iReal0, iImag0, iReal1;
557
558 iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
559 iImag0 = interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
560 iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
561
562 maxVal = fAbs(iReal0) | fAbs(iImag0);
563 maxVal |= fAbs(iReal1);
564
565 s = fMax(CntLeadingZeros(maxVal) - 1, 0);
566 s = fMin(s, scale_param_m2);
567
568 mReal0 = FX_DBL2FX_SGL(iReal0 << s);
569 mImag0 = FX_DBL2FX_SGL(iImag0 << s);
570 mReal1 = FX_DBL2FX_SGL(iReal1 << s);
571
572 s = scale_param_m2 - s;
573
574 INT i = pWidth[pb];
575
576 do {
577 FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
578
579 wReal0 = *pWReal0++;
580 wImag0 = *pWImag0++;
581 wReal1 = *pWReal1++;
582 wImag1 = *pWImag1++;
583
584 cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
585
586 *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
587 *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
588 } while (--i != 0);
589 }
590 }
591
592 return err;
593 }
594
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)595 SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha,
596 FIXP_DBL **wReal, FIXP_DBL **wImag,
597 FIXP_DBL **hybOutputRealDry,
598 FIXP_DBL **hybOutputImagDry,
599 FIXP_DBL **hybOutputRealWet,
600 FIXP_DBL **hybOutputImagWet) {
601 SACDEC_ERROR err = MPS_OK;
602
603 {
604 int qs, row, col;
605 int complexHybBands;
606 int complexParBands;
607 int scale_param_m2 = 0;
608 int toolsDisabled;
609
610 UCHAR activParamBands;
611 FIXP_DBL *RESTRICT pWReal, *RESTRICT pWImag, *RESTRICT pHybOutRealDry,
612 *RESTRICT pHybOutImagDry, *RESTRICT pHybOutRealWet,
613 *RESTRICT pHybOutImagWet;
614 C_ALLOC_SCRATCH_START(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
615
616 /* The wet signal is added to the dry signal directly in applyM2 if GES and
617 * STP are disabled */
618 toolsDisabled =
619 ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) ? 0 : 1;
620
621 {
622 complexHybBands = self->hybridBands;
623 complexParBands = self->numParameterBands;
624 }
625
626 FDKmemclear(hybOutputImagDry[0],
627 self->createParams.maxNumOutputChannels *
628 self->createParams.maxNumCmplxHybBands * sizeof(FIXP_DBL));
629 FDKmemclear(hybOutputRealDry[0], self->createParams.maxNumOutputChannels *
630 self->createParams.maxNumHybridBands *
631 sizeof(FIXP_DBL));
632
633 if (!toolsDisabled) {
634 FDKmemclear(hybOutputRealWet[0],
635 self->createParams.maxNumOutputChannels *
636 self->createParams.maxNumHybridBands * sizeof(FIXP_DBL));
637 FDKmemclear(hybOutputImagWet[0],
638 self->createParams.maxNumOutputChannels *
639 self->createParams.maxNumCmplxHybBands *
640 sizeof(FIXP_DBL));
641 }
642
643 if (self->phaseCoding == 3) {
644 scale_param_m2 = -(SCALE_DATA_APPLY_M2_PC - 1);
645 }
646
647 for (row = 0; row < self->numM2rows; row++) {
648 pHybOutRealDry = hybOutputRealDry[row];
649 pHybOutImagDry = hybOutputImagDry[row];
650
651 if (toolsDisabled) {
652 pHybOutRealWet = hybOutputRealDry[row];
653 pHybOutImagWet = hybOutputImagDry[row];
654 } else {
655 pHybOutRealWet = hybOutputRealWet[row];
656 pHybOutImagWet = hybOutputImagWet[row];
657 }
658
659 for (col = 0; col < self->numDirektSignals; col++) {
660 if (self->pActivM2ParamBands ==
661 0) { /* default setting, calculate all rows and columns */
662 activParamBands = 1;
663 } else {
664 if (self->pActivM2ParamBands[MAX_M2_INPUT * row +
665 col]) /* table with activ and inactiv
666 bands exists for current
667 configuration */
668 activParamBands = 1;
669 else
670 activParamBands = 0;
671 }
672 if (activParamBands) {
673 pWReal = wReal[col];
674 pWImag = wImag[col];
675
676 M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
677 self->M2RealPrev__FDK[row][col],
678 self->kernels_width, alpha,
679 self->numParameterBands);
680
681 if (1 && (self->phaseCoding != 3)) {
682 /* direct signals */
683 {
684 /* only one sample will be assigned to each row, hence
685 * accumulation is not neccessary; that is valid for all
686 * configurations */
687 for (qs = 0; qs < complexHybBands; qs++) {
688 pHybOutRealDry[qs] = fMult(pWReal[qs], pKernel[qs]);
689 pHybOutImagDry[qs] = fMult(pWImag[qs], pKernel[qs]);
690 }
691 }
692 } else { /* isBinauralMode(self->upmixType) */
693
694 for (qs = 0; qs < complexHybBands; qs++) {
695 pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE(
696 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
697 pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
698 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
699 }
700
701 M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
702 self->M2ImagPrev__FDK[row][col],
703 self->kernels_width, alpha, complexParBands);
704
705 /* direct signals sign is -1 for qs = 0,2 */
706 pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE(
707 fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
708 pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE(
709 fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
710
711 pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE(
712 fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
713 pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE(
714 fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
715
716 /* direct signals sign is +1 for qs = 1,3,4,5,...,complexHybBands */
717 pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE(
718 fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
719 pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE(
720 fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
721
722 for (qs = 3; qs < complexHybBands; qs++) {
723 pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE(
724 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
725 pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
726 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
727 }
728 } /* self->upmixType */
729 } /* if (activParamBands) */
730 } /* self->numDirektSignals */
731
732 for (; col < self->numVChannels; col++) {
733 if (self->pActivM2ParamBands ==
734 0) { /* default setting, calculate all rows and columns */
735 activParamBands = 1;
736 } else {
737 if (self->pActivM2ParamBands[MAX_M2_INPUT * row +
738 col]) /* table with activ and inactiv
739 bands exists for current
740 configuration */
741 activParamBands = 1;
742 else
743 activParamBands = 0;
744 }
745
746 if (activParamBands) {
747 int resBandIndex;
748 int resHybIndex;
749
750 resBandIndex =
751 self->residualBands[SpatialDecGetResidualIndex(self, col)];
752 resHybIndex = self->param2hyb[resBandIndex];
753
754 pWReal = wReal[col];
755 pWImag = wImag[col];
756
757 M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
758 self->M2RealPrev__FDK[row][col],
759 self->kernels_width, alpha,
760 self->numParameterBands);
761
762 if (1 && (self->phaseCoding != 3)) {
763 /* residual signals */
764 for (qs = 0; qs < resHybIndex; qs++) {
765 pHybOutRealDry[qs] += fMult(pWReal[qs], pKernel[qs]);
766 pHybOutImagDry[qs] += fMult(pWImag[qs], pKernel[qs]);
767 }
768 /* decor signals */
769 for (; qs < complexHybBands; qs++) {
770 pHybOutRealWet[qs] += fMult(pWReal[qs], pKernel[qs]);
771 pHybOutImagWet[qs] += fMult(pWImag[qs], pKernel[qs]);
772 }
773 } else { /* self->upmixType */
774 /* residual signals */
775 FIXP_DBL *RESTRICT pHybOutReal;
776 FIXP_DBL *RESTRICT pHybOutImag;
777
778 for (qs = 0; qs < resHybIndex; qs++) {
779 pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE(
780 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
781 pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
782 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
783 }
784 /* decor signals */
785 for (; qs < complexHybBands; qs++) {
786 pHybOutRealWet[qs] += SAC_DEC_APPLY_M2_SCALE(
787 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
788 pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE(
789 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
790 }
791
792 M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
793 self->M2ImagPrev__FDK[row][col],
794 self->kernels_width, alpha, complexParBands);
795
796 /* direct signals sign is -1 for qs = 0,2 */
797 /* direct signals sign is +1 for qs = 1,3.. */
798 if (toolsDisabled) {
799 pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE(
800 fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
801 pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE(
802 fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
803
804 pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE(
805 fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
806 pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE(
807 fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
808
809 pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE(
810 fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
811 pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE(
812 fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
813 } else {
814 pHybOutReal = &pHybOutRealDry[0];
815 pHybOutImag = &pHybOutImagDry[0];
816 if (0 == resHybIndex) {
817 pHybOutReal = &pHybOutRealWet[0];
818 pHybOutImag = &pHybOutImagWet[0];
819 }
820 pHybOutReal[0] += SAC_DEC_APPLY_M2_SCALE(
821 fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
822 pHybOutImag[0] -= SAC_DEC_APPLY_M2_SCALE(
823 fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
824
825 if (1 == resHybIndex) {
826 pHybOutReal = &pHybOutRealWet[0];
827 pHybOutImag = &pHybOutImagWet[0];
828 }
829 pHybOutReal[1] -= SAC_DEC_APPLY_M2_SCALE(
830 fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
831 pHybOutImag[1] += SAC_DEC_APPLY_M2_SCALE(
832 fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
833
834 if (2 == resHybIndex) {
835 pHybOutReal = &pHybOutRealWet[0];
836 pHybOutImag = &pHybOutImagWet[0];
837 }
838 pHybOutReal[2] += SAC_DEC_APPLY_M2_SCALE(
839 fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
840 pHybOutImag[2] -= SAC_DEC_APPLY_M2_SCALE(
841 fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
842 }
843
844 for (qs = 3; qs < resHybIndex; qs++) {
845 pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE(
846 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
847 pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
848 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
849 }
850 /* decor signals */
851 for (; qs < complexHybBands; qs++) {
852 pHybOutRealWet[qs] -= SAC_DEC_APPLY_M2_SCALE(
853 fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
854 pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE(
855 fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
856 }
857 } /* self->upmixType */
858 } /* if (activParamBands) { */
859 } /* self->numVChannels */
860
861 if (self->phaseCoding == 3) {
862 scaleValuesSaturate(pHybOutRealDry, complexHybBands,
863 SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
864 scaleValuesSaturate(pHybOutImagDry, complexHybBands,
865 SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
866
867 if (!toolsDisabled) {
868 scaleValuesSaturate(pHybOutRealWet, complexHybBands,
869 SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
870 scaleValuesSaturate(pHybOutImagWet, complexHybBands,
871 SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
872 }
873 }
874 }
875
876 C_ALLOC_SCRATCH_END(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
877 }
878
879 return err;
880 }
881
SpatialDecSynthesis(spatialDec * self,const INT ts,FIXP_DBL ** hybOutputReal,FIXP_DBL ** hybOutputImag,PCM_MPS * timeOut,const INT numInputChannels,const FDK_channelMapDescr * const mapDescr)882 SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts,
883 FIXP_DBL **hybOutputReal,
884 FIXP_DBL **hybOutputImag, PCM_MPS *timeOut,
885 const INT numInputChannels,
886 const FDK_channelMapDescr *const mapDescr) {
887 SACDEC_ERROR err = MPS_OK;
888
889 int ch;
890 int stride, offset;
891
892 stride = self->numOutputChannelsAT;
893 offset = 1;
894
895 PCM_MPS *pTimeOut__FDK =
896 &timeOut[stride * self->pQmfDomain->globalConf.nBandsSynthesis * ts];
897 C_ALLOC_SCRATCH_START(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
898 C_ALLOC_SCRATCH_START(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
899
900 for (ch = 0; ch < self->numOutputChannelsAT; ch++) {
901 if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
902 int k;
903 /* No hybrid filtering. Just copy the QMF data. */
904 for (k = 0; k < self->hybridBands; k += 1) {
905 pQmfReal[k] = hybOutputReal[ch][k];
906 pQmfImag[k] = hybOutputImag[ch][k];
907 }
908 } else {
909 FDKhybridSynthesisApply(&self->hybridSynthesis[ch], hybOutputReal[ch],
910 hybOutputImag[ch], pQmfReal, pQmfImag);
911 }
912
913 /* Map channel indices from MPEG Surround -> PCE style -> channelMapping[]
914 */
915 FDK_ASSERT(self->numOutputChannelsAT <= 6);
916 int outCh = FDK_chMapDescr_getMapValue(mapDescr, mapChannel(self, ch),
917 self->numOutputChannelsAT);
918
919 {
920 if (self->stereoConfigIndex == 3) {
921 /* MPS -> SBR */
922 int i;
923 FIXP_DBL *pWorkBufReal, *pWorkBufImag;
924 FDK_ASSERT((self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_m ==
925 (FIXP_DBL)0x80000000) &&
926 (self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_e == 0));
927 FDK_QmfDomain_GetWorkBuffer(&self->pQmfDomain->QmfDomainIn[outCh], ts,
928 &pWorkBufReal, &pWorkBufImag);
929 FDK_ASSERT(self->qmfBands <=
930 self->pQmfDomain->QmfDomainIn[outCh].workBuf_nBands);
931 for (i = 0; i < self->qmfBands; i++) {
932 pWorkBufReal[i] = pQmfReal[i];
933 pWorkBufImag[i] = pQmfImag[i];
934 }
935 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale =
936 -7; /*-ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;*/
937 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
938 self->pQmfDomain->QmfDomainIn[outCh].fb.filterScale;
939 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
940 self->clipProtectGainSF__FDK;
941
942 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= (1);
943 } else {
944 /* Call the QMF synthesis for dry. */
945 err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh],
946 pQmfReal, pQmfImag, stride,
947 pTimeOut__FDK + (offset * outCh));
948 }
949 if (err != MPS_OK) goto bail;
950 }
951 } /* ch loop */
952
953 bail:
954 C_ALLOC_SCRATCH_END(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
955 C_ALLOC_SCRATCH_END(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
956
957 return err;
958 }
959
SpatialDecBufferMatrices(spatialDec * self)960 void SpatialDecBufferMatrices(spatialDec *self) {
961 int row, col;
962 int complexParBands;
963 complexParBands = self->numParameterBands;
964
965 /*
966 buffer matrices M2
967 */
968 for (row = 0; row < self->numM2rows; row++) {
969 for (col = 0; col < self->numVChannels; col++) {
970 FDKmemcpy(self->M2RealPrev__FDK[row][col], self->M2Real__FDK[row][col],
971 self->numParameterBands * sizeof(FIXP_DBL));
972 if (0 || (self->phaseCoding == 3)) {
973 FDKmemcpy(self->M2ImagPrev__FDK[row][col], self->M2Imag__FDK[row][col],
974 complexParBands * sizeof(FIXP_DBL));
975 }
976 }
977 }
978
979 /* buffer phase */
980 FDKmemcpy(self->PhasePrevLeft__FDK, self->PhaseLeft__FDK,
981 self->numParameterBands * sizeof(FIXP_DBL));
982 FDKmemcpy(self->PhasePrevRight__FDK, self->PhaseRight__FDK,
983 self->numParameterBands * sizeof(FIXP_DBL));
984 }
985
986 #define PHASE_SCALE 2
987
988 #ifndef P_PI
989 #define P_PI 3.1415926535897932
990 #endif
991
992 /* 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)993 static FIXP_DBL interp_angle__FDK(FIXP_DBL angle1, FIXP_DBL angle2,
994 FIXP_SGL alpha, FIXP_DBL pi_x2) {
995 if (angle2 - angle1 > (pi_x2 >> 1)) angle2 -= pi_x2;
996
997 if (angle1 - angle2 > (pi_x2 >> 1)) angle1 -= pi_x2;
998
999 return interpolateParameter(alpha, angle2, angle1);
1000 }
1001
1002 /*
1003 *
1004 */
SpatialDecApplyPhase(spatialDec * self,FIXP_SGL alpha__FDK,int lastSlotOfParamSet)1005 void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha__FDK,
1006 int lastSlotOfParamSet) {
1007 int pb, qs;
1008 FIXP_DBL ppb[MAX_PARAMETER_BANDS *
1009 4]; /* left real, imag - right real, imag interleaved */
1010
1011 const FIXP_DBL pi_x2 = PIx2__IPD;
1012 for (pb = 0; pb < self->numParameterBands; pb++) {
1013 FIXP_DBL pl, pr;
1014
1015 pl = interp_angle__FDK(self->PhasePrevLeft__FDK[pb],
1016 self->PhaseLeft__FDK[pb], alpha__FDK, pi_x2);
1017 pr = interp_angle__FDK(self->PhasePrevRight__FDK[pb],
1018 self->PhaseRight__FDK[pb], alpha__FDK, pi_x2);
1019
1020 inline_fixp_cos_sin(pl, pr, IPD_SCALE, &ppb[4 * pb]);
1021 }
1022
1023 /* sign is -1 for qs = 0,2 and +1 for qs = 1 */
1024
1025 const SCHAR *kernels = &self->kernels[0];
1026
1027 FIXP_DBL *Dry_real0 = &self->hybOutputRealDry__FDK[0][0];
1028 FIXP_DBL *Dry_imag0 = &self->hybOutputImagDry__FDK[0][0];
1029 FIXP_DBL *Dry_real1 = &self->hybOutputRealDry__FDK[1][0];
1030 FIXP_DBL *Dry_imag1 = &self->hybOutputImagDry__FDK[1][0];
1031
1032 for (qs = 2; qs >= 0; qs--) {
1033 FIXP_DBL out_re, out_im;
1034
1035 pb = *kernels++;
1036 if (qs == 1) /* sign[qs] >= 0 */
1037 {
1038 cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1039 ppb[4 * pb + 1]);
1040 out_re <<= PHASE_SCALE - 1;
1041 out_im <<= PHASE_SCALE - 1;
1042 *Dry_real0++ = out_re;
1043 *Dry_imag0++ = out_im;
1044
1045 cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1046 ppb[4 * pb + 3]);
1047 out_re <<= PHASE_SCALE - 1;
1048 out_im <<= PHASE_SCALE - 1;
1049 *Dry_real1++ = out_re;
1050 *Dry_imag1++ = out_im;
1051 } else {
1052 cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1053 -ppb[4 * pb + 1]);
1054 out_re <<= PHASE_SCALE - 1;
1055 out_im <<= PHASE_SCALE - 1;
1056 *Dry_real0++ = out_re;
1057 *Dry_imag0++ = out_im;
1058
1059 cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1060 -ppb[4 * pb + 3]);
1061 out_re <<= PHASE_SCALE - 1;
1062 out_im <<= PHASE_SCALE - 1;
1063 *Dry_real1++ = out_re;
1064 *Dry_imag1++ = out_im;
1065 }
1066 }
1067
1068 /* sign is +1 for qs >=3 */
1069 for (qs = self->hybridBands - 3; qs--;) {
1070 FIXP_DBL out_re, out_im;
1071
1072 pb = *kernels++;
1073 cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1074 ppb[4 * pb + 1]);
1075 out_re <<= PHASE_SCALE - 1;
1076 out_im <<= PHASE_SCALE - 1;
1077 *Dry_real0++ = out_re;
1078 *Dry_imag0++ = out_im;
1079
1080 cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1081 ppb[4 * pb + 3]);
1082 out_re <<= PHASE_SCALE - 1;
1083 out_im <<= PHASE_SCALE - 1;
1084 *Dry_real1++ = out_re;
1085 *Dry_imag1++ = out_im;
1086 }
1087 }
1088