1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
22 ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23 Available from http://www.3gpp.org
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 ****************************************************************************************/
30 ------------------------------------------------------------------------------
35 Funtions: calc_unfilt_energies
39 ------------------------------------------------------------------------------
42 This file contains the functions that calculate the energy coefficients
43 for unfiltered and filtered excitation signals, the LTP coding gain, and
46 ------------------------------------------------------------------------------
50 /*----------------------------------------------------------------------------
52 ----------------------------------------------------------------------------*/
56 #include "basicop_malloc.h"
62 /*----------------------------------------------------------------------------
64 ; Define module specific macros here
65 ----------------------------------------------------------------------------*/
68 /*----------------------------------------------------------------------------
70 ; Include all pre-processor statements here. Include conditional
71 ; compile variables also.
72 ----------------------------------------------------------------------------*/
75 /*----------------------------------------------------------------------------
76 ; LOCAL FUNCTION DEFINITIONS
77 ; Function Prototype declaration
78 ----------------------------------------------------------------------------*/
80 /*----------------------------------------------------------------------------
81 ; LOCAL VARIABLE DEFINITIONS
82 ; Variable declaration - defined here and used outside this module
83 ----------------------------------------------------------------------------*/
87 ------------------------------------------------------------------------------
88 FUNCTION NAME: calc_unfilt_energies
89 ------------------------------------------------------------------------------
90 INPUT AND OUTPUT DEFINITIONS
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)
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.
112 Global Variables Used:
115 Local Variables Needed:
118 ------------------------------------------------------------------------------
121 This function calculates several energy coefficients for unfiltered
122 excitation signals and the LTP coding gain
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)
131 ------------------------------------------------------------------------------
136 ------------------------------------------------------------------------------
139 calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
141 ------------------------------------------------------------------------------
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
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
159 Word16 ltp_res_en, pred_gain;
160 Word16 ltpg_exp, ltpg_frac;
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]);
167 // ResEn := 0 if ResEn < 200.0 (= 400 Q1)
168 if (L_sub (s, 400L) < 0)
176 frac_en[0] = extract_h(L_shl(s, exp));
177 exp_en[0] = sub(15, exp);
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]);
186 frac_en[1] = extract_h(L_shl(s, exp));
187 exp_en[1] = sub(15, exp);
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]);
195 frac_en[2] = extract_h(L_shl(s, exp));
196 exp_en[2] = sub(16-14, exp);
198 // Compute energy of LTP residual
200 for (i = 0; i < L_subfr; i++)
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);
209 ltp_res_en = extract_h (L_shl (s, exp));
212 frac_en[3] = ltp_res_en;
215 // calculate LTP coding gain, i.e. energy reduction LP res -> LTP res
216 if (ltp_res_en > 0 && frac_en[0] != 0)
218 // gain = ResEn / LTPResEn
219 pred_gain = div_s (shr (frac_en[0], 1), ltp_res_en);
220 exp = sub (exp, exp_en[0]);
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));
227 // Log2 = log2() + 27
228 Log2(L_temp, <pg_exp, <pg_frac);
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
241 ------------------------------------------------------------------------------
243 [State any special notes, constraints or cautions for users of this function]
245 ------------------------------------------------------------------------------
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 */
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 */
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 */
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 */
272 Word16 pred_gain; /* predictor gain */
273 Word16 ltpg_exp; /* LTP gain (exponent) */
274 Word16 ltpg_frac; /* LTP gain (mantissa or fractional part) */
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)
286 ----------------------------------------------------------------------------*/
288 for (i = 0; i < L_subfr; i++)
290 tmp1 = res[i]; /* avoid multiple accesses to memory */
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 */
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 */
315 /* ResEn := 0 if ResEn < 200.0 (= 400 Q1) */
324 frac_en[0] = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
325 exp_en[0] = (15 - exp);
335 frac_en[1] = (Word16)(L_shl(s2, exp, pOverflow) >> 16);
336 exp_en[1] = 15 - exp;
338 /* s3 is not always sum of squares */
340 frac_en[2] = (Word16)(L_shl(s3, exp, pOverflow) >> 16);
344 ltp_res_en = (Word16)(L_shl(s4, exp, pOverflow) >> 16);
347 frac_en[3] = ltp_res_en;
350 /* calculate LTP coding gain, i.e. energy reduction LP res -> LTP res */
352 if (ltp_res_en > 0 && frac_en[0] != 0)
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);
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);
363 /* Log2 = log2() + 27 */
364 Log2(L_temp, <pg_exp, <pg_frac, pOverflow);
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 */
378 /****************************************************************************/
382 ------------------------------------------------------------------------------
383 FUNCTION NAME: calc_filt_energies
384 ------------------------------------------------------------------------------
385 INPUT AND OUTPUT DEFINITIONS
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)
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.
411 Global Variables Used:
414 Local Variables Needed:
417 ------------------------------------------------------------------------------
420 This function calculates several energy coefficients for filtered
423 Compute coefficients need for the quantization and the optimum
424 codebook gain gcu (for MR475 only).
432 gcu = <xn2, y2> / <y2, y2> (0 if <xn2, y2> <= 0)
434 Product <y1 y1> and <xn y1> have been computed in G_pitch() and
435 are in vector g_coeff[].
437 ------------------------------------------------------------------------------
442 ------------------------------------------------------------------------------
445 calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
447 ------------------------------------------------------------------------------
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()
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
470 if (sub(mode, MR795) == 0 || sub(mode, MR475) == 0)
479 for (i = 0; i < L_SUBFR; i++) {
480 y2[i] = shr(Y2[i], 3);
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);
489 // Compute scalar product <y2[],y2[]>
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]);
496 frac_coeff[2] = extract_h(L_shl(s, exp));
497 exp_coeff[2] = sub(15 - 18, exp);
499 // Compute scalar product -2*<xn[],y2[]>
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]);
506 frac_coeff[3] = negate(extract_h(L_shl(s, exp)));
507 exp_coeff[3] = sub(15 - 9 + 1, exp);
510 // Compute scalar product 2*<y1[],y2[]>
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]);
517 frac_coeff[4] = extract_h(L_shl(s, exp));
518 exp_coeff[4] = sub(15 - 9 + 1, exp);
520 if (sub(mode, MR475) == 0 || sub(mode, MR795) == 0)
522 // Compute scalar product <xn2[],y2[]>
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]);
529 frac = extract_h(L_shl(s, exp));
530 exp = sub(15 - 9, exp);
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)
546 *cod_gain_frac = div_s (shr (frac,1), frac_coeff[2]);
547 *cod_gain_exp = sub (sub (exp, exp_coeff[2]), 14);
553 ------------------------------------------------------------------------------
555 [State any special notes, constraints or cautions for users of this function]
557 ------------------------------------------------------------------------------
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 */
575 Word32 s1; /* Intermediate energy accumulator */
576 Word32 s2; /* Intermediate energy accumulator */
577 Word32 s3; /* Intermediate energy accumulator */
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];
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;
591 if ((mode == MR795) || (mode == MR475))
604 for (i = 0; i < L_SUBFR; i++)
606 /* avoid multiple accesses to memory */
610 /* Compute scalar product <scaled_y2[],scaled_y2[]> */
611 s1 = L_mac(s1, tmp, tmp, pOverflow);
613 /* Compute scalar product -2*<xn[],scaled_y2[]> */
614 s2 = L_mac(s2, xn[i], tmp, pOverflow);
616 /* Compute scalar product 2*<y1[],scaled_y2[]> */
617 s3 = L_mac(s3, y1[i], tmp, pOverflow);
621 frac_coeff[2] = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
622 exp_coeff[2] = (-3 - exp);
625 frac_coeff[3] = negate((Word16)(L_shl(s2, exp, pOverflow) >> 16));
626 exp_coeff[3] = (7 - exp);
629 frac_coeff[4] = (Word16)(L_shl(s3, exp, pOverflow) >> 16);
630 exp_coeff[4] = (7 - exp);
633 if ((mode == MR795) || (mode == MR475))
635 /* Compute scalar product <xn2[],scaled_y2[]> */
638 for (i = 0; i < L_SUBFR; i++)
640 s1 = amrnb_fxp_mac_16_by_16bb((Word32) xn2[i], (Word32)scaled_y2[i], s1);
646 frac = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
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)
662 *cod_gain_frac = div_s(shr(frac, 1, pOverflow), frac_coeff[2]);
663 *cod_gain_exp = ((exp - exp_coeff[2]) - 14);
670 /****************************************************************************/
673 ------------------------------------------------------------------------------
674 FUNCTION NAME: calc_target_energy
675 ------------------------------------------------------------------------------
676 INPUT AND OUTPUT DEFINITIONS
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)
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.
692 Global Variables Used:
695 Local Variables Needed:
698 ------------------------------------------------------------------------------
701 This function calculates the target energy using the formula,
704 ------------------------------------------------------------------------------
709 ------------------------------------------------------------------------------
712 calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
714 ------------------------------------------------------------------------------
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
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]);
732 // s = SUM 2*xn(i) * xn(i) = <xn xn> * 2
734 *en_frac = extract_h(L_shl(s, exp));
735 *en_exp = sub(16, exp);
738 ------------------------------------------------------------------------------
740 [State any special notes, constraints or cautions for users of this function]
742 ------------------------------------------------------------------------------
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 */
752 Word32 s; /* Intermediate energy accumulator */
753 Word16 i; /* index used in all loops */
756 /* Compute scalar product <xn[], xn[]> */
758 for (i = 0; i < L_SUBFR; i++)
760 s = amrnb_fxp_mac_16_by_16bb((Word32) xn[i], (Word32) xn[i], s);
769 /* s = SUM 2*xn(i) * xn(i) = <xn xn> * 2 */
771 *en_frac = (Word16)(L_shl(s, exp, pOverflow) >> 16);
772 *en_exp = (16 - exp);