Home | History | Annotate | Download | only in src
      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 
     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 
     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