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