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