summaryrefslogtreecommitdiff
path: root/audio_codec/libcook/ra_gainctrl.c (plain)
blob: 9e4d741870121aab3faec72ac6b7a2baee9846cd
1/* ***** BEGIN LICENSE BLOCK *****
2 * Source last modified: $Id: gainctrl.c,v 1.6 2005/04/27 19:20:50 hubbe Exp $
3 *
4 * REALNETWORKS CONFIDENTIAL--NOT FOR DISTRIBUTION IN SOURCE CODE FORM
5 * Portions Copyright (c) 1995-2002 RealNetworks, Inc.
6 * All Rights Reserved.
7 *
8 * The contents of this file, and the files included with this file,
9 * are subject to the current version of the Real Format Source Code
10 * Porting and Optimization License, available at
11 * https://helixcommunity.org/2005/license/realformatsource (unless
12 * RealNetworks otherwise expressly agrees in writing that you are
13 * subject to a different license). You may also obtain the license
14 * terms directly from RealNetworks. You may not use this file except
15 * in compliance with the Real Format Source Code Porting and
16 * Optimization License. There are no redistribution rights for the
17 * source code of this file. Please see the Real Format Source Code
18 * Porting and Optimization License for the rights, obligations and
19 * limitations governing use of the contents of the file.
20 *
21 * RealNetworks is the developer of the Original Code and owns the
22 * copyrights in the portions it created.
23 *
24 * This file, and the files included with this file, is distributed and
25 * made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND,
26 * EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL
27 * SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT
29 * OR NON-INFRINGEMENT.
30 *
31 * Technology Compatibility Kit Test Suite(s) Location:
32 * https://rarvcode-tck.helixcommunity.org
33 *
34 * Contributor(s):
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/**************************************************************************************
39 * Fixed-point RealAudio 8 decoder
40 * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
41 * October 2003
42 *
43 * gainctrl.c - time-domain gain control processing
44 *
45 * Discussion of interpolating gain control window:
46 * gain ranges from -7 to 4 so window ranges from 2^-7 to 2^4
47 * If gain0 != gain1, we start at 2^gain0 and increase logarithmically
48 * to a final value of gain1
49 **************************************************************************************/
50
51#include "coder.h"
52#include "assembly.h"
53
54#define MAX_NPSAMPS (1024 / NPARTS)
55#define MAX_LOGNPSAMPS 7 /* log2(MAX_NPSAMPS) */
56#define FRAC_MASK (MAX_NPSAMPS - 1)
57
58static const int npsampsTab[NUM_MLT_SIZES] = {256 / NPARTS, 512 / NPARTS, 1024 / NPARTS};
59static const int nplog2Tab[NUM_MLT_SIZES] = {5, 6, 7};
60
61/* 2^(x/128) - format = Q30 */
62static const int POW2NTAB[128] = {
63 0x40000000, 0x4058f6a8, 0x40b268fa, 0x410c57a2, 0x4166c34c, 0x41c1aca7, 0x421d1462, 0x4278fb2b,
64 0x42d561b4, 0x433248ae, 0x438fb0cb, 0x43ed9ac0, 0x444c0740, 0x44aaf702, 0x450a6abb, 0x456a6323,
65 0x45cae0f2, 0x462be4e2, 0x468d6fae, 0x46ef8210, 0x47521cc6, 0x47b5408c, 0x4818ee22, 0x487d2646,
66 0x48e1e9ba, 0x4947393f, 0x49ad1598, 0x4a137f88, 0x4a7a77d4, 0x4ae1ff43, 0x4b4a169c, 0x4bb2bea5,
67 0x4c1bf829, 0x4c85c3f1, 0x4cf022ca, 0x4d5b157e, 0x4dc69cdd, 0x4e32b9b4, 0x4e9f6cd4, 0x4f0cb70c,
68 0x4f7a9930, 0x4fe91413, 0x50582888, 0x50c7d765, 0x51382182, 0x51a907b4, 0x521a8ad7, 0x528cabc3,
69 0x52ff6b55, 0x5372ca68, 0x53e6c9da, 0x545b6a8b, 0x54d0ad5a, 0x55469329, 0x55bd1cdb, 0x56344b52,
70 0x56ac1f75, 0x57249a29, 0x579dbc57, 0x581786e6, 0x5891fac1, 0x590d18d3, 0x5988e209, 0x5a055751,
71 0x5a82799a, 0x5b0049d4, 0x5b7ec8f2, 0x5bfdf7e5, 0x5c7dd7a4, 0x5cfe6923, 0x5d7fad59, 0x5e01a53f,
72 0x5e8451d0, 0x5f07b405, 0x5f8bccdb, 0x60109d51, 0x60962665, 0x611c6919, 0x61a3666d, 0x622b1f66,
73 0x62b39509, 0x633cc85b, 0x63c6ba64, 0x64516c2e, 0x64dcdec3, 0x6569132f, 0x65f60a7f, 0x6683c5c3,
74 0x6712460b, 0x67a18c68, 0x683199ed, 0x68c26fb1, 0x69540ec9, 0x69e6784d, 0x6a79ad56, 0x6b0daeff,
75 0x6ba27e65, 0x6c381ca6, 0x6cce8ae1, 0x6d65ca38, 0x6dfddbcc, 0x6e96c0c3, 0x6f307a41, 0x6fcb096f,
76 0x70666f76, 0x7102ad80, 0x719fc4b9, 0x723db650, 0x72dc8374, 0x737c2d55, 0x741cb528, 0x74be1c20,
77 0x75606374, 0x76038c5b, 0x76a7980f, 0x774c87cc, 0x77f25cce, 0x78991854, 0x7940bb9e, 0x79e947ef,
78 0x7a92be8b, 0x7b3d20b6, 0x7be86fba, 0x7c94acde, 0x7d41d96e, 0x7deff6b6, 0x7e9f0606, 0x7f4f08ae,
79};
80
81/**************************************************************************************
82 * Function: DecodeGainInfo
83 *
84 * Description: decode the gain window parameters for each frame
85 *
86 * Inputs: pointer to initialized Gecko2Info struct
87 * pointer to uninitialized GAINC struct
88 * number of bits remaining in bitstream for this frame
89 *
90 * Outputs: GAINC struct filled in with number and location of attacks, and gains
91 *
92 * Return: number of bits remaining in bitstream, -1 if out-of-bits
93 **************************************************************************************/
94int DecodeGainInfo(Gecko2Info *gi, GAINC *gainc, int availbits)
95{
96 int i, nbits, code;
97 BitStreamInfo *bsi = &(gi->bsi);
98
99 /* unpack nattacks */
100 nbits = 0;
101 do {
102 code = GetBits(bsi, 1, 1); /* count bits until zero reached */
103 nbits++;
104 } while (code);
105 gainc->nats = nbits - 1; /* nats = number of ones */
106 availbits -= nbits;
107
108 if (availbits < 0) {
109 return -1;
110 }
111
112 ASSERT(gainc->nats <= MAXNATS);
113
114 /* unpack any location/gain pairs */
115 if (gainc->nats > 0) {
116 for (i = 0; i < gainc->nats; i++) {
117 /* location */
118 gainc->loc[i] = GetBits(bsi, LOCBITS, 1);
119 availbits -= LOCBITS;
120
121 /* gain code */
122 code = GetBits(bsi, 1, 1);
123 availbits--;
124
125 if (!code) {
126 gainc->gain[i] = -1;
127 } else {
128 code = GetBits(bsi, GAINBITS, 1);
129 availbits -= GAINBITS;
130 gainc->gain[i] = CODE2GAIN(code);
131 }
132 }
133 }
134 gainc->maxExGain = 0;
135
136 if (availbits < 0) {
137 return -1;
138 }
139
140 return availbits;
141}
142
143/**************************************************************************************
144 * Function: CopyGainInfo
145 *
146 * Description: copy contents of one GAINC struct into another one
147 *
148 * Inputs: pointer to initialized GAINC struct (source)
149 * pointer to uninitialized GAINC struct (destination)
150 *
151 * Outputs: gaincDest which is identical to gaincSource
152 *
153 * Return: none
154 *
155 * Notes: this prevents compiler from generating a memcpy for gainc0 = gainc1
156 * (we want to avoid a CRT lib call, for portability of asm)
157 **************************************************************************************/
158void CopyGainInfo(GAINC *gaincDest, GAINC *gaincSource)
159{
160 int nBytes = sizeof(GAINC);
161 unsigned char *d = (unsigned char *)gaincDest;
162 unsigned char *s = (unsigned char *)gaincSource;
163
164 for (; nBytes != 0; nBytes--) {
165 *d++ = *s++;
166 }
167
168}
169
170/**************************************************************************************
171 * Function: CalcGainChanges
172 *
173 * Description: reconstruct segmented gain window
174 *
175 * Inputs: pointer to uninitialized exgain array
176 * pointer to old (overlap) and current gain info structs
177 *
178 * Outputs: exgain[0, ... 2*NPARTS] with expanded gains at each switch point
179 *
180 * Return: none
181 *
182 * Notes: each frame is divided into NPARTS segments, with
183 * npsamps = nSamples / NPARTS samples in each one
184 * the gain window can only change at these boundaries
185 * if exgain[i] != exgain[i-1] the gain is interpolated logarithmically
186 * between the two points (buf[(i-1)*npsamps to buf[i*npsamps])
187 **************************************************************************************/
188static void CalcGainChanges(short *exgain, GAINC *gainc0, GAINC *gainc1)
189{
190 short i, nats, maxGain, offset;
191
192 /* second half - expand gains, working backwards */
193 exgain[NPARTS + NPARTS] = 0; /* always finish at 1.0 */
194 nats = gainc1->nats; /* gain changes left */
195 for (i = NPARTS - 1; i >= 0; i--) {
196 if (nats && (i == gainc1->loc[nats - 1])) { /* at gain change */
197 exgain[i + NPARTS] = gainc1->gain[--nats]; /* use it */
198 } else {
199 exgain[i + NPARTS] = exgain[i + NPARTS + 1]; /* repeat last gain */
200 }
201 }
202
203 /* pull any discontinuity through first half by offsetting all
204 * gains with starting gain of second half
205 */
206 offset = exgain[NPARTS];
207
208 /* first half - expand gains, working backwards */
209 nats = gainc0->nats; /* gain changes left */
210 for (i = NPARTS - 1; i >= 0; i--) {
211 if (nats && (i == gainc0->loc[nats - 1])) { /* at gain change */
212 exgain[i] = gainc0->gain[--nats] + offset; /* use it */
213 } else {
214 exgain[i] = exgain[i + 1]; /* repeat last gain */
215 }
216 }
217
218 /* find max gain for each half (input and overlap) */
219 maxGain = 0;
220 for (i = 0; i <= NPARTS; i++) {
221 if (exgain[i] > maxGain) {
222 maxGain = exgain[i];
223 }
224 }
225 gainc0->maxExGain = maxGain;
226
227 maxGain = 0;
228 for (i = NPARTS; i <= 2 * NPARTS; i++) {
229 if (exgain[i] > maxGain) {
230 maxGain = exgain[i];
231 }
232 }
233 gainc1->maxExGain = maxGain;
234
235 return;
236}
237
238/**************************************************************************************
239 * Function: InterpolatePCM
240 *
241 * Description: apply gain window to first half of current frame, and overlap-add
242 * with second half of previous frame, to produce PCM output
243 *
244 * Inputs: table index (for transform size)
245 * pointer to initialized exgain array (NPARTS+1 gain values)
246 * first half of IMLT output for current frame (buf),
247 * synthesis window has not yet been applied
248 * overlap from previous frame (buf + MAXNMLT), synthesis and gain
249 * windows were already applied
250 * max exgain for first half of current frame
251 * buffer for output PCM
252 * number of channels
253 * number of fraction bits present in current and overlap data
254 *
255 * Outputs: nSamples samples of 16-bit PCM output
256 *
257 * Return: none
258 *
259 * Notes: this processes one channel at a time, but skips every other sample in
260 * the output buffer (pcm) for stereo interleaving
261 **************************************************************************************/
262static void InterpolatePCM(int tabidx, short *exgain, int *buf, int *overlap, short maxGain, short *pcm, int nChans, int fbitsPCM, int fbitsOver)
263{
264 int in, npsamps, part;
265 int shiftLo, shiftHi, currGainLo, currGainHi, gainDiffLo, gainDiffHi;
266 int gainLo0, gainLo1, gainHi0, gainHi1, w0, w1, f0, f1, oc;
267 int *over0, *over1, shift[2], rndMask;
268 short *pcm0, *pcm1;
269 const int *wnd;
270
271 shift[0] = 0;
272 shift[1] = 0;
273 rndMask = 0;
274 if (fbitsPCM > fbitsOver) {
275 shift[0] = MIN(fbitsPCM - fbitsOver, 31);
276 fbitsPCM = fbitsOver;
277 } else if (fbitsPCM < fbitsOver) {
278 shift[1] = MIN(fbitsOver - fbitsPCM, 31);
279 }
280
281 if (fbitsPCM > 0) {
282 rndMask = (1 << (fbitsPCM - 1));
283 }
284 ASSERT(fbitsPCM >= 0);
285
286 npsamps = npsampsTab[tabidx];
287 over0 = overlap;//buf + MAXNMLT;
288 over1 = over0 + NPARTS * npsamps - 1;
289 buf += (nmltTab[tabidx] >> 1) - 1;
290
291 wnd = window + windowOffset[tabidx];
292 pcm0 = pcm;
293 pcm1 = pcm + (NPARTS * npsamps - 1) * nChans;
294
295 gainLo1 = exgain[0];
296 gainHi0 = exgain[NPARTS];
297
298 for (part = 0; part < NPARTS / 2; part++) {
299 npsamps = npsampsTab[tabidx];
300
301 gainLo0 = gainLo1;
302 gainLo1 = exgain[part + 1];
303 gainHi1 = gainHi0;
304 gainHi0 = exgain[NPARTS - part - 1];
305
306 currGainHi = gainHi1 << MAX_LOGNPSAMPS;
307 gainDiffHi = (gainHi0 - gainHi1) << (MAX_LOGNPSAMPS - nplog2Tab[tabidx]);
308 currGainHi += gainDiffHi;
309
310 currGainLo = gainLo0 << MAX_LOGNPSAMPS;
311 gainDiffLo = (gainLo1 - gainLo0) << (MAX_LOGNPSAMPS - nplog2Tab[tabidx]);
312
313 /* interpolate the gain window: in = in * 2^(gain0) * 2^((gain1 - gain0)*i/npsamps) */
314 if (gainDiffLo || gainDiffHi) {
315 /* slow path - interpolated section of gain window */
316 for (; npsamps != 0; npsamps--) {
317 in = *buf--;
318 w0 = *wnd++;
319 w1 = *wnd++;
320
321 shiftLo = maxGain - (currGainLo >> MAX_LOGNPSAMPS) + shift[0];
322 oc = *over0++;
323 f0 = MULSHIFT32(w0, in);
324 f0 = MULSHIFT32(POW2NTAB[currGainLo & FRAC_MASK], f0) << 2;
325 *pcm0 = CLIPTOSHORT(((f0 >> shiftLo) + (oc >> shift[1]) + rndMask) >> fbitsPCM);
326 pcm0 += nChans;
327 currGainLo += gainDiffLo;
328
329 shiftHi = maxGain - (currGainHi >> MAX_LOGNPSAMPS) + shift[0];
330 oc = *over1--;
331 f1 = MULSHIFT32(w1, in);
332 f1 = MULSHIFT32(POW2NTAB[currGainHi & FRAC_MASK], f1) << 2;
333 *pcm1 = CLIPTOSHORT(((f1 >> shiftHi) + (oc >> shift[1]) + rndMask) >> fbitsPCM);
334 pcm1 -= nChans;
335 currGainHi += gainDiffHi;
336 }
337 } else {
338 /* fast path - constant section of gain window */
339 shiftLo = maxGain - gainLo0 + shift[0];
340 shiftHi = maxGain - gainHi1 + shift[0];
341 for (; npsamps != 0; npsamps--) {
342 in = *buf--;
343 w0 = *wnd++;
344 w1 = *wnd++;
345
346 oc = *over0++;
347 f0 = MULSHIFT32(w0, in);
348 *pcm0 = CLIPTOSHORT(((f0 >> shiftLo) + (oc >> shift[1]) + rndMask) >> fbitsPCM);
349 pcm0 += nChans;
350
351 oc = *over1--;
352 f1 = MULSHIFT32(w1, in);
353 *pcm1 = CLIPTOSHORT(((f1 >> shiftHi) + (oc >> shift[1]) + rndMask) >> fbitsPCM);
354 pcm1 -= nChans;
355 }
356 }
357 }
358}
359
360/**************************************************************************************
361 * Function: InterpolateOverlap
362 *
363 * Description: apply gain window to second half of current frame, and save for
364 * overlap-add next frame
365 *
366 * Inputs: table index (for transform size)
367 * pointer to initialized exgain array (NPARTS+1 gain values)
368 * second half of IMLT output for current frame (buf + nmlt/2),
369 * synthesis window has not yet been applied
370 * max exgain for second half of current frame
371 *
372 * Outputs: nSamples samples of gain windowed data for overlap
373 * (stored at buf + MAXNMLT)
374 *
375 * Return: none
376 **************************************************************************************/
377static void InterpolateOverlap(int tabidx, short *exgain, int *buf, int *overlap, short maxGain)
378{
379 int in, npsamps, part;
380 int shiftLo, shiftHi, currGainLo, currGainHi, gainDiffLo, gainDiffHi;
381 int gainLo0, gainLo1, gainHi0, gainHi1, w0, w1;
382 int *over0, *over1;
383 const int *wnd;
384
385 npsamps = npsampsTab[tabidx];
386 over0 = overlap;//buf + MAXNMLT;
387 over1 = over0 + NPARTS * npsamps - 1;
388 buf += (nmltTab[tabidx] >> 1);
389 wnd = window + windowOffset[tabidx];
390
391 gainLo1 = exgain[0];
392 gainHi0 = exgain[NPARTS];
393
394 for (part = 0; part < NPARTS / 2; part++) {
395 npsamps = npsampsTab[tabidx];
396
397 gainLo0 = gainLo1;
398 gainLo1 = exgain[part + 1];
399 gainHi1 = gainHi0;
400 gainHi0 = exgain[NPARTS - part - 1];
401
402 currGainHi = gainHi1 << MAX_LOGNPSAMPS;
403 gainDiffHi = (gainHi0 - gainHi1) << (MAX_LOGNPSAMPS - nplog2Tab[tabidx]);
404 currGainHi += gainDiffHi;
405
406 currGainLo = gainLo0 << MAX_LOGNPSAMPS;
407 gainDiffLo = (gainLo1 - gainLo0) << (MAX_LOGNPSAMPS - nplog2Tab[tabidx]);
408
409 /* interpolate the gain window: in = in * 2^(gain0) * 2^((gain1 - gain0)*i/npsamps) */
410 if (gainDiffLo || gainDiffHi) {
411 /* slow path - interpolated section of gain window */
412 for (; npsamps != 0; npsamps--) {
413 in = *buf++;
414 w0 = *wnd++;
415 w1 = *wnd++;
416
417 shiftLo = maxGain - (currGainLo >> MAX_LOGNPSAMPS);
418 w1 = MULSHIFT32(w1, in) >> shiftLo;
419 *over0++ = MULSHIFT32(POW2NTAB[currGainLo & FRAC_MASK], w1) << 2;
420 currGainLo += gainDiffLo;
421
422 shiftHi = maxGain - (currGainHi >> MAX_LOGNPSAMPS);
423 w0 = -MULSHIFT32(w0, in) >> shiftHi;
424 *over1-- = MULSHIFT32(POW2NTAB[currGainHi & FRAC_MASK], w0) << 2;
425 currGainHi += gainDiffHi;
426 }
427 } else {
428 /* fast path - constant section of gain window */
429 shiftLo = maxGain - gainLo0;
430 shiftHi = maxGain - gainHi1;
431 for (; npsamps != 0; npsamps--) {
432 in = *buf++;
433 w0 = *wnd++;
434 w1 = *wnd++;
435
436 *over0++ = MULSHIFT32(w1, in) >> shiftLo;
437 *over1-- = -MULSHIFT32(w0, in) >> shiftHi;
438 }
439 }
440 }
441}
442
443/* default fraction bits, not counting any extras from dequantizer */
444#define FBITS_OUT_IMLT (FBITS_OUT_DQ - FBITS_LOST_IMLT)
445
446/**************************************************************************************
447 * Function: DecWindowWithAttacks
448 *
449 * Description: apply synthesis window, perform gain windowing of current frame,
450 * do overlap-add, and produce one frame of decoded PCM
451 * (general case - either gain window has attacks or the default Q format
452 * is not being used)
453 *
454 * Inputs: table index (for transform size)
455 * input buffer (output of IMLT, before synthesis window)
456 * buffer for output PCM
457 * number of channels
458 * gain control structs for overlap and current frames
459 * number of extra integer bits present in current and overlap data
460 * (relative to the default format of FBITS_OUT_IMLT)
461 *
462 * Outputs: nSamples samples of 16-bit PCM output
463 *
464 * Return: none
465 *
466 * Notes: this processes one channel at a time, but skips every other sample in
467 * the output buffer (pcm) for stereo interleaving
468 **************************************************************************************/
469void DecWindowWithAttacks(int tabidx, int *buf, int *overlap, short *pcm, int nChans, GAINC *gainc0, GAINC *gainc1, short xbits[2])
470{
471 int i, s, fbitsPCM, fbitsOver;
472 short exgain[2 * NPARTS + 1];
473
474 fbitsOver = FBITS_OUT_IMLT - xbits[0] - gainc0->maxExGain;
475 CalcGainChanges(exgain, gainc0, gainc1);
476 fbitsPCM = FBITS_OUT_IMLT - xbits[1] - gainc0->maxExGain;
477
478 /* this is EXTREMELY unlikely (gain window so high that we would have negative fraction bits)
479 * so just do << and clip whole frame to 0 fraction bits
480 * can think of this as artifically adding fraction bits, or just doing gain window
481 * in 2 stages (first pass = window by constant power of 2, second pass = window
482 * by original gain window / constant power of 2)
483 * whole purpose is so Interpolate functions can be hard-coded to >> only (fast)
484 */
485 s = 0;
486 if (fbitsOver < 0 || fbitsPCM < 0) {
487 s = MAX(-fbitsOver, -fbitsPCM);
488 for (i = 0; i < npsampsTab[tabidx]*NPARTS; i++) {
489 CLIP_2N_SHIFT(buf[i], s);
490 }
491 for (i = 0; i < npsampsTab[tabidx]*NPARTS; i++) {
492 CLIP_2N_SHIFT(overlap[i], s);
493 }
494 //for (i = MAXNSAMP; i < MAXNSAMP + npsampsTab[tabidx]*NPARTS; i++)
495 // CLIP_2N_SHIFT(buf[i], s);
496 fbitsOver += s;
497 fbitsPCM += s;
498 }
499
500 InterpolatePCM(tabidx, exgain, buf, overlap, gainc0->maxExGain, pcm, nChans, fbitsPCM, fbitsOver);
501 InterpolateOverlap(tabidx, exgain + NPARTS, buf, overlap, gainc1->maxExGain);
502
503 /* undo extreme gain window scaling */
504 if (s) {
505 for (i = 0; i < npsampsTab[tabidx]*NPARTS; i++) {
506 buf[i] >>= s;
507 }
508 for (i = 0; i < npsampsTab[tabidx]*NPARTS; i++) {
509 overlap[i] >>= s;
510 }
511 //for (i = MAXNSAMP; i < MAXNSAMP + npsampsTab[tabidx]*NPARTS; i++)
512 // buf[i] >>= s;
513 }
514
515 return;
516}
517
518/**************************************************************************************
519 * Function: DecWindowNoAttacks
520 *
521 * Description: apply synthesis window, perform gain windowing of current frame,
522 * do overlap-add, and produce one frame of decoded PCM
523 * (fast case - no gain window attacks and the data is in the default
524 * Q format with FBITS_OUT_IMLT fraction bits in input)
525 *
526 * Inputs: table index (for transform size)
527 * input buffer (output of IMLT, before synthesis window)
528 * pcm buffer
529 * number of channels
530 *
531 * Outputs: nSamples samples of 16-bit PCM output
532 *
533 * Return: none
534 *
535 * Notes: this processes one channel at a time, but skips every other sample in
536 * the output buffer (pcm) for stereo interleaving
537 * this should fit in registers on ARM - make sure compiler does this
538 * correctly!
539 **************************************************************************************/
540void DecWindowNoAttacks(int tabidx, int *buf0, int *overlap, short *pcm0, int nChans)
541{
542 int nmlt, nmltHalf;
543 int in, oc, w0, w1, f0, f1;
544 int *buf1, *over0, *over1;
545 short *pcm1;
546 const int *wnd;
547
548 nmlt = nmltTab[tabidx];
549 nmltHalf = nmlt >> 1;
550
551 over0 = overlap;//buf0 + MAXNMLT;
552 over1 = over0 + nmlt - 1;
553
554 buf0 += nmltHalf;
555 buf1 = buf0 - 1;
556 wnd = window + windowOffset[tabidx];
557 pcm1 = pcm0 + (nmlt - 1) * nChans;
558
559 for (; nmltHalf != 0; nmltHalf--) {
560 /* load window coefficients */
561 w0 = *wnd++;
562 w1 = *wnd++;
563
564 /* apply window to generate first N samples */
565 in = *buf1--;
566 f0 = MULSHIFT32(w0, in);
567 f1 = MULSHIFT32(w1, in);
568
569 /* overlap-add with second N samples from last frame */
570 oc = *over0;
571 *pcm0 = CLIPTOSHORT((f0 + oc + (1 << (FBITS_OUT_IMLT - 1))) >> FBITS_OUT_IMLT);
572 pcm0 += nChans;
573 oc = *over1;
574 *pcm1 = CLIPTOSHORT((f1 + oc + (1 << (FBITS_OUT_IMLT - 1))) >> FBITS_OUT_IMLT);
575 pcm1 -= nChans;
576
577 /* apply window to generate second nmlt samples, save for overlap with next frame */
578 in = *buf0++;
579 *over0++ = MULSHIFT32(w1, in);
580 *over1-- = -MULSHIFT32(w0, in);
581 }
582
583 return;
584}
585