blob: 54ef4e8431c2bb7ed2a29875683c99e6d4efe87f
1 | /* ***** BEGIN LICENSE BLOCK ***** |
2 | * Source last modified: $Id: stproc.c,v 1.3 2005/05/24 16:01:55 albertofloyd Exp $ |
3 | * |
4 | * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved. |
5 | * |
6 | * The contents of this file, and the files included with this file, |
7 | * are subject to the current version of the RealNetworks Public |
8 | * Source License (the "RPSL") available at |
9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed |
10 | * the file under the current version of the RealNetworks Community |
11 | * Source License (the "RCSL") available at |
12 | * http://www.helixcommunity.org/content/rcsl, in which case the RCSL |
13 | * will apply. You may also obtain the license terms directly from |
14 | * RealNetworks. You may not use this file except in compliance with |
15 | * the RPSL or, if you have a valid RCSL with RealNetworks applicable |
16 | * to this file, the RCSL. Please see the applicable RPSL or RCSL for |
17 | * the rights, obligations and limitations governing use of the |
18 | * contents of the file. |
19 | * |
20 | * This file is part of the Helix DNA Technology. RealNetworks is the |
21 | * developer of the Original Code and owns the copyrights in the |
22 | * portions it created. |
23 | * |
24 | * This file, and the files included with this file, is distributed |
25 | * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY |
26 | * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS |
27 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES |
28 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET |
29 | * ENJOYMENT OR NON-INFRINGEMENT. |
30 | * |
31 | * Technology Compatibility Kit Test Suite(s) Location: |
32 | * http://www.helixcommunity.org/content/tck |
33 | * |
34 | * Contributor(s): |
35 | * |
36 | * ***** END LICENSE BLOCK ***** */ |
37 | |
38 | /************************************************************************************** |
39 | * Fixed-point HE-AAC decoder |
40 | * Jon Recker (jrecker@real.com) |
41 | * February 2005 |
42 | * |
43 | * stproc.c - mid-side and intensity stereo processing |
44 | **************************************************************************************/ |
45 | |
46 | #include "coder.h" |
47 | #include "assembly.h" |
48 | |
49 | /* pow14[0][i] = -pow(2, i/4.0) |
50 | * pow14[1][i] = +pow(2, i/4.0) |
51 | * |
52 | * i = [0,1,2,3] |
53 | * format = Q30 |
54 | */ |
55 | static const int pow14[2][4] = { |
56 | { 0xc0000000, 0xb3e407d7, 0xa57d8666, 0x945d819b }, |
57 | { 0x40000000, 0x4c1bf829, 0x5a82799a, 0x6ba27e65 } |
58 | }; |
59 | |
60 | /************************************************************************************** |
61 | * Function: StereoProcessGroup |
62 | * |
63 | * Description: apply mid-side and intensity stereo to group of transform coefficients |
64 | * |
65 | * Inputs: dequantized transform coefficients for both channels |
66 | * pointer to appropriate scalefactor band table |
67 | * mid-side mask enabled flag |
68 | * buffer with mid-side mask (one bit for each scalefactor band) |
69 | * bit offset into mid-side mask buffer |
70 | * max coded scalefactor band |
71 | * buffer of codebook indices for right channel |
72 | * buffer of scalefactors for right channel, range = [0, 256] |
73 | * |
74 | * Outputs: updated transform coefficients in Q(FBITS_OUT_DQ_OFF) |
75 | * updated minimum guard bit count for both channels |
76 | * |
77 | * Return: none |
78 | * |
79 | * Notes: assume no guard bits in input |
80 | * gains 0 int bits |
81 | **************************************************************************************/ |
82 | static void StereoProcessGroup(int *coefL, int *coefR, const short *sfbTab, |
83 | int msMaskPres, unsigned char *msMaskPtr, int msMaskOffset, int maxSFB, |
84 | unsigned char *cbRight, short *sfRight, int *gbCurrent) |
85 | { |
86 | int sfb, width, cbIdx, sf, cl, cr, scalef, scalei; |
87 | int gbMaskL, gbMaskR; |
88 | unsigned char msMask; |
89 | |
90 | msMask = (*msMaskPtr++) >> msMaskOffset; |
91 | gbMaskL = 0; |
92 | gbMaskR = 0; |
93 | |
94 | for (sfb = 0; sfb < maxSFB; sfb++) { |
95 | width = sfbTab[sfb + 1] - sfbTab[sfb]; /* assume >= 0 (see sfBandTabLong/sfBandTabShort) */ |
96 | cbIdx = cbRight[sfb]; |
97 | |
98 | if (cbIdx == 14 || cbIdx == 15) { |
99 | /* intensity stereo */ |
100 | if (msMaskPres == 1 && (msMask & 0x01)) { |
101 | cbIdx ^= 0x01; /* invert_intensity(): 14 becomes 15, or 15 becomes 14 */ |
102 | } |
103 | sf = -sfRight[sfb]; /* negative since we use identity 0.5^(x) = 2^(-x) (see spec) */ |
104 | cbIdx &= 0x01; /* choose - or + scale factor */ |
105 | scalef = pow14[cbIdx][sf & 0x03]; |
106 | scalei = (sf >> 2) + 2; /* +2 to compensate for scalef = Q30 */ |
107 | |
108 | if (scalei > 0) { |
109 | if (scalei > 30) { |
110 | scalei = 30; |
111 | } |
112 | do { |
113 | cr = MULSHIFT32(*coefL++, scalef); |
114 | CLIP_2N(cr, 31 - scalei); |
115 | cr <<= scalei; |
116 | gbMaskR |= FASTABS(cr); |
117 | *coefR++ = cr; |
118 | } while (--width); |
119 | } else { |
120 | scalei = -scalei; |
121 | if (scalei > 31) { |
122 | scalei = 31; |
123 | } |
124 | do { |
125 | cr = MULSHIFT32(*coefL++, scalef) >> scalei; |
126 | gbMaskR |= FASTABS(cr); |
127 | *coefR++ = cr; |
128 | } while (--width); |
129 | } |
130 | } else if (cbIdx != 13 && ((msMaskPres == 1 && (msMask & 0x01)) || msMaskPres == 2)) { |
131 | /* mid-side stereo (assumes no GB in inputs) */ |
132 | do { |
133 | cl = *coefL; |
134 | cr = *coefR; |
135 | |
136 | if ((FASTABS(cl) | FASTABS(cr)) >> 30) { |
137 | /* avoid overflow (rare) */ |
138 | cl >>= 1; |
139 | sf = cl + (cr >> 1); |
140 | CLIP_2N(sf, 30); |
141 | sf <<= 1; |
142 | cl = cl - (cr >> 1); |
143 | CLIP_2N(cl, 30); |
144 | cl <<= 1; |
145 | } else { |
146 | /* usual case */ |
147 | sf = cl + cr; |
148 | cl -= cr; |
149 | } |
150 | |
151 | *coefL++ = sf; |
152 | gbMaskL |= FASTABS(sf); |
153 | *coefR++ = cl; |
154 | gbMaskR |= FASTABS(cl); |
155 | } while (--width); |
156 | |
157 | } else { |
158 | /* nothing to do */ |
159 | coefL += width; |
160 | coefR += width; |
161 | } |
162 | |
163 | /* get next mask bit (should be branchless on ARM) */ |
164 | msMask >>= 1; |
165 | if (++msMaskOffset == 8) { |
166 | msMask = *msMaskPtr++; |
167 | msMaskOffset = 0; |
168 | } |
169 | } |
170 | |
171 | cl = CLZ(gbMaskL) - 1; |
172 | if (gbCurrent[0] > cl) { |
173 | gbCurrent[0] = cl; |
174 | } |
175 | |
176 | cr = CLZ(gbMaskR) - 1; |
177 | if (gbCurrent[1] > cr) { |
178 | gbCurrent[1] = cr; |
179 | } |
180 | |
181 | return; |
182 | } |
183 | |
184 | /************************************************************************************** |
185 | * Function: StereoProcess |
186 | * |
187 | * Description: apply mid-side and intensity stereo, if enabled |
188 | * |
189 | * Inputs: valid AACDecInfo struct (including dequantized transform coefficients) |
190 | * |
191 | * Outputs: updated transform coefficients in Q(FBITS_OUT_DQ_OFF) |
192 | * updated minimum guard bit count for both channels |
193 | * |
194 | * Return: 0 if successful, -1 if error |
195 | **************************************************************************************/ |
196 | int StereoProcess(AACDecInfo *aacDecInfo) |
197 | { |
198 | PSInfoBase *psi; |
199 | ICSInfo *icsInfo; |
200 | int gp, win, nSamps, msMaskOffset; |
201 | int *coefL, *coefR; |
202 | unsigned char *msMaskPtr; |
203 | const short *sfbTab; |
204 | |
205 | /* validate pointers */ |
206 | if (!aacDecInfo || !aacDecInfo->psInfoBase) { |
207 | return -1; |
208 | } |
209 | psi = (PSInfoBase *)(aacDecInfo->psInfoBase); |
210 | |
211 | /* mid-side and intensity stereo require common_window == 1 (see MPEG4 spec, Correction 2, 2004) */ |
212 | if (psi->commonWin != 1 || aacDecInfo->currBlockID != AAC_ID_CPE) { |
213 | return 0; |
214 | } |
215 | |
216 | /* nothing to do */ |
217 | if (!psi->msMaskPresent && !psi->intensityUsed[1]) { |
218 | return 0; |
219 | } |
220 | |
221 | icsInfo = &(psi->icsInfo[0]); |
222 | if (icsInfo->winSequence == 2) { |
223 | sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx]; |
224 | nSamps = NSAMPS_SHORT; |
225 | } else { |
226 | sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx]; |
227 | nSamps = NSAMPS_LONG; |
228 | } |
229 | coefL = psi->coef[0]; |
230 | coefR = psi->coef[1]; |
231 | |
232 | /* do fused mid-side/intensity processing for each block (one long or eight short) */ |
233 | msMaskOffset = 0; |
234 | msMaskPtr = psi->msMaskBits; |
235 | for (gp = 0; gp < icsInfo->numWinGroup; gp++) { |
236 | for (win = 0; win < icsInfo->winGroupLen[gp]; win++) { |
237 | StereoProcessGroup(coefL, coefR, sfbTab, psi->msMaskPresent, |
238 | msMaskPtr, msMaskOffset, icsInfo->maxSFB, psi->sfbCodeBook[1] + gp * icsInfo->maxSFB, |
239 | psi->scaleFactors[1] + gp * icsInfo->maxSFB, psi->gbCurrent); |
240 | coefL += nSamps; |
241 | coefR += nSamps; |
242 | } |
243 | /* we use one bit per sfb, so there are maxSFB bits for each window group */ |
244 | msMaskPtr += (msMaskOffset + icsInfo->maxSFB) >> 3; |
245 | msMaskOffset = (msMaskOffset + icsInfo->maxSFB) & 0x07; |
246 | } |
247 | |
248 | ASSERT(coefL == psi->coef[0] + 1024); |
249 | ASSERT(coefR == psi->coef[1] + 1024); |
250 | |
251 | return 0; |
252 | } |
253 |