diff options
Diffstat (limited to 'media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp')
-rw-r--r-- | media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp | 1445 |
1 files changed, 1445 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp b/media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp new file mode 100644 index 0000000..f8da589 --- /dev/null +++ b/media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp @@ -0,0 +1,1445 @@ +/* ------------------------------------------------------------------ + * 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); +} |