1
2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5 � Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
6 All rights reserved.
7
8 1. INTRODUCTION
9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16 of the MPEG specifications.
17
18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
24
25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27 applications information and documentation.
28
29 2. COPYRIGHT LICENSE
30
31 Redistribution and use in source and binary forms, with or without modification, are permitted without
32 payment of copyright license fees provided that you satisfy the following conditions:
33
34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35 your modifications thereto in source code form.
36
37 You must retain the complete text of this software license in the documentation and/or other materials
38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40 modifications thereto to recipients of copies in binary form.
41
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
44
45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46 software or your modifications thereto.
47
48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49 and the date of any change. For modified versions of the FDK AAC Codec, the term
50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
52
53 3. NO PATENT LICENSE
54
55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57 respect to this software.
58
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
61
62 4. DISCLAIMER
63
64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69 or business interruption, however caused and on any theory of liability, whether in contract, strict
70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
71 advised of the possibility of such damage.
72
73 5. CONTACT INFORMATION
74
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
77 Am Wolfsmantel 33
78 91058 Erlangen, Germany
79
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
83
84 /*!
85 \file
86 \brief parametric stereo decoder
87 */
88
89 #include "psdec.h"
90
91
92
93 #include "FDK_bitbuffer.h"
94 #include "psdec_hybrid.h"
95
96 #include "sbr_rom.h"
97 #include "sbr_ram.h"
98
99 #include "FDK_tools_rom.h"
100
101 #include "genericStds.h"
102
103 #include "FDK_trigFcts.h"
104
105
106 /********************************************************************/
107 /* MLQUAL DEFINES */
108 /********************************************************************/
109
110 #define FRACT_ZERO FRACT_BITS-1
111 /********************************************************************/
112
113 SBR_ERROR ResetPsDec( HANDLE_PS_DEC h_ps_d );
114
115 void ResetPsDeCor( HANDLE_PS_DEC h_ps_d );
116
117
118 /***** HELPERS *****/
119
120 static void assignTimeSlotsPS (FIXP_DBL *bufAdr, FIXP_DBL **bufPtr, const int numSlots, const int numChan);
121
122
123
124 /*******************/
125
126 #define DIV3 FL2FXCONST_DBL(1.f/3.f) /* division 3.0 */
127 #define DIV1_5 FL2FXCONST_DBL(2.f/3.f) /* division 1.5 */
128
129 /***************************************************************************/
130 /*!
131 \brief Creates one instance of the PS_DEC struct
132
133 \return Error info
134
135 ****************************************************************************/
136 int
CreatePsDec(HANDLE_PS_DEC * h_PS_DEC,int aacSamplesPerFrame)137 CreatePsDec( HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */
138 int aacSamplesPerFrame
139 )
140 {
141 SBR_ERROR errorInfo = SBRDEC_OK;
142 HANDLE_PS_DEC h_ps_d;
143 int i;
144
145 if (*h_PS_DEC == NULL) {
146 /* Get ps dec ram */
147 h_ps_d = GetRam_ps_dec();
148 if (h_ps_d == NULL) {
149 errorInfo = SBRDEC_MEM_ALLOC_FAILED;
150 goto bail;
151 }
152 } else {
153 /* Reset an open instance */
154 h_ps_d = *h_PS_DEC;
155 }
156
157 /* initialisation */
158 switch (aacSamplesPerFrame) {
159 case 960:
160 h_ps_d->noSubSamples = 30; /* col */
161 break;
162 case 1024:
163 h_ps_d->noSubSamples = 32; /* col */
164 break;
165 default:
166 h_ps_d->noSubSamples = -1;
167 break;
168 }
169
170 if (h_ps_d->noSubSamples > MAX_NUM_COL
171 || h_ps_d->noSubSamples <= 0)
172 {
173 goto bail;
174 }
175 h_ps_d->noChannels = NO_QMF_CHANNELS; /* row */
176
177 h_ps_d->psDecodedPrv = 0;
178 h_ps_d->procFrameBased = -1;
179 for (i = 0; i < (1)+1; i++) {
180 h_ps_d->bPsDataAvail[i] = ppt_none;
181 }
182
183
184 for (i = 0; i < (1)+1; i++) {
185 FDKmemclear(&h_ps_d->bsData[i].mpeg, sizeof(MPEG_PS_BS_DATA));
186 }
187
188 errorInfo = ResetPsDec( h_ps_d );
189
190 if ( errorInfo != SBRDEC_OK )
191 goto bail;
192
193 ResetPsDeCor( h_ps_d );
194
195 *h_PS_DEC = h_ps_d;
196
197
198
199 return 0;
200
201 bail:
202 DeletePsDec(&h_ps_d);
203
204 return -1;
205 } /*END CreatePsDec */
206
207 /***************************************************************************/
208 /*!
209 \brief Delete one instance of the PS_DEC struct
210
211 \return Error info
212
213 ****************************************************************************/
214 int
DeletePsDec(HANDLE_PS_DEC * h_PS_DEC)215 DeletePsDec( HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */
216 {
217 if (*h_PS_DEC == NULL) {
218 return -1;
219 }
220
221
222 FreeRam_ps_dec(h_PS_DEC);
223
224
225 return 0;
226 } /*END DeletePsDec */
227
228 /***************************************************************************/
229 /*!
230 \brief resets some values of the PS handle to default states
231
232 \return
233
234 ****************************************************************************/
ResetPsDec(HANDLE_PS_DEC h_ps_d)235 SBR_ERROR ResetPsDec( HANDLE_PS_DEC h_ps_d ) /*!< pointer to the module state */
236 {
237 SBR_ERROR errorInfo = SBRDEC_OK;
238 INT i;
239
240 const UCHAR noQmfBandsInHybrid20 = 3;
241 /* const UCHAR noQmfBandsInHybrid34 = 5; */
242
243 const UCHAR aHybridResolution20[] = { HYBRID_8_CPLX,
244 HYBRID_2_REAL,
245 HYBRID_2_REAL };
246
247 h_ps_d->specificTo.mpeg.delayBufIndex = 0;
248
249 /* explicitly init state variables to safe values (until first ps header arrives) */
250
251 h_ps_d->specificTo.mpeg.lastUsb = 0;
252
253 h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer = -(DFRACT_BITS-1);
254
255 FDKmemclear(h_ps_d->specificTo.mpeg.aDelayBufIndexDelayQmf, (NO_QMF_CHANNELS-FIRST_DELAY_SB)*sizeof(UCHAR));
256 h_ps_d->specificTo.mpeg.noSampleDelay = delayIndexQmf[0];
257
258 for (i=0 ; i < NO_SERIAL_ALLPASS_LINKS; i++) {
259 h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[i] = 0;
260 }
261
262 h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0] = h_ps_d->specificTo.mpeg.aaQmfDelayBufReal;
263
264 assignTimeSlotsPS ( h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0] + (NO_QMF_CHANNELS-FIRST_DELAY_SB),
265 &h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[1],
266 h_ps_d->specificTo.mpeg.noSampleDelay-1,
267 (NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB));
268
269 h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0] = h_ps_d->specificTo.mpeg.aaQmfDelayBufImag;
270
271 assignTimeSlotsPS ( h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0] + (NO_QMF_CHANNELS-FIRST_DELAY_SB),
272 &h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[1],
273 h_ps_d->specificTo.mpeg.noSampleDelay-1,
274 (NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB));
275
276 /* Hybrid Filter Bank 1 creation. */
277 errorInfo = InitHybridFilterBank ( &h_ps_d->specificTo.mpeg.hybrid,
278 h_ps_d->noSubSamples,
279 noQmfBandsInHybrid20,
280 aHybridResolution20 );
281
282 for ( i = 0; i < NO_IID_GROUPS; i++ )
283 {
284 h_ps_d->specificTo.mpeg.h11rPrev[i] = FL2FXCONST_DBL(0.5f);
285 h_ps_d->specificTo.mpeg.h12rPrev[i] = FL2FXCONST_DBL(0.5f);
286 }
287
288 FDKmemclear( h_ps_d->specificTo.mpeg.h21rPrev, sizeof( h_ps_d->specificTo.mpeg.h21rPrev ) );
289 FDKmemclear( h_ps_d->specificTo.mpeg.h22rPrev, sizeof( h_ps_d->specificTo.mpeg.h22rPrev ) );
290
291 return errorInfo;
292 }
293
294 /***************************************************************************/
295 /*!
296 \brief clear some buffers used in decorrelation process
297
298 \return
299
300 ****************************************************************************/
ResetPsDeCor(HANDLE_PS_DEC h_ps_d)301 void ResetPsDeCor( HANDLE_PS_DEC h_ps_d ) /*!< pointer to the module state */
302 {
303 INT i;
304
305 FDKmemclear(h_ps_d->specificTo.mpeg.aPeakDecayFastBin, NO_MID_RES_BINS*sizeof(FIXP_DBL));
306 FDKmemclear(h_ps_d->specificTo.mpeg.aPrevNrgBin, NO_MID_RES_BINS*sizeof(FIXP_DBL));
307 FDKmemclear(h_ps_d->specificTo.mpeg.aPrevPeakDiffBin, NO_MID_RES_BINS*sizeof(FIXP_DBL));
308 FDKmemclear(h_ps_d->specificTo.mpeg.aPowerPrevScal, NO_MID_RES_BINS*sizeof(SCHAR));
309
310 for (i=0 ; i < FIRST_DELAY_SB ; i++) {
311 FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
312 FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
313 }
314 for (i=0 ; i < NO_SUB_QMF_CHANNELS ; i++) {
315 FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
316 FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
317 }
318
319 }
320
321 /*******************************************************************************/
322
323 /* slot based funcion prototypes */
324
325 static void deCorrelateSlotBased( HANDLE_PS_DEC h_ps_d,
326
327 FIXP_DBL *mHybridRealLeft,
328 FIXP_DBL *mHybridImagLeft,
329 SCHAR sf_mHybridLeft,
330
331 FIXP_DBL *rIntBufferLeft,
332 FIXP_DBL *iIntBufferLeft,
333 SCHAR sf_IntBuffer,
334
335 FIXP_DBL *mHybridRealRight,
336 FIXP_DBL *mHybridImagRight,
337
338 FIXP_DBL *rIntBufferRight,
339 FIXP_DBL *iIntBufferRight );
340
341 static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d,
342
343 FIXP_DBL *mHybridRealLeft,
344 FIXP_DBL *mHybridImagLeft,
345
346 FIXP_DBL *QmfLeftReal,
347 FIXP_DBL *QmfLeftImag,
348
349 FIXP_DBL *mHybridRealRight,
350 FIXP_DBL *mHybridImagRight,
351
352 FIXP_DBL *QmfRightReal,
353 FIXP_DBL *QmfRightImag
354 );
355
356
357 /***************************************************************************/
358 /*!
359 \brief Get scale factor for all ps delay buffer.
360
361 \return
362
363 ****************************************************************************/
364 static
getScaleFactorPsStatesBuffer(HANDLE_PS_DEC h_ps_d)365 int getScaleFactorPsStatesBuffer(HANDLE_PS_DEC h_ps_d)
366 {
367 INT i;
368 int scale = DFRACT_BITS-1;
369
370 for (i=0; i<NO_QMF_BANDS_HYBRID20; i++) {
371 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.hybrid.mQmfBufferRealSlot[i], NO_SUB_QMF_CHANNELS));
372 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.hybrid.mQmfBufferImagSlot[i], NO_SUB_QMF_CHANNELS));
373 }
374
375 for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) {
376 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaRealDelayBufferQmf[i], FIRST_DELAY_SB));
377 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[i], FIRST_DELAY_SB));
378 }
379
380 for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) {
381 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaRealDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS));
382 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS));
383 }
384
385 for (i=0; i<FIRST_DELAY_SB; i++) {
386 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS));
387 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS));
388 }
389
390 for (i=0; i<NO_SUB_QMF_CHANNELS; i++) {
391 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS));
392 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS));
393 }
394
395 for (i=0; i<MAX_DELAY_BUFFER_SIZE; i++)
396 {
397 INT len;
398 if (i==0)
399 len = NO_QMF_CHANNELS-FIRST_DELAY_SB;
400 else
401 len = NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB;
402
403 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[i], len));
404 scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[i], len));
405 }
406
407 return (scale);
408 }
409
410 /***************************************************************************/
411 /*!
412 \brief Rescale all ps delay buffer.
413
414 \return
415
416 ****************************************************************************/
417 static
scalePsStatesBuffer(HANDLE_PS_DEC h_ps_d,int scale)418 void scalePsStatesBuffer(HANDLE_PS_DEC h_ps_d,
419 int scale)
420 {
421 INT i;
422
423 if (scale < 0)
424 scale = fixMax((INT)scale,(INT)-(DFRACT_BITS-1));
425 else
426 scale = fixMin((INT)scale,(INT)DFRACT_BITS-1);
427
428 for (i=0; i<NO_QMF_BANDS_HYBRID20; i++) {
429 scaleValues( h_ps_d->specificTo.mpeg.hybrid.mQmfBufferRealSlot[i], NO_SUB_QMF_CHANNELS, scale );
430 scaleValues( h_ps_d->specificTo.mpeg.hybrid.mQmfBufferImagSlot[i], NO_SUB_QMF_CHANNELS, scale );
431 }
432
433 for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) {
434 scaleValues( h_ps_d->specificTo.mpeg.aaRealDelayBufferQmf[i], FIRST_DELAY_SB, scale );
435 scaleValues( h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[i], FIRST_DELAY_SB, scale );
436 }
437
438 for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) {
439 scaleValues( h_ps_d->specificTo.mpeg.aaRealDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS, scale );
440 scaleValues( h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS, scale );
441 }
442
443 for (i=0; i<FIRST_DELAY_SB; i++) {
444 scaleValues( h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS, scale );
445 scaleValues( h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS, scale );
446 }
447
448 for (i=0; i<NO_SUB_QMF_CHANNELS; i++) {
449 scaleValues( h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS, scale );
450 scaleValues( h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS, scale );
451 }
452
453 for (i=0; i<MAX_DELAY_BUFFER_SIZE; i++) {
454 INT len;
455 if (i==0)
456 len = NO_QMF_CHANNELS-FIRST_DELAY_SB;
457 else
458 len = NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB;
459
460 scaleValues( h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[i], len, scale );
461 scaleValues( h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[i], len, scale );
462 }
463
464 scale <<= 1;
465
466 scaleValues( h_ps_d->specificTo.mpeg.aPeakDecayFastBin, NO_MID_RES_BINS, scale );
467 scaleValues( h_ps_d->specificTo.mpeg.aPrevPeakDiffBin, NO_MID_RES_BINS, scale );
468 scaleValues( h_ps_d->specificTo.mpeg.aPrevNrgBin, NO_MID_RES_BINS, scale );
469 }
470
471 /***************************************************************************/
472 /*!
473 \brief Scale input channel to the same scalefactor and rescale hybrid
474 filterbank values
475
476 \return
477
478 ****************************************************************************/
479
scalFilterBankValues(HANDLE_PS_DEC h_ps_d,FIXP_DBL ** fixpQmfReal,FIXP_DBL ** fixpQmfImag,int lsb,int scaleFactorLowBandSplitLow,int scaleFactorLowBandSplitHigh,SCHAR * scaleFactorLowBand_lb,SCHAR * scaleFactorLowBand_hb,int scaleFactorHighBands,INT * scaleFactorHighBand,INT noCols)480 void scalFilterBankValues( HANDLE_PS_DEC h_ps_d,
481 FIXP_DBL **fixpQmfReal,
482 FIXP_DBL **fixpQmfImag,
483 int lsb,
484 int scaleFactorLowBandSplitLow,
485 int scaleFactorLowBandSplitHigh,
486 SCHAR *scaleFactorLowBand_lb,
487 SCHAR *scaleFactorLowBand_hb,
488 int scaleFactorHighBands,
489 INT *scaleFactorHighBand,
490 INT noCols
491 )
492 {
493 INT maxScal;
494
495 INT i;
496
497 scaleFactorHighBands = -scaleFactorHighBands;
498 scaleFactorLowBandSplitLow = -scaleFactorLowBandSplitLow;
499 scaleFactorLowBandSplitHigh = -scaleFactorLowBandSplitHigh;
500
501 /* get max scale factor */
502 maxScal = fixMax(scaleFactorHighBands,fixMax(scaleFactorLowBandSplitLow, scaleFactorLowBandSplitHigh ));
503
504 {
505 int headroom = getScaleFactorPsStatesBuffer(h_ps_d);
506 maxScal = fixMax(maxScal,(INT)(h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer-headroom));
507 maxScal += 1;
508 }
509
510 /* scale whole left channel to the same scale factor */
511
512 /* low band ( overlap buffer ) */
513 if ( maxScal != scaleFactorLowBandSplitLow ) {
514 INT scale = scaleFactorLowBandSplitLow - maxScal;
515 for ( i=0; i<(6); i++ ) {
516 scaleValues( fixpQmfReal[i], lsb, scale );
517 scaleValues( fixpQmfImag[i], lsb, scale );
518 }
519 }
520 /* low band ( current frame ) */
521 if ( maxScal != scaleFactorLowBandSplitHigh ) {
522 INT scale = scaleFactorLowBandSplitHigh - maxScal;
523 /* for ( i=(6); i<(6)+MAX_NUM_COL; i++ ) { */
524 for ( i=(6); i<(6)+noCols; i++ ) {
525 scaleValues( fixpQmfReal[i], lsb, scale );
526 scaleValues( fixpQmfImag[i], lsb, scale );
527 }
528 }
529 /* high band */
530 if ( maxScal != scaleFactorHighBands ) {
531 INT scale = scaleFactorHighBands - maxScal;
532 /* for ( i=0; i<MAX_NUM_COL; i++ ) { */
533 for ( i=0; i<noCols; i++ ) {
534 scaleValues( &fixpQmfReal[i][lsb], (64)-lsb, scale );
535 scaleValues( &fixpQmfImag[i][lsb], (64)-lsb, scale );
536 }
537 }
538
539 if ( maxScal != h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer )
540 scalePsStatesBuffer(h_ps_d,(h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer-maxScal));
541
542 h_ps_d->specificTo.mpeg.hybrid.sf_mQmfBuffer = maxScal;
543 h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer = maxScal;
544
545 *scaleFactorHighBand += maxScal - scaleFactorHighBands;
546
547 h_ps_d->rescal = maxScal - scaleFactorLowBandSplitHigh;
548 h_ps_d->sf_IntBuffer = maxScal;
549
550 *scaleFactorLowBand_lb += maxScal - scaleFactorLowBandSplitLow;
551 *scaleFactorLowBand_hb += maxScal - scaleFactorLowBandSplitHigh;
552 }
553
rescalFilterBankValues(HANDLE_PS_DEC h_ps_d,FIXP_DBL ** QmfBufferReal,FIXP_DBL ** QmfBufferImag,int lsb,INT noCols)554 void rescalFilterBankValues( HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */
555 FIXP_DBL **QmfBufferReal, /* qmf filterbank values */
556 FIXP_DBL **QmfBufferImag, /* qmf filterbank values */
557 int lsb, /* sbr start subband */
558 INT noCols)
559 {
560 int i;
561 /* scale back 6 timeslots look ahead for hybrid filterbank to original value */
562 for ( i=noCols; i<noCols + (6); i++ ) {
563 scaleValues( QmfBufferReal[i], lsb, h_ps_d->rescal );
564 scaleValues( QmfBufferImag[i], lsb, h_ps_d->rescal );
565 }
566 }
567
568 /***************************************************************************/
569 /*!
570 \brief Generate decorrelated side channel using allpass/delay
571
572 \return
573
574 ****************************************************************************/
575 static void
deCorrelateSlotBased(HANDLE_PS_DEC h_ps_d,FIXP_DBL * mHybridRealLeft,FIXP_DBL * mHybridImagLeft,SCHAR sf_mHybridLeft,FIXP_DBL * rIntBufferLeft,FIXP_DBL * iIntBufferLeft,SCHAR sf_IntBuffer,FIXP_DBL * mHybridRealRight,FIXP_DBL * mHybridImagRight,FIXP_DBL * rIntBufferRight,FIXP_DBL * iIntBufferRight)576 deCorrelateSlotBased( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */
577
578 FIXP_DBL *mHybridRealLeft, /*!< left (mono) hybrid values real */
579 FIXP_DBL *mHybridImagLeft, /*!< left (mono) hybrid values imag */
580 SCHAR sf_mHybridLeft, /*!< scalefactor for left (mono) hybrid bands */
581
582 FIXP_DBL *rIntBufferLeft, /*!< real qmf bands left (mono) (38x64) */
583 FIXP_DBL *iIntBufferLeft, /*!< real qmf bands left (mono) (38x64) */
584 SCHAR sf_IntBuffer, /*!< scalefactor for all left and right qmf bands */
585
586 FIXP_DBL *mHybridRealRight, /*!< right (decorrelated) hybrid values real */
587 FIXP_DBL *mHybridImagRight, /*!< right (decorrelated) hybrid values imag */
588
589 FIXP_DBL *rIntBufferRight, /*!< real qmf bands right (decorrelated) (38x64) */
590 FIXP_DBL *iIntBufferRight ) /*!< real qmf bands right (decorrelated) (38x64) */
591 {
592
593 INT i, m, sb, gr, bin;
594
595 FIXP_DBL peakDiff, nrg, transRatio;
596
597 FIXP_DBL *RESTRICT aaLeftReal;
598 FIXP_DBL *RESTRICT aaLeftImag;
599
600 FIXP_DBL *RESTRICT aaRightReal;
601 FIXP_DBL *RESTRICT aaRightImag;
602
603 FIXP_DBL *RESTRICT pRealDelayBuffer;
604 FIXP_DBL *RESTRICT pImagDelayBuffer;
605
606 C_ALLOC_SCRATCH_START(aaPowerSlot, FIXP_DBL, NO_MID_RES_BINS);
607 C_ALLOC_SCRATCH_START(aaTransRatioSlot, FIXP_DBL, NO_MID_RES_BINS);
608
609 /*!
610 <pre>
611 parameter index qmf bands hybrid bands
612 ----------------------------------------------------------------------------
613 0 0 0,7
614 1 0 1,6
615 2 0 2
616 3 0 3 HYBRID BANDS
617 4 1 9
618 5 1 8
619 6 2 10
620 7 2 11
621 ----------------------------------------------------------------------------
622 8 3
623 9 4
624 10 5
625 11 6
626 12 7
627 13 8
628 14 9,10 (2 ) QMF BANDS
629 15 11 - 13 (3 )
630 16 14 - 17 (4 )
631 17 18 - 22 (5 )
632 18 23 - 34 (12)
633 19 35 - 63 (29)
634 ----------------------------------------------------------------------------
635 </pre>
636 */
637
638 #define FLTR_SCALE 3
639
640 /* hybrid bands (parameter index 0 - 7) */
641 aaLeftReal = mHybridRealLeft;
642 aaLeftImag = mHybridImagLeft;
643
644 aaPowerSlot[0] = ( fMultAddDiv2( fMultDiv2(aaLeftReal[0], aaLeftReal[0]), aaLeftImag[0], aaLeftImag[0] ) >> FLTR_SCALE ) +
645 ( fMultAddDiv2( fMultDiv2(aaLeftReal[7], aaLeftReal[7]), aaLeftImag[7], aaLeftImag[7] ) >> FLTR_SCALE );
646
647 aaPowerSlot[1] = ( fMultAddDiv2( fMultDiv2(aaLeftReal[1], aaLeftReal[1]), aaLeftImag[1], aaLeftImag[1] ) >> FLTR_SCALE ) +
648 ( fMultAddDiv2( fMultDiv2(aaLeftReal[6], aaLeftReal[6]), aaLeftImag[6], aaLeftImag[6] ) >> FLTR_SCALE );
649
650 aaPowerSlot[2] = fMultAddDiv2( fMultDiv2(aaLeftReal[2], aaLeftReal[2]), aaLeftImag[2], aaLeftImag[2] ) >> FLTR_SCALE;
651 aaPowerSlot[3] = fMultAddDiv2( fMultDiv2(aaLeftReal[3], aaLeftReal[3]), aaLeftImag[3], aaLeftImag[3] ) >> FLTR_SCALE;
652
653 aaPowerSlot[4] = fMultAddDiv2( fMultDiv2(aaLeftReal[9], aaLeftReal[9]), aaLeftImag[9], aaLeftImag[9] ) >> FLTR_SCALE;
654 aaPowerSlot[5] = fMultAddDiv2( fMultDiv2(aaLeftReal[8], aaLeftReal[8]), aaLeftImag[8], aaLeftImag[8] ) >> FLTR_SCALE;
655
656 aaPowerSlot[6] = fMultAddDiv2( fMultDiv2(aaLeftReal[10], aaLeftReal[10]), aaLeftImag[10], aaLeftImag[10] ) >> FLTR_SCALE;
657 aaPowerSlot[7] = fMultAddDiv2( fMultDiv2(aaLeftReal[11], aaLeftReal[11]), aaLeftImag[11], aaLeftImag[11] ) >> FLTR_SCALE;
658
659 /* qmf bands (parameter index 8 - 19) */
660 for ( bin = 8; bin < NO_MID_RES_BINS; bin++ ) {
661 FIXP_DBL slotNrg = FL2FXCONST_DBL(0.f);
662
663 for ( i = groupBorders20[bin+2]; i < groupBorders20[bin+3]; i++ ) { /* max loops: 29 */
664 slotNrg += fMultAddDiv2 ( fMultDiv2(rIntBufferLeft[i], rIntBufferLeft[i]), iIntBufferLeft[i], iIntBufferLeft[i]) >> FLTR_SCALE;
665 }
666 aaPowerSlot[bin] = slotNrg;
667
668 }
669
670
671 /* calculation of transient ratio */
672 for (bin=0; bin < NO_MID_RES_BINS; bin++) { /* noBins = 20 ( BASELINE_PS ) */
673
674 h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] = fMult( h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin], PEAK_DECAY_FACTOR );
675
676 if (h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] < aaPowerSlot[bin]) {
677 h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] = aaPowerSlot[bin];
678 }
679
680 /* calculate PSmoothPeakDecayDiffNrg */
681 peakDiff = fMultAdd ( (h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin]>>1),
682 INT_FILTER_COEFF, h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] - aaPowerSlot[bin] - h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin]);
683
684 /* save peakDiff for the next frame */
685 h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin] = peakDiff;
686
687 nrg = h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] + fMult( INT_FILTER_COEFF, aaPowerSlot[bin] - h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] );
688
689 /* Negative energies don't exist. But sometimes they appear due to rounding. */
690
691 nrg = fixMax(nrg,FL2FXCONST_DBL(0.f));
692
693 /* save nrg for the next frame */
694 h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] = nrg;
695
696 nrg = fMult( nrg, TRANSIENT_IMPACT_FACTOR );
697
698 /* save transient impact factor */
699 if ( peakDiff <= nrg || peakDiff == FL2FXCONST_DBL(0.0) ) {
700 aaTransRatioSlot[bin] = (FIXP_DBL)MAXVAL_DBL /* FL2FXCONST_DBL(1.0f)*/;
701 }
702 else if ( nrg <= FL2FXCONST_DBL(0.0f) ) {
703 aaTransRatioSlot[bin] = FL2FXCONST_DBL(0.f);
704 }
705 else {
706 /* scale to denominator */
707 INT scale_left = fixMax(0, CntLeadingZeros(peakDiff) - 1);
708 aaTransRatioSlot[bin] = schur_div( nrg<<scale_left, peakDiff<<scale_left, 16);
709 }
710 } /* bin */
711
712
713
714
715 #define DELAY_GROUP_OFFSET 20
716 #define NR_OF_DELAY_GROUPS 2
717
718 FIXP_DBL rTmp, iTmp, rTmp0, iTmp0, rR0, iR0;
719
720 INT TempDelay = h_ps_d->specificTo.mpeg.delayBufIndex; /* set delay indices */
721
722 pRealDelayBuffer = h_ps_d->specificTo.mpeg.aaRealDelayBufferSubQmf[TempDelay];
723 pImagDelayBuffer = h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[TempDelay];
724
725 aaLeftReal = mHybridRealLeft;
726 aaLeftImag = mHybridImagLeft;
727 aaRightReal = mHybridRealRight;
728 aaRightImag = mHybridImagRight;
729
730 /************************/
731 /* ICC groups : 0 - 9 */
732 /************************/
733
734 /* gr = ICC groups */
735 for (gr=0; gr < SUBQMF_GROUPS; gr++) {
736
737 transRatio = aaTransRatioSlot[bins2groupMap20[gr]];
738
739 /* sb = subQMF/QMF subband */
740 sb = groupBorders20[gr];
741
742 /* Update delay buffers, sample delay allpass = 2 */
743 rTmp0 = pRealDelayBuffer[sb];
744 iTmp0 = pImagDelayBuffer[sb];
745
746 pRealDelayBuffer[sb] = aaLeftReal[sb];
747 pImagDelayBuffer[sb] = aaLeftImag[sb];
748
749 /* delay by fraction */
750 cplxMultDiv2(&rR0, &iR0, rTmp0, iTmp0, aaFractDelayPhaseFactorReSubQmf20[sb], aaFractDelayPhaseFactorImSubQmf20[sb]);
751 rR0<<=1;
752 iR0<<=1;
753
754 FIXP_DBL *pAaaRealDelayRBufferSerSubQmf = h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[sb];
755 FIXP_DBL *pAaaImagDelayRBufferSerSubQmf = h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[sb];
756
757 for (m=0; m<NO_SERIAL_ALLPASS_LINKS ; m++) {
758
759 INT tmpDelayRSer = h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m];
760
761 /* get delayed values from according buffer : m(0)=3; m(1)=4; m(2)=5; */
762 rTmp0 = pAaaRealDelayRBufferSerSubQmf[tmpDelayRSer];
763 iTmp0 = pAaaImagDelayRBufferSerSubQmf[tmpDelayRSer];
764
765 /* delay by fraction */
766 cplxMultDiv2(&rTmp, &iTmp, rTmp0, iTmp0, aaFractDelayPhaseFactorSerReSubQmf20[sb][m], aaFractDelayPhaseFactorSerImSubQmf20[sb][m]);
767
768 rTmp = (rTmp - fMultDiv2(aAllpassLinkDecaySer[m], rR0)) << 1;
769 iTmp = (iTmp - fMultDiv2(aAllpassLinkDecaySer[m], iR0)) << 1;
770
771 pAaaRealDelayRBufferSerSubQmf[tmpDelayRSer] = rR0 + fMult(aAllpassLinkDecaySer[m], rTmp);
772 pAaaImagDelayRBufferSerSubQmf[tmpDelayRSer] = iR0 + fMult(aAllpassLinkDecaySer[m], iTmp);
773
774 rR0 = rTmp;
775 iR0 = iTmp;
776
777 pAaaRealDelayRBufferSerSubQmf += aAllpassLinkDelaySer[m];
778 pAaaImagDelayRBufferSerSubQmf += aAllpassLinkDelaySer[m];
779
780 } /* m */
781
782 /* duck if a past transient is found */
783 aaRightReal[sb] = fMult(transRatio, rR0);
784 aaRightImag[sb] = fMult(transRatio, iR0);
785
786 } /* gr */
787
788
789 scaleValues( mHybridRealLeft, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM );
790 scaleValues( mHybridImagLeft, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM );
791 scaleValues( mHybridRealRight, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM );
792 scaleValues( mHybridImagRight, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM );
793
794
795 /************************/
796
797 aaLeftReal = rIntBufferLeft;
798 aaLeftImag = iIntBufferLeft;
799 aaRightReal = rIntBufferRight;
800 aaRightImag = iIntBufferRight;
801
802 pRealDelayBuffer = h_ps_d->specificTo.mpeg.aaRealDelayBufferQmf[TempDelay];
803 pImagDelayBuffer = h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[TempDelay];
804
805 /************************/
806 /* ICC groups : 10 - 19 */
807 /************************/
808
809
810 /* gr = ICC groups */
811 for (gr=SUBQMF_GROUPS; gr < NO_IID_GROUPS - NR_OF_DELAY_GROUPS; gr++) {
812
813 transRatio = aaTransRatioSlot[bins2groupMap20[gr]];
814
815 /* sb = subQMF/QMF subband */
816 for (sb = groupBorders20[gr]; sb < groupBorders20[gr+1]; sb++) {
817 FIXP_DBL resR, resI;
818
819 /* decayScaleFactor = 1.0f + decay_cutoff * DECAY_SLOPE - DECAY_SLOPE * sb; DECAY_SLOPE = 0.05 */
820 FIXP_DBL decayScaleFactor = decayScaleFactTable[sb];
821
822 /* Update delay buffers, sample delay allpass = 2 */
823 rTmp0 = pRealDelayBuffer[sb];
824 iTmp0 = pImagDelayBuffer[sb];
825
826 pRealDelayBuffer[sb] = aaLeftReal[sb];
827 pImagDelayBuffer[sb] = aaLeftImag[sb];
828
829 /* delay by fraction */
830 cplxMultDiv2(&rR0, &iR0, rTmp0, iTmp0, aaFractDelayPhaseFactorReQmf[sb], aaFractDelayPhaseFactorImQmf[sb]);
831 rR0<<=1;
832 iR0<<=1;
833
834 resR = fMult(decayScaleFactor, rR0);
835 resI = fMult(decayScaleFactor, iR0);
836
837 FIXP_DBL *pAaaRealDelayRBufferSerQmf = h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[sb];
838 FIXP_DBL *pAaaImagDelayRBufferSerQmf = h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[sb];
839
840 for (m=0; m<NO_SERIAL_ALLPASS_LINKS ; m++) {
841
842 INT tmpDelayRSer = h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m];
843
844 /* get delayed values from according buffer : m(0)=3; m(1)=4; m(2)=5; */
845 rTmp0 = pAaaRealDelayRBufferSerQmf[tmpDelayRSer];
846 iTmp0 = pAaaImagDelayRBufferSerQmf[tmpDelayRSer];
847
848 /* delay by fraction */
849 cplxMultDiv2(&rTmp, &iTmp, rTmp0, iTmp0, aaFractDelayPhaseFactorSerReQmf[sb][m], aaFractDelayPhaseFactorSerImQmf[sb][m]);
850
851 rTmp = (rTmp - fMultDiv2(aAllpassLinkDecaySer[m], resR))<<1;
852 iTmp = (iTmp - fMultDiv2(aAllpassLinkDecaySer[m], resI))<<1;
853
854 resR = fMult(decayScaleFactor, rTmp);
855 resI = fMult(decayScaleFactor, iTmp);
856
857 pAaaRealDelayRBufferSerQmf[tmpDelayRSer] = rR0 + fMult(aAllpassLinkDecaySer[m], resR);
858 pAaaImagDelayRBufferSerQmf[tmpDelayRSer] = iR0 + fMult(aAllpassLinkDecaySer[m], resI);
859
860 rR0 = rTmp;
861 iR0 = iTmp;
862
863 pAaaRealDelayRBufferSerQmf += aAllpassLinkDelaySer[m];
864 pAaaImagDelayRBufferSerQmf += aAllpassLinkDelaySer[m];
865
866 } /* m */
867
868 /* duck if a past transient is found */
869 aaRightReal[sb] = fMult(transRatio, rR0);
870 aaRightImag[sb] = fMult(transRatio, iR0);
871
872 } /* sb */
873 } /* gr */
874
875 /************************/
876 /* ICC groups : 20, 21 */
877 /************************/
878
879
880 /* gr = ICC groups */
881 for (gr=DELAY_GROUP_OFFSET; gr < NO_IID_GROUPS; gr++) {
882
883 INT sbStart = groupBorders20[gr];
884 INT sbStop = groupBorders20[gr+1];
885
886 UCHAR *pDelayBufIdx = &h_ps_d->specificTo.mpeg.aDelayBufIndexDelayQmf[sbStart-FIRST_DELAY_SB];
887
888 transRatio = aaTransRatioSlot[bins2groupMap20[gr]];
889
890 /* sb = subQMF/QMF subband */
891 for (sb = sbStart; sb < sbStop; sb++) {
892
893 /* Update delay buffers */
894 rR0 = h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB];
895 iR0 = h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB];
896
897 h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB] = aaLeftReal[sb];
898 h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB] = aaLeftImag[sb];
899
900 /* duck if a past transient is found */
901 aaRightReal[sb] = fMult(transRatio, rR0);
902 aaRightImag[sb] = fMult(transRatio, iR0);
903
904 if (++(*pDelayBufIdx) >= delayIndexQmf[sb]) {
905 *pDelayBufIdx = 0;
906 }
907 pDelayBufIdx++;
908
909 } /* sb */
910 } /* gr */
911
912
913 /* Update delay buffer index */
914 if (++h_ps_d->specificTo.mpeg.delayBufIndex >= NO_SAMPLE_DELAY_ALLPASS)
915 h_ps_d->specificTo.mpeg.delayBufIndex = 0;
916
917 for (m=0; m<NO_SERIAL_ALLPASS_LINKS ; m++) {
918 if (++h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m] >= aAllpassLinkDelaySer[m])
919 h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m] = 0;
920 }
921
922
923 scaleValues( &rIntBufferLeft[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM );
924 scaleValues( &iIntBufferLeft[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM );
925 scaleValues( &rIntBufferRight[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM );
926 scaleValues( &iIntBufferRight[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM );
927
928 /* free memory on scratch */
929 C_ALLOC_SCRATCH_END(aaTransRatioSlot, FIXP_DBL, NO_MID_RES_BINS);
930 C_ALLOC_SCRATCH_END(aaPowerSlot, FIXP_DBL, NO_MID_RES_BINS);
931 }
932
933
initSlotBasedRotation(HANDLE_PS_DEC h_ps_d,int env,int usb)934 void initSlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */
935 int env,
936 int usb
937 ) {
938
939 INT group = 0;
940 INT bin = 0;
941 INT noIidSteps;
942
943 /* const UCHAR *pQuantizedIIDs;*/
944
945 FIXP_SGL invL;
946 FIXP_DBL ScaleL, ScaleR;
947 FIXP_DBL Alpha, Beta;
948 FIXP_DBL h11r, h12r, h21r, h22r;
949
950 const FIXP_DBL *PScaleFactors;
951
952 /* Overwrite old values in delay buffers when upper subband is higher than in last frame */
953 if (env == 0) {
954
955 if ((usb > h_ps_d->specificTo.mpeg.lastUsb) && h_ps_d->specificTo.mpeg.lastUsb) {
956
957 INT i,k,length;
958
959 for (i=h_ps_d->specificTo.mpeg.lastUsb ; i < FIRST_DELAY_SB; i++) {
960 FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
961 FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
962 }
963
964 for (k=0 ; k<NO_SAMPLE_DELAY_ALLPASS; k++) {
965 FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[k], FIRST_DELAY_SB*sizeof(FIXP_DBL));
966 }
967 length = (usb-FIRST_DELAY_SB)*sizeof(FIXP_DBL);
968 if(length>0) {
969 FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0], length);
970 FDKmemclear(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0], length);
971 }
972 length = (fixMin(NO_DELAY_BUFFER_BANDS,(INT)usb)-FIRST_DELAY_SB)*sizeof(FIXP_DBL);
973 if(length>0) {
974 for (k=1 ; k < h_ps_d->specificTo.mpeg.noSampleDelay; k++) {
975 FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[k], length);
976 FDKmemclear(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[k], length);
977 }
978 }
979 }
980 h_ps_d->specificTo.mpeg.lastUsb = usb;
981 } /* env == 0 */
982
983 if (h_ps_d->bsData[h_ps_d->processSlot].mpeg.bFineIidQ)
984 {
985 PScaleFactors = ScaleFactorsFine; /* values are shiftet right by one */
986 noIidSteps = NO_IID_STEPS_FINE;
987 /*pQuantizedIIDs = quantizedIIDsFine;*/
988 }
989
990 else
991 {
992 PScaleFactors = ScaleFactors; /* values are shiftet right by one */
993 noIidSteps = NO_IID_STEPS;
994 /*pQuantizedIIDs = quantizedIIDs;*/
995 }
996
997
998 /* dequantize and decode */
999 for ( group = 0; group < NO_IID_GROUPS; group++ ) {
1000
1001 bin = bins2groupMap20[group];
1002
1003 /*!
1004 <h3> type 'A' rotation </h3>
1005 mixing procedure R_a, used in baseline version<br>
1006
1007 Scale-factor vectors c1 and c2 are precalculated in initPsTables () and stored in
1008 scaleFactors[] and scaleFactorsFine[] = pScaleFactors [].
1009 From the linearized IID parameters (intensity differences), two scale factors are
1010 calculated. They are used to obtain the coefficients h11... h22.
1011 */
1012
1013 /* ScaleR and ScaleL are scaled by 1 shift right */
1014
1015 ScaleR = PScaleFactors[noIidSteps + h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env][bin]];
1016 ScaleL = PScaleFactors[noIidSteps - h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env][bin]];
1017
1018 Beta = fMult (fMult( Alphas[h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env][bin]], ( ScaleR - ScaleL )), FIXP_SQRT05);
1019 Alpha = Alphas[h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env][bin]]>>1;
1020
1021 /* Alpha and Beta are now both scaled by 2 shifts right */
1022
1023 /* calculate the coefficients h11... h22 from scale-factors and ICC parameters */
1024
1025 /* h values are scaled by 1 shift right */
1026 {
1027 FIXP_DBL trigData[4];
1028
1029 inline_fixp_cos_sin(Beta + Alpha, Beta - Alpha, 2, trigData);
1030 h11r = fMult( ScaleL, trigData[0]);
1031 h12r = fMult( ScaleR, trigData[2]);
1032 h21r = fMult( ScaleL, trigData[1]);
1033 h22r = fMult( ScaleR, trigData[3]);
1034 }
1035 /*****************************************************************************************/
1036 /* Interpolation of the matrices H11... H22: */
1037 /* */
1038 /* H11(k,n) = H11(k,n[e]) + (n-n[e]) * (H11(k,n[e+1] - H11(k,n[e])) / (n[e+1] - n[e]) */
1039 /* ... */
1040 /*****************************************************************************************/
1041
1042 /* invL = 1/(length of envelope) */
1043 invL = FX_DBL2FX_SGL(GetInvInt(h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env + 1] - h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env]));
1044
1045 h_ps_d->specificTo.mpeg.coef.H11r[group] = h_ps_d->specificTo.mpeg.h11rPrev[group];
1046 h_ps_d->specificTo.mpeg.coef.H12r[group] = h_ps_d->specificTo.mpeg.h12rPrev[group];
1047 h_ps_d->specificTo.mpeg.coef.H21r[group] = h_ps_d->specificTo.mpeg.h21rPrev[group];
1048 h_ps_d->specificTo.mpeg.coef.H22r[group] = h_ps_d->specificTo.mpeg.h22rPrev[group];
1049
1050 h_ps_d->specificTo.mpeg.coef.DeltaH11r[group] = fMult ( h11r - h_ps_d->specificTo.mpeg.coef.H11r[group], invL );
1051 h_ps_d->specificTo.mpeg.coef.DeltaH12r[group] = fMult ( h12r - h_ps_d->specificTo.mpeg.coef.H12r[group], invL );
1052 h_ps_d->specificTo.mpeg.coef.DeltaH21r[group] = fMult ( h21r - h_ps_d->specificTo.mpeg.coef.H21r[group], invL );
1053 h_ps_d->specificTo.mpeg.coef.DeltaH22r[group] = fMult ( h22r - h_ps_d->specificTo.mpeg.coef.H22r[group], invL );
1054
1055 /* update prev coefficients for interpolation in next envelope */
1056
1057 h_ps_d->specificTo.mpeg.h11rPrev[group] = h11r;
1058 h_ps_d->specificTo.mpeg.h12rPrev[group] = h12r;
1059 h_ps_d->specificTo.mpeg.h21rPrev[group] = h21r;
1060 h_ps_d->specificTo.mpeg.h22rPrev[group] = h22r;
1061
1062 } /* group loop */
1063 }
1064
1065
applySlotBasedRotation(HANDLE_PS_DEC h_ps_d,FIXP_DBL * mHybridRealLeft,FIXP_DBL * mHybridImagLeft,FIXP_DBL * QmfLeftReal,FIXP_DBL * QmfLeftImag,FIXP_DBL * mHybridRealRight,FIXP_DBL * mHybridImagRight,FIXP_DBL * QmfRightReal,FIXP_DBL * QmfRightImag)1066 static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */
1067
1068 FIXP_DBL *mHybridRealLeft, /*!< hybrid values real left */
1069 FIXP_DBL *mHybridImagLeft, /*!< hybrid values imag left */
1070
1071 FIXP_DBL *QmfLeftReal, /*!< real bands left qmf channel */
1072 FIXP_DBL *QmfLeftImag, /*!< imag bands left qmf channel */
1073
1074 FIXP_DBL *mHybridRealRight, /*!< hybrid values real right */
1075 FIXP_DBL *mHybridImagRight, /*!< hybrid values imag right */
1076
1077 FIXP_DBL *QmfRightReal, /*!< real bands right qmf channel */
1078 FIXP_DBL *QmfRightImag /*!< imag bands right qmf channel */
1079 )
1080 {
1081 INT group;
1082 INT subband;
1083
1084 FIXP_DBL *RESTRICT HybrLeftReal;
1085 FIXP_DBL *RESTRICT HybrLeftImag;
1086 FIXP_DBL *RESTRICT HybrRightReal;
1087 FIXP_DBL *RESTRICT HybrRightImag;
1088
1089 FIXP_DBL tmpLeft, tmpRight;
1090
1091
1092 /**********************************************************************************************/
1093 /*!
1094 <h2> Mapping </h2>
1095
1096 The number of stereo bands that is actually used depends on the number of availble
1097 parameters for IID and ICC:
1098 <pre>
1099 nr. of IID para.| nr. of ICC para. | nr. of Stereo bands
1100 ----------------|------------------|-------------------
1101 10,20 | 10,20 | 20
1102 10,20 | 34 | 34
1103 34 | 10,20 | 34
1104 34 | 34 | 34
1105 </pre>
1106 In the case the number of parameters for IIS and ICC differs from the number of stereo
1107 bands, a mapping from the lower number to the higher number of parameters is applied.
1108 Index mapping of IID and ICC parameters is already done in psbitdec.cpp. Further mapping is
1109 not needed here in baseline version.
1110 **********************************************************************************************/
1111
1112 /************************************************************************************************/
1113 /*!
1114 <h2> Mixing </h2>
1115
1116 To generate the QMF subband signals for the subband samples n = n[e]+1 ,,, n_[e+1] the
1117 parameters at position n[e] and n[e+1] are required as well as the subband domain signals
1118 s_k(n) and d_k(n) for n = n[e]+1... n_[e+1]. n[e] represents the start position for
1119 envelope e. The border positions n[e] are handled in DecodePS().
1120
1121 The stereo sub subband signals are constructed as:
1122 <pre>
1123 l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n)
1124 r_k(n) = H21(k,n) s_k(n) + H22(k,n) d_k(n)
1125 </pre>
1126 In order to obtain the matrices H11(k,n)... H22 (k,n), the vectors h11(b)... h22(b) need to
1127 be calculated first (b: parameter index). Depending on ICC mode either mixing procedure R_a
1128 or R_b is used for that. For both procedures, the parameters for parameter position n[e+1]
1129 is used.
1130 ************************************************************************************************/
1131
1132
1133 /************************************************************************************************/
1134 /*!
1135 <h2>Phase parameters </h2>
1136 With disabled phase parameters (which is the case in baseline version), the H-matrices are
1137 just calculated by:
1138
1139 <pre>
1140 H11(k,n[e+1] = h11(b(k))
1141 (...)
1142 b(k): parameter index according to mapping table
1143 </pre>
1144
1145 <h2>Processing of the samples in the sub subbands </h2>
1146 this loop includes the interpolation of the coefficients Hxx
1147 ************************************************************************************************/
1148
1149
1150 /* loop thru all groups ... */
1151 HybrLeftReal = mHybridRealLeft;
1152 HybrLeftImag = mHybridImagLeft;
1153 HybrRightReal = mHybridRealRight;
1154 HybrRightImag = mHybridImagRight;
1155
1156 /******************************************************/
1157 /* construct stereo sub subband signals according to: */
1158 /* */
1159 /* l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n) */
1160 /* r_k(n) = H12(k,n) s_k(n) + H22(k,n) d_k(n) */
1161 /******************************************************/
1162 for ( group = 0; group < SUBQMF_GROUPS; group++ ) {
1163
1164 h_ps_d->specificTo.mpeg.coef.H11r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH11r[group];
1165 h_ps_d->specificTo.mpeg.coef.H12r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH12r[group];
1166 h_ps_d->specificTo.mpeg.coef.H21r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH21r[group];
1167 h_ps_d->specificTo.mpeg.coef.H22r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH22r[group];
1168
1169 subband = groupBorders20[group];
1170
1171 tmpLeft = fMultAddDiv2( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightReal[subband]);
1172 tmpRight = fMultAddDiv2( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightReal[subband]);
1173 HybrLeftReal [subband] = tmpLeft<<1;
1174 HybrRightReal[subband] = tmpRight<<1;
1175
1176 tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightImag[subband]);
1177 tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightImag[subband]);
1178 HybrLeftImag [subband] = tmpLeft;
1179 HybrRightImag[subband] = tmpRight;
1180 }
1181
1182 /* continue in the qmf buffers */
1183 HybrLeftReal = QmfLeftReal;
1184 HybrLeftImag = QmfLeftImag;
1185 HybrRightReal = QmfRightReal;
1186 HybrRightImag = QmfRightImag;
1187
1188 for (; group < NO_IID_GROUPS; group++ ) {
1189
1190 h_ps_d->specificTo.mpeg.coef.H11r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH11r[group];
1191 h_ps_d->specificTo.mpeg.coef.H12r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH12r[group];
1192 h_ps_d->specificTo.mpeg.coef.H21r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH21r[group];
1193 h_ps_d->specificTo.mpeg.coef.H22r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH22r[group];
1194
1195 for ( subband = groupBorders20[group]; subband < groupBorders20[group + 1]; subband++ )
1196 {
1197 tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightReal[subband]);
1198 tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightReal[subband]);
1199 HybrLeftReal [subband] = tmpLeft;
1200 HybrRightReal[subband] = tmpRight;
1201
1202 tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightImag[subband]);
1203 tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightImag[subband]);
1204 HybrLeftImag [subband] = tmpLeft;
1205 HybrRightImag[subband] = tmpRight;
1206
1207 } /* subband */
1208 }
1209 }
1210
1211
1212 /***************************************************************************/
1213 /*!
1214 \brief Applies IID, ICC, IPD and OPD parameters to the current frame.
1215
1216 \return none
1217
1218 ****************************************************************************/
1219 void
ApplyPsSlot(HANDLE_PS_DEC h_ps_d,FIXP_DBL ** rIntBufferLeft,FIXP_DBL ** iIntBufferLeft,FIXP_DBL * rIntBufferRight,FIXP_DBL * iIntBufferRight)1220 ApplyPsSlot( HANDLE_PS_DEC h_ps_d, /*!< handle PS_DEC*/
1221 FIXP_DBL **rIntBufferLeft, /*!< real bands left qmf channel (38x64) */
1222 FIXP_DBL **iIntBufferLeft, /*!< imag bands left qmf channel (38x64) */
1223 FIXP_DBL *rIntBufferRight, /*!< real bands right qmf channel (38x64) */
1224 FIXP_DBL *iIntBufferRight /*!< imag bands right qmf channel (38x64) */
1225 )
1226 {
1227
1228 /*!
1229 The 64-band QMF representation of the monaural signal generated by the SBR tool
1230 is used as input of the PS tool. After the PS processing, the outputs of the left
1231 and right hybrid synthesis filterbanks are used to generate the stereo output
1232 signal.
1233
1234 <pre>
1235
1236 ------------- ---------- -------------
1237 | Hybrid | M_n[k,m] | | L_n[k,m] | Hybrid | l[n]
1238 m[n] --->| analysis |--------->| |--------->| synthesis |----->
1239 | filter bank | | | | filter bank |
1240 ------------- | Stereo | -------------
1241 | | recon- |
1242 | | stuction |
1243 \|/ | |
1244 ------------- | |
1245 | De- | D_n[k,m] | |
1246 | correlation |--------->| |
1247 ------------- | | -------------
1248 | | R_n[k,m] | Hybrid | r[n]
1249 | |--------->| synthesis |----->
1250 IID, ICC ------------------------>| | | filter bank |
1251 (IPD, OPD) ---------- -------------
1252
1253 m[n]: QMF represantation of the mono input
1254 M_n[k,m]: (sub-)sub-band domain signals of the mono input
1255 D_n[k,m]: decorrelated (sub-)sub-band domain signals
1256 L_n[k,m]: (sub-)sub-band domain signals of the left output
1257 R_n[k,m]: (sub-)sub-band domain signals of the right output
1258 l[n],r[n]: left/right output signals
1259
1260 </pre>
1261 */
1262
1263 /* get temporary hybrid qmf values of one timeslot */
1264 C_ALLOC_SCRATCH_START(hybridRealLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS);
1265 C_ALLOC_SCRATCH_START(hybridImagLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS);
1266 C_ALLOC_SCRATCH_START(hybridRealRight, FIXP_DBL, NO_SUB_QMF_CHANNELS);
1267 C_ALLOC_SCRATCH_START(hybridImagRight, FIXP_DBL, NO_SUB_QMF_CHANNELS);
1268
1269 SCHAR sf_IntBuffer = h_ps_d->sf_IntBuffer;
1270
1271 /* clear workbuffer */
1272 FDKmemclear(hybridRealLeft, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL));
1273 FDKmemclear(hybridImagLeft, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL));
1274 FDKmemclear(hybridRealRight, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL));
1275 FDKmemclear(hybridImagRight, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL));
1276
1277
1278 /*!
1279 Hybrid analysis filterbank:
1280 The lower 3 (5) of the 64 QMF subbands are further split to provide better frequency resolution.
1281 for PS processing.
1282 For the 10 and 20 stereo bands configuration, the QMF band H_0(w) is split
1283 up into 8 (sub-) sub-bands and the QMF bands H_1(w) and H_2(w) are spit into 2 (sub-)
1284 4th. (See figures 8.20 and 8.22 of ISO/IEC 14496-3:2001/FDAM 2:2004(E) )
1285 */
1286
1287
1288 if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot based processing */
1289 { /* fill hybrid delay buffer. */
1290 h_ps_d->procFrameBased = 0;
1291
1292 fillHybridDelayLine( rIntBufferLeft,
1293 iIntBufferLeft,
1294 hybridRealLeft,
1295 hybridImagLeft,
1296 hybridRealRight,
1297 hybridImagRight,
1298 &h_ps_d->specificTo.mpeg.hybrid );
1299 }
1300
1301 slotBasedHybridAnalysis ( rIntBufferLeft[HYBRID_FILTER_DELAY], /* qmf filterbank values */
1302 iIntBufferLeft[HYBRID_FILTER_DELAY], /* qmf filterbank values */
1303 hybridRealLeft, /* hybrid filterbank values */
1304 hybridImagLeft, /* hybrid filterbank values */
1305 &h_ps_d->specificTo.mpeg.hybrid); /* hybrid filterbank handle */
1306
1307
1308 SCHAR hybridScal = h_ps_d->specificTo.mpeg.hybrid.sf_mQmfBuffer;
1309
1310
1311 /*!
1312 Decorrelation:
1313 By means of all-pass filtering and delaying, the (sub-)sub-band samples s_k(n) are
1314 converted into de-correlated (sub-)sub-band samples d_k(n).
1315 - k: frequency in hybrid spectrum
1316 - n: time index
1317 */
1318
1319 deCorrelateSlotBased( h_ps_d, /* parametric stereo decoder handle */
1320 hybridRealLeft, /* left hybrid time slot */
1321 hybridImagLeft,
1322 hybridScal, /* scale factor of left hybrid time slot */
1323 rIntBufferLeft[0], /* left qmf time slot */
1324 iIntBufferLeft[0],
1325 sf_IntBuffer, /* scale factor of left and right qmf time slot */
1326 hybridRealRight, /* right hybrid time slot */
1327 hybridImagRight,
1328 rIntBufferRight, /* right qmf time slot */
1329 iIntBufferRight );
1330
1331
1332
1333 /*!
1334 Stereo Processing:
1335 The sets of (sub-)sub-band samples s_k(n) and d_k(n) are processed according to
1336 the stereo cues which are defined per stereo band.
1337 */
1338
1339
1340 applySlotBasedRotation( h_ps_d, /* parametric stereo decoder handle */
1341 hybridRealLeft, /* left hybrid time slot */
1342 hybridImagLeft,
1343 rIntBufferLeft[0], /* left qmf time slot */
1344 iIntBufferLeft[0],
1345 hybridRealRight, /* right hybrid time slot */
1346 hybridImagRight,
1347 rIntBufferRight, /* right qmf time slot */
1348 iIntBufferRight );
1349
1350
1351
1352
1353 /*!
1354 Hybrid synthesis filterbank:
1355 The stereo processed hybrid subband signals l_k(n) and r_k(n) are fed into the hybrid synthesis
1356 filterbanks which are identical to the 64 complex synthesis filterbank of the SBR tool. The
1357 input to the filterbank are slots of 64 QMF samples. For each slot the filterbank outputs one
1358 block of 64 samples of one reconstructed stereo channel. The hybrid synthesis filterbank is
1359 computed seperatly for the left and right channel.
1360 */
1361
1362
1363 /* left channel */
1364 slotBasedHybridSynthesis ( hybridRealLeft, /* one timeslot of hybrid filterbank values */
1365 hybridImagLeft,
1366 rIntBufferLeft[0], /* one timeslot of qmf filterbank values */
1367 iIntBufferLeft[0],
1368 &h_ps_d->specificTo.mpeg.hybrid ); /* hybrid filterbank handle */
1369
1370 /* right channel */
1371 slotBasedHybridSynthesis ( hybridRealRight, /* one timeslot of hybrid filterbank values */
1372 hybridImagRight,
1373 rIntBufferRight, /* one timeslot of qmf filterbank values */
1374 iIntBufferRight,
1375 &h_ps_d->specificTo.mpeg.hybrid ); /* hybrid filterbank handle */
1376
1377
1378
1379
1380
1381
1382
1383 /* free temporary hybrid qmf values of one timeslot */
1384 C_ALLOC_SCRATCH_END(hybridImagRight, FIXP_DBL, NO_SUB_QMF_CHANNELS);
1385 C_ALLOC_SCRATCH_END(hybridRealRight, FIXP_DBL, NO_SUB_QMF_CHANNELS);
1386 C_ALLOC_SCRATCH_END(hybridImagLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS);
1387 C_ALLOC_SCRATCH_END(hybridRealLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS);
1388
1389 }/* END ApplyPsSlot */
1390
1391
1392 /***************************************************************************/
1393 /*!
1394
1395 \brief assigns timeslots to an array
1396
1397 \return
1398
1399 ****************************************************************************/
1400
assignTimeSlotsPS(FIXP_DBL * bufAdr,FIXP_DBL ** bufPtr,const int numSlots,const int numChan)1401 static void assignTimeSlotsPS (FIXP_DBL *bufAdr,
1402 FIXP_DBL **bufPtr,
1403 const int numSlots,
1404 const int numChan)
1405 {
1406 FIXP_DBL *ptr;
1407 int slot;
1408 ptr = bufAdr;
1409 for(slot=0; slot < numSlots; slot++) {
1410 bufPtr [slot] = ptr;
1411 ptr += numChan;
1412 }
1413 }
1414
1415