• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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