Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 /****************************************************************************************
     19 Portions of this file are derived from the following 3GPP standard:
     20 
     21     3GPP TS 26.073
     22     ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
     23     Available from http://www.3gpp.org
     24 
     25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
     26 Permission to distribute, modify and use this file under the standard license
     27 terms listed above has been obtained from the copyright holder.
     28 ****************************************************************************************/
     29 /*
     30 ------------------------------------------------------------------------------
     31 
     32 
     33 
     34  Pathname: ./audio/gsm-amr/c/src/calc_en.c
     35  Funtions: calc_unfilt_energies
     36            calc_filt_energies
     37            calc_target_energy
     38 
     39 ------------------------------------------------------------------------------
     40  MODULE DESCRIPTION
     41 
     42  This file contains the functions that calculate the energy coefficients
     43  for unfiltered and filtered excitation signals, the LTP coding gain, and
     44  the target energy.
     45 
     46 ------------------------------------------------------------------------------
     47 */
     48 
     49 
     50 /*----------------------------------------------------------------------------
     51 ; INCLUDES
     52 ----------------------------------------------------------------------------*/
     53 
     54 #include "calc_en.h"
     55 #include "typedef.h"
     56 #include "basicop_malloc.h"
     57 #include "l_comp.h"
     58 #include "cnst.h"
     59 #include "log2.h"
     60 #include "basic_op.h"
     61 
     62 /*----------------------------------------------------------------------------
     63 ; MACROS
     64 ; Define module specific macros here
     65 ----------------------------------------------------------------------------*/
     66 
     67 
     68 /*----------------------------------------------------------------------------
     69 ; DEFINES
     70 ; Include all pre-processor statements here. Include conditional
     71 ; compile variables also.
     72 ----------------------------------------------------------------------------*/
     73 
     74 
     75 /*----------------------------------------------------------------------------
     76 ; LOCAL FUNCTION DEFINITIONS
     77 ; Function Prototype declaration
     78 ----------------------------------------------------------------------------*/
     79 
     80 /*----------------------------------------------------------------------------
     81 ; LOCAL VARIABLE DEFINITIONS
     82 ; Variable declaration - defined here and used outside this module
     83 ----------------------------------------------------------------------------*/
     84 
     85 
     86 /*
     87 ------------------------------------------------------------------------------
     88  FUNCTION NAME: calc_unfilt_energies
     89 ------------------------------------------------------------------------------
     90  INPUT AND OUTPUT DEFINITIONS
     91 
     92  Inputs:
     93     res      = LP residual, buffer type Word16
     94     exc      = LTP excitation (unfiltered), buffer type Word16
     95     code     = CB innovation (unfiltered), buffer type Word16
     96     gain_pit = pitch gain,  type Word16
     97     L_subfr  = Subframe length, type Word16
     98     frac_en  = energy coefficients (4), fraction part, buffer type Word16
     99     exp_en   = energy coefficients (4), exponent part, buffer type Word16
    100     ltpg     = LTP coding gain (log2()), pointer to type Word16
    101     pOverflow= pointer to value indicating existence of overflow (Flag)
    102 
    103  Outputs:
    104     frac_en buffer containing new fractional parts of energy coefficients
    105     exp_en buffer containing new exponential parts of energy coefficients
    106     ltpg points to new LTP coding gain
    107     pOverflow = 1 if there is an overflow else it is zero.
    108 
    109  Returns:
    110     None.
    111 
    112  Global Variables Used:
    113     None
    114 
    115  Local Variables Needed:
    116     None
    117 
    118 ------------------------------------------------------------------------------
    119  FUNCTION DESCRIPTION
    120 
    121  This function calculates several energy coefficients for unfiltered
    122  excitation signals and the LTP coding gain
    123 
    124     frac_en[0]*2^exp_en[0] = <res res>    LP residual energy
    125     frac_en[1]*2^exp_en[1] = <exc exc>    LTP residual energy
    126     frac_en[2]*2^exp_en[2] = <exc code>   LTP/CB innovation dot product
    127     frac_en[3]*2^exp_en[3] = <lres lres>  LTP residual energy
    128     (lres = res - gain_pit*exc)
    129     ltpg = log2(LP_res_en / LTP_res_en)
    130 
    131 ------------------------------------------------------------------------------
    132  REQUIREMENTS
    133 
    134   None.
    135 
    136 ------------------------------------------------------------------------------
    137  REFERENCES
    138 
    139  calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    140 
    141 ------------------------------------------------------------------------------
    142  PSEUDO-CODE
    143 
    144 void
    145 calc_unfilt_energies(
    146     Word16 res[],     // i  : LP residual,                               Q0
    147     Word16 exc[],     // i  : LTP excitation (unfiltered),               Q0
    148     Word16 code[],    // i  : CB innovation (unfiltered),                Q13
    149     Word16 gain_pit,  // i  : pitch gain,                                Q14
    150     Word16 L_subfr,   // i  : Subframe length
    151 
    152     Word16 frac_en[], // o  : energy coefficients (4), fraction part,    Q15
    153     Word16 exp_en[],  // o  : energy coefficients (4), exponent part,    Q0
    154     Word16 *ltpg      // o  : LTP coding gain (log2()),                  Q13
    155 )
    156 {
    157     Word32 s, L_temp;
    158     Word16 i, exp, tmp;
    159     Word16 ltp_res_en, pred_gain;
    160     Word16 ltpg_exp, ltpg_frac;
    161 
    162     // Compute residual energy
    163     s = L_mac((Word32) 0, res[0], res[0]);
    164     for (i = 1; i < L_subfr; i++)
    165         s = L_mac(s, res[i], res[i]);
    166 
    167     // ResEn := 0 if ResEn < 200.0 (= 400 Q1)
    168     if (L_sub (s, 400L) < 0)
    169     {
    170         frac_en[0] = 0;
    171         exp_en[0] = -15;
    172     }
    173     else
    174     {
    175         exp = norm_l(s);
    176         frac_en[0] = extract_h(L_shl(s, exp));
    177         exp_en[0] = sub(15, exp);
    178     }
    179 
    180     // Compute ltp excitation energy
    181     s = L_mac((Word32) 0, exc[0], exc[0]);
    182     for (i = 1; i < L_subfr; i++)
    183         s = L_mac(s, exc[i], exc[i]);
    184 
    185     exp = norm_l(s);
    186     frac_en[1] = extract_h(L_shl(s, exp));
    187     exp_en[1] = sub(15, exp);
    188 
    189     // Compute scalar product <exc[],code[]>
    190     s = L_mac((Word32) 0, exc[0], code[0]);
    191     for (i = 1; i < L_subfr; i++)
    192         s = L_mac(s, exc[i], code[i]);
    193 
    194     exp = norm_l(s);
    195     frac_en[2] = extract_h(L_shl(s, exp));
    196     exp_en[2] = sub(16-14, exp);
    197 
    198     // Compute energy of LTP residual
    199     s = 0L;
    200     for (i = 0; i < L_subfr; i++)
    201     {
    202         L_temp = L_mult(exc[i], gain_pit);
    203         L_temp = L_shl(L_temp, 1);
    204         tmp = sub(res[i], pv_round(L_temp)); // LTP residual, Q0
    205         s = L_mac (s, tmp, tmp);
    206     }
    207 
    208     exp = norm_l(s);
    209     ltp_res_en = extract_h (L_shl (s, exp));
    210     exp = sub (15, exp);
    211 
    212     frac_en[3] = ltp_res_en;
    213     exp_en[3] = exp;
    214 
    215     // calculate LTP coding gain, i.e. energy reduction LP res -> LTP res
    216     if (ltp_res_en > 0 && frac_en[0] != 0)
    217     {
    218         // gain = ResEn / LTPResEn
    219         pred_gain = div_s (shr (frac_en[0], 1), ltp_res_en);
    220         exp = sub (exp, exp_en[0]);
    221 
    222         // L_temp = ltpGain * 2^(30 + exp)
    223         L_temp = L_deposit_h (pred_gain);
    224         // L_temp = ltpGain * 2^27
    225         L_temp = L_shr (L_temp, add (exp, 3));
    226 
    227         // Log2 = log2() + 27
    228         Log2(L_temp, &ltpg_exp, &ltpg_frac);
    229 
    230         // ltpg = log2(LtpGain) * 2^13 --> range: +- 4 = +- 12 dB
    231         L_temp = L_Comp (sub (ltpg_exp, 27), ltpg_frac);
    232         *ltpg = pv_round (L_shl (L_temp, 13)); // Q13
    233     }
    234     else
    235     {
    236         *ltpg = 0;
    237     }
    238 }
    239 
    240 
    241 ------------------------------------------------------------------------------
    242  RESOURCES USED [optional]
    243 
    244  When the code is written for a specific target processor the
    245  the resources used should be documented below.
    246 
    247  HEAP MEMORY USED: x bytes
    248 
    249  STACK MEMORY USED: x bytes
    250 
    251  CLOCK CYCLES: (cycle count equation for this function) + (variable
    252                 used to represent cycle count for each subroutine
    253                 called)
    254      where: (cycle count variable) = cycle count for [subroutine
    255                                      name]
    256 
    257 ------------------------------------------------------------------------------
    258  CAUTION [optional]
    259  [State any special notes, constraints or cautions for users of this function]
    260 
    261 ------------------------------------------------------------------------------
    262 */
    263 
    264 void calc_unfilt_energies(
    265     Word16 res[],     /* i  : LP residual,                               Q0  */
    266     Word16 exc[],     /* i  : LTP excitation (unfiltered),               Q0  */
    267     Word16 code[],    /* i  : CB innovation (unfiltered),                Q13 */
    268     Word16 gain_pit,  /* i  : pitch gain,                                Q14 */
    269     Word16 L_subfr,   /* i  : Subframe length                                */
    270 
    271     Word16 frac_en[], /* o  : energy coefficients (4), fraction part,    Q15 */
    272     Word16 exp_en[],  /* o  : energy coefficients (4), exponent part,    Q0  */
    273     Word16 *ltpg,     /* o  : LTP coding gain (log2()),                  Q13 */
    274     Flag   *pOverflow
    275 )
    276 {
    277     Word32 s1;      /* Intermediate energy accumulator */
    278     Word32 s2;      /* Intermediate energy accumulator */
    279     Word32 s3;      /* Intermediate energy accumulator */
    280     Word32 s4;      /* Intermediate energy accumulator */
    281     Word32 L_temp;      /* temporal 32 bits storage */
    282 
    283     Word16 i;       /* index used in all loops */
    284     Word16 exp;     /* nunmber of '0's or '1's before MSB != 0 */
    285     Word16 tmp1;        /* temporal storage */
    286     Word16 tmp2;        /* temporal storage */
    287     Word16 ltp_res_en;
    288     Word16 pred_gain;   /* predictor gain */
    289     Word16 ltpg_exp;    /* LTP gain (exponent) */
    290     Word16 ltpg_frac;   /* LTP gain (mantissa or fractional part) */
    291 
    292     s1 = 0;
    293     s2 = 0;
    294     s3 = 0;
    295     s4 = 0;
    296 
    297     /*----------------------------------------------------------------------------
    298     NOTE: Overflow is expected as a result of multiply and accumulated without
    299         scale down the inputs. This modification is not made at this point
    300         to have bit exact results with the pre-optimization code. (JT 6/20/00)
    301 
    302     ----------------------------------------------------------------------------*/
    303 
    304     for (i = 0; i < L_subfr; i++)
    305     {
    306         tmp1 = res[i];              /* avoid multiple accesses to memory */
    307         tmp2 = exc[i];
    308 
    309         s1 = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s1);   /* Compute residual energy */
    310         s2 = amrnb_fxp_mac_16_by_16bb((Word32) tmp2, (Word32) tmp2, s2);   /* Compute ltp excitation energy */
    311         s3 = amrnb_fxp_mac_16_by_16bb((Word32) tmp2, (Word32) code[i], s3);/* Compute scalar product */
    312         /* <exc[],code[]>         */
    313 
    314         L_temp = L_mult(tmp2, gain_pit, pOverflow);
    315         L_temp = L_shl(L_temp, 1, pOverflow);
    316         tmp2   = sub(tmp1, pv_round(L_temp, pOverflow), pOverflow);
    317         /* LTP residual, Q0 */
    318         s4     = L_mac(s4, tmp2, tmp2, pOverflow);
    319         /* Compute energy of LTP residual */
    320     }
    321     s1 = s1 << 1;
    322     s2 = s2 << 1;
    323     s3 = s3 << 1;
    324 
    325     if (s1 & MIN_32)
    326     {
    327         s1 = MAX_32;
    328         *pOverflow = 1;
    329     }
    330 
    331     /* ResEn := 0 if ResEn < 200.0 (= 400 Q1) */
    332     if (s1 < 400L)
    333     {
    334         frac_en[0] = 0;
    335         exp_en[0] = -15;
    336     }
    337     else
    338     {
    339         exp = norm_l(s1);
    340         frac_en[0] = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
    341         exp_en[0] = (15 - exp);
    342     }
    343 
    344     if (s2 & MIN_32)
    345     {
    346         s2 = MAX_32;
    347         *pOverflow = 1;
    348     }
    349 
    350     exp = norm_l(s2);
    351     frac_en[1] = (Word16)(L_shl(s2, exp, pOverflow) >> 16);
    352     exp_en[1] = sub(15, exp, pOverflow);
    353 
    354     /*  s3 is not always sum of squares */
    355     exp = norm_l(s3);
    356     frac_en[2] = (Word16)(L_shl(s3, exp, pOverflow) >> 16);
    357     exp_en[2]  = 2 - exp;
    358 
    359     exp = norm_l(s4);
    360     ltp_res_en = (Word16)(L_shl(s4, exp, pOverflow) >> 16);
    361     exp = sub(15, exp, pOverflow);
    362 
    363     frac_en[3] = ltp_res_en;
    364     exp_en[3] = exp;
    365 
    366     /* calculate LTP coding gain, i.e. energy reduction LP res -> LTP res */
    367 
    368     if (ltp_res_en > 0 && frac_en[0] != 0)
    369     {
    370         /* gain = ResEn / LTPResEn */
    371         pred_gain = div_s(shr(frac_en[0], 1, pOverflow), ltp_res_en);
    372         exp = sub(exp, exp_en[0], pOverflow);
    373 
    374         /* L_temp = ltpGain * 2^(30 + exp) */
    375         L_temp = (Word32) pred_gain << 16;
    376         /* L_temp = ltpGain * 2^27 */
    377         L_temp = L_shr(L_temp, (Word16)(exp + 3), pOverflow);
    378 
    379         /* Log2 = log2() + 27 */
    380         Log2(L_temp, &ltpg_exp, &ltpg_frac, pOverflow);
    381 
    382         /* ltpg = log2(LtpGain) * 2^13 --> range: +- 4 = +- 12 dB */
    383         L_temp = L_Comp(sub(ltpg_exp, 27, pOverflow), ltpg_frac, pOverflow);
    384         *ltpg = pv_round(L_shl(L_temp, 13, pOverflow), pOverflow);   /* Q13 */
    385     }
    386     else
    387     {
    388         *ltpg = 0;
    389     }
    390 
    391     return;
    392 }
    393 
    394 /****************************************************************************/
    395 
    396 
    397 /*
    398 ------------------------------------------------------------------------------
    399  FUNCTION NAME: calc_filt_energies
    400 ------------------------------------------------------------------------------
    401  INPUT AND OUTPUT DEFINITIONS
    402 
    403  Inputs:
    404     mode = coder mode, type Mode
    405     xn = LTP target vector, buffer type Word16
    406     xn2 = CB target vector,  buffer type Word16
    407     y1 = Adaptive codebook,  buffer type Word16
    408     Y2 = Filtered innovative vector,  buffer type Word16
    409     g_coeff = Correlations <xn y1> <y1 y1>
    410     computed in G_pitch()  buffer type Word16
    411     frac_coeff = energy coefficients (5), fraction part, buffer type Word16
    412     exp_coeff = energy coefficients (5), exponent part, buffer type Word16
    413     cod_gain_frac = optimum codebook gain (fraction part), pointer type Word16
    414     cod_gain_exp = optimum codebook gain (exponent part), pointer type Word16
    415     pOverflow    = pointer to overflow indicator (Flag)
    416 
    417  Outputs:
    418     frac_coeff contains new fraction part energy coefficients
    419     exp_coeff contains new exponent part energy coefficients
    420     cod_gain_frac points to the new optimum codebook gain (fraction part)
    421     cod_gain_exp points to the new optimum codebook gain (exponent part)
    422     pOverflow = 1 if there is an overflow else it is zero.
    423 
    424  Returns:
    425     None.
    426 
    427  Global Variables Used:
    428     None
    429 
    430  Local Variables Needed:
    431     None
    432 
    433 ------------------------------------------------------------------------------
    434  FUNCTION DESCRIPTION
    435 
    436  This function calculates several energy coefficients for filtered
    437  excitation signals
    438 
    439  Compute coefficients need for the quantization and the optimum
    440  codebook gain gcu (for MR475 only).
    441 
    442     coeff[0] =    y1 y1
    443     coeff[1] = -2 xn y1
    444     coeff[2] =    y2 y2
    445     coeff[3] = -2 xn y2
    446     coeff[4] =  2 y1 y2
    447 
    448     gcu = <xn2, y2> / <y2, y2> (0 if <xn2, y2> <= 0)
    449 
    450  Product <y1 y1> and <xn y1> have been computed in G_pitch() and
    451  are in vector g_coeff[].
    452 
    453 ------------------------------------------------------------------------------
    454  REQUIREMENTS
    455 
    456  None.
    457 
    458 ------------------------------------------------------------------------------
    459  REFERENCES
    460 
    461  calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    462 
    463 ------------------------------------------------------------------------------
    464  PSEUDO-CODE
    465 
    466 void
    467 calc_filt_energies(
    468     enum Mode mode,     // i  : coder mode
    469     Word16 xn[],        // i  : LTP target vector,                       Q0
    470     Word16 xn2[],       // i  : CB target vector,                        Q0
    471     Word16 y1[],        // i  : Adaptive codebook,                       Q0
    472     Word16 Y2[],        // i  : Filtered innovative vector,              Q12
    473     Word16 g_coeff[],   // i  : Correlations <xn y1> <y1 y1>
    474                         //      computed in G_pitch()
    475 
    476     Word16 frac_coeff[],// o  : energy coefficients (5), fraction part,  Q15
    477     Word16 exp_coeff[], // o  : energy coefficients (5), exponent part,  Q0
    478     Word16 *cod_gain_frac,// o: optimum codebook gain (fraction part),   Q15
    479     Word16 *cod_gain_exp  // o: optimum codebook gain (exponent part),   Q0
    480 )
    481 {
    482     Word32 s, ener_init;
    483     Word16 i, exp, frac;
    484     Word16 y2[L_SUBFR];
    485 
    486     if (sub(mode, MR795) == 0 || sub(mode, MR475) == 0)
    487     {
    488         ener_init = 0L;
    489     }
    490     else
    491     {
    492         ener_init = 1L;
    493     }
    494 
    495     for (i = 0; i < L_SUBFR; i++) {
    496         y2[i] = shr(Y2[i], 3);
    497     }
    498 
    499     frac_coeff[0] = g_coeff[0];
    500     exp_coeff[0] = g_coeff[1];
    501     frac_coeff[1] = negate(g_coeff[2]); // coeff[1] = -2 xn y1
    502     exp_coeff[1] = add(g_coeff[3], 1);
    503 
    504 
    505     // Compute scalar product <y2[],y2[]>
    506 
    507     s = L_mac(ener_init, y2[0], y2[0]);
    508     for (i = 1; i < L_SUBFR; i++)
    509         s = L_mac(s, y2[i], y2[i]);
    510 
    511     exp = norm_l(s);
    512     frac_coeff[2] = extract_h(L_shl(s, exp));
    513     exp_coeff[2] = sub(15 - 18, exp);
    514 
    515     // Compute scalar product -2*<xn[],y2[]>
    516 
    517     s = L_mac(ener_init, xn[0], y2[0]);
    518     for (i = 1; i < L_SUBFR; i++)
    519         s = L_mac(s, xn[i], y2[i]);
    520 
    521     exp = norm_l(s);
    522     frac_coeff[3] = negate(extract_h(L_shl(s, exp)));
    523     exp_coeff[3] = sub(15 - 9 + 1, exp);
    524 
    525 
    526     // Compute scalar product 2*<y1[],y2[]>
    527 
    528     s = L_mac(ener_init, y1[0], y2[0]);
    529     for (i = 1; i < L_SUBFR; i++)
    530         s = L_mac(s, y1[i], y2[i]);
    531 
    532     exp = norm_l(s);
    533     frac_coeff[4] = extract_h(L_shl(s, exp));
    534     exp_coeff[4] = sub(15 - 9 + 1, exp);
    535 
    536     if (sub(mode, MR475) == 0 || sub(mode, MR795) == 0)
    537     {
    538         // Compute scalar product <xn2[],y2[]>
    539 
    540         s = L_mac(ener_init, xn2[0], y2[0]);
    541         for (i = 1; i < L_SUBFR; i++)
    542             s = L_mac(s, xn2[i], y2[i]);
    543 
    544         exp = norm_l(s);
    545         frac = extract_h(L_shl(s, exp));
    546         exp = sub(15 - 9, exp);
    547 
    548 
    549         if (frac <= 0)
    550         {
    551             *cod_gain_frac = 0;
    552             *cod_gain_exp = 0;
    553         }
    554         else
    555         {
    556             //
    557               gcu = <xn2, y2> / c[2]
    558                   = (frac>>1)/frac[2]             * 2^(exp+1-exp[2])
    559                   = div_s(frac>>1, frac[2])*2^-15 * 2^(exp+1-exp[2])
    560                   = div_s * 2^(exp-exp[2]-14)
    561 
    562             *cod_gain_frac = div_s (shr (frac,1), frac_coeff[2]);
    563             *cod_gain_exp = sub (sub (exp, exp_coeff[2]), 14);
    564 
    565         }
    566     }
    567 }
    568 
    569 ------------------------------------------------------------------------------
    570  RESOURCES USED [optional]
    571 
    572  When the code is written for a specific target processor the
    573  the resources used should be documented below.
    574 
    575  HEAP MEMORY USED: x bytes
    576 
    577  STACK MEMORY USED: x bytes
    578 
    579  CLOCK CYCLES: (cycle count equation for this function) + (variable
    580                 used to represent cycle count for each subroutine
    581                 called)
    582      where: (cycle count variable) = cycle count for [subroutine
    583                                      name]
    584 
    585 ------------------------------------------------------------------------------
    586  CAUTION [optional]
    587  [State any special notes, constraints or cautions for users of this function]
    588 
    589 ------------------------------------------------------------------------------
    590 */
    591 
    592 void calc_filt_energies(
    593     enum Mode mode,     /* i  : coder mode                                   */
    594     Word16 xn[],        /* i  : LTP target vector,                       Q0  */
    595     Word16 xn2[],       /* i  : CB target vector,                        Q0  */
    596     Word16 y1[],        /* i  : Adaptive codebook,                       Q0  */
    597     Word16 Y2[],        /* i  : Filtered innovative vector,              Q12 */
    598     Word16 g_coeff[],   /* i  : Correlations <xn y1> <y1 y1>                 */
    599     /*      computed in G_pitch()                        */
    600     Word16 frac_coeff[], /* o  : energy coefficients (5), fraction part, Q15 */
    601     Word16 exp_coeff[], /* o  : energy coefficients (5), exponent part,  Q0  */
    602     Word16 *cod_gain_frac, /* o  : optimum codebook gain (fraction part),Q15 */
    603     Word16 *cod_gain_exp, /* o  : optimum codebook gain (exponent part), Q0  */
    604     Flag   *pOverflow
    605 )
    606 {
    607     Word32 s1;      /* Intermediate energy accumulator  */
    608     Word32 s2;      /* Intermediate energy accumulator  */
    609     Word32 s3;      /* Intermediate energy accumulator  */
    610 
    611     Word16 i;       /* index used in all loops  */
    612     Word16 exp;     /* number of '0's or '1's before MSB != 0   */
    613     Word16 frac;        /* fractional part  */
    614     Word16 tmp;     /* temporal storage */
    615     Word16 scaled_y2[L_SUBFR];
    616 
    617 
    618     frac_coeff[0] = g_coeff[0];
    619     exp_coeff[0]  = g_coeff[1];
    620     frac_coeff[1] = negate(g_coeff[2]);    /* coeff[1] = -2 xn y1 */
    621     exp_coeff[1]  = add(g_coeff[3], 1, pOverflow);
    622 
    623     if ((mode == MR795) || (mode == MR475))
    624     {
    625         s1 = 0L;
    626         s2 = 0L;
    627         s3 = 0L;
    628     }
    629     else
    630     {
    631         s1 = 1L;
    632         s2 = 1L;
    633         s3 = 1L;
    634     }
    635 
    636     for (i = 0; i < L_SUBFR; i++)
    637     {
    638         /* avoid multiple accesses to memory  */
    639         tmp   = (Y2[i] >> 3);
    640         scaled_y2[i] = tmp;
    641 
    642         /* Compute scalar product <scaled_y2[],scaled_y2[]> */
    643         s1 = L_mac(s1, tmp, tmp, pOverflow);
    644 
    645         /* Compute scalar product -2*<xn[],scaled_y2[]> */
    646         s2 = L_mac(s2, xn[i], tmp, pOverflow);
    647 
    648         /* Compute scalar product 2*<y1[],scaled_y2[]> */
    649         s3 = L_mac(s3, y1[i], tmp, pOverflow);
    650     }
    651 
    652     exp = norm_l(s1);
    653     frac_coeff[2] = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
    654     exp_coeff[2] = (-3 - exp);
    655 
    656     exp = norm_l(s2);
    657     frac_coeff[3] = negate((Word16)(L_shl(s2, exp, pOverflow) >> 16));
    658     exp_coeff[3] = (7 - exp);
    659 
    660     exp = norm_l(s3);
    661     frac_coeff[4] = (Word16)(L_shl(s3, exp, pOverflow) >> 16);
    662     exp_coeff[4] = sub(7, exp, pOverflow);
    663 
    664 
    665     if ((mode == MR795) || (mode == MR475))
    666     {
    667         /* Compute scalar product <xn2[],scaled_y2[]> */
    668         s1 = 0L;
    669 
    670         for (i = 0; i < L_SUBFR; i++)
    671         {
    672             s1 = amrnb_fxp_mac_16_by_16bb((Word32) xn2[i], (Word32)scaled_y2[i], s1);
    673         }
    674 
    675         s1 = s1 << 1;
    676 
    677         exp = norm_l(s1);
    678         frac = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
    679         exp = (6 - exp);
    680 
    681         if (frac <= 0)
    682         {
    683             *cod_gain_frac = 0;
    684             *cod_gain_exp = 0;
    685         }
    686         else
    687         {
    688             /*
    689             gcu = <xn2, scaled_y2> / c[2]
    690                 = (frac>>1)/frac[2]             * 2^(exp+1-exp[2])
    691                 = div_s(frac>>1, frac[2])*2^-15 * 2^(exp+1-exp[2])
    692                 = div_s * 2^(exp-exp[2]-14)
    693             */
    694             *cod_gain_frac = div_s(shr(frac, 1, pOverflow), frac_coeff[2]);
    695             *cod_gain_exp = ((exp - exp_coeff[2]) - 14);
    696         }
    697     }
    698 
    699     return;
    700 }
    701 
    702 /****************************************************************************/
    703 
    704 /*
    705 ------------------------------------------------------------------------------
    706  FUNCTION NAME: calc_target_energy
    707 ------------------------------------------------------------------------------
    708  INPUT AND OUTPUT DEFINITIONS
    709 
    710  Inputs:
    711     xn =  LTP target vector, buffer to type Word16  Q0
    712     en_exp = optimum codebook gain (exponent part) pointer to type Word16
    713     en_frac = optimum codebook gain (fraction part) pointer to type Word16
    714     pOverflow = pointer to overflow indicator (Flag)
    715 
    716  Outputs:
    717     en_exp points to new optimum codebook gain (exponent part)
    718     en_frac points to new optimum codebook gain (fraction part)
    719     pOverflow = 1 if there is an overflow else it is zero.
    720 
    721  Returns:
    722     None.
    723 
    724  Global Variables Used:
    725     None
    726 
    727  Local Variables Needed:
    728     None
    729 
    730 ------------------------------------------------------------------------------
    731  FUNCTION DESCRIPTION
    732 
    733  This function calculates the target energy using the formula,
    734  en = <xn, xn>
    735 
    736 ------------------------------------------------------------------------------
    737  REQUIREMENTS
    738 
    739  None.
    740 
    741 ------------------------------------------------------------------------------
    742  REFERENCES
    743 
    744  calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    745 
    746 ------------------------------------------------------------------------------
    747  PSEUDO-CODE
    748 
    749 void
    750 calc_target_energy(
    751     Word16 xn[],     // i: LTP target vector,                       Q0
    752     Word16 *en_exp,  // o: optimum codebook gain (exponent part),   Q0
    753     Word16 *en_frac  // o: optimum codebook gain (fraction part),   Q15
    754 )
    755 {
    756     Word32 s;
    757     Word16 i, exp;
    758 
    759     // Compute scalar product <xn[], xn[]>
    760     s = L_mac(0L, xn[0], xn[0]);
    761     for (i = 1; i < L_SUBFR; i++)
    762         s = L_mac(s, xn[i], xn[i]);
    763 
    764     // s = SUM 2*xn(i) * xn(i) = <xn xn> * 2
    765     exp = norm_l(s);
    766     *en_frac = extract_h(L_shl(s, exp));
    767     *en_exp = sub(16, exp);
    768 }
    769 
    770 ------------------------------------------------------------------------------
    771  RESOURCES USED [optional]
    772 
    773  When the code is written for a specific target processor the
    774  the resources used should be documented below.
    775 
    776  HEAP MEMORY USED: x bytes
    777 
    778  STACK MEMORY USED: x bytes
    779 
    780  CLOCK CYCLES: (cycle count equation for this function) + (variable
    781                 used to represent cycle count for each subroutine
    782                 called)
    783      where: (cycle count variable) = cycle count for [subroutine
    784                                      name]
    785 
    786 ------------------------------------------------------------------------------
    787  CAUTION [optional]
    788  [State any special notes, constraints or cautions for users of this function]
    789 
    790 ------------------------------------------------------------------------------
    791 */
    792 
    793 void calc_target_energy(
    794     Word16 xn[],     /* i: LTP target vector,                       Q0  */
    795     Word16 *en_exp,  /* o: optimum codebook gain (exponent part),   Q0  */
    796     Word16 *en_frac, /* o: optimum codebook gain (fraction part),   Q15 */
    797     Flag   *pOverflow
    798 )
    799 {
    800     Word32 s;       /* Intermediate energy accumulator  */
    801     Word16 i;       /* index used in all loops  */
    802     Word16 exp;
    803 
    804     /* Compute scalar product <xn[], xn[]> */
    805     s = 0;
    806     for (i = 0; i < L_SUBFR; i++)
    807     {
    808         s = amrnb_fxp_mac_16_by_16bb((Word32) xn[i], (Word32) xn[i], s);
    809     }
    810 
    811     if (s < 0)
    812     {
    813         *pOverflow = 1;
    814         s = MAX_32;
    815     }
    816 
    817     /* s = SUM 2*xn(i) * xn(i) = <xn xn> * 2 */
    818     exp = norm_l(s);
    819     *en_frac = (Word16)(L_shl(s, exp, pOverflow) >> 16);
    820     *en_exp = (16 - exp);
    821 
    822     return;
    823 }
    824 
    825 
    826