1 /*
2 ** Copyright 2003-2010, VisualOn, Inc.
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17 /**************************************************************************
18 * File: q_gain2.c *
19 * *
20 * Description: *
21 * Quantization of pitch and codebook gains. *
22 * MA prediction is performed on the innovation energy (in dB with mean *
23 * removed). *
24 * An initial predicted gain, g_0, is first determined and the correction *
25 * factor alpha = gain / g_0 is quantized. *
26 * The pitch gain and the correction factor are vector quantized and the *
27 * mean-squared weighted error criterion is used in the quantizer search. *
28 ****************************************************************************/
29
30 #include "typedef.h"
31 #include "basic_op.h"
32 #include "oper_32b.h"
33 #include "math_op.h"
34 #include "log2.h"
35 #include "acelp.h"
36 #include "q_gain2.tab"
37
38 #define MEAN_ENER 30
39 #define RANGE 64
40 #define PRED_ORDER 4
41
42
43 /* MA prediction coeff ={0.5, 0.4, 0.3, 0.2} in Q13 */
44 static Word16 pred[PRED_ORDER] = {4096, 3277, 2458, 1638};
45
46
Init_Q_gain2(Word16 * mem)47 void Init_Q_gain2(
48 Word16 * mem /* output :static memory (2 words) */
49 )
50 {
51 Word32 i;
52
53 /* 4nd order quantizer energy predictor (init to -14.0 in Q10) */
54 for (i = 0; i < PRED_ORDER; i++)
55 {
56 mem[i] = -14336; /* past_qua_en[i] */
57 }
58
59 return;
60 }
61
Q_gain2(Word16 xn[],Word16 y1[],Word16 Q_xn,Word16 y2[],Word16 code[],Word16 g_coeff[],Word16 L_subfr,Word16 nbits,Word16 * gain_pit,Word32 * gain_cod,Word16 gp_clip,Word16 * mem)62 Word16 Q_gain2( /* Return index of quantization. */
63 Word16 xn[], /* (i) Q_xn: Target vector. */
64 Word16 y1[], /* (i) Q_xn: Adaptive codebook. */
65 Word16 Q_xn, /* (i) : xn and y1 format */
66 Word16 y2[], /* (i) Q9 : Filtered innovative vector. */
67 Word16 code[], /* (i) Q9 : Innovative vector. */
68 Word16 g_coeff[], /* (i) : Correlations <xn y1> <y1 y1> */
69 /* Compute in G_pitch(). */
70 Word16 L_subfr, /* (i) : Subframe lenght. */
71 Word16 nbits, /* (i) : number of bits (6 or 7) */
72 Word16 * gain_pit, /* (i/o)Q14: Pitch gain. */
73 Word32 * gain_cod, /* (o) Q16 : Code gain. */
74 Word16 gp_clip, /* (i) : Gp Clipping flag */
75 Word16 * mem /* (i/o) : static memory (2 words) */
76 )
77 {
78 Word16 index, *p, min_ind, size;
79 Word16 exp, frac, gcode0, exp_gcode0, e_max, exp_code, qua_ener;
80 Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo;
81 Word16 coeff[5], coeff_lo[5], exp_coeff[5];
82 Word16 exp_max[5];
83 Word32 i, j, L_tmp, dist_min;
84 Word16 *past_qua_en, *t_qua_gain;
85
86 past_qua_en = mem;
87
88 /*-----------------------------------------------------------------*
89 * - Find the initial quantization pitch index *
90 * - Set gains search range *
91 *-----------------------------------------------------------------*/
92 if (nbits == 6)
93 {
94 t_qua_gain = t_qua_gain6b;
95 min_ind = 0;
96 size = RANGE;
97
98 if(gp_clip == 1)
99 {
100 size = size - 16; /* limit gain pitch to 1.0 */
101 }
102 } else
103 {
104 t_qua_gain = t_qua_gain7b;
105
106 p = t_qua_gain7b + RANGE; /* pt at 1/4th of table */
107
108 j = nb_qua_gain7b - RANGE;
109
110 if (gp_clip == 1)
111 {
112 j = j - 27; /* limit gain pitch to 1.0 */
113 }
114 min_ind = 0;
115 g_pitch = *gain_pit;
116
117 for (i = 0; i < j; i++, p += 2)
118 {
119 if (g_pitch > *p)
120 {
121 min_ind = min_ind + 1;
122 }
123 }
124 size = RANGE;
125 }
126
127 /*------------------------------------------------------------------*
128 * Compute coefficient need for the quantization. *
129 * *
130 * coeff[0] = y1 y1 *
131 * coeff[1] = -2 xn y1 *
132 * coeff[2] = y2 y2 *
133 * coeff[3] = -2 xn y2 *
134 * coeff[4] = 2 y1 y2 *
135 * *
136 * Product <y1 y1> and <xn y1> have been compute in G_pitch() and *
137 * are in vector g_coeff[]. *
138 *------------------------------------------------------------------*/
139
140 coeff[0] = g_coeff[0];
141 exp_coeff[0] = g_coeff[1];
142 coeff[1] = negate(g_coeff[2]); /* coeff[1] = -2 xn y1 */
143 exp_coeff[1] = g_coeff[3] + 1;
144
145 /* Compute scalar product <y2[],y2[]> */
146 #ifdef ASM_OPT /* asm optimization branch */
147 coeff[2] = extract_h(Dot_product12_asm(y2, y2, L_subfr, &exp));
148 #else
149 coeff[2] = extract_h(Dot_product12(y2, y2, L_subfr, &exp));
150 #endif
151 exp_coeff[2] = (exp - 18) + (Q_xn << 1); /* -18 (y2 Q9) */
152
153 /* Compute scalar product -2*<xn[],y2[]> */
154 #ifdef ASM_OPT /* asm optimization branch */
155 coeff[3] = extract_h(L_negate(Dot_product12_asm(xn, y2, L_subfr, &exp)));
156 #else
157 coeff[3] = extract_h(L_negate(Dot_product12(xn, y2, L_subfr, &exp)));
158 #endif
159
160 exp_coeff[3] = (exp - 8) + Q_xn; /* -9 (y2 Q9), +1 (2 xn y2) */
161
162 /* Compute scalar product 2*<y1[],y2[]> */
163 #ifdef ASM_OPT /* asm optimization branch */
164 coeff[4] = extract_h(Dot_product12_asm(y1, y2, L_subfr, &exp));
165 #else
166 coeff[4] = extract_h(Dot_product12(y1, y2, L_subfr, &exp));
167 #endif
168 exp_coeff[4] = (exp - 8) + Q_xn; /* -9 (y2 Q9), +1 (2 y1 y2) */
169
170 /*-----------------------------------------------------------------*
171 * Find energy of code and compute: *
172 * *
173 * L_tmp = MEAN_ENER - 10log10(energy of code/ L_subfr) *
174 * = MEAN_ENER - 3.0103*log2(energy of code/ L_subfr) *
175 *-----------------------------------------------------------------*/
176 #ifdef ASM_OPT /* asm optimization branch */
177 L_tmp = Dot_product12_asm(code, code, L_subfr, &exp_code);
178 #else
179 L_tmp = Dot_product12(code, code, L_subfr, &exp_code);
180 #endif
181 /* exp_code: -18 (code in Q9), -6 (/L_subfr), -31 (L_tmp Q31->Q0) */
182 exp_code = (exp_code - (18 + 6 + 31));
183
184 Log2(L_tmp, &exp, &frac);
185 exp += exp_code;
186 L_tmp = Mpy_32_16(exp, frac, -24660); /* x -3.0103(Q13) -> Q14 */
187
188 L_tmp += (MEAN_ENER * 8192)<<1; /* + MEAN_ENER in Q14 */
189
190 /*-----------------------------------------------------------------*
191 * Compute gcode0. *
192 * = Sum(i=0,1) pred[i]*past_qua_en[i] + mean_ener - ener_code *
193 *-----------------------------------------------------------------*/
194 L_tmp = (L_tmp << 10); /* From Q14 to Q24 */
195 L_tmp += (pred[0] * past_qua_en[0])<<1; /* Q13*Q10 -> Q24 */
196 L_tmp += (pred[1] * past_qua_en[1])<<1; /* Q13*Q10 -> Q24 */
197 L_tmp += (pred[2] * past_qua_en[2])<<1; /* Q13*Q10 -> Q24 */
198 L_tmp += (pred[3] * past_qua_en[3])<<1; /* Q13*Q10 -> Q24 */
199
200 gcode0 = extract_h(L_tmp); /* From Q24 to Q8 */
201
202 /*-----------------------------------------------------------------*
203 * gcode0 = pow(10.0, gcode0/20) *
204 * = pow(2, 3.321928*gcode0/20) *
205 * = pow(2, 0.166096*gcode0) *
206 *-----------------------------------------------------------------*/
207
208 L_tmp = vo_L_mult(gcode0, 5443); /* *0.166096 in Q15 -> Q24 */
209 L_tmp = L_tmp >> 8; /* From Q24 to Q16 */
210 VO_L_Extract(L_tmp, &exp_gcode0, &frac); /* Extract exponent of gcode0 */
211
212 gcode0 = (Word16)(Pow2(14, frac)); /* Put 14 as exponent so that */
213 /* output of Pow2() will be: */
214 /* 16384 < Pow2() <= 32767 */
215 exp_gcode0 -= 14;
216
217 /*-------------------------------------------------------------------------*
218 * Find the best quantizer *
219 * ~~~~~~~~~~~~~~~~~~~~~~~ *
220 * Before doing the computation we need to aling exponents of coeff[] *
221 * to be sure to have the maximum precision. *
222 * *
223 * In the table the pitch gains are in Q14, the code gains are in Q11 and *
224 * are multiply by gcode0 which have been multiply by 2^exp_gcode0. *
225 * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code *
226 * we divide by 2^15. *
227 * Considering all the scaling above we have: *
228 * *
229 * exp_code = exp_gcode0-11+15 = exp_gcode0+4 *
230 * *
231 * g_pitch*g_pitch = -14-14+15 *
232 * g_pitch = -14 *
233 * g_code*g_code = (2*exp_code)+15 *
234 * g_code = exp_code *
235 * g_pitch*g_code = -14 + exp_code +15 *
236 * *
237 * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13 *
238 * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14 *
239 * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code) *
240 * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code *
241 * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code *
242 *-------------------------------------------------------------------------*/
243
244 exp_code = (exp_gcode0 + 4);
245 exp_max[0] = (exp_coeff[0] - 13);
246 exp_max[1] = (exp_coeff[1] - 14);
247 exp_max[2] = (exp_coeff[2] + (15 + (exp_code << 1)));
248 exp_max[3] = (exp_coeff[3] + exp_code);
249 exp_max[4] = (exp_coeff[4] + (1 + exp_code));
250
251 /* Find maximum exponant */
252
253 e_max = exp_max[0];
254 for (i = 1; i < 5; i++)
255 {
256 if(exp_max[i] > e_max)
257 {
258 e_max = exp_max[i];
259 }
260 }
261
262 /* align coeff[] and save in special 32 bit double precision */
263
264 for (i = 0; i < 5; i++)
265 {
266 j = add1(vo_sub(e_max, exp_max[i]), 2);/* /4 to avoid overflow */
267 L_tmp = L_deposit_h(coeff[i]);
268 L_tmp = L_shr(L_tmp, j);
269 VO_L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);
270 coeff_lo[i] = (coeff_lo[i] >> 3); /* lo >> 3 */
271 }
272
273 /* Codebook search */
274 dist_min = MAX_32;
275 p = &t_qua_gain[min_ind << 1];
276
277 index = 0;
278 for (i = 0; i < size; i++)
279 {
280 g_pitch = *p++;
281 g_code = *p++;
282
283 g_code = ((g_code * gcode0) + 0x4000)>>15;
284 g2_pitch = ((g_pitch * g_pitch) + 0x4000)>>15;
285 g_pit_cod = ((g_code * g_pitch) + 0x4000)>>15;
286 L_tmp = (g_code * g_code)<<1;
287 VO_L_Extract(L_tmp, &g2_code, &g2_code_lo);
288
289 L_tmp = (coeff[2] * g2_code_lo)<<1;
290 L_tmp = (L_tmp >> 3);
291 L_tmp += (coeff_lo[0] * g2_pitch)<<1;
292 L_tmp += (coeff_lo[1] * g_pitch)<<1;
293 L_tmp += (coeff_lo[2] * g2_code)<<1;
294 L_tmp += (coeff_lo[3] * g_code)<<1;
295 L_tmp += (coeff_lo[4] * g_pit_cod)<<1;
296 L_tmp = (L_tmp >> 12);
297 L_tmp += (coeff[0] * g2_pitch)<<1;
298 L_tmp += (coeff[1] * g_pitch)<<1;
299 L_tmp += (coeff[2] * g2_code)<<1;
300 L_tmp += (coeff[3] * g_code)<<1;
301 L_tmp += (coeff[4] * g_pit_cod)<<1;
302
303 if(L_tmp < dist_min)
304 {
305 dist_min = L_tmp;
306 index = i;
307 }
308 }
309
310 /* Read the quantized gains */
311 index = index + min_ind;
312 p = &t_qua_gain[(index + index)];
313 *gain_pit = *p++; /* selected pitch gain in Q14 */
314 g_code = *p++; /* selected code gain in Q11 */
315
316 L_tmp = vo_L_mult(g_code, gcode0); /* Q11*Q0 -> Q12 */
317 L_tmp = L_shl(L_tmp, (exp_gcode0 + 4)); /* Q12 -> Q16 */
318
319 *gain_cod = L_tmp; /* gain of code in Q16 */
320
321 /*---------------------------------------------------*
322 * qua_ener = 20*log10(g_code) *
323 * = 6.0206*log2(g_code) *
324 * = 6.0206*(log2(g_codeQ11) - 11) *
325 *---------------------------------------------------*/
326
327 L_tmp = L_deposit_l(g_code);
328 Log2(L_tmp, &exp, &frac);
329 exp -= 11;
330 L_tmp = Mpy_32_16(exp, frac, 24660); /* x 6.0206 in Q12 */
331
332 qua_ener = (Word16)(L_tmp >> 3); /* result in Q10 */
333
334 /* update table of past quantized energies */
335
336 past_qua_en[3] = past_qua_en[2];
337 past_qua_en[2] = past_qua_en[1];
338 past_qua_en[1] = past_qua_en[0];
339 past_qua_en[0] = qua_ener;
340
341 return (index);
342 }
343
344
345
346
347