summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp')
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp1445
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);
+}