summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/aacenc/src/quantize.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/aacenc/src/quantize.c')
-rw-r--r--media/libstagefright/codecs/aacenc/src/quantize.c445
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;
+}