diff options
Diffstat (limited to 'media/libstagefright/codecs/aacenc/src/quantize.c')
-rw-r--r-- | media/libstagefright/codecs/aacenc/src/quantize.c | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/aacenc/src/quantize.c b/media/libstagefright/codecs/aacenc/src/quantize.c new file mode 100644 index 0000000..0d0f550 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/quantize.c @@ -0,0 +1,445 @@ +/* + ** 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; + const 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; + const 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; +} |