| /* |
| ** Copyright 2003-2010, VisualOn, Inc. |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| /******************************************************************************* |
| File: quantize.c |
| |
| Content: quantization functions |
| |
| *******************************************************************************/ |
| |
| #include "typedef.h" |
| #include "basic_op.h" |
| #include "oper_32b.h" |
| #include "quantize.h" |
| #include "aac_rom.h" |
| |
| #define MANT_DIGITS 9 |
| #define MANT_SIZE (1<<MANT_DIGITS) |
| |
| static const Word32 XROUND = 0x33e425af; /* final rounding constant (-0.0946f+ 0.5f) */ |
| |
| |
| /***************************************************************************** |
| * |
| * function name:pow34 |
| * description: calculate $x^{\frac{3}{4}}, for 0.5 < x < 1.0$. |
| * |
| *****************************************************************************/ |
| __inline Word32 pow34(Word32 x) |
| { |
| /* index table using MANT_DIGITS bits, but mask out the sign bit and the MSB |
| which is always one */ |
| return mTab_3_4[(x >> (INT_BITS-2-MANT_DIGITS)) & (MANT_SIZE-1)]; |
| } |
| |
| |
| /***************************************************************************** |
| * |
| * function name:quantizeSingleLine |
| * description: quantizes spectrum |
| * quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain) |
| * |
| *****************************************************************************/ |
| static Word16 quantizeSingleLine(const Word16 gain, const Word32 absSpectrum) |
| { |
| Word32 e, minusFinalExp, finalShift; |
| Word32 x; |
| Word16 qua = 0; |
| |
| |
| if (absSpectrum) { |
| e = norm_l(absSpectrum); |
| x = pow34(absSpectrum << e); |
| |
| /* calculate the final fractional exponent times 16 (was 3*(4*e + gain) + (INT_BITS-1)*16) */ |
| minusFinalExp = (e << 2) + gain; |
| minusFinalExp = (minusFinalExp << 1) + minusFinalExp; |
| minusFinalExp = minusFinalExp + ((INT_BITS-1) << 4); |
| |
| /* separate the exponent into a shift, and a multiply */ |
| finalShift = minusFinalExp >> 4; |
| |
| if (finalShift < INT_BITS) { |
| x = L_mpy_wx(x, pow2tominusNover16[minusFinalExp & 15]); |
| |
| x += XROUND >> (INT_BITS - finalShift); |
| |
| /* shift and quantize */ |
| finalShift--; |
| |
| if(finalShift >= 0) |
| x >>= finalShift; |
| else |
| x <<= (-finalShift); |
| |
| qua = saturate(x); |
| } |
| } |
| |
| return qua; |
| } |
| |
| /***************************************************************************** |
| * |
| * function name:quantizeLines |
| * description: quantizes spectrum lines |
| * quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain) |
| * input: global gain, number of lines to process, spectral data |
| * output: quantized spectrum |
| * |
| *****************************************************************************/ |
| static void quantizeLines(const Word16 gain, |
| const Word16 noOfLines, |
| const Word32 *mdctSpectrum, |
| Word16 *quaSpectrum) |
| { |
| Word32 line; |
| Word32 m = gain&3; |
| Word32 g = (gain >> 2) + 4; |
| Word32 mdctSpeL; |
| Word16 *pquat; |
| /* gain&3 */ |
| |
| pquat = quantBorders[m]; |
| |
| g += 16; |
| |
| if(g >= 0) |
| { |
| for (line=0; line<noOfLines; line++) { |
| Word32 qua; |
| qua = 0; |
| |
| mdctSpeL = mdctSpectrum[line]; |
| |
| if (mdctSpeL) { |
| Word32 sa; |
| Word32 saShft; |
| |
| sa = L_abs(mdctSpeL); |
| //saShft = L_shr(sa, 16 + g); |
| saShft = sa >> g; |
| |
| if (saShft > pquat[0]) { |
| |
| if (saShft < pquat[1]) { |
| |
| qua = mdctSpeL>0 ? 1 : -1; |
| } |
| else { |
| |
| if (saShft < pquat[2]) { |
| |
| qua = mdctSpeL>0 ? 2 : -2; |
| } |
| else { |
| |
| if (saShft < pquat[3]) { |
| |
| qua = mdctSpeL>0 ? 3 : -3; |
| } |
| else { |
| qua = quantizeSingleLine(gain, sa); |
| /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */ |
| |
| if (mdctSpeL < 0) |
| qua = -qua; |
| } |
| } |
| } |
| } |
| } |
| quaSpectrum[line] = qua ; |
| } |
| } |
| else |
| { |
| for (line=0; line<noOfLines; line++) { |
| Word32 qua; |
| qua = 0; |
| |
| mdctSpeL = mdctSpectrum[line]; |
| |
| if (mdctSpeL) { |
| Word32 sa; |
| Word32 saShft; |
| |
| sa = L_abs(mdctSpeL); |
| saShft = sa << g; |
| |
| if (saShft > pquat[0]) { |
| |
| if (saShft < pquat[1]) { |
| |
| qua = mdctSpeL>0 ? 1 : -1; |
| } |
| else { |
| |
| if (saShft < pquat[2]) { |
| |
| qua = mdctSpeL>0 ? 2 : -2; |
| } |
| else { |
| |
| if (saShft < pquat[3]) { |
| |
| qua = mdctSpeL>0 ? 3 : -3; |
| } |
| else { |
| qua = quantizeSingleLine(gain, sa); |
| /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */ |
| |
| if (mdctSpeL < 0) |
| qua = -qua; |
| } |
| } |
| } |
| } |
| } |
| quaSpectrum[line] = qua ; |
| } |
| } |
| |
| } |
| |
| |
| /***************************************************************************** |
| * |
| * function name:iquantizeLines |
| * description: iquantizes spectrum lines without sign |
| * mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain) |
| * input: global gain, number of lines to process,quantized spectrum |
| * output: spectral data |
| * |
| *****************************************************************************/ |
| static void iquantizeLines(const Word16 gain, |
| const Word16 noOfLines, |
| const Word16 *quantSpectrum, |
| Word32 *mdctSpectrum) |
| { |
| Word32 iquantizermod; |
| Word32 iquantizershift; |
| Word32 line; |
| |
| iquantizermod = gain & 3; |
| iquantizershift = gain >> 2; |
| |
| for (line=0; line<noOfLines; line++) { |
| |
| if( quantSpectrum[line] != 0 ) { |
| Word32 accu; |
| Word32 ex; |
| Word32 tabIndex; |
| Word32 specExp; |
| Word32 s,t; |
| |
| accu = quantSpectrum[line]; |
| |
| ex = norm_l(accu); |
| accu = accu << ex; |
| specExp = INT_BITS-1 - ex; |
| |
| tabIndex = (accu >> (INT_BITS-2-MANT_DIGITS)) & (~MANT_SIZE); |
| |
| /* calculate "mantissa" ^4/3 */ |
| s = mTab_4_3[tabIndex]; |
| |
| /* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */ |
| t = specExpMantTableComb_enc[iquantizermod][specExp]; |
| |
| /* multiply "mantissa" ^4/3 with exponent multiplier */ |
| accu = MULHIGH(s, t); |
| |
| /* get approperiate exponent shifter */ |
| specExp = specExpTableComb_enc[iquantizermod][specExp]; |
| |
| specExp += iquantizershift + 1; |
| if(specExp >= 0) |
| mdctSpectrum[line] = accu << specExp; |
| else |
| mdctSpectrum[line] = accu >> (-specExp); |
| } |
| else { |
| mdctSpectrum[line] = 0; |
| } |
| } |
| } |
| |
| /***************************************************************************** |
| * |
| * function name: QuantizeSpectrum |
| * description: quantizes the entire spectrum |
| * returns: |
| * input: number of scalefactor bands to be quantized, ... |
| * output: quantized spectrum |
| * |
| *****************************************************************************/ |
| void QuantizeSpectrum(Word16 sfbCnt, |
| Word16 maxSfbPerGroup, |
| Word16 sfbPerGroup, |
| Word16 *sfbOffset, |
| Word32 *mdctSpectrum, |
| Word16 globalGain, |
| Word16 *scalefactors, |
| Word16 *quantizedSpectrum) |
| { |
| Word32 sfbOffs, sfb; |
| |
| for(sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup) { |
| Word32 sfbNext ; |
| for (sfb = 0; sfb < maxSfbPerGroup; sfb = sfbNext) { |
| Word16 scalefactor = scalefactors[sfbOffs+sfb]; |
| /* coalesce sfbs with the same scalefactor */ |
| for (sfbNext = sfb+1; |
| sfbNext < maxSfbPerGroup && scalefactor == scalefactors[sfbOffs+sfbNext]; |
| sfbNext++) ; |
| |
| quantizeLines(globalGain - scalefactor, |
| sfbOffset[sfbOffs+sfbNext] - sfbOffset[sfbOffs+sfb], |
| mdctSpectrum + sfbOffset[sfbOffs+sfb], |
| quantizedSpectrum + sfbOffset[sfbOffs+sfb]); |
| } |
| } |
| } |
| |
| |
| /***************************************************************************** |
| * |
| * function name:calcSfbDist |
| * description: quantizes and requantizes lines to calculate distortion |
| * input: number of lines to be quantized, ... |
| * output: distortion |
| * |
| *****************************************************************************/ |
| Word32 calcSfbDist(const Word32 *spec, |
| Word16 sfbWidth, |
| Word16 gain) |
| { |
| Word32 line; |
| Word32 dist; |
| Word32 m = gain&3; |
| Word32 g = (gain >> 2) + 4; |
| Word32 g2 = (g << 1) + 1; |
| Word16 *pquat, *repquat; |
| /* gain&3 */ |
| |
| pquat = quantBorders[m]; |
| repquat = quantRecon[m]; |
| |
| dist = 0; |
| g += 16; |
| if(g2 < 0 && g >= 0) |
| { |
| g2 = -g2; |
| for(line=0; line<sfbWidth; line++) { |
| if (spec[line]) { |
| Word32 diff; |
| Word32 distSingle; |
| Word32 sa; |
| Word32 saShft; |
| sa = L_abs(spec[line]); |
| //saShft = round16(L_shr(sa, g)); |
| //saShft = L_shr(sa, 16+g); |
| saShft = sa >> g; |
| |
| if (saShft < pquat[0]) { |
| distSingle = (saShft * saShft) >> g2; |
| } |
| else { |
| |
| if (saShft < pquat[1]) { |
| diff = saShft - repquat[0]; |
| distSingle = (diff * diff) >> g2; |
| } |
| else { |
| |
| if (saShft < pquat[2]) { |
| diff = saShft - repquat[1]; |
| distSingle = (diff * diff) >> g2; |
| } |
| else { |
| |
| if (saShft < pquat[3]) { |
| diff = saShft - repquat[2]; |
| distSingle = (diff * diff) >> g2; |
| } |
| else { |
| Word16 qua = quantizeSingleLine(gain, sa); |
| Word32 iqval, diff32; |
| /* now that we have quantized x, re-quantize it. */ |
| iquantizeLines(gain, 1, &qua, &iqval); |
| diff32 = sa - iqval; |
| distSingle = fixmul(diff32, diff32); |
| } |
| } |
| } |
| } |
| |
| dist = L_add(dist, distSingle); |
| } |
| } |
| } |
| else |
| { |
| for(line=0; line<sfbWidth; line++) { |
| if (spec[line]) { |
| Word32 diff; |
| Word32 distSingle; |
| Word32 sa; |
| Word32 saShft; |
| sa = L_abs(spec[line]); |
| //saShft = round16(L_shr(sa, g)); |
| saShft = L_shr(sa, g); |
| |
| if (saShft < pquat[0]) { |
| distSingle = L_shl((saShft * saShft), g2); |
| } |
| else { |
| |
| if (saShft < pquat[1]) { |
| diff = saShft - repquat[0]; |
| distSingle = L_shl((diff * diff), g2); |
| } |
| else { |
| |
| if (saShft < pquat[2]) { |
| diff = saShft - repquat[1]; |
| distSingle = L_shl((diff * diff), g2); |
| } |
| else { |
| |
| if (saShft < pquat[3]) { |
| diff = saShft - repquat[2]; |
| distSingle = L_shl((diff * diff), g2); |
| } |
| else { |
| Word16 qua = quantizeSingleLine(gain, sa); |
| Word32 iqval, diff32; |
| /* now that we have quantized x, re-quantize it. */ |
| iquantizeLines(gain, 1, &qua, &iqval); |
| diff32 = sa - iqval; |
| distSingle = fixmul(diff32, diff32); |
| } |
| } |
| } |
| } |
| dist = L_add(dist, distSingle); |
| } |
| } |
| } |
| |
| return dist; |
| } |