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/****************************************************************************************
19Portions 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)
26Permission to distribute, modify and use this file under the standard license
27terms 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
144void
145calc_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
264void 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
466void
467calc_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
592void 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
749void
750calc_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
793void 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