Initialize Tizen 2.3
[external/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / enc / src / calc_en.cpp
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  Filename: calc_en.cpp
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  CAUTION [optional]
243  [State any special notes, constraints or cautions for users of this function]
244
245 ------------------------------------------------------------------------------
246 */
247
248 void calc_unfilt_energies(
249     Word16 res[],     /* i  : LP residual,                               Q0  */
250     Word16 exc[],     /* i  : LTP excitation (unfiltered),               Q0  */
251     Word16 code[],    /* i  : CB innovation (unfiltered),                Q13 */
252     Word16 gain_pit,  /* i  : pitch gain,                                Q14 */
253     Word16 L_subfr,   /* i  : Subframe length                                */
254
255     Word16 frac_en[], /* o  : energy coefficients (4), fraction part,    Q15 */
256     Word16 exp_en[],  /* o  : energy coefficients (4), exponent part,    Q0  */
257     Word16 *ltpg,     /* o  : LTP coding gain (log2()),                  Q13 */
258     Flag   *pOverflow
259 )
260 {
261     Word32 s1;      /* Intermediate energy accumulator */
262     Word32 s2;      /* Intermediate energy accumulator */
263     Word32 s3;      /* Intermediate energy accumulator */
264     Word32 s4;      /* Intermediate energy accumulator */
265     Word32 L_temp;      /* temporal 32 bits storage */
266
267     Word16 i;       /* index used in all loops */
268     Word16 exp;     /* nunmber of '0's or '1's before MSB != 0 */
269     Word16 tmp1;        /* temporal storage */
270     Word16 tmp2;        /* temporal storage */
271     Word16 ltp_res_en;
272     Word16 pred_gain;   /* predictor gain */
273     Word16 ltpg_exp;    /* LTP gain (exponent) */
274     Word16 ltpg_frac;   /* LTP gain (mantissa or fractional part) */
275
276     s1 = 0;
277     s2 = 0;
278     s3 = 0;
279     s4 = 0;
280
281     /*----------------------------------------------------------------------------
282     NOTE: Overflow is expected as a result of multiply and accumulated without
283         scale down the inputs. This modification is not made at this point
284         to have bit exact results with the pre-optimization code. (JT 6/20/00)
285
286     ----------------------------------------------------------------------------*/
287
288     for (i = 0; i < L_subfr; i++)
289     {
290         tmp1 = res[i];              /* avoid multiple accesses to memory */
291         tmp2 = exc[i];
292
293         s1 = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s1);   /* Compute residual energy */
294         s2 = amrnb_fxp_mac_16_by_16bb((Word32) tmp2, (Word32) tmp2, s2);   /* Compute ltp excitation energy */
295         s3 = amrnb_fxp_mac_16_by_16bb((Word32) tmp2, (Word32) code[i], s3);/* Compute scalar product */
296         /* <exc[],code[]>         */
297
298         L_temp = L_mult(tmp2, gain_pit, pOverflow);
299         L_temp = L_shl(L_temp, 1, pOverflow);
300         tmp2   = sub(tmp1, pv_round(L_temp, pOverflow), pOverflow);
301         /* LTP residual, Q0 */
302         s4     = L_mac(s4, tmp2, tmp2, pOverflow);
303         /* Compute energy of LTP residual */
304     }
305     s1 = s1 << 1;
306     s2 = s2 << 1;
307     s3 = s3 << 1;
308
309     if (s1 & MIN_32)
310     {
311         s1 = MAX_32;
312         *pOverflow = 1;
313     }
314
315     /* ResEn := 0 if ResEn < 200.0 (= 400 Q1) */
316     if (s1 < 400L)
317     {
318         frac_en[0] = 0;
319         exp_en[0] = -15;
320     }
321     else
322     {
323         exp = norm_l(s1);
324         frac_en[0] = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
325         exp_en[0] = (15 - exp);
326     }
327
328     if (s2 & MIN_32)
329     {
330         s2 = MAX_32;
331         *pOverflow = 1;
332     }
333
334     exp = norm_l(s2);
335     frac_en[1] = (Word16)(L_shl(s2, exp, pOverflow) >> 16);
336     exp_en[1] = 15 - exp;
337
338     /*  s3 is not always sum of squares */
339     exp = norm_l(s3);
340     frac_en[2] = (Word16)(L_shl(s3, exp, pOverflow) >> 16);
341     exp_en[2]  = 2 - exp;
342
343     exp = norm_l(s4);
344     ltp_res_en = (Word16)(L_shl(s4, exp, pOverflow) >> 16);
345     exp = 15 - exp;
346
347     frac_en[3] = ltp_res_en;
348     exp_en[3] = exp;
349
350     /* calculate LTP coding gain, i.e. energy reduction LP res -> LTP res */
351
352     if (ltp_res_en > 0 && frac_en[0] != 0)
353     {
354         /* gain = ResEn / LTPResEn */
355         pred_gain = div_s(shr(frac_en[0], 1, pOverflow), ltp_res_en);
356         exp = sub(exp, exp_en[0], pOverflow);
357
358         /* L_temp = ltpGain * 2^(30 + exp) */
359         L_temp = (Word32) pred_gain << 16;
360         /* L_temp = ltpGain * 2^27 */
361         L_temp = L_shr(L_temp, (Word16)(exp + 3), pOverflow);
362
363         /* Log2 = log2() + 27 */
364         Log2(L_temp, &ltpg_exp, &ltpg_frac, pOverflow);
365
366         /* ltpg = log2(LtpGain) * 2^13 --> range: +- 4 = +- 12 dB */
367         L_temp = L_Comp((ltpg_exp - 27), ltpg_frac, pOverflow);
368         *ltpg = pv_round(L_shl(L_temp, 13, pOverflow), pOverflow);   /* Q13 */
369     }
370     else
371     {
372         *ltpg = 0;
373     }
374
375     return;
376 }
377
378 /****************************************************************************/
379
380
381 /*
382 ------------------------------------------------------------------------------
383  FUNCTION NAME: calc_filt_energies
384 ------------------------------------------------------------------------------
385  INPUT AND OUTPUT DEFINITIONS
386
387  Inputs:
388     mode = coder mode, type Mode
389     xn = LTP target vector, buffer type Word16
390     xn2 = CB target vector,  buffer type Word16
391     y1 = Adaptive codebook,  buffer type Word16
392     Y2 = Filtered innovative vector,  buffer type Word16
393     g_coeff = Correlations <xn y1> <y1 y1>
394     computed in G_pitch()  buffer type Word16
395     frac_coeff = energy coefficients (5), fraction part, buffer type Word16
396     exp_coeff = energy coefficients (5), exponent part, buffer type Word16
397     cod_gain_frac = optimum codebook gain (fraction part), pointer type Word16
398     cod_gain_exp = optimum codebook gain (exponent part), pointer type Word16
399     pOverflow    = pointer to overflow indicator (Flag)
400
401  Outputs:
402     frac_coeff contains new fraction part energy coefficients
403     exp_coeff contains new exponent part energy coefficients
404     cod_gain_frac points to the new optimum codebook gain (fraction part)
405     cod_gain_exp points to the new optimum codebook gain (exponent part)
406     pOverflow = 1 if there is an overflow else it is zero.
407
408  Returns:
409     None.
410
411  Global Variables Used:
412     None
413
414  Local Variables Needed:
415     None
416
417 ------------------------------------------------------------------------------
418  FUNCTION DESCRIPTION
419
420  This function calculates several energy coefficients for filtered
421  excitation signals
422
423  Compute coefficients need for the quantization and the optimum
424  codebook gain gcu (for MR475 only).
425
426     coeff[0] =    y1 y1
427     coeff[1] = -2 xn y1
428     coeff[2] =    y2 y2
429     coeff[3] = -2 xn y2
430     coeff[4] =  2 y1 y2
431
432     gcu = <xn2, y2> / <y2, y2> (0 if <xn2, y2> <= 0)
433
434  Product <y1 y1> and <xn y1> have been computed in G_pitch() and
435  are in vector g_coeff[].
436
437 ------------------------------------------------------------------------------
438  REQUIREMENTS
439
440  None.
441
442 ------------------------------------------------------------------------------
443  REFERENCES
444
445  calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
446
447 ------------------------------------------------------------------------------
448  PSEUDO-CODE
449
450 void
451 calc_filt_energies(
452     enum Mode mode,     // i  : coder mode
453     Word16 xn[],        // i  : LTP target vector,                       Q0
454     Word16 xn2[],       // i  : CB target vector,                        Q0
455     Word16 y1[],        // i  : Adaptive codebook,                       Q0
456     Word16 Y2[],        // i  : Filtered innovative vector,              Q12
457     Word16 g_coeff[],   // i  : Correlations <xn y1> <y1 y1>
458                         //      computed in G_pitch()
459
460     Word16 frac_coeff[],// o  : energy coefficients (5), fraction part,  Q15
461     Word16 exp_coeff[], // o  : energy coefficients (5), exponent part,  Q0
462     Word16 *cod_gain_frac,// o: optimum codebook gain (fraction part),   Q15
463     Word16 *cod_gain_exp  // o: optimum codebook gain (exponent part),   Q0
464 )
465 {
466     Word32 s, ener_init;
467     Word16 i, exp, frac;
468     Word16 y2[L_SUBFR];
469
470     if (sub(mode, MR795) == 0 || sub(mode, MR475) == 0)
471     {
472         ener_init = 0L;
473     }
474     else
475     {
476         ener_init = 1L;
477     }
478
479     for (i = 0; i < L_SUBFR; i++) {
480         y2[i] = shr(Y2[i], 3);
481     }
482
483     frac_coeff[0] = g_coeff[0];
484     exp_coeff[0] = g_coeff[1];
485     frac_coeff[1] = negate(g_coeff[2]); // coeff[1] = -2 xn y1
486     exp_coeff[1] = add(g_coeff[3], 1);
487
488
489     // Compute scalar product <y2[],y2[]>
490
491     s = L_mac(ener_init, y2[0], y2[0]);
492     for (i = 1; i < L_SUBFR; i++)
493         s = L_mac(s, y2[i], y2[i]);
494
495     exp = norm_l(s);
496     frac_coeff[2] = extract_h(L_shl(s, exp));
497     exp_coeff[2] = sub(15 - 18, exp);
498
499     // Compute scalar product -2*<xn[],y2[]>
500
501     s = L_mac(ener_init, xn[0], y2[0]);
502     for (i = 1; i < L_SUBFR; i++)
503         s = L_mac(s, xn[i], y2[i]);
504
505     exp = norm_l(s);
506     frac_coeff[3] = negate(extract_h(L_shl(s, exp)));
507     exp_coeff[3] = sub(15 - 9 + 1, exp);
508
509
510     // Compute scalar product 2*<y1[],y2[]>
511
512     s = L_mac(ener_init, y1[0], y2[0]);
513     for (i = 1; i < L_SUBFR; i++)
514         s = L_mac(s, y1[i], y2[i]);
515
516     exp = norm_l(s);
517     frac_coeff[4] = extract_h(L_shl(s, exp));
518     exp_coeff[4] = sub(15 - 9 + 1, exp);
519
520     if (sub(mode, MR475) == 0 || sub(mode, MR795) == 0)
521     {
522         // Compute scalar product <xn2[],y2[]>
523
524         s = L_mac(ener_init, xn2[0], y2[0]);
525         for (i = 1; i < L_SUBFR; i++)
526             s = L_mac(s, xn2[i], y2[i]);
527
528         exp = norm_l(s);
529         frac = extract_h(L_shl(s, exp));
530         exp = sub(15 - 9, exp);
531
532
533         if (frac <= 0)
534         {
535             *cod_gain_frac = 0;
536             *cod_gain_exp = 0;
537         }
538         else
539         {
540             //
541               gcu = <xn2, y2> / c[2]
542                   = (frac>>1)/frac[2]             * 2^(exp+1-exp[2])
543                   = div_s(frac>>1, frac[2])*2^-15 * 2^(exp+1-exp[2])
544                   = div_s * 2^(exp-exp[2]-14)
545
546             *cod_gain_frac = div_s (shr (frac,1), frac_coeff[2]);
547             *cod_gain_exp = sub (sub (exp, exp_coeff[2]), 14);
548
549         }
550     }
551 }
552
553 ------------------------------------------------------------------------------
554  CAUTION [optional]
555  [State any special notes, constraints or cautions for users of this function]
556
557 ------------------------------------------------------------------------------
558 */
559
560 void calc_filt_energies(
561     enum Mode mode,     /* i  : coder mode                                   */
562     Word16 xn[],        /* i  : LTP target vector,                       Q0  */
563     Word16 xn2[],       /* i  : CB target vector,                        Q0  */
564     Word16 y1[],        /* i  : Adaptive codebook,                       Q0  */
565     Word16 Y2[],        /* i  : Filtered innovative vector,              Q12 */
566     Word16 g_coeff[],   /* i  : Correlations <xn y1> <y1 y1>                 */
567     /*      computed in G_pitch()                        */
568     Word16 frac_coeff[], /* o  : energy coefficients (5), fraction part, Q15 */
569     Word16 exp_coeff[], /* o  : energy coefficients (5), exponent part,  Q0  */
570     Word16 *cod_gain_frac, /* o  : optimum codebook gain (fraction part),Q15 */
571     Word16 *cod_gain_exp, /* o  : optimum codebook gain (exponent part), Q0  */
572     Flag   *pOverflow
573 )
574 {
575     Word32 s1;      /* Intermediate energy accumulator  */
576     Word32 s2;      /* Intermediate energy accumulator  */
577     Word32 s3;      /* Intermediate energy accumulator  */
578
579     Word16 i;       /* index used in all loops  */
580     Word16 exp;     /* number of '0's or '1's before MSB != 0   */
581     Word16 frac;        /* fractional part  */
582     Word16 tmp;     /* temporal storage */
583     Word16 scaled_y2[L_SUBFR];
584
585
586     frac_coeff[0] = g_coeff[0];
587     exp_coeff[0]  = g_coeff[1];
588     frac_coeff[1] = negate(g_coeff[2]);    /* coeff[1] = -2 xn y1 */
589     exp_coeff[1]  = g_coeff[3] + 1;
590
591     if ((mode == MR795) || (mode == MR475))
592     {
593         s1 = 0L;
594         s2 = 0L;
595         s3 = 0L;
596     }
597     else
598     {
599         s1 = 1L;
600         s2 = 1L;
601         s3 = 1L;
602     }
603
604     for (i = 0; i < L_SUBFR; i++)
605     {
606         /* avoid multiple accesses to memory  */
607         tmp   = (Y2[i] >> 3);
608         scaled_y2[i] = tmp;
609
610         /* Compute scalar product <scaled_y2[],scaled_y2[]> */
611         s1 = L_mac(s1, tmp, tmp, pOverflow);
612
613         /* Compute scalar product -2*<xn[],scaled_y2[]> */
614         s2 = L_mac(s2, xn[i], tmp, pOverflow);
615
616         /* Compute scalar product 2*<y1[],scaled_y2[]> */
617         s3 = L_mac(s3, y1[i], tmp, pOverflow);
618     }
619
620     exp = norm_l(s1);
621     frac_coeff[2] = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
622     exp_coeff[2] = (-3 - exp);
623
624     exp = norm_l(s2);
625     frac_coeff[3] = negate((Word16)(L_shl(s2, exp, pOverflow) >> 16));
626     exp_coeff[3] = (7 - exp);
627
628     exp = norm_l(s3);
629     frac_coeff[4] = (Word16)(L_shl(s3, exp, pOverflow) >> 16);
630     exp_coeff[4] = (7 - exp);
631
632
633     if ((mode == MR795) || (mode == MR475))
634     {
635         /* Compute scalar product <xn2[],scaled_y2[]> */
636         s1 = 0L;
637
638         for (i = 0; i < L_SUBFR; i++)
639         {
640             s1 = amrnb_fxp_mac_16_by_16bb((Word32) xn2[i], (Word32)scaled_y2[i], s1);
641         }
642
643         s1 = s1 << 1;
644
645         exp = norm_l(s1);
646         frac = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
647         exp = (6 - exp);
648
649         if (frac <= 0)
650         {
651             *cod_gain_frac = 0;
652             *cod_gain_exp = 0;
653         }
654         else
655         {
656             /*
657             gcu = <xn2, scaled_y2> / c[2]
658                 = (frac>>1)/frac[2]             * 2^(exp+1-exp[2])
659                 = div_s(frac>>1, frac[2])*2^-15 * 2^(exp+1-exp[2])
660                 = div_s * 2^(exp-exp[2]-14)
661             */
662             *cod_gain_frac = div_s(shr(frac, 1, pOverflow), frac_coeff[2]);
663             *cod_gain_exp = ((exp - exp_coeff[2]) - 14);
664         }
665     }
666
667     return;
668 }
669
670 /****************************************************************************/
671
672 /*
673 ------------------------------------------------------------------------------
674  FUNCTION NAME: calc_target_energy
675 ------------------------------------------------------------------------------
676  INPUT AND OUTPUT DEFINITIONS
677
678  Inputs:
679     xn =  LTP target vector, buffer to type Word16  Q0
680     en_exp = optimum codebook gain (exponent part) pointer to type Word16
681     en_frac = optimum codebook gain (fraction part) pointer to type Word16
682     pOverflow = pointer to overflow indicator (Flag)
683
684  Outputs:
685     en_exp points to new optimum codebook gain (exponent part)
686     en_frac points to new optimum codebook gain (fraction part)
687     pOverflow = 1 if there is an overflow else it is zero.
688
689  Returns:
690     None.
691
692  Global Variables Used:
693     None
694
695  Local Variables Needed:
696     None
697
698 ------------------------------------------------------------------------------
699  FUNCTION DESCRIPTION
700
701  This function calculates the target energy using the formula,
702  en = <xn, xn>
703
704 ------------------------------------------------------------------------------
705  REQUIREMENTS
706
707  None.
708
709 ------------------------------------------------------------------------------
710  REFERENCES
711
712  calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
713
714 ------------------------------------------------------------------------------
715  PSEUDO-CODE
716
717 void
718 calc_target_energy(
719     Word16 xn[],     // i: LTP target vector,                       Q0
720     Word16 *en_exp,  // o: optimum codebook gain (exponent part),   Q0
721     Word16 *en_frac  // o: optimum codebook gain (fraction part),   Q15
722 )
723 {
724     Word32 s;
725     Word16 i, exp;
726
727     // Compute scalar product <xn[], xn[]>
728     s = L_mac(0L, xn[0], xn[0]);
729     for (i = 1; i < L_SUBFR; i++)
730         s = L_mac(s, xn[i], xn[i]);
731
732     // s = SUM 2*xn(i) * xn(i) = <xn xn> * 2
733     exp = norm_l(s);
734     *en_frac = extract_h(L_shl(s, exp));
735     *en_exp = sub(16, exp);
736 }
737
738 ------------------------------------------------------------------------------
739  CAUTION [optional]
740  [State any special notes, constraints or cautions for users of this function]
741
742 ------------------------------------------------------------------------------
743 */
744
745 void calc_target_energy(
746     Word16 xn[],     /* i: LTP target vector,                       Q0  */
747     Word16 *en_exp,  /* o: optimum codebook gain (exponent part),   Q0  */
748     Word16 *en_frac, /* o: optimum codebook gain (fraction part),   Q15 */
749     Flag   *pOverflow
750 )
751 {
752     Word32 s;       /* Intermediate energy accumulator  */
753     Word16 i;       /* index used in all loops  */
754     Word16 exp;
755
756     /* Compute scalar product <xn[], xn[]> */
757     s = 0;
758     for (i = 0; i < L_SUBFR; i++)
759     {
760         s = amrnb_fxp_mac_16_by_16bb((Word32) xn[i], (Word32) xn[i], s);
761     }
762
763     if (s < 0)
764     {
765         *pOverflow = 1;
766         s = MAX_32;
767     }
768
769     /* s = SUM 2*xn(i) * xn(i) = <xn xn> * 2 */
770     exp = norm_l(s);
771     *en_frac = (Word16)(L_shl(s, exp, pOverflow) >> 16);
772     *en_exp = (16 - exp);
773
774     return;
775 }
776
777