/* ** 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<> (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> 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 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> (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> 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> 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