1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*
2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Copyright 2003-2010, VisualOn, Inc.
3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Licensed under the Apache License, Version 2.0 (the "License");
5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** you may not use this file except in compliance with the License.
6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** You may obtain a copy of the License at
7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **     http://www.apache.org/licenses/LICENSE-2.0
9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Unless required by applicable law or agreed to in writing, software
11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** distributed under the License is distributed on an "AS IS" BASIS,
12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** See the License for the specific language governing permissions and
14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** limitations under the License.
15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard */
16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*******************************************************************************
17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	File:		quantize.c
18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	Content:	quantization functions
20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
21956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*******************************************************************************/
22956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "typedef.h"
24e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "basic_op.h"
25956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "oper_32b.h"
26956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "quantize.h"
27956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "aac_rom.h"
28956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
29956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#define MANT_DIGITS 9
30956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#define MANT_SIZE   (1<<MANT_DIGITS)
31956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
32956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 XROUND = 0x33e425af; /* final rounding constant (-0.0946f+ 0.5f) */
33956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
34956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
35956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
36956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
37b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* function name:pow34
38b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description: calculate $x^{\frac{3}{4}}, for 0.5 < x < 1.0$.
39956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
40956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
41956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong__inline Word32 pow34(Word32 x)
42956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
43956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* index table using MANT_DIGITS bits, but mask out the sign bit and the MSB
44b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard     which is always one */
45956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return mTab_3_4[(x >> (INT_BITS-2-MANT_DIGITS)) & (MANT_SIZE-1)];
46956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
47956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
48956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
49956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
50956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
51b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* function name:quantizeSingleLine
52b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description: quantizes spectrum
53b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard*              quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain)
54956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
55956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
56956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 quantizeSingleLine(const Word16 gain, const Word32 absSpectrum)
57956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
58956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 e, minusFinalExp, finalShift;
59956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 x;
60b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  Word16 qua = 0;
61b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
62956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
63956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (absSpectrum) {
64956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    e = norm_l(absSpectrum);
65956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    x = pow34(absSpectrum << e);
66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* calculate the final fractional exponent times 16 (was 3*(4*e + gain) + (INT_BITS-1)*16) */
68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    minusFinalExp = (e << 2) + gain;
69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    minusFinalExp = (minusFinalExp << 1) + minusFinalExp;
70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    minusFinalExp = minusFinalExp + ((INT_BITS-1) << 4);
71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
72956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* separate the exponent into a shift, and a multiply */
73956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    finalShift = minusFinalExp >> 4;
74b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
75956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (finalShift < INT_BITS) {
76956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      x = L_mpy_wx(x, pow2tominusNover16[minusFinalExp & 15]);
77956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
78956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      x += XROUND >> (INT_BITS - finalShift);
79956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
80e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      /* shift and quantize */
81e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  finalShift--;
82e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
83e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  if(finalShift >= 0)
84e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		  x >>= finalShift;
85e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  else
86e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		  x <<= (-finalShift);
87b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
88956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  qua = saturate(x);
89956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
90956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
91956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
92956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return qua;
93956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
94956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
95956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
96956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
97b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* function name:quantizeLines
98b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description: quantizes spectrum lines
99b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard*              quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain)
100b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard*  input: global gain, number of lines to process, spectral data
101956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*  output: quantized spectrum
102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void quantizeLines(const Word16 gain,
105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                          const Word16 noOfLines,
106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                          const Word32 *mdctSpectrum,
107956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                          Word16 *quaSpectrum)
108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
109956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 line;
110956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 m = gain&3;
111e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 g = (gain >> 2) + 4;
112e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 mdctSpeL;
1139fc4dfb69df0b5a13b7a1904272eb1dcf8113d0cMartin Storsjo  const Word16 *pquat;
114e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    /* gain&3 */
115e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
116e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  pquat = quantBorders[m];
117e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
118e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  g += 16;
119b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
120e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  if(g >= 0)
121e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
122956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	for (line=0; line<noOfLines; line++) {
123956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  Word32 qua;
124b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  qua = 0;
125b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
126e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  mdctSpeL = mdctSpectrum[line];
127b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
128956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  if (mdctSpeL) {
129956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		Word32 sa;
130956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		Word32 saShft;
131956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
132956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        sa = L_abs(mdctSpeL);
133e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        //saShft = L_shr(sa, 16 + g);
134956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	    saShft = sa >> g;
135956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
136956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (saShft > pquat[0]) {
137b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
138956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong          if (saShft < pquat[1]) {
139b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
140956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            qua = mdctSpeL>0 ? 1 : -1;
141956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  }
142956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong          else {
143b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
144956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            if (saShft < pquat[2]) {
145b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
146956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              qua = mdctSpeL>0 ? 2 : -2;
147956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			}
148956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            else {
149b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
150956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              if (saShft < pquat[3]) {
151b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
152956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                qua = mdctSpeL>0 ? 3 : -3;
153956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			  }
154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong              else {
155956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                qua = quantizeSingleLine(gain, sa);
156956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */
157b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
158956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                if (mdctSpeL < 0)
159956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  qua = -qua;
160956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			  }
161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			}
162956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  }
163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		}
164956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  }
165b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      quaSpectrum[line] = qua ;
166e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	}
167e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  }
168e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  else
169e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
170e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	for (line=0; line<noOfLines; line++) {
171e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  Word32 qua;
172b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  qua = 0;
173b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
174e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  mdctSpeL = mdctSpectrum[line];
175b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
176e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  if (mdctSpeL) {
177e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		Word32 sa;
178e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		Word32 saShft;
179e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
180e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        sa = L_abs(mdctSpeL);
181e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        saShft = sa << g;
182e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
183e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        if (saShft > pquat[0]) {
184b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
185e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard          if (saShft < pquat[1]) {
186b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
187e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            qua = mdctSpeL>0 ? 1 : -1;
188e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		  }
189e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard          else {
190b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
191e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            if (saShft < pquat[2]) {
192b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
193e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard              qua = mdctSpeL>0 ? 2 : -2;
194e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			}
195e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            else {
196b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
197e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard              if (saShft < pquat[3]) {
198b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
199e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                qua = mdctSpeL>0 ? 3 : -3;
200e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  }
201e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard              else {
202e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                qua = quantizeSingleLine(gain, sa);
203e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */
204b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
205e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                if (mdctSpeL < 0)
206e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                  qua = -qua;
207e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  }
208e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			}
209e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		  }
210e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		}
211e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  }
212b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      quaSpectrum[line] = qua ;
213b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	}
214956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
215956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
216956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
217956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
218956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
219956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
220956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
221b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* function name:iquantizeLines
222956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: iquantizes spectrum lines without sign
223b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard*              mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain)
224b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* input: global gain, number of lines to process,quantized spectrum
225956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: spectral data
226956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
227956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
228956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void iquantizeLines(const Word16 gain,
229956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           const Word16 noOfLines,
230956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           const Word16 *quantSpectrum,
231956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                           Word32 *mdctSpectrum)
232956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
233956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32   iquantizermod;
234956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32   iquantizershift;
235956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32   line;
236956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
237b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  iquantizermod = gain & 3;
238956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  iquantizershift = gain >> 2;
239956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
240956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (line=0; line<noOfLines; line++) {
241b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
242956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if( quantSpectrum[line] != 0 ) {
243956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Word32 accu;
244956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Word32 ex;
245956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  Word32 tabIndex;
246956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Word32 specExp;
247956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Word32 s,t;
248956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
249956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      accu = quantSpectrum[line];
250956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
251956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      ex = norm_l(accu);
252956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      accu = accu << ex;
253956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      specExp = INT_BITS-1 - ex;
254956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
255b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tabIndex = (accu >> (INT_BITS-2-MANT_DIGITS)) & (~MANT_SIZE);
256956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
257956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* calculate "mantissa" ^4/3 */
258b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      s = mTab_4_3[tabIndex];
259956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
260956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */
261b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      t = specExpMantTableComb_enc[iquantizermod][specExp];
262956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
263956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* multiply "mantissa" ^4/3 with exponent multiplier */
264956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      accu = MULHIGH(s, t);
265956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
266956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* get approperiate exponent shifter */
267b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      specExp = specExpTableComb_enc[iquantizermod][specExp];
268956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
269e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      specExp += iquantizershift + 1;
270e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  if(specExp >= 0)
271e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		  mdctSpectrum[line] = accu << specExp;
272e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  else
273956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  mdctSpectrum[line] = accu >> (-specExp);
274956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else {
276b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      mdctSpectrum[line] = 0;
277956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
278956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
279956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
280956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
281956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
282956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
283956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: QuantizeSpectrum
284956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: quantizes the entire spectrum
285956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:
286956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: number of scalefactor bands to be quantized, ...
287956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: quantized spectrum
288956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
289956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
290956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid QuantizeSpectrum(Word16 sfbCnt,
291956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      Word16 maxSfbPerGroup,
292956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      Word16 sfbPerGroup,
293956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      Word16 *sfbOffset,
294956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      Word32 *mdctSpectrum,
295956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      Word16 globalGain,
296956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      Word16 *scalefactors,
297956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      Word16 *quantizedSpectrum)
298956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
299956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 sfbOffs, sfb;
300956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
301956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup) {
302956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word32 sfbNext ;
303956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for (sfb = 0; sfb < maxSfbPerGroup; sfb = sfbNext) {
304b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      Word16 scalefactor = scalefactors[sfbOffs+sfb];
305956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* coalesce sfbs with the same scalefactor */
306956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      for (sfbNext = sfb+1;
307956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong           sfbNext < maxSfbPerGroup && scalefactor == scalefactors[sfbOffs+sfbNext];
308956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong           sfbNext++) ;
309956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
310956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      quantizeLines(globalGain - scalefactor,
311956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    sfbOffset[sfbOffs+sfbNext] - sfbOffset[sfbOffs+sfb],
312956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    mdctSpectrum + sfbOffset[sfbOffs+sfb],
313956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    quantizedSpectrum + sfbOffset[sfbOffs+sfb]);
314956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
315956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
316956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
317956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
318956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
319956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
320956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
321b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* function name:calcSfbDist
322956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: quantizes and requantizes lines to calculate distortion
323956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input:  number of lines to be quantized, ...
324956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: distortion
325956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
326956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
327956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord32 calcSfbDist(const Word32 *spec,
328956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word16  sfbWidth,
329956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   Word16  gain)
330956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
331956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 line;
332956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 dist;
333956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 m = gain&3;
334e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 g = (gain >> 2) + 4;
335e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 g2 = (g << 1) + 1;
3369fc4dfb69df0b5a13b7a1904272eb1dcf8113d0cMartin Storsjo  const Word16 *pquat, *repquat;
337956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* gain&3 */
338e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
339e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  pquat = quantBorders[m];
340956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  repquat = quantRecon[m];
341b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
342b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  dist = 0;
343e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  g += 16;
344e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  if(g2 < 0 && g >= 0)
345b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  {
346e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  g2 = -g2;
347b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  for(line=0; line<sfbWidth; line++) {
348b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard		  if (spec[line]) {
349e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  Word32 diff;
350e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  Word32 distSingle;
351e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  Word32 sa;
352e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  Word32 saShft;
353e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  sa = L_abs(spec[line]);
354e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  //saShft = round16(L_shr(sa, g));
355e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  //saShft = L_shr(sa, 16+g);
356e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  saShft = sa >> g;
357e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
358e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  if (saShft < pquat[0]) {
359e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard				  distSingle = (saShft * saShft) >> g2;
360e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  }
361e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  else {
362b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
363e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard				  if (saShft < pquat[1]) {
364e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  diff = saShft - repquat[0];
365e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  distSingle = (diff * diff) >> g2;
366e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard				  }
367e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard				  else {
368b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
369e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  if (saShft < pquat[2]) {
370e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  diff = saShft - repquat[1];
371e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  distSingle = (diff * diff) >> g2;
372e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  }
373e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  else {
374b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
375e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  if (saShft < pquat[3]) {
376e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  diff = saShft - repquat[2];
377e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  distSingle = (diff * diff) >> g2;
378e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  }
379e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  else {
380e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  Word16 qua = quantizeSingleLine(gain, sa);
381e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  Word32 iqval, diff32;
382e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  /* now that we have quantized x, re-quantize it. */
383e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  iquantizeLines(gain, 1, &qua, &iqval);
384e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  diff32 = sa - iqval;
385e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  distSingle = fixmul(diff32, diff32);
386e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  }
387e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  }
388e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard				  }
389e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  }
390b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
391e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  dist = L_add(dist, distSingle);
392e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		  }
393e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  }
394e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  }
395e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  else
396e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  {
397b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  for(line=0; line<sfbWidth; line++) {
398b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard		  if (spec[line]) {
399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			  Word32 diff;
400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			  Word32 distSingle;
401956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			  Word32 sa;
402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			  Word32 saShft;
403956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			  sa = L_abs(spec[line]);
404956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			  //saShft = round16(L_shr(sa, g));
405e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  saShft = L_shr(sa, g);
406e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
407e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  if (saShft < pquat[0]) {
408e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard				  distSingle = L_shl((saShft * saShft), g2);
409e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  }
410e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  else {
411b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
412e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard				  if (saShft < pquat[1]) {
413e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  diff = saShft - repquat[0];
414e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  distSingle = L_shl((diff * diff), g2);
415e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard				  }
416e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard				  else {
417b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
418e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  if (saShft < pquat[2]) {
419e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  diff = saShft - repquat[1];
420e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  distSingle = L_shl((diff * diff), g2);
421e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  }
422e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  else {
423b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
424e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  if (saShft < pquat[3]) {
425e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  diff = saShft - repquat[2];
426e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  distSingle = L_shl((diff * diff), g2);
427e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  }
428e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  else {
429e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  Word16 qua = quantizeSingleLine(gain, sa);
430e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  Word32 iqval, diff32;
431e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  /* now that we have quantized x, re-quantize it. */
432e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  iquantizeLines(gain, 1, &qua, &iqval);
433e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  diff32 = sa - iqval;
434e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard							  distSingle = fixmul(diff32, diff32);
435e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard						  }
436e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard					  }
437e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard				  }
438e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  }
439e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			  dist = L_add(dist, distSingle);
440956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  }
441b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  }
442956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
443956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
444956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return dist;
445956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
446