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, <pg_exp, <pg_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, <pg_exp, <pg_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