• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
calc_unfilt_energies(Word16 res[],Word16 exc[],Word16 code[],Word16 gain_pit,Word16 L_subfr,Word16 frac_en[],Word16 exp_en[],Word16 * ltpg,Flag * pOverflow)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 
calc_filt_energies(enum Mode mode,Word16 xn[],Word16 xn2[],Word16 y1[],Word16 Y2[],Word16 g_coeff[],Word16 frac_coeff[],Word16 exp_coeff[],Word16 * cod_gain_frac,Word16 * cod_gain_exp,Flag * pOverflow)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 
calc_target_energy(Word16 xn[],Word16 * en_exp,Word16 * en_frac,Flag * pOverflow)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