/src/aac/libSBRdec/src/psdec.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 - 2018 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 | | /**************************** SBR decoder library ****************************** |
96 | | |
97 | | Author(s): |
98 | | |
99 | | Description: |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | /*! |
104 | | \file |
105 | | \brief parametric stereo decoder |
106 | | */ |
107 | | |
108 | | #include "psdec.h" |
109 | | |
110 | | #include "FDK_bitbuffer.h" |
111 | | |
112 | | #include "sbr_rom.h" |
113 | | #include "sbr_ram.h" |
114 | | |
115 | | #include "FDK_tools_rom.h" |
116 | | |
117 | | #include "genericStds.h" |
118 | | |
119 | | #include "FDK_trigFcts.h" |
120 | | |
121 | | /********************************************************************/ |
122 | | /* MLQUAL DEFINES */ |
123 | | /********************************************************************/ |
124 | | |
125 | | #define FRACT_ZERO FRACT_BITS - 1 |
126 | | /********************************************************************/ |
127 | | |
128 | | SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d); |
129 | | |
130 | | /***** HELPERS *****/ |
131 | | |
132 | | /***************************************************************************/ |
133 | | /*! |
134 | | \brief Creates one instance of the PS_DEC struct |
135 | | |
136 | | \return Error info |
137 | | |
138 | | ****************************************************************************/ |
139 | | int CreatePsDec(HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */ |
140 | 0 | int aacSamplesPerFrame) { |
141 | 0 | SBR_ERROR errorInfo = SBRDEC_OK; |
142 | 0 | HANDLE_PS_DEC h_ps_d; |
143 | 0 | int i; |
144 | |
|
145 | 0 | if (*h_PS_DEC == NULL) { |
146 | | /* Get ps dec ram */ |
147 | 0 | h_ps_d = GetRam_ps_dec(); |
148 | 0 | if (h_ps_d == NULL) { |
149 | 0 | goto bail; |
150 | 0 | } |
151 | 0 | } else { |
152 | | /* Reset an open instance */ |
153 | 0 | h_ps_d = *h_PS_DEC; |
154 | 0 | } |
155 | | |
156 | | /* |
157 | | * Create Analysis Hybrid filterbank. |
158 | | */ |
159 | 0 | FDKhybridAnalysisOpen(&h_ps_d->specificTo.mpeg.hybridAnalysis, |
160 | 0 | h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx, |
161 | 0 | sizeof(h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx), |
162 | 0 | NULL, 0); |
163 | | |
164 | | /* initialisation */ |
165 | 0 | switch (aacSamplesPerFrame) { |
166 | 0 | case 960: |
167 | 0 | h_ps_d->noSubSamples = 30; /* col */ |
168 | 0 | break; |
169 | 0 | case 1024: |
170 | 0 | h_ps_d->noSubSamples = 32; /* col */ |
171 | 0 | break; |
172 | 0 | default: |
173 | 0 | h_ps_d->noSubSamples = -1; |
174 | 0 | break; |
175 | 0 | } |
176 | | |
177 | 0 | if (h_ps_d->noSubSamples > MAX_NUM_COL || h_ps_d->noSubSamples <= 0) { |
178 | 0 | goto bail; |
179 | 0 | } |
180 | 0 | h_ps_d->noChannels = NO_QMF_CHANNELS; /* row */ |
181 | |
|
182 | 0 | h_ps_d->psDecodedPrv = 0; |
183 | 0 | h_ps_d->procFrameBased = -1; |
184 | 0 | for (i = 0; i < (1) + 1; i++) { |
185 | 0 | h_ps_d->bPsDataAvail[i] = ppt_none; |
186 | 0 | } |
187 | 0 | { |
188 | 0 | int error; |
189 | 0 | error = FDKdecorrelateOpen(&(h_ps_d->specificTo.mpeg.apDecor), |
190 | 0 | h_ps_d->specificTo.mpeg.decorrBufferCplx, |
191 | 0 | (2 * ((825) + (373)))); |
192 | 0 | if (error) goto bail; |
193 | 0 | } |
194 | | |
195 | 0 | for (i = 0; i < (1) + 1; i++) { |
196 | 0 | FDKmemclear(&h_ps_d->bsData[i].mpeg, sizeof(MPEG_PS_BS_DATA)); |
197 | 0 | } |
198 | |
|
199 | 0 | errorInfo = ResetPsDec(h_ps_d); |
200 | |
|
201 | 0 | if (errorInfo != SBRDEC_OK) goto bail; |
202 | | |
203 | 0 | *h_PS_DEC = h_ps_d; |
204 | |
|
205 | 0 | return 0; |
206 | | |
207 | 0 | bail: |
208 | 0 | if (h_ps_d != NULL) { |
209 | 0 | DeletePsDec(&h_ps_d); |
210 | 0 | } |
211 | |
|
212 | 0 | return -1; |
213 | 0 | } /*END CreatePsDec */ |
214 | | |
215 | | /***************************************************************************/ |
216 | | /*! |
217 | | \brief Delete one instance of the PS_DEC struct |
218 | | |
219 | | \return Error info |
220 | | |
221 | | ****************************************************************************/ |
222 | | int DeletePsDec(HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */ |
223 | 0 | { |
224 | 0 | if (*h_PS_DEC == NULL) { |
225 | 0 | return -1; |
226 | 0 | } |
227 | | |
228 | 0 | { |
229 | 0 | HANDLE_PS_DEC h_ps_d = *h_PS_DEC; |
230 | 0 | FDKdecorrelateClose(&(h_ps_d->specificTo.mpeg.apDecor)); |
231 | 0 | } |
232 | |
|
233 | 0 | FreeRam_ps_dec(h_PS_DEC); |
234 | |
|
235 | 0 | return 0; |
236 | 0 | } /*END DeletePsDec */ |
237 | | |
238 | | /***************************************************************************/ |
239 | | /*! |
240 | | \brief resets some values of the PS handle to default states |
241 | | |
242 | | \return |
243 | | |
244 | | ****************************************************************************/ |
245 | | SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d) /*!< pointer to the module state */ |
246 | 0 | { |
247 | 0 | SBR_ERROR errorInfo = SBRDEC_OK; |
248 | 0 | INT i; |
249 | | |
250 | | /* explicitly init state variables to safe values (until first ps header |
251 | | * arrives) */ |
252 | |
|
253 | 0 | h_ps_d->specificTo.mpeg.lastUsb = 0; |
254 | | |
255 | | /* |
256 | | * Initialize Analysis Hybrid filterbank. |
257 | | */ |
258 | 0 | FDKhybridAnalysisInit(&h_ps_d->specificTo.mpeg.hybridAnalysis, THREE_TO_TEN, |
259 | 0 | NO_QMF_BANDS_HYBRID20, NO_QMF_BANDS_HYBRID20, 1); |
260 | | |
261 | | /* |
262 | | * Initialize Synthesis Hybrid filterbank. |
263 | | */ |
264 | 0 | for (i = 0; i < 2; i++) { |
265 | 0 | FDKhybridSynthesisInit(&h_ps_d->specificTo.mpeg.hybridSynthesis[i], |
266 | 0 | THREE_TO_TEN, NO_QMF_CHANNELS, NO_QMF_CHANNELS); |
267 | 0 | } |
268 | 0 | { |
269 | 0 | INT error; |
270 | 0 | error = FDKdecorrelateInit(&h_ps_d->specificTo.mpeg.apDecor, 71, DECORR_PS, |
271 | 0 | DUCKER_AUTOMATIC, 0, 0, 0, 0, 1, /* isLegacyPS */ |
272 | 0 | 1); |
273 | 0 | if (error) return SBRDEC_NOT_INITIALIZED; |
274 | 0 | } |
275 | | |
276 | 0 | for (i = 0; i < NO_IID_GROUPS; i++) { |
277 | 0 | h_ps_d->specificTo.mpeg.h11rPrev[i] = FL2FXCONST_DBL(0.5f); |
278 | 0 | h_ps_d->specificTo.mpeg.h12rPrev[i] = FL2FXCONST_DBL(0.5f); |
279 | 0 | } |
280 | |
|
281 | 0 | FDKmemclear(h_ps_d->specificTo.mpeg.h21rPrev, |
282 | 0 | sizeof(h_ps_d->specificTo.mpeg.h21rPrev)); |
283 | 0 | FDKmemclear(h_ps_d->specificTo.mpeg.h22rPrev, |
284 | 0 | sizeof(h_ps_d->specificTo.mpeg.h22rPrev)); |
285 | |
|
286 | 0 | return errorInfo; |
287 | 0 | } |
288 | | |
289 | | /***************************************************************************/ |
290 | | /*! |
291 | | \brief Feed delaylines when parametric stereo is switched on. |
292 | | \return |
293 | | ****************************************************************************/ |
294 | | void PreparePsProcessing(HANDLE_PS_DEC h_ps_d, |
295 | | const FIXP_DBL *const *const rIntBufferLeft, |
296 | | const FIXP_DBL *const *const iIntBufferLeft, |
297 | 0 | const int scaleFactorLowBand) { |
298 | 0 | if (h_ps_d->procFrameBased == |
299 | 0 | 1) /* If we have switched from frame to slot based processing */ |
300 | 0 | { /* fill hybrid delay buffer. */ |
301 | 0 | int i, j; |
302 | |
|
303 | 0 | for (i = 0; i < HYBRID_FILTER_DELAY; i++) { |
304 | 0 | FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20]; |
305 | 0 | FIXP_DBL hybridOutputData[2][NO_SUB_QMF_CHANNELS]; |
306 | |
|
307 | 0 | for (j = 0; j < NO_QMF_BANDS_HYBRID20; j++) { |
308 | 0 | qmfInputData[0][j] = |
309 | 0 | scaleValue(rIntBufferLeft[i][j], scaleFactorLowBand); |
310 | 0 | qmfInputData[1][j] = |
311 | 0 | scaleValue(iIntBufferLeft[i][j], scaleFactorLowBand); |
312 | 0 | } |
313 | |
|
314 | 0 | FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis, |
315 | 0 | qmfInputData[0], qmfInputData[1], |
316 | 0 | hybridOutputData[0], hybridOutputData[1]); |
317 | 0 | } |
318 | 0 | h_ps_d->procFrameBased = 0; /* switch to slot based processing. */ |
319 | |
|
320 | 0 | } /* procFrameBased==1 */ |
321 | 0 | } |
322 | | |
323 | | void initSlotBasedRotation( |
324 | | HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ |
325 | 0 | int env, int usb) { |
326 | 0 | INT group = 0; |
327 | 0 | INT bin = 0; |
328 | 0 | INT noIidSteps; |
329 | |
|
330 | 0 | FIXP_SGL invL; |
331 | 0 | FIXP_DBL ScaleL, ScaleR; |
332 | 0 | FIXP_DBL Alpha, Beta; |
333 | 0 | FIXP_DBL h11r, h12r, h21r, h22r; |
334 | |
|
335 | 0 | const FIXP_DBL *PScaleFactors; |
336 | |
|
337 | 0 | if (h_ps_d->bsData[h_ps_d->processSlot].mpeg.bFineIidQ) { |
338 | 0 | PScaleFactors = ScaleFactorsFine; /* values are shiftet right by one */ |
339 | 0 | noIidSteps = NO_IID_STEPS_FINE; |
340 | 0 | } else { |
341 | 0 | PScaleFactors = ScaleFactors; /* values are shiftet right by one */ |
342 | 0 | noIidSteps = NO_IID_STEPS; |
343 | 0 | } |
344 | | |
345 | | /* dequantize and decode */ |
346 | 0 | for (group = 0; group < NO_IID_GROUPS; group++) { |
347 | 0 | bin = bins2groupMap20[group]; |
348 | | |
349 | | /*! |
350 | | <h3> type 'A' rotation </h3> |
351 | | mixing procedure R_a, used in baseline version<br> |
352 | | |
353 | | Scale-factor vectors c1 and c2 are precalculated in initPsTables () and |
354 | | stored in scaleFactors[] and scaleFactorsFine[] = pScaleFactors []. From the |
355 | | linearized IID parameters (intensity differences), two scale factors are |
356 | | calculated. They are used to obtain the coefficients h11... h22. |
357 | | */ |
358 | | |
359 | | /* ScaleR and ScaleL are scaled by 1 shift right */ |
360 | |
|
361 | 0 | ScaleR = PScaleFactors[noIidSteps + h_ps_d->specificTo.mpeg.pCoef |
362 | 0 | ->aaIidIndexMapped[env][bin]]; |
363 | 0 | ScaleL = PScaleFactors[noIidSteps - h_ps_d->specificTo.mpeg.pCoef |
364 | 0 | ->aaIidIndexMapped[env][bin]]; |
365 | |
|
366 | 0 | Beta = fMult( |
367 | 0 | fMult(Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]], |
368 | 0 | (ScaleR - ScaleL)), |
369 | 0 | FIXP_SQRT05); |
370 | 0 | Alpha = |
371 | 0 | Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]] >> 1; |
372 | | |
373 | | /* Alpha and Beta are now both scaled by 2 shifts right */ |
374 | | |
375 | | /* calculate the coefficients h11... h22 from scale-factors and ICC |
376 | | * parameters */ |
377 | | |
378 | | /* h values are scaled by 1 shift right */ |
379 | 0 | { |
380 | 0 | FIXP_DBL trigData[4]; |
381 | |
|
382 | 0 | inline_fixp_cos_sin(Beta + Alpha, Beta - Alpha, 2, trigData); |
383 | 0 | h11r = fMult(ScaleL, trigData[0]); |
384 | 0 | h12r = fMult(ScaleR, trigData[2]); |
385 | 0 | h21r = fMult(ScaleL, trigData[1]); |
386 | 0 | h22r = fMult(ScaleR, trigData[3]); |
387 | 0 | } |
388 | | /*****************************************************************************************/ |
389 | | /* Interpolation of the matrices H11... H22: */ |
390 | | /* */ |
391 | | /* H11(k,n) = H11(k,n[e]) + (n-n[e]) * (H11(k,n[e+1] - H11(k,n[e])) / |
392 | | * (n[e+1] - n[e]) */ |
393 | | /* ... */ |
394 | | /*****************************************************************************************/ |
395 | | |
396 | | /* invL = 1/(length of envelope) */ |
397 | 0 | invL = FX_DBL2FX_SGL(GetInvInt( |
398 | 0 | h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env + 1] - |
399 | 0 | h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env])); |
400 | |
|
401 | 0 | h_ps_d->specificTo.mpeg.pCoef->H11r[group] = |
402 | 0 | h_ps_d->specificTo.mpeg.h11rPrev[group]; |
403 | 0 | h_ps_d->specificTo.mpeg.pCoef->H12r[group] = |
404 | 0 | h_ps_d->specificTo.mpeg.h12rPrev[group]; |
405 | 0 | h_ps_d->specificTo.mpeg.pCoef->H21r[group] = |
406 | 0 | h_ps_d->specificTo.mpeg.h21rPrev[group]; |
407 | 0 | h_ps_d->specificTo.mpeg.pCoef->H22r[group] = |
408 | 0 | h_ps_d->specificTo.mpeg.h22rPrev[group]; |
409 | |
|
410 | 0 | h_ps_d->specificTo.mpeg.pCoef->DeltaH11r[group] = |
411 | 0 | fMult(h11r - h_ps_d->specificTo.mpeg.pCoef->H11r[group], invL); |
412 | 0 | h_ps_d->specificTo.mpeg.pCoef->DeltaH12r[group] = |
413 | 0 | fMult(h12r - h_ps_d->specificTo.mpeg.pCoef->H12r[group], invL); |
414 | 0 | h_ps_d->specificTo.mpeg.pCoef->DeltaH21r[group] = |
415 | 0 | fMult(h21r - h_ps_d->specificTo.mpeg.pCoef->H21r[group], invL); |
416 | 0 | h_ps_d->specificTo.mpeg.pCoef->DeltaH22r[group] = |
417 | 0 | fMult(h22r - h_ps_d->specificTo.mpeg.pCoef->H22r[group], invL); |
418 | | |
419 | | /* update prev coefficients for interpolation in next envelope */ |
420 | |
|
421 | 0 | h_ps_d->specificTo.mpeg.h11rPrev[group] = h11r; |
422 | 0 | h_ps_d->specificTo.mpeg.h12rPrev[group] = h12r; |
423 | 0 | h_ps_d->specificTo.mpeg.h21rPrev[group] = h21r; |
424 | 0 | h_ps_d->specificTo.mpeg.h22rPrev[group] = h22r; |
425 | |
|
426 | 0 | } /* group loop */ |
427 | 0 | } |
428 | | |
429 | | static const UCHAR groupTable[NO_IID_GROUPS + 1] = { |
430 | | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, |
431 | | 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71}; |
432 | | |
433 | | static void applySlotBasedRotation( |
434 | | HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ |
435 | | |
436 | | FIXP_DBL *mHybridRealLeft, /*!< hybrid values real left */ |
437 | | FIXP_DBL *mHybridImagLeft, /*!< hybrid values imag left */ |
438 | | |
439 | | FIXP_DBL *mHybridRealRight, /*!< hybrid values real right */ |
440 | | FIXP_DBL *mHybridImagRight /*!< hybrid values imag right */ |
441 | 0 | ) { |
442 | 0 | INT group; |
443 | 0 | INT subband; |
444 | | |
445 | | /**********************************************************************************************/ |
446 | | /*! |
447 | | <h2> Mapping </h2> |
448 | | |
449 | | The number of stereo bands that is actually used depends on the number of |
450 | | availble parameters for IID and ICC: <pre> nr. of IID para.| nr. of ICC para. |
451 | | | nr. of Stereo bands |
452 | | ----------------|------------------|------------------- |
453 | | 10,20 | 10,20 | 20 |
454 | | 10,20 | 34 | 34 |
455 | | 34 | 10,20 | 34 |
456 | | 34 | 34 | 34 |
457 | | </pre> |
458 | | In the case the number of parameters for IIS and ICC differs from the number |
459 | | of stereo bands, a mapping from the lower number to the higher number of |
460 | | parameters is applied. Index mapping of IID and ICC parameters is already done |
461 | | in psbitdec.cpp. Further mapping is not needed here in baseline version. |
462 | | **********************************************************************************************/ |
463 | | |
464 | | /************************************************************************************************/ |
465 | | /*! |
466 | | <h2> Mixing </h2> |
467 | | |
468 | | To generate the QMF subband signals for the subband samples n = n[e]+1 ,,, |
469 | | n_[e+1] the parameters at position n[e] and n[e+1] are required as well as the |
470 | | subband domain signals s_k(n) and d_k(n) for n = n[e]+1... n_[e+1]. n[e] |
471 | | represents the start position for envelope e. The border positions n[e] are |
472 | | handled in DecodePS(). |
473 | | |
474 | | The stereo sub subband signals are constructed as: |
475 | | <pre> |
476 | | l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n) |
477 | | r_k(n) = H21(k,n) s_k(n) + H22(k,n) d_k(n) |
478 | | </pre> |
479 | | In order to obtain the matrices H11(k,n)... H22 (k,n), the vectors h11(b)... |
480 | | h22(b) need to be calculated first (b: parameter index). Depending on ICC mode |
481 | | either mixing procedure R_a or R_b is used for that. For both procedures, the |
482 | | parameters for parameter position n[e+1] is used. |
483 | | ************************************************************************************************/ |
484 | | |
485 | | /************************************************************************************************/ |
486 | | /*! |
487 | | <h2>Phase parameters </h2> |
488 | | With disabled phase parameters (which is the case in baseline version), the |
489 | | H-matrices are just calculated by: |
490 | | |
491 | | <pre> |
492 | | H11(k,n[e+1] = h11(b(k)) |
493 | | (...) |
494 | | b(k): parameter index according to mapping table |
495 | | </pre> |
496 | | |
497 | | <h2>Processing of the samples in the sub subbands </h2> |
498 | | this loop includes the interpolation of the coefficients Hxx |
499 | | ************************************************************************************************/ |
500 | | |
501 | | /******************************************************/ |
502 | | /* construct stereo sub subband signals according to: */ |
503 | | /* */ |
504 | | /* l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n) */ |
505 | | /* r_k(n) = H12(k,n) s_k(n) + H22(k,n) d_k(n) */ |
506 | | /******************************************************/ |
507 | 0 | PS_DEC_COEFFICIENTS *pCoef = h_ps_d->specificTo.mpeg.pCoef; |
508 | |
|
509 | 0 | for (group = 0; group < NO_IID_GROUPS; group++) { |
510 | 0 | pCoef->H11r[group] += pCoef->DeltaH11r[group]; |
511 | 0 | pCoef->H12r[group] += pCoef->DeltaH12r[group]; |
512 | 0 | pCoef->H21r[group] += pCoef->DeltaH21r[group]; |
513 | 0 | pCoef->H22r[group] += pCoef->DeltaH22r[group]; |
514 | |
|
515 | 0 | const int start = groupTable[group]; |
516 | 0 | const int stop = groupTable[group + 1]; |
517 | 0 | for (subband = start; subband < stop; subband++) { |
518 | 0 | FIXP_DBL tmpLeft = |
519 | 0 | fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridRealLeft[subband]), |
520 | 0 | pCoef->H21r[group], mHybridRealRight[subband]); |
521 | 0 | FIXP_DBL tmpRight = |
522 | 0 | fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridRealLeft[subband]), |
523 | 0 | pCoef->H22r[group], mHybridRealRight[subband]); |
524 | 0 | mHybridRealLeft[subband] = tmpLeft; |
525 | 0 | mHybridRealRight[subband] = tmpRight; |
526 | |
|
527 | 0 | tmpLeft = |
528 | 0 | fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridImagLeft[subband]), |
529 | 0 | pCoef->H21r[group], mHybridImagRight[subband]); |
530 | 0 | tmpRight = |
531 | 0 | fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridImagLeft[subband]), |
532 | 0 | pCoef->H22r[group], mHybridImagRight[subband]); |
533 | 0 | mHybridImagLeft[subband] = tmpLeft; |
534 | 0 | mHybridImagRight[subband] = tmpRight; |
535 | 0 | } /* subband */ |
536 | 0 | } |
537 | 0 | } |
538 | | |
539 | | /***************************************************************************/ |
540 | | /*! |
541 | | \brief Applies IID, ICC, IPD and OPD parameters to the current frame. |
542 | | |
543 | | \return none |
544 | | |
545 | | ****************************************************************************/ |
546 | | void ApplyPsSlot( |
547 | | HANDLE_PS_DEC h_ps_d, /*!< handle PS_DEC*/ |
548 | | FIXP_DBL **rIntBufferLeft, /*!< real bands left qmf channel (38x64) */ |
549 | | FIXP_DBL **iIntBufferLeft, /*!< imag bands left qmf channel (38x64) */ |
550 | | FIXP_DBL *rIntBufferRight, /*!< real bands right qmf channel (38x64) */ |
551 | | FIXP_DBL *iIntBufferRight, /*!< imag bands right qmf channel (38x64) */ |
552 | | const int scaleFactorLowBand_no_ov, const int scaleFactorLowBand, |
553 | 0 | const int scaleFactorHighBand, const int lsb, const int usb) { |
554 | | /*! |
555 | | The 64-band QMF representation of the monaural signal generated by the SBR tool |
556 | | is used as input of the PS tool. After the PS processing, the outputs of the |
557 | | left and right hybrid synthesis filterbanks are used to generate the stereo |
558 | | output signal. |
559 | | |
560 | | <pre> |
561 | | |
562 | | ------------- ---------- ------------- |
563 | | | Hybrid | M_n[k,m] | | L_n[k,m] | Hybrid | l[n] |
564 | | m[n] --->| analysis |--------->| |--------->| synthesis |-----> |
565 | | ------------- | Stereo | ------------- |
566 | | | | recon- | |
567 | | | | stuction | |
568 | | \|/ | | |
569 | | ------------- | | |
570 | | | De- | D_n[k,m] | | |
571 | | | correlation |--------->| | |
572 | | ------------- | | ------------- |
573 | | | | R_n[k,m] | Hybrid | r[n] |
574 | | | |--------->| synthesis |-----> |
575 | | IID, ICC ------------------------>| | | filter bank | |
576 | | (IPD, OPD) ---------- ------------- |
577 | | |
578 | | m[n]: QMF represantation of the mono input |
579 | | M_n[k,m]: (sub-)sub-band domain signals of the mono input |
580 | | D_n[k,m]: decorrelated (sub-)sub-band domain signals |
581 | | L_n[k,m]: (sub-)sub-band domain signals of the left output |
582 | | R_n[k,m]: (sub-)sub-band domain signals of the right output |
583 | | l[n],r[n]: left/right output signals |
584 | | |
585 | | </pre> |
586 | | */ |
587 | 0 | #define NO_HYBRID_DATA_BANDS (71) |
588 | |
|
589 | 0 | int i; |
590 | 0 | FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20]; |
591 | 0 | FIXP_DBL *hybridData[2][2]; |
592 | 0 | C_ALLOC_SCRATCH_START(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS); |
593 | |
|
594 | 0 | hybridData[0][0] = |
595 | 0 | pHybridData + 0 * NO_HYBRID_DATA_BANDS; /* left real hybrid data */ |
596 | 0 | hybridData[0][1] = |
597 | 0 | pHybridData + 1 * NO_HYBRID_DATA_BANDS; /* left imag hybrid data */ |
598 | 0 | hybridData[1][0] = |
599 | 0 | pHybridData + 2 * NO_HYBRID_DATA_BANDS; /* right real hybrid data */ |
600 | 0 | hybridData[1][1] = |
601 | 0 | pHybridData + 3 * NO_HYBRID_DATA_BANDS; /* right imag hybrid data */ |
602 | | |
603 | | /*! |
604 | | Hybrid analysis filterbank: |
605 | | The lower 3 (5) of the 64 QMF subbands are further split to provide better |
606 | | frequency resolution. for PS processing. For the 10 and 20 stereo bands |
607 | | configuration, the QMF band H_0(w) is split up into 8 (sub-) sub-bands and the |
608 | | QMF bands H_1(w) and H_2(w) are spit into 2 (sub-) 4th. (See figures 8.20 |
609 | | and 8.22 of ISO/IEC 14496-3:2001/FDAM 2:2004(E) ) |
610 | | */ |
611 | | |
612 | | /* |
613 | | * Hybrid analysis. |
614 | | */ |
615 | | |
616 | | /* Get qmf input data and apply descaling */ |
617 | 0 | for (i = 0; i < NO_QMF_BANDS_HYBRID20; i++) { |
618 | 0 | qmfInputData[0][i] = scaleValue(rIntBufferLeft[HYBRID_FILTER_DELAY][i], |
619 | 0 | scaleFactorLowBand_no_ov); |
620 | 0 | qmfInputData[1][i] = scaleValue(iIntBufferLeft[HYBRID_FILTER_DELAY][i], |
621 | 0 | scaleFactorLowBand_no_ov); |
622 | 0 | } |
623 | | |
624 | | /* LF - part */ |
625 | 0 | FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis, |
626 | 0 | qmfInputData[0], qmfInputData[1], hybridData[0][0], |
627 | 0 | hybridData[0][1]); |
628 | | |
629 | | /* HF - part */ |
630 | | /* bands up to lsb */ |
631 | 0 | scaleValues(&hybridData[0][0][NO_SUB_QMF_CHANNELS - 2], |
632 | 0 | &rIntBufferLeft[0][NO_QMF_BANDS_HYBRID20], |
633 | 0 | lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand); |
634 | 0 | scaleValues(&hybridData[0][1][NO_SUB_QMF_CHANNELS - 2], |
635 | 0 | &iIntBufferLeft[0][NO_QMF_BANDS_HYBRID20], |
636 | 0 | lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand); |
637 | | |
638 | | /* bands from lsb to usb */ |
639 | 0 | scaleValues(&hybridData[0][0][lsb + (NO_SUB_QMF_CHANNELS - 2 - |
640 | 0 | NO_QMF_BANDS_HYBRID20)], |
641 | 0 | &rIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand); |
642 | 0 | scaleValues(&hybridData[0][1][lsb + (NO_SUB_QMF_CHANNELS - 2 - |
643 | 0 | NO_QMF_BANDS_HYBRID20)], |
644 | 0 | &iIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand); |
645 | | |
646 | | /* bands from usb to NO_SUB_QMF_CHANNELS which should be zero for non-overlap |
647 | | slots but can be non-zero for overlap slots */ |
648 | 0 | FDKmemcpy( |
649 | 0 | &hybridData[0][0] |
650 | 0 | [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)], |
651 | 0 | &rIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb)); |
652 | 0 | FDKmemcpy( |
653 | 0 | &hybridData[0][1] |
654 | 0 | [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)], |
655 | 0 | &iIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb)); |
656 | | |
657 | | /*! |
658 | | Decorrelation: |
659 | | By means of all-pass filtering and delaying, the (sub-)sub-band samples s_k(n) |
660 | | are converted into de-correlated (sub-)sub-band samples d_k(n). |
661 | | - k: frequency in hybrid spectrum |
662 | | - n: time index |
663 | | */ |
664 | |
|
665 | 0 | FDKdecorrelateApply(&h_ps_d->specificTo.mpeg.apDecor, |
666 | 0 | &hybridData[0][0][0], /* left real hybrid data */ |
667 | 0 | &hybridData[0][1][0], /* left imag hybrid data */ |
668 | 0 | &hybridData[1][0][0], /* right real hybrid data */ |
669 | 0 | &hybridData[1][1][0], /* right imag hybrid data */ |
670 | 0 | 0 /* startHybBand */ |
671 | 0 | ); |
672 | | |
673 | | /*! |
674 | | Stereo Processing: |
675 | | The sets of (sub-)sub-band samples s_k(n) and d_k(n) are processed according |
676 | | to the stereo cues which are defined per stereo band. |
677 | | */ |
678 | |
|
679 | 0 | applySlotBasedRotation(h_ps_d, |
680 | 0 | &hybridData[0][0][0], /* left real hybrid data */ |
681 | 0 | &hybridData[0][1][0], /* left imag hybrid data */ |
682 | 0 | &hybridData[1][0][0], /* right real hybrid data */ |
683 | 0 | &hybridData[1][1][0] /* right imag hybrid data */ |
684 | 0 | ); |
685 | | |
686 | | /*! |
687 | | Hybrid synthesis filterbank: |
688 | | The stereo processed hybrid subband signals l_k(n) and r_k(n) are fed into the |
689 | | hybrid synthesis filterbanks which are identical to the 64 complex synthesis |
690 | | filterbank of the SBR tool. The input to the filterbank are slots of 64 QMF |
691 | | samples. For each slot the filterbank outputs one block of 64 samples of one |
692 | | reconstructed stereo channel. The hybrid synthesis filterbank is computed |
693 | | seperatly for the left and right channel. |
694 | | */ |
695 | | |
696 | | /* |
697 | | * Hybrid synthesis. |
698 | | */ |
699 | 0 | for (i = 0; i < 2; i++) { |
700 | 0 | FDKhybridSynthesisApply( |
701 | 0 | &h_ps_d->specificTo.mpeg.hybridSynthesis[i], |
702 | 0 | hybridData[i][0], /* real hybrid data */ |
703 | 0 | hybridData[i][1], /* imag hybrid data */ |
704 | 0 | (i == 0) ? rIntBufferLeft[0] |
705 | 0 | : rIntBufferRight, /* output real qmf buffer */ |
706 | 0 | (i == 0) ? iIntBufferLeft[0] |
707 | 0 | : iIntBufferRight /* output imag qmf buffer */ |
708 | 0 | ); |
709 | 0 | } |
710 | | |
711 | | /* free temporary hybrid qmf values of one timeslot */ |
712 | 0 | C_ALLOC_SCRATCH_END(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS); |
713 | |
|
714 | 0 | } /* END ApplyPsSlot */ |