blob: f8da5898aebb04500e902eca8697eb7f4442b3cb [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* 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.
* -------------------------------------------------------------------
*/
/****************************************************************************************
Portions of this file are derived from the following 3GPP standard:
3GPP TS 26.073
ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
Available from http://www.3gpp.org
(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
Permission to distribute, modify and use this file under the standard license
terms listed above has been obtained from the copyright holder.
****************************************************************************************/
/*
------------------------------------------------------------------------------
Pathname: ./audio/gsm-amr/c/src/qgain475.c
Funtions: MR475_quant_store_results
MR475_update_unq_pred
MR475_gain_quant
------------------------------------------------------------------------------
MODULE DESCRIPTION
These modules handle the quantization of pitch and codebook gains for MR475.
------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/
#include "qgain475.h"
#include "typedef.h"
#include "basic_op.h"
#include "mode.h"
#include "cnst.h"
#include "pow2.h"
#include "log2.h"
/*----------------------------------------------------------------------------
; MACROS
; Define module specific macros here
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; DEFINES
; Include all pre-processor statements here. Include conditional
; compile variables also.
----------------------------------------------------------------------------*/
#define MR475_VQ_SIZE 256
/*----------------------------------------------------------------------------
; LOCAL FUNCTION DEFINITIONS
; Function Prototype declaration
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; LOCAL VARIABLE DEFINITIONS
; Variable declaration - defined here and used outside this module
----------------------------------------------------------------------------*/
/* The table contains the following data:
*
* g_pitch(0) (Q14) // for sub-
* g_fac(0) (Q12) // frame 0 and 2
* g_pitch(1) (Q14) // for sub-
* g_fac(2) (Q12) // frame 1 and 3
*
*/
static const Word16 table_gain_MR475[MR475_VQ_SIZE*4] =
{
/*g_pit(0), g_fac(0), g_pit(1), g_fac(1) */
812, 128, 542, 140,
2873, 1135, 2266, 3402,
2067, 563, 12677, 647,
4132, 1798, 5601, 5285,
7689, 374, 3735, 441,
10912, 2638, 11807, 2494,
20490, 797, 5218, 675,
6724, 8354, 5282, 1696,
1488, 428, 5882, 452,
5332, 4072, 3583, 1268,
2469, 901, 15894, 1005,
14982, 3271, 10331, 4858,
3635, 2021, 2596, 835,
12360, 4892, 12206, 1704,
13432, 1604, 9118, 2341,
3968, 1538, 5479, 9936,
3795, 417, 1359, 414,
3640, 1569, 7995, 3541,
11405, 645, 8552, 635,
4056, 1377, 16608, 6124,
11420, 700, 2007, 607,
12415, 1578, 11119, 4654,
13680, 1708, 11990, 1229,
7996, 7297, 13231, 5715,
2428, 1159, 2073, 1941,
6218, 6121, 3546, 1804,
8925, 1802, 8679, 1580,
13935, 3576, 13313, 6237,
6142, 1130, 5994, 1734,
14141, 4662, 11271, 3321,
12226, 1551, 13931, 3015,
5081, 10464, 9444, 6706,
1689, 683, 1436, 1306,
7212, 3933, 4082, 2713,
7793, 704, 15070, 802,
6299, 5212, 4337, 5357,
6676, 541, 6062, 626,
13651, 3700, 11498, 2408,
16156, 716, 12177, 751,
8065, 11489, 6314, 2256,
4466, 496, 7293, 523,
10213, 3833, 8394, 3037,
8403, 966, 14228, 1880,
8703, 5409, 16395, 4863,
7420, 1979, 6089, 1230,
9371, 4398, 14558, 3363,
13559, 2873, 13163, 1465,
5534, 1678, 13138, 14771,
7338, 600, 1318, 548,
4252, 3539, 10044, 2364,
10587, 622, 13088, 669,
14126, 3526, 5039, 9784,
15338, 619, 3115, 590,
16442, 3013, 15542, 4168,
15537, 1611, 15405, 1228,
16023, 9299, 7534, 4976,
1990, 1213, 11447, 1157,
12512, 5519, 9475, 2644,
7716, 2034, 13280, 2239,
16011, 5093, 8066, 6761,
10083, 1413, 5002, 2347,
12523, 5975, 15126, 2899,
18264, 2289, 15827, 2527,
16265, 10254, 14651, 11319,
1797, 337, 3115, 397,
3510, 2928, 4592, 2670,
7519, 628, 11415, 656,
5946, 2435, 6544, 7367,
8238, 829, 4000, 863,
10032, 2492, 16057, 3551,
18204, 1054, 6103, 1454,
5884, 7900, 18752, 3468,
1864, 544, 9198, 683,
11623, 4160, 4594, 1644,
3158, 1157, 15953, 2560,
12349, 3733, 17420, 5260,
6106, 2004, 2917, 1742,
16467, 5257, 16787, 1680,
17205, 1759, 4773, 3231,
7386, 6035, 14342, 10012,
4035, 442, 4194, 458,
9214, 2242, 7427, 4217,
12860, 801, 11186, 825,
12648, 2084, 12956, 6554,
9505, 996, 6629, 985,
10537, 2502, 15289, 5006,
12602, 2055, 15484, 1653,
16194, 6921, 14231, 5790,
2626, 828, 5615, 1686,
13663, 5778, 3668, 1554,
11313, 2633, 9770, 1459,
14003, 4733, 15897, 6291,
6278, 1870, 7910, 2285,
16978, 4571, 16576, 3849,
15248, 2311, 16023, 3244,
14459, 17808, 11847, 2763,
1981, 1407, 1400, 876,
4335, 3547, 4391, 4210,
5405, 680, 17461, 781,
6501, 5118, 8091, 7677,
7355, 794, 8333, 1182,
15041, 3160, 14928, 3039,
20421, 880, 14545, 852,
12337, 14708, 6904, 1920,
4225, 933, 8218, 1087,
10659, 4084, 10082, 4533,
2735, 840, 20657, 1081,
16711, 5966, 15873, 4578,
10871, 2574, 3773, 1166,
14519, 4044, 20699, 2627,
15219, 2734, 15274, 2186,
6257, 3226, 13125, 19480,
7196, 930, 2462, 1618,
4515, 3092, 13852, 4277,
10460, 833, 17339, 810,
16891, 2289, 15546, 8217,
13603, 1684, 3197, 1834,
15948, 2820, 15812, 5327,
17006, 2438, 16788, 1326,
15671, 8156, 11726, 8556,
3762, 2053, 9563, 1317,
13561, 6790, 12227, 1936,
8180, 3550, 13287, 1778,
16299, 6599, 16291, 7758,
8521, 2551, 7225, 2645,
18269, 7489, 16885, 2248,
17882, 2884, 17265, 3328,
9417, 20162, 11042, 8320,
1286, 620, 1431, 583,
5993, 2289, 3978, 3626,
5144, 752, 13409, 830,
5553, 2860, 11764, 5908,
10737, 560, 5446, 564,
13321, 3008, 11946, 3683,
19887, 798, 9825, 728,
13663, 8748, 7391, 3053,
2515, 778, 6050, 833,
6469, 5074, 8305, 2463,
6141, 1865, 15308, 1262,
14408, 4547, 13663, 4515,
3137, 2983, 2479, 1259,
15088, 4647, 15382, 2607,
14492, 2392, 12462, 2537,
7539, 2949, 12909, 12060,
5468, 684, 3141, 722,
5081, 1274, 12732, 4200,
15302, 681, 7819, 592,
6534, 2021, 16478, 8737,
13364, 882, 5397, 899,
14656, 2178, 14741, 4227,
14270, 1298, 13929, 2029,
15477, 7482, 15815, 4572,
2521, 2013, 5062, 1804,
5159, 6582, 7130, 3597,
10920, 1611, 11729, 1708,
16903, 3455, 16268, 6640,
9306, 1007, 9369, 2106,
19182, 5037, 12441, 4269,
15919, 1332, 15357, 3512,
11898, 14141, 16101, 6854,
2010, 737, 3779, 861,
11454, 2880, 3564, 3540,
9057, 1241, 12391, 896,
8546, 4629, 11561, 5776,
8129, 589, 8218, 588,
18728, 3755, 12973, 3149,
15729, 758, 16634, 754,
15222, 11138, 15871, 2208,
4673, 610, 10218, 678,
15257, 4146, 5729, 3327,
8377, 1670, 19862, 2321,
15450, 5511, 14054, 5481,
5728, 2888, 7580, 1346,
14384, 5325, 16236, 3950,
15118, 3744, 15306, 1435,
14597, 4070, 12301, 15696,
7617, 1699, 2170, 884,
4459, 4567, 18094, 3306,
12742, 815, 14926, 907,
15016, 4281, 15518, 8368,
17994, 1087, 2358, 865,
16281, 3787, 15679, 4596,
16356, 1534, 16584, 2210,
16833, 9697, 15929, 4513,
3277, 1085, 9643, 2187,
11973, 6068, 9199, 4462,
8955, 1629, 10289, 3062,
16481, 5155, 15466, 7066,
13678, 2543, 5273, 2277,
16746, 6213, 16655, 3408,
20304, 3363, 18688, 1985,
14172, 12867, 15154, 15703,
4473, 1020, 1681, 886,
4311, 4301, 8952, 3657,
5893, 1147, 11647, 1452,
15886, 2227, 4582, 6644,
6929, 1205, 6220, 799,
12415, 3409, 15968, 3877,
19859, 2109, 9689, 2141,
14742, 8830, 14480, 2599,
1817, 1238, 7771, 813,
19079, 4410, 5554, 2064,
3687, 2844, 17435, 2256,
16697, 4486, 16199, 5388,
8028, 2763, 3405, 2119,
17426, 5477, 13698, 2786,
19879, 2720, 9098, 3880,
18172, 4833, 17336, 12207,
5116, 996, 4935, 988,
9888, 3081, 6014, 5371,
15881, 1667, 8405, 1183,
15087, 2366, 19777, 7002,
11963, 1562, 7279, 1128,
16859, 1532, 15762, 5381,
14708, 2065, 20105, 2155,
17158, 8245, 17911, 6318,
5467, 1504, 4100, 2574,
17421, 6810, 5673, 2888,
16636, 3382, 8975, 1831,
20159, 4737, 19550, 7294,
6658, 2781, 11472, 3321,
19397, 5054, 18878, 4722,
16439, 2373, 20430, 4386,
11353, 26526, 11593, 3068,
2866, 1566, 5108, 1070,
9614, 4915, 4939, 3536,
7541, 878, 20717, 851,
6938, 4395, 16799, 7733,
10137, 1019, 9845, 964,
15494, 3955, 15459, 3430,
18863, 982, 20120, 963,
16876, 12887, 14334, 4200,
6599, 1220, 9222, 814,
16942, 5134, 5661, 4898,
5488, 1798, 20258, 3962,
17005, 6178, 17929, 5929,
9365, 3420, 7474, 1971,
19537, 5177, 19003, 3006,
16454, 3788, 16070, 2367,
8664, 2743, 9445, 26358,
10856, 1287, 3555, 1009,
5606, 3622, 19453, 5512,
12453, 797, 20634, 911,
15427, 3066, 17037, 10275,
18883, 2633, 3913, 1268,
19519, 3371, 18052, 5230,
19291, 1678, 19508, 3172,
18072, 10754, 16625, 6845,
3134, 2298, 10869, 2437,
15580, 6913, 12597, 3381,
11116, 3297, 16762, 2424,
18853, 6715, 17171, 9887,
12743, 2605, 8937, 3140,
19033, 7764, 18347, 3880,
20475, 3682, 19602, 3380,
13044, 19373, 10526, 23124
};
/*
------------------------------------------------------------------------------
FUNCTION NAME: MR475_quant_store_results
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
pred_st = pointer to structure of type gc_predState
p = pointer to selected quantizer table entry (const Word16)
gcode0 = predicted CB gain (Word16)
exp_gcode0 = exponent of predicted CB gain (Word16)
gain_pit = pointer to Pitch gain (Word16)
gain_cod = pointer to Code gain (Word16)
Outputs:
pred_st points to the updated structure of type gc_predState
gain_pit points to Pitch gain
gain_cod points to Code gain
pOverflow points to overflow indicator (Flag)
Returns:
None.
Global Variables Used:
None.
Local Variables Needed:
None.
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
This function calculates the final fixed codebook gain and the predictor
update values, and updates the gain predictor.
------------------------------------------------------------------------------
REQUIREMENTS
None.
------------------------------------------------------------------------------
REFERENCES
qgain475.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
static void MR475_quant_store_results(
gc_predState *pred_st, // i/o: gain predictor state struct
const Word16 *p, // i : pointer to selected quantizer table entry
Word16 gcode0, // i : predicted CB gain, Q(14 - exp_gcode0)
Word16 exp_gcode0, // i : exponent of predicted CB gain, Q0
Word16 *gain_pit, // o : Pitch gain, Q14
Word16 *gain_cod // o : Code gain, Q1
)
{
Word16 g_code, exp, frac, tmp;
Word32 L_tmp;
Word16 qua_ener_MR122; // o : quantized energy error, MR122 version Q10
Word16 qua_ener; // o : quantized energy error, Q10
// Read the quantized gains
*gain_pit = *p++;
g_code = *p++;
//------------------------------------------------------------------*
* calculate final fixed codebook gain: *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* *
* gc = gc0 * g *
*------------------------------------------------------------------
L_tmp = L_mult(g_code, gcode0);
L_tmp = L_shr(L_tmp, sub(10, exp_gcode0));
*gain_cod = extract_h(L_tmp);
//------------------------------------------------------------------*
* calculate predictor update values and update gain predictor: *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* *
* qua_ener = log2(g) *
* qua_ener_MR122 = 20*log10(g) *
*------------------------------------------------------------------
Log2 (L_deposit_l (g_code), &exp, &frac); // Log2(x Q12) = log2(x) + 12
exp = sub(exp, 12);
tmp = shr_r (frac, 5);
qua_ener_MR122 = add (tmp, shl (exp, 10));
L_tmp = Mpy_32_16(exp, frac, 24660); // 24660 Q12 ~= 6.0206 = 20*log10(2)
qua_ener = pv_round (L_shl (L_tmp, 13)); // Q12 * Q0 = Q13 -> Q10
gc_pred_update(pred_st, qua_ener_MR122, qua_ener);
}
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
static void MR475_quant_store_results(
gc_predState *pred_st, /* i/o: gain predictor state struct */
const Word16 *p, /* i : pointer to selected quantizer table entry */
Word16 gcode0, /* i : predicted CB gain, Q(14 - exp_gcode0) */
Word16 exp_gcode0, /* i : exponent of predicted CB gain, Q0 */
Word16 *gain_pit, /* o : Pitch gain, Q14 */
Word16 *gain_cod, /* o : Code gain, Q1 */
Flag *pOverflow /* o : overflow indicator */
)
{
Word16 g_code;
Word16 exp;
Word16 frac;
Word16 tmp;
Word32 L_tmp;
Word16 qua_ener_MR122; /* o : quantized energy error, MR122 version Q10 */
Word16 qua_ener; /* o : quantized energy error, Q10 */
/* Read the quantized gains */
*gain_pit = *p++;
g_code = *p++;
/*------------------------------------------------------------------*
* calculate final fixed codebook gain: *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* *
* gc = gc0 * g *
*------------------------------------------------------------------*/
L_tmp = ((Word32) g_code * gcode0) << 1;
tmp = 10 - exp_gcode0;
L_tmp = L_shr(L_tmp, tmp, pOverflow);
*gain_cod = (Word16)(L_tmp >> 16);
/*------------------------------------------------------------------*
* calculate predictor update values and update gain predictor: *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* *
* qua_ener = log2(g) *
* qua_ener_MR122 = 20*log10(g) *
*------------------------------------------------------------------*/
/* Log2(x Q12) = log2(x) + 12 */
Log2((Word32) g_code, &exp, &frac, pOverflow);
exp -= 12;
tmp = shr_r(frac, 5, pOverflow);
qua_ener_MR122 = exp << 10;
qua_ener_MR122 = tmp + qua_ener_MR122;
/* 24660 Q12 ~= 6.0206 = 20*log10(2) */
L_tmp = Mpy_32_16(exp, frac, 24660, pOverflow);
L_tmp = L_tmp << 13;
/* Q12 * Q0 = Q13 -> Q10 */
qua_ener = (Word16)((L_tmp + (Word32) 0x00008000L) >> 16);
gc_pred_update(pred_st, qua_ener_MR122, qua_ener);
return;
}
/****************************************************************************/
/*
------------------------------------------------------------------------------
FUNCTION NAME: MR475_update_unq_pred
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
pred_st = pointer to structure of type gc_predState
exp_gcode0 = predicted CB gain (exponent MSW) (Word16)
frac_gcode0 = predicted CB gain (exponent LSW) (Word16)
cod_gain_exp = optimum codebook gain (exponent)(Word16)
cod_gain_frac = optimum codebook gain (fraction) (Word16)
Outputs:
pred_st points to the updated structure of type gc_predState
pOverflow points to overflow indicator (Flag)
Returns:
None.
Global Variables Used:
None.
Local Variables Needed:
None.
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
This module uses the optimum codebook gain and updates the "unquantized"
gain predictor with the (bounded) prediction error.
------------------------------------------------------------------------------
REQUIREMENTS
None.
------------------------------------------------------------------------------
REFERENCES
qgain475.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
void
MR475_update_unq_pred(
gc_predState *pred_st, // i/o: gain predictor state struct
Word16 exp_gcode0, // i : predicted CB gain (exponent MSW), Q0
Word16 frac_gcode0, // i : predicted CB gain (exponent LSW), Q15
Word16 cod_gain_exp, // i : optimum codebook gain (exponent), Q0
Word16 cod_gain_frac // i : optimum codebook gain (fraction), Q15
)
{
Word16 tmp, exp, frac;
Word16 qua_ener, qua_ener_MR122;
Word32 L_tmp;
// calculate prediction error factor (given optimum CB gain gcu):
// predErrFact = gcu / gcode0
// (limit to MIN_PRED_ERR_FACT <= predErrFact <= MAX_PRED_ERR_FACT
// -> limit qua_ener*)
//
// calculate prediction error (log):
//
// qua_ener_MR122 = log2(predErrFact)
// qua_ener = 20*log10(predErrFact)
if (cod_gain_frac <= 0)
{
// if gcu <= 0 -> predErrFact = 0 < MIN_PRED_ERR_FACT
// -> set qua_ener(_MR122) directly
qua_ener = MIN_QUA_ENER;
qua_ener_MR122 = MIN_QUA_ENER_MR122;
}
else
{
// convert gcode0 from DPF to standard fraction/exponent format
// with normalized frac, i.e. 16384 <= frac <= 32767
// Note: exponent correction (exp=exp-14) is done after div_s
frac_gcode0 = extract_l (Pow2 (14, frac_gcode0));
// make sure cod_gain_frac < frac_gcode0 for div_s
if (sub(cod_gain_frac, frac_gcode0) >= 0)
{
cod_gain_frac = shr (cod_gain_frac, 1);
cod_gain_exp = add (cod_gain_exp, 1);
}
// predErrFact
// = gcu / gcode0
// = cod_gain_frac/frac_gcode0 * 2^(cod_gain_exp-(exp_gcode0-14))
// = div_s (c_g_f, frac_gcode0)*2^-15 * 2^(c_g_e-exp_gcode0+14)
// = div_s * 2^(cod_gain_exp-exp_gcode0 - 1)
frac = div_s (cod_gain_frac, frac_gcode0);
tmp = sub (sub (cod_gain_exp, exp_gcode0), 1);
Log2 (L_deposit_l (frac), &exp, &frac);
exp = add (exp, tmp);
// calculate prediction error (log2, Q10)
qua_ener_MR122 = shr_r (frac, 5);
qua_ener_MR122 = add (qua_ener_MR122, shl (exp, 10));
if (sub(qua_ener_MR122, MIN_QUA_ENER_MR122) < 0)
{
qua_ener = MIN_QUA_ENER;
qua_ener_MR122 = MIN_QUA_ENER_MR122;
}
else if (sub(qua_ener_MR122, MAX_QUA_ENER_MR122) > 0)
{
qua_ener = MAX_QUA_ENER;
qua_ener_MR122 = MAX_QUA_ENER_MR122;
}
else
{
// calculate prediction error (20*log10, Q10)
L_tmp = Mpy_32_16(exp, frac, 24660);
// 24660 Q12 ~= 6.0206 = 20*log10(2)
qua_ener = pv_round (L_shl (L_tmp, 13));
// Q12 * Q0 = Q13 -> Q26 -> Q10
}
}
// update MA predictor memory
gc_pred_update(pred_st, qua_ener_MR122, qua_ener);
}
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
void MR475_update_unq_pred(
gc_predState *pred_st, /* i/o: gain predictor state struct */
Word16 exp_gcode0, /* i : predicted CB gain (exponent MSW), Q0 */
Word16 frac_gcode0, /* i : predicted CB gain (exponent LSW), Q15 */
Word16 cod_gain_exp, /* i : optimum codebook gain (exponent), Q0 */
Word16 cod_gain_frac, /* i : optimum codebook gain (fraction), Q15 */
Flag *pOverflow /* o : overflow indicator */
)
{
Word16 tmp;
Word16 exp;
Word16 frac;
Word16 qua_ener;
Word16 qua_ener_MR122;
Word32 L_tmp;
/* calculate prediction error factor (given optimum CB gain gcu):
*
* predErrFact = gcu / gcode0
* (limit to MIN_PRED_ERR_FACT <= predErrFact <= MAX_PRED_ERR_FACT
* -> limit qua_ener*)
*
* calculate prediction error (log):
*
* qua_ener_MR122 = log2(predErrFact)
* qua_ener = 20*log10(predErrFact)
*
*/
if (cod_gain_frac <= 0)
{
/* if gcu <= 0 -> predErrFact = 0 < MIN_PRED_ERR_FACT */
/* -> set qua_ener(_MR122) directly */
qua_ener = MIN_QUA_ENER;
qua_ener_MR122 = MIN_QUA_ENER_MR122;
}
else
{
/* convert gcode0 from DPF to standard fraction/exponent format */
/* with normalized frac, i.e. 16384 <= frac <= 32767 */
/* Note: exponent correction (exp=exp-14) is done after div_s */
frac_gcode0 = (Word16)(Pow2(14, frac_gcode0, pOverflow));
/* make sure cod_gain_frac < frac_gcode0 for div_s */
if (cod_gain_frac >= frac_gcode0)
{
cod_gain_frac >>= 1;
cod_gain_exp += 1;
}
/*
predErrFact
= gcu / gcode0
= cod_gain_frac/frac_gcode0 * 2^(cod_gain_exp-(exp_gcode0-14))
= div_s (c_g_f, frac_gcode0)*2^-15 * 2^(c_g_e-exp_gcode0+14)
= div_s * 2^(cod_gain_exp-exp_gcode0 - 1)
*/
frac = div_s(cod_gain_frac, frac_gcode0);
tmp = cod_gain_exp - exp_gcode0;
tmp -= 1;
Log2((Word32) frac, &exp, &frac, pOverflow);
exp += tmp;
/* calculate prediction error (log2, Q10) */
qua_ener_MR122 = shr_r(frac, 5, pOverflow);
tmp = exp << 10;
qua_ener_MR122 += tmp;
if (qua_ener_MR122 > MAX_QUA_ENER_MR122)
{
qua_ener = MAX_QUA_ENER;
qua_ener_MR122 = MAX_QUA_ENER_MR122;
}
else
{
/* calculate prediction error (20*log10, Q10) */
L_tmp = Mpy_32_16(exp, frac, 24660, pOverflow);
/* 24660 Q12 ~= 6.0206 = 20*log10(2) */
L_tmp = L_shl(L_tmp, 13, pOverflow);
qua_ener = pv_round(L_tmp, pOverflow);
/* Q12 * Q0 = Q13 -> Q26 -> Q10 */
}
}
/* update MA predictor memory */
gc_pred_update(pred_st, qua_ener_MR122, qua_ener);
return;
}
/****************************************************************************/
/*
------------------------------------------------------------------------------
FUNCTION NAME: MR475_gain_quant
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
pred_st = pointer to structure of type gc_predState
sf0_exp_gcode0 = predicted CB gain (exponent) (Word16)
f0_frac_gcode0 = predicted CB gain (fraction) (Word16)
sf0_exp_coeff = energy coeff. (exponent part) (Word16)
sf0_frac_coeff = energy coeff. ((fraction part) (Word16)
sf0_exp_target_en = exponent of target energy (Word16)
sf0_frac_target_en = fraction of target energy (Word16)
sf1_code_nosharp = innovative codebook vector (Word16)
sf1_exp_gcode0 = predicted CB gain (exponent) (Word16)
sf1_frac_gcode0 = predicted CB gain (fraction) (Word16)
sf1_exp_coeff = energy coeff. (exponent part) (Word16)
sf1_frac_coeff = energy coeff. (fraction part) (Word16)
sf1_exp_target_en = exponent of target energy (Word16)
sf1_frac_target_en = fraction of target energy (Word16)
gp_limit = pitch gain limit (Word16)
sf0_gain_pit = pointer to Pitch gain (Word16)
sf0_gain_cod = pointer to Code gain (Word16)
sf1_gain_pit = pointer to Pitch gain (Word16)
sf1_gain_cod = pointer to Code gain (Word16)
Outputs:
pred_st points to the updated structure of type gc_predState
sf0_gain_pit points to Pitch gain
sf0_gain_cod points to Code gain
sf1_gain_pit points to Pitch gain
sf1_gain_cod points to Code gain
Returns:
index = index of quantization
Global Variables Used:
None.
Local Variables Needed:
None.
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
This module provides quantization of pitch and codebook gains for two
subframes using the predicted codebook gain.
------------------------------------------------------------------------------
REQUIREMENTS
None.
------------------------------------------------------------------------------
REFERENCES
qgain475.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
Word16
MR475_gain_quant( // o : index of quantization.
gc_predState *pred_st, // i/o: gain predictor state struct
// data from subframe 0 (or 2)
Word16 sf0_exp_gcode0, // i : predicted CB gain (exponent), Q0
Word16 sf0_frac_gcode0, // i : predicted CB gain (fraction), Q15
Word16 sf0_exp_coeff[], // i : energy coeff. (5), exponent part, Q0
Word16 sf0_frac_coeff[], // i : energy coeff. (5), fraction part, Q15
// (frac_coeff and exp_coeff computed in
// calc_filt_energies())
Word16 sf0_exp_target_en, // i : exponent of target energy, Q0
Word16 sf0_frac_target_en, // i : fraction of target energy, Q15
// data from subframe 1 (or 3)
Word16 sf1_code_nosharp[], // i : innovative codebook vector (L_SUBFR)
// (whithout pitch sharpening)
Word16 sf1_exp_gcode0, // i : predicted CB gain (exponent), Q0
Word16 sf1_frac_gcode0, // i : predicted CB gain (fraction), Q15
Word16 sf1_exp_coeff[], // i : energy coeff. (5), exponent part, Q0
Word16 sf1_frac_coeff[], // i : energy coeff. (5), fraction part, Q15
// (frac_coeff and exp_coeff computed in
// calc_filt_energies())
Word16 sf1_exp_target_en, // i : exponent of target energy, Q0
Word16 sf1_frac_target_en, // i : fraction of target energy, Q15
Word16 gp_limit, // i : pitch gain limit
Word16 *sf0_gain_pit, // o : Pitch gain, Q14
Word16 *sf0_gain_cod, // o : Code gain, Q1
Word16 *sf1_gain_pit, // o : Pitch gain, Q14
Word16 *sf1_gain_cod // o : Code gain, Q1
)
{
const Word16 *p;
Word16 i, index = 0;
Word16 tmp;
Word16 exp;
Word16 sf0_gcode0, sf1_gcode0;
Word16 g_pitch, g2_pitch, g_code, g2_code, g_pit_cod;
Word16 coeff[10], coeff_lo[10], exp_max[10]; // 0..4: sf0; 5..9: sf1
Word32 L_tmp, dist_min;
*-------------------------------------------------------------------*
* predicted codebook gain *
* ~~~~~~~~~~~~~~~~~~~~~~~ *
* gc0 = 2^exp_gcode0 + 2^frac_gcode0 *
* *
* gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0) *
*-------------------------------------------------------------------*
sf0_gcode0 = extract_l(Pow2(14, sf0_frac_gcode0));
sf1_gcode0 = extract_l(Pow2(14, sf1_frac_gcode0));
* For each subframe, the error energy (sum) to be minimized consists
* of five terms, t[0..4].
*
* t[0] = gp^2 * <y1 y1>
* t[1] = -2*gp * <xn y1>
* t[2] = gc^2 * <y2 y2>
* t[3] = -2*gc * <xn y2>
* t[4] = 2*gp*gc * <y1 y2>
*
// sf 0
// determine the scaling exponent for g_code: ec = ec0 - 11
exp = sub(sf0_exp_gcode0, 11);
// calculate exp_max[i] = s[i]-1
exp_max[0] = sub(sf0_exp_coeff[0], 13);
exp_max[1] = sub(sf0_exp_coeff[1], 14);
exp_max[2] = add(sf0_exp_coeff[2], add(15, shl(exp, 1)));
exp_max[3] = add(sf0_exp_coeff[3], exp);
exp_max[4] = add(sf0_exp_coeff[4], add(1, exp));
// sf 1
// determine the scaling exponent for g_code: ec = ec0 - 11
exp = sub(sf1_exp_gcode0, 11);
// calculate exp_max[i] = s[i]-1
exp_max[5] = sub(sf1_exp_coeff[0], 13);
exp_max[6] = sub(sf1_exp_coeff[1], 14);
exp_max[7] = add(sf1_exp_coeff[2], add(15, shl(exp, 1)));
exp_max[8] = add(sf1_exp_coeff[3], exp);
exp_max[9] = add(sf1_exp_coeff[4], add(1, exp));
*-------------------------------------------------------------------*
* Gain search equalisation: *
* ~~~~~~~~~~~~~~~~~~~~~~~~~ *
* The MSE for the two subframes is weighted differently if there *
* is a big difference in the corresponding target energies *
*-------------------------------------------------------------------*
// make the target energy exponents the same by de-normalizing the
// fraction of the smaller one. This is necessary to be able to compare
// them
exp = sf0_exp_target_en - sf1_exp_target_en;
if (exp > 0)
{
sf1_frac_target_en = shr (sf1_frac_target_en, exp);
}
else
{
sf0_frac_target_en = shl (sf0_frac_target_en, exp);
}
// assume no change of exponents
exp = 0;
// test for target energy difference; set exp to +1 or -1 to scale
// up/down coefficients for sf 1
tmp = shr_r (sf1_frac_target_en, 1); // tmp = ceil(0.5*en(sf1))
if (sub (tmp, sf0_frac_target_en) > 0) // tmp > en(sf0)?
{
// target_energy(sf1) > 2*target_energy(sf0)
// -> scale up MSE(sf0) by 2 by adding 1 to exponents 0..4
exp = 1;
}
else
{
tmp = shr (add (sf0_frac_target_en, 3), 2); // tmp=ceil(0.25*en(sf0))
if (sub (tmp, sf1_frac_target_en) > 0) // tmp > en(sf1)?
{
// target_energy(sf1) < 0.25*target_energy(sf0)
// -> scale down MSE(sf0) by 0.5 by subtracting 1 from
// coefficients 0..4
exp = -1;
}
}
for (i = 0; i < 5; i++)
{
exp_max[i] = add (exp_max[i], exp);
}
*-------------------------------------------------------------------*
* Find maximum exponent: *
* ~~~~~~~~~~~~~~~~~~~~~~ *
* *
* For the sum operation, all terms must have the same scaling; *
* that scaling should be low enough to prevent overflow. There- *
* fore, the maximum scale is determined and all coefficients are *
* re-scaled: *
* *
* exp = max(exp_max[i]) + 1; *
* e = exp_max[i]-exp; e <= 0! *
* c[i] = c[i]*2^e *
*-------------------------------------------------------------------*
exp = exp_max[0];
for (i = 1; i < 10; i++)
{
if (sub(exp_max[i], exp) > 0)
{
exp = exp_max[i];
}
}
exp = add(exp, 1); // To avoid overflow
p = &sf0_frac_coeff[0];
for (i = 0; i < 5; i++) {
tmp = sub(exp, exp_max[i]);
L_tmp = L_deposit_h(*p++);
L_tmp = L_shr(L_tmp, tmp);
L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);
}
p = &sf1_frac_coeff[0];
for (; i < 10; i++) {
tmp = sub(exp, exp_max[i]);
L_tmp = L_deposit_h(*p++);
L_tmp = L_shr(L_tmp, tmp);
L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);
}
//-------------------------------------------------------------------*
* Codebook search: *
* ~~~~~~~~~~~~~~~~ *
* *
* For each pair (g_pitch, g_fac) in the table calculate the *
* terms t[0..4] and sum them up; the result is the mean squared *
* error for the quantized gains from the table. The index for the *
* minimum MSE is stored and finally used to retrieve the quantized *
* gains *
*-------------------------------------------------------------------
// start with "infinite" MSE
dist_min = MAX_32;
p = &table_gain_MR475[0];
for (i = 0; i < MR475_VQ_SIZE; i++)
{
// subframe 0 (and 2) calculations
g_pitch = *p++;
g_code = *p++;
g_code = mult(g_code, sf0_gcode0);
g2_pitch = mult(g_pitch, g_pitch);
g2_code = mult(g_code, g_code);
g_pit_cod = mult(g_code, g_pitch);
L_tmp = Mpy_32_16( coeff[0], coeff_lo[0], g2_pitch);
L_tmp = Mac_32_16(L_tmp, coeff[1], coeff_lo[1], g_pitch);
L_tmp = Mac_32_16(L_tmp, coeff[2], coeff_lo[2], g2_code);
L_tmp = Mac_32_16(L_tmp, coeff[3], coeff_lo[3], g_code);
L_tmp = Mac_32_16(L_tmp, coeff[4], coeff_lo[4], g_pit_cod);
tmp = sub (g_pitch, gp_limit);
// subframe 1 (and 3) calculations
g_pitch = *p++;
g_code = *p++;
if (tmp <= 0 && sub(g_pitch, gp_limit) <= 0)
{
g_code = mult(g_code, sf1_gcode0);
g2_pitch = mult(g_pitch, g_pitch);
g2_code = mult(g_code, g_code);
g_pit_cod = mult(g_code, g_pitch);
L_tmp = Mac_32_16(L_tmp, coeff[5], coeff_lo[5], g2_pitch);
L_tmp = Mac_32_16(L_tmp, coeff[6], coeff_lo[6], g_pitch);
L_tmp = Mac_32_16(L_tmp, coeff[7], coeff_lo[7], g2_code);
L_tmp = Mac_32_16(L_tmp, coeff[8], coeff_lo[8], g_code);
L_tmp = Mac_32_16(L_tmp, coeff[9], coeff_lo[9], g_pit_cod);
// store table index if MSE for this index is lower
than the minimum MSE seen so far
if (L_sub(L_tmp, dist_min) < (Word32) 0)
{
dist_min = L_tmp;
index = i;
}
}
}
*------------------------------------------------------------------*
* read quantized gains and update MA predictor memories *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
*------------------------------------------------------------------*
// for subframe 0, the pre-calculated gcode0/exp_gcode0 are the same
// as those calculated from the "real" predictor using quantized gains
tmp = shl(index, 2);
MR475_quant_store_results(pred_st,
&table_gain_MR475[tmp],
sf0_gcode0,
sf0_exp_gcode0,
sf0_gain_pit,
sf0_gain_cod);
// calculate new predicted gain for subframe 1 (this time using
// the real, quantized gains)
gc_pred(pred_st, MR475, sf1_code_nosharp,
&sf1_exp_gcode0, &sf1_frac_gcode0,
&sf0_exp_gcode0, &sf0_gcode0); // last two args are dummy
sf1_gcode0 = extract_l(Pow2(14, sf1_frac_gcode0));
tmp = add (tmp, 2);
MR475_quant_store_results(pred_st,
&table_gain_MR475[tmp],
sf1_gcode0,
sf1_exp_gcode0,
sf1_gain_pit,
sf1_gain_cod);
return index;
}
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
Word16 MR475_gain_quant( /* o : index of quantization. */
gc_predState *pred_st, /* i/o: gain predictor state struct */
/* data from subframe 0 (or 2) */
Word16 sf0_exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
Word16 sf0_frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
Word16 sf0_exp_coeff[], /* i : energy coeff. (5), exponent part, Q0 */
Word16 sf0_frac_coeff[], /* i : energy coeff. (5), fraction part, Q15 */
/* (frac_coeff and exp_coeff computed in */
/* calc_filt_energies()) */
Word16 sf0_exp_target_en, /* i : exponent of target energy, Q0 */
Word16 sf0_frac_target_en, /* i : fraction of target energy, Q15 */
/* data from subframe 1 (or 3) */
Word16 sf1_code_nosharp[], /* i : innovative codebook vector (L_SUBFR) */
/* (whithout pitch sharpening) */
Word16 sf1_exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
Word16 sf1_frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
Word16 sf1_exp_coeff[], /* i : energy coeff. (5), exponent part, Q0 */
Word16 sf1_frac_coeff[], /* i : energy coeff. (5), fraction part, Q15 */
/* (frac_coeff and exp_coeff computed in */
/* calc_filt_energies()) */
Word16 sf1_exp_target_en, /* i : exponent of target energy, Q0 */
Word16 sf1_frac_target_en, /* i : fraction of target energy, Q15 */
Word16 gp_limit, /* i : pitch gain limit */
Word16 *sf0_gain_pit, /* o : Pitch gain, Q14 */
Word16 *sf0_gain_cod, /* o : Code gain, Q1 */
Word16 *sf1_gain_pit, /* o : Pitch gain, Q14 */
Word16 *sf1_gain_cod, /* o : Code gain, Q1 */
Flag *pOverflow /* o : overflow indicator */
)
{
const Word16 *p;
Word16 i;
Word16 index = 0;
Word16 tmp;
Word16 exp;
Word16 sf0_gcode0;
Word16 sf1_gcode0;
Word16 g_pitch;
Word16 g2_pitch;
Word16 g_code;
Word16 g2_code;
Word16 g_pit_cod;
Word16 coeff[10];
Word16 coeff_lo[10];
Word16 exp_max[10]; /* 0..4: sf0; 5..9: sf1 */
Word32 L_tmp;
Word32 dist_min;
/*-------------------------------------------------------------------*
* predicted codebook gain *
* ~~~~~~~~~~~~~~~~~~~~~~~ *
* gc0 = 2^exp_gcode0 + 2^frac_gcode0 *
* *
* gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0) *
*-------------------------------------------------------------------*/
sf0_gcode0 = (Word16)(Pow2(14, sf0_frac_gcode0, pOverflow));
sf1_gcode0 = (Word16)(Pow2(14, sf1_frac_gcode0, pOverflow));
/*
* For each subframe, the error energy (sum) to be minimized consists
* of five terms, t[0..4].
*
* t[0] = gp^2 * <y1 y1>
* t[1] = -2*gp * <xn y1>
* t[2] = gc^2 * <y2 y2>
* t[3] = -2*gc * <xn y2>
* t[4] = 2*gp*gc * <y1 y2>
*
*/
/* sf 0 */
/* determine the scaling exponent for g_code: ec = ec0 - 11 */
exp = sf0_exp_gcode0 - 11;
/* calculate exp_max[i] = s[i]-1 */
exp_max[0] = (sf0_exp_coeff[0] - 13);
exp_max[1] = (sf0_exp_coeff[1] - 14);
exp_max[2] = (sf0_exp_coeff[2] + (15 + (exp << 1)));
exp_max[3] = (sf0_exp_coeff[3] + exp);
exp_max[4] = (sf0_exp_coeff[4] + (1 + exp));
/* sf 1 */
/* determine the scaling exponent for g_code: ec = ec0 - 11 */
exp = sf1_exp_gcode0 - 11;
/* calculate exp_max[i] = s[i]-1 */
exp_max[5] = (sf1_exp_coeff[0] - 13);
exp_max[6] = (sf1_exp_coeff[1] - 14);
exp_max[7] = (sf1_exp_coeff[2] + (15 + (exp << 1)));
exp_max[8] = (sf1_exp_coeff[3] + exp);
exp_max[9] = (sf1_exp_coeff[4] + (1 + exp));
/*-------------------------------------------------------------------*
* Gain search equalisation: *
* ~~~~~~~~~~~~~~~~~~~~~~~~~ *
* The MSE for the two subframes is weighted differently if there *
* is a big difference in the corresponding target energies *
*-------------------------------------------------------------------*/
/* make the target energy exponents the same by de-normalizing the
fraction of the smaller one. This is necessary to be able to compare
them
*/
exp = sf0_exp_target_en - sf1_exp_target_en;
if (exp > 0)
{
sf1_frac_target_en >>= exp;
}
else
{
sf0_frac_target_en >>= (-exp);
}
/* assume no change of exponents */
exp = 0;
/* test for target energy difference; set exp to +1 or -1 to scale
* up/down coefficients for sf 1
*/
tmp = shr_r(sf1_frac_target_en, 1, pOverflow); /* tmp = ceil(0.5*en(sf1)) */
if (tmp > sf0_frac_target_en) /* tmp > en(sf0)? */
{
/*
* target_energy(sf1) > 2*target_energy(sf0)
* -> scale up MSE(sf0) by 2 by adding 1 to exponents 0..4
*/
exp = 1;
}
else
{
tmp = ((sf0_frac_target_en + 3) >> 2); /* tmp=ceil(0.25*en(sf0)) */
if (tmp > sf1_frac_target_en) /* tmp > en(sf1)? */
{
/*
* target_energy(sf1) < 0.25*target_energy(sf0)
* -> scale down MSE(sf0) by 0.5 by subtracting 1 from
* coefficients 0..4
*/
exp = -1;
}
}
for (i = 0; i < 5; i++)
{
exp_max[i] += exp;
}
/*-------------------------------------------------------------------*
* Find maximum exponent: *
* ~~~~~~~~~~~~~~~~~~~~~~ *
* *
* For the sum operation, all terms must have the same scaling; *
* that scaling should be low enough to prevent overflow. There- *
* fore, the maximum scale is determined and all coefficients are *
* re-scaled: *
* *
* exp = max(exp_max[i]) + 1; *
* e = exp_max[i]-exp; e <= 0! *
* c[i] = c[i]*2^e *
*-------------------------------------------------------------------*/
exp = exp_max[0];
for (i = 9; i > 0; i--)
{
if (exp_max[i] > exp)
{
exp = exp_max[i];
}
}
exp++; /* To avoid overflow */
p = &sf0_frac_coeff[0];
for (i = 0; i < 5; i++)
{
tmp = (exp - exp_max[i]);
L_tmp = ((Word32)(*p++) << 16);
L_tmp = L_shr(L_tmp, tmp, pOverflow);
coeff[i] = (Word16)(L_tmp >> 16);
coeff_lo[i] = (Word16)((L_tmp >> 1) - ((L_tmp >> 16) << 15));
}
p = &sf1_frac_coeff[0];
for (; i < 10; i++)
{
tmp = exp - exp_max[i];
L_tmp = ((Word32)(*p++) << 16);
L_tmp = L_shr(L_tmp, tmp, pOverflow);
coeff[i] = (Word16)(L_tmp >> 16);
coeff_lo[i] = (Word16)((L_tmp >> 1) - ((L_tmp >> 16) << 15));
}
/*-------------------------------------------------------------------*
* Codebook search: *
* ~~~~~~~~~~~~~~~~ *
* *
* For each pair (g_pitch, g_fac) in the table calculate the *
* terms t[0..4] and sum them up; the result is the mean squared *
* error for the quantized gains from the table. The index for the *
* minimum MSE is stored and finally used to retrieve the quantized *
* gains *
*-------------------------------------------------------------------*/
/* start with "infinite" MSE */
dist_min = MAX_32;
p = &table_gain_MR475[0];
for (i = 0; i < MR475_VQ_SIZE; i++)
{
/* subframe 0 (and 2) calculations */
g_pitch = *p++;
g_code = *p++;
/* Need to be there OKA */
g_code = (Word16)(((Word32) g_code * sf0_gcode0) >> 15);
g2_pitch = (Word16)(((Word32) g_pitch * g_pitch) >> 15);
g2_code = (Word16)(((Word32) g_code * g_code) >> 15);
g_pit_cod = (Word16)(((Word32) g_code * g_pitch) >> 15);
L_tmp = Mpy_32_16(coeff[0], coeff_lo[0], g2_pitch, pOverflow) +
Mpy_32_16(coeff[1], coeff_lo[1], g_pitch, pOverflow) +
Mpy_32_16(coeff[2], coeff_lo[2], g2_code, pOverflow) +
Mpy_32_16(coeff[3], coeff_lo[3], g_code, pOverflow) +
Mpy_32_16(coeff[4], coeff_lo[4], g_pit_cod, pOverflow);
tmp = (g_pitch - gp_limit);
/* subframe 1 (and 3) calculations */
g_pitch = *p++;
g_code = *p++;
if ((tmp <= 0) && (g_pitch <= gp_limit))
{
g_code = (Word16)(((Word32) g_code * sf1_gcode0) >> 15);
g2_pitch = (Word16)(((Word32) g_pitch * g_pitch) >> 15);
g2_code = (Word16)(((Word32) g_code * g_code) >> 15);
g_pit_cod = (Word16)(((Word32) g_code * g_pitch) >> 15);
L_tmp += (Mpy_32_16(coeff[5], coeff_lo[5], g2_pitch, pOverflow) +
Mpy_32_16(coeff[6], coeff_lo[6], g_pitch, pOverflow) +
Mpy_32_16(coeff[7], coeff_lo[7], g2_code, pOverflow) +
Mpy_32_16(coeff[8], coeff_lo[8], g_code, pOverflow) +
Mpy_32_16(coeff[9], coeff_lo[9], g_pit_cod, pOverflow));
/* store table index if MSE for this index is lower
than the minimum MSE seen so far */
if (L_tmp < dist_min)
{
dist_min = L_tmp;
index = i;
}
}
}
/*------------------------------------------------------------------*
* read quantized gains and update MA predictor memories *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
*------------------------------------------------------------------*/
/* for subframe 0, the pre-calculated gcode0/exp_gcode0 are the same
as those calculated from the "real" predictor using quantized gains */
tmp = index << 2;
MR475_quant_store_results(pred_st,
&table_gain_MR475[tmp],
sf0_gcode0,
sf0_exp_gcode0,
sf0_gain_pit,
sf0_gain_cod,
pOverflow);
/* calculate new predicted gain for subframe 1 (this time using
the real, quantized gains) */
gc_pred(pred_st, MR475, sf1_code_nosharp,
&sf1_exp_gcode0, &sf1_frac_gcode0,
&sf0_exp_gcode0, &sf0_gcode0, /* dummy args */
pOverflow);
sf1_gcode0 = (Word16)(Pow2(14, sf1_frac_gcode0, pOverflow));
tmp += 2;
MR475_quant_store_results(
pred_st,
&table_gain_MR475[tmp],
sf1_gcode0,
sf1_exp_gcode0,
sf1_gain_pit,
sf1_gain_cod,
pOverflow);
return(index);
}