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