Home | History | Annotate | Download | only in src
      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 *****************************************************************************/
     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 *****************************************************************************/
     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 *****************************************************************************/
    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   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 *****************************************************************************/
    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 *****************************************************************************/
    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 *****************************************************************************/
    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   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