1 /*
2 ** Copyright 2003-2010, VisualOn, Inc.
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16 /*******************************************************************************
17 File: quantize.c
18
19 Content: quantization functions
20
21 *******************************************************************************/
22
23 #include "typedef.h"
24 #include "basic_op.h"
25 #include "oper_32b.h"
26 #include "quantize.h"
27 #include "aac_rom.h"
28
29 #define MANT_DIGITS 9
30 #define MANT_SIZE (1<<MANT_DIGITS)
31
32 static const Word32 XROUND = 0x33e425af; /* final rounding constant (-0.0946f+ 0.5f) */
33
34
35 /*****************************************************************************
36 *
37 * function name:pow34
38 * description: calculate $x^{\frac{3}{4}}, for 0.5 < x < 1.0$.
39 *
40 *****************************************************************************/
pow34(Word32 x)41 __inline Word32 pow34(Word32 x)
42 {
43 /* index table using MANT_DIGITS bits, but mask out the sign bit and the MSB
44 which is always one */
45 return mTab_3_4[(x >> (INT_BITS-2-MANT_DIGITS)) & (MANT_SIZE-1)];
46 }
47
48
49 /*****************************************************************************
50 *
51 * function name:quantizeSingleLine
52 * description: quantizes spectrum
53 * quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain)
54 *
55 *****************************************************************************/
quantizeSingleLine(const Word16 gain,const Word32 absSpectrum)56 static Word16 quantizeSingleLine(const Word16 gain, const Word32 absSpectrum)
57 {
58 Word32 e, minusFinalExp, finalShift;
59 Word32 x;
60 Word16 qua = 0;
61
62
63 if (absSpectrum) {
64 e = norm_l(absSpectrum);
65 x = pow34(absSpectrum << e);
66
67 /* calculate the final fractional exponent times 16 (was 3*(4*e + gain) + (INT_BITS-1)*16) */
68 minusFinalExp = (e << 2) + gain;
69 minusFinalExp = (minusFinalExp << 1) + minusFinalExp;
70 minusFinalExp = minusFinalExp + ((INT_BITS-1) << 4);
71
72 /* separate the exponent into a shift, and a multiply */
73 finalShift = minusFinalExp >> 4;
74
75 if (finalShift < INT_BITS) {
76 x = L_mpy_wx(x, pow2tominusNover16[minusFinalExp & 15]);
77
78 x += XROUND >> (INT_BITS - finalShift);
79
80 /* shift and quantize */
81 finalShift--;
82
83 if(finalShift >= 0)
84 x >>= finalShift;
85 else
86 x <<= (-finalShift);
87
88 qua = saturate(x);
89 }
90 }
91
92 return qua;
93 }
94
95 /*****************************************************************************
96 *
97 * function name:quantizeLines
98 * description: quantizes spectrum lines
99 * quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain)
100 * input: global gain, number of lines to process, spectral data
101 * output: quantized spectrum
102 *
103 *****************************************************************************/
quantizeLines(const Word16 gain,const Word16 noOfLines,const Word32 * mdctSpectrum,Word16 * quaSpectrum)104 static void quantizeLines(const Word16 gain,
105 const Word16 noOfLines,
106 const Word32 *mdctSpectrum,
107 Word16 *quaSpectrum)
108 {
109 Word32 line;
110 Word32 m = gain&3;
111 Word32 g = (gain >> 2) + 4;
112 Word32 mdctSpeL;
113 const Word16 *pquat;
114 /* gain&3 */
115
116 pquat = quantBorders[m];
117
118 g += 16;
119
120 if(g >= 0)
121 {
122 for (line=0; line<noOfLines; line++) {
123 Word32 qua;
124 qua = 0;
125
126 mdctSpeL = mdctSpectrum[line];
127
128 if (mdctSpeL) {
129 Word32 sa;
130 Word32 saShft;
131
132 sa = L_abs(mdctSpeL);
133 //saShft = L_shr(sa, 16 + g);
134 saShft = sa >> g;
135
136 if (saShft > pquat[0]) {
137
138 if (saShft < pquat[1]) {
139
140 qua = mdctSpeL>0 ? 1 : -1;
141 }
142 else {
143
144 if (saShft < pquat[2]) {
145
146 qua = mdctSpeL>0 ? 2 : -2;
147 }
148 else {
149
150 if (saShft < pquat[3]) {
151
152 qua = mdctSpeL>0 ? 3 : -3;
153 }
154 else {
155 qua = quantizeSingleLine(gain, sa);
156 /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */
157
158 if (mdctSpeL < 0)
159 qua = -qua;
160 }
161 }
162 }
163 }
164 }
165 quaSpectrum[line] = qua ;
166 }
167 }
168 else
169 {
170 for (line=0; line<noOfLines; line++) {
171 Word32 qua;
172 qua = 0;
173
174 mdctSpeL = mdctSpectrum[line];
175
176 if (mdctSpeL) {
177 Word32 sa;
178 Word32 saShft;
179
180 sa = L_abs(mdctSpeL);
181 saShft = sa << g;
182
183 if (saShft > pquat[0]) {
184
185 if (saShft < pquat[1]) {
186
187 qua = mdctSpeL>0 ? 1 : -1;
188 }
189 else {
190
191 if (saShft < pquat[2]) {
192
193 qua = mdctSpeL>0 ? 2 : -2;
194 }
195 else {
196
197 if (saShft < pquat[3]) {
198
199 qua = mdctSpeL>0 ? 3 : -3;
200 }
201 else {
202 qua = quantizeSingleLine(gain, sa);
203 /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */
204
205 if (mdctSpeL < 0)
206 qua = -qua;
207 }
208 }
209 }
210 }
211 }
212 quaSpectrum[line] = qua ;
213 }
214 }
215
216 }
217
218
219 /*****************************************************************************
220 *
221 * function name:iquantizeLines
222 * description: iquantizes spectrum lines without sign
223 * mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain)
224 * input: global gain, number of lines to process,quantized spectrum
225 * output: spectral data
226 *
227 *****************************************************************************/
iquantizeLines(const Word16 gain,const Word16 noOfLines,const Word16 * quantSpectrum,Word32 * mdctSpectrum)228 static void iquantizeLines(const Word16 gain,
229 const Word16 noOfLines,
230 const Word16 *quantSpectrum,
231 Word32 *mdctSpectrum)
232 {
233 Word32 iquantizermod;
234 Word32 iquantizershift;
235 Word32 line;
236
237 iquantizermod = gain & 3;
238 iquantizershift = gain >> 2;
239
240 for (line=0; line<noOfLines; line++) {
241
242 if( quantSpectrum[line] != 0 ) {
243 Word32 accu;
244 Word32 ex;
245 Word32 tabIndex;
246 Word32 specExp;
247 Word32 s,t;
248
249 accu = quantSpectrum[line];
250
251 ex = norm_l(accu);
252 accu = accu << ex;
253 specExp = INT_BITS-1 - ex;
254
255 tabIndex = (accu >> (INT_BITS-2-MANT_DIGITS)) & (~MANT_SIZE);
256
257 /* calculate "mantissa" ^4/3 */
258 s = mTab_4_3[tabIndex];
259
260 /* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */
261 t = specExpMantTableComb_enc[iquantizermod][specExp];
262
263 /* multiply "mantissa" ^4/3 with exponent multiplier */
264 accu = MULHIGH(s, t);
265
266 /* get approperiate exponent shifter */
267 specExp = specExpTableComb_enc[iquantizermod][specExp];
268
269 specExp += iquantizershift + 1;
270 if(specExp >= 0)
271 mdctSpectrum[line] = accu << specExp;
272 else
273 mdctSpectrum[line] = accu >> (-specExp);
274 }
275 else {
276 mdctSpectrum[line] = 0;
277 }
278 }
279 }
280
281 /*****************************************************************************
282 *
283 * function name: QuantizeSpectrum
284 * description: quantizes the entire spectrum
285 * returns:
286 * input: number of scalefactor bands to be quantized, ...
287 * output: quantized spectrum
288 *
289 *****************************************************************************/
QuantizeSpectrum(Word16 sfbCnt,Word16 maxSfbPerGroup,Word16 sfbPerGroup,Word16 * sfbOffset,Word32 * mdctSpectrum,Word16 globalGain,Word16 * scalefactors,Word16 * quantizedSpectrum)290 void QuantizeSpectrum(Word16 sfbCnt,
291 Word16 maxSfbPerGroup,
292 Word16 sfbPerGroup,
293 Word16 *sfbOffset,
294 Word32 *mdctSpectrum,
295 Word16 globalGain,
296 Word16 *scalefactors,
297 Word16 *quantizedSpectrum)
298 {
299 Word32 sfbOffs, sfb;
300
301 for(sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup) {
302 Word32 sfbNext ;
303 for (sfb = 0; sfb < maxSfbPerGroup; sfb = sfbNext) {
304 Word16 scalefactor = scalefactors[sfbOffs+sfb];
305 /* coalesce sfbs with the same scalefactor */
306 for (sfbNext = sfb+1;
307 sfbNext < maxSfbPerGroup && scalefactor == scalefactors[sfbOffs+sfbNext];
308 sfbNext++) ;
309
310 quantizeLines(globalGain - scalefactor,
311 sfbOffset[sfbOffs+sfbNext] - sfbOffset[sfbOffs+sfb],
312 mdctSpectrum + sfbOffset[sfbOffs+sfb],
313 quantizedSpectrum + sfbOffset[sfbOffs+sfb]);
314 }
315 }
316 }
317
318
319 /*****************************************************************************
320 *
321 * function name:calcSfbDist
322 * description: quantizes and requantizes lines to calculate distortion
323 * input: number of lines to be quantized, ...
324 * output: distortion
325 *
326 *****************************************************************************/
calcSfbDist(const Word32 * spec,Word16 sfbWidth,Word16 gain)327 Word32 calcSfbDist(const Word32 *spec,
328 Word16 sfbWidth,
329 Word16 gain)
330 {
331 Word32 line;
332 Word32 dist;
333 Word32 m = gain&3;
334 Word32 g = (gain >> 2) + 4;
335 Word32 g2 = (g << 1) + 1;
336 const Word16 *pquat, *repquat;
337 /* gain&3 */
338
339 pquat = quantBorders[m];
340 repquat = quantRecon[m];
341
342 dist = 0;
343 g += 16;
344 if(g2 < 0 && g >= 0)
345 {
346 g2 = -g2;
347 for(line=0; line<sfbWidth; line++) {
348 if (spec[line]) {
349 Word32 diff;
350 Word32 distSingle;
351 Word32 sa;
352 Word32 saShft;
353 sa = L_abs(spec[line]);
354 //saShft = round16(L_shr(sa, g));
355 //saShft = L_shr(sa, 16+g);
356 saShft = sa >> g;
357
358 if (saShft < pquat[0]) {
359 distSingle = (saShft * saShft) >> g2;
360 }
361 else {
362
363 if (saShft < pquat[1]) {
364 diff = saShft - repquat[0];
365 distSingle = (diff * diff) >> g2;
366 }
367 else {
368
369 if (saShft < pquat[2]) {
370 diff = saShft - repquat[1];
371 distSingle = (diff * diff) >> g2;
372 }
373 else {
374
375 if (saShft < pquat[3]) {
376 diff = saShft - repquat[2];
377 distSingle = (diff * diff) >> g2;
378 }
379 else {
380 Word16 qua = quantizeSingleLine(gain, sa);
381 Word32 iqval, diff32;
382 /* now that we have quantized x, re-quantize it. */
383 iquantizeLines(gain, 1, &qua, &iqval);
384 diff32 = sa - iqval;
385 distSingle = fixmul(diff32, diff32);
386 }
387 }
388 }
389 }
390
391 dist = L_add(dist, distSingle);
392 }
393 }
394 }
395 else
396 {
397 for(line=0; line<sfbWidth; line++) {
398 if (spec[line]) {
399 Word32 diff;
400 Word32 distSingle;
401 Word32 sa;
402 Word32 saShft;
403 sa = L_abs(spec[line]);
404 //saShft = round16(L_shr(sa, g));
405 saShft = L_shr(sa, g);
406
407 if (saShft < pquat[0]) {
408 distSingle = L_shl((saShft * saShft), g2);
409 }
410 else {
411
412 if (saShft < pquat[1]) {
413 diff = saShft - repquat[0];
414 distSingle = L_shl((diff * diff), g2);
415 }
416 else {
417
418 if (saShft < pquat[2]) {
419 diff = saShft - repquat[1];
420 distSingle = L_shl((diff * diff), g2);
421 }
422 else {
423
424 if (saShft < pquat[3]) {
425 diff = saShft - repquat[2];
426 distSingle = L_shl((diff * diff), g2);
427 }
428 else {
429 Word16 qua = quantizeSingleLine(gain, sa);
430 Word32 iqval, diff32;
431 /* now that we have quantized x, re-quantize it. */
432 iquantizeLines(gain, 1, &qua, &iqval);
433 diff32 = sa - iqval;
434 distSingle = fixmul(diff32, diff32);
435 }
436 }
437 }
438 }
439 dist = L_add(dist, distSingle);
440 }
441 }
442 }
443
444 return dist;
445 }
446