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 ------------------------------------------------------------------------------
34 Pathname: ./audio/gsm-amr/c/src/c_g_aver.c
41 ------------------------------------------------------------------------------
44 Description: Made some changes to the comments to match the comments from
47 Description: Made changes based on comments from the review meeting.
49 Description: Synchronized file with UMTS version 3.2.0. Updated coding
52 Description: Made the following changes per comments from Phase 2/3 review:
53 1. Defined one local variable per line.
55 Description: Removed the functions Cb_gain_average_init and
56 Cb_gain_average_exit. The Cb_gain_average related structure is no longer
57 dynamically allocated.
59 Description: Passing in pOverflow to comply with changes needed for EPOC
60 Updated the include files for the module.
62 Description: Changed round function name to pv_round to avoid conflict with
63 round function in C standard library.
66 Description: Replaced OSCL mem type functions and eliminated include
67 files that now are chosen by OSCL definitions
70 ------------------------------------------------------------------------------
73 This file contains functions that reset and perform
74 codebook gain calculations.
76 ------------------------------------------------------------------------------
80 /*----------------------------------------------------------------------------
82 ----------------------------------------------------------------------------*/
92 /*----------------------------------------------------------------------------
94 ; Define module specific macros here
95 ----------------------------------------------------------------------------*/
98 /*----------------------------------------------------------------------------
100 ; Include all pre-processor statements here. Include conditional
101 ; compile variables also.
102 ----------------------------------------------------------------------------*/
104 /*----------------------------------------------------------------------------
105 ; LOCAL FUNCTION DEFINITIONS
106 ; Function Prototype declaration
107 ----------------------------------------------------------------------------*/
109 /*----------------------------------------------------------------------------
110 ; LOCAL VARIABLE DEFINITIONS
111 ; Variable declaration - defined here and used outside this module
112 ----------------------------------------------------------------------------*/
115 ------------------------------------------------------------------------------
116 FUNCTION NAME: Cb_gain_average_reset
117 ------------------------------------------------------------------------------
118 INPUT AND OUTPUT DEFINITIONS
121 state = pointer to a structure of type Cb_gain_averageState
124 Structure pointed to by state is initialized to zeros
127 Returns 0 if memory was successfully initialized,
128 otherwise returns -1.
130 Global Variables Used:
133 Local Variables Needed:
136 ------------------------------------------------------------------------------
141 ------------------------------------------------------------------------------
146 ------------------------------------------------------------------------------
149 c_g_aver.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
151 ------------------------------------------------------------------------------
154 Word16 Cb_gain_average_reset (Cb_gain_averageState *state)
156 if (state == (Cb_gain_averageState *) NULL){
157 fprintf(stderr, "Cb_gain_average_reset: invalid parameter\n");
161 // Static vectors to zero
162 Set_zero (state->cbGainHistory, L_CBGAINHIST);
164 // Initialize hangover handling
171 ------------------------------------------------------------------------------
172 RESOURCES USED [optional]
174 When the code is written for a specific target processor the
175 the resources used should be documented below.
177 HEAP MEMORY USED: x bytes
179 STACK MEMORY USED: x bytes
181 CLOCK CYCLES: (cycle count equation for this function) + (variable
182 used to represent cycle count for each subroutine
184 where: (cycle count variable) = cycle count for [subroutine
187 ------------------------------------------------------------------------------
189 [State any special notes, constraints or cautions for users of this function]
191 ------------------------------------------------------------------------------
194 Word16 Cb_gain_average_reset(Cb_gain_averageState *state)
196 if (state == (Cb_gain_averageState *) NULL)
198 /* fprint(stderr, "Cb_gain_average_reset: invalid parameter\n"); */
202 /* Static vectors to zero */
203 memset(state->cbGainHistory, 0, L_CBGAINHIST*sizeof(Word16));
205 /* Initialize hangover handling */
207 state->hangCount = 0;
212 /****************************************************************************/
215 ------------------------------------------------------------------------------
216 FUNCTION NAME: Cb_gain_average
217 ------------------------------------------------------------------------------
218 INPUT AND OUTPUT DEFINITIONS
221 st = pointer to structure of type Cb_gain_averageState
222 mode = AMR mode (enum Mode)
223 gain_code = CB gain (Word16)
224 lsp = the LSP for the current frame (Word16)
225 lspAver = the average of LSP for 8 frames (Word16)
226 bfi = bad frame indication flag (Word16)
227 prev_bf = previous bad frame indication flag (Word16)
228 pdfi = potential degraded bad frame ind flag (Word16)
229 prev_pdf = prev pot. degraded bad frame ind flag (Word16)
230 inBackgroundNoise = background noise decision (Word16)
231 voicedHangover = # of frames after last voiced frame (Word16)
232 pOverflow = address of overflow (Flag)
235 cbGainMix = codebook gain (Word16)
240 Global Variables Used:
243 Local Variables Needed:
246 ------------------------------------------------------------------------------
249 The mix cb gains for MR475, MR515, MR59, MR67, MR102; gain_code other modes
251 ------------------------------------------------------------------------------
256 ------------------------------------------------------------------------------
259 c_g_aver.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
261 ------------------------------------------------------------------------------
264 Word16 Cb_gain_average (
265 Cb_gain_averageState *st, // i/o : State variables for CB gain avergeing
266 enum Mode mode, // i : AMR mode
267 Word16 gain_code, // i : CB gain Q1
268 Word16 lsp[], // i : The LSP for the current frame Q15
269 Word16 lspAver[], // i : The average of LSP for 8 frames Q15
270 Word16 bfi, // i : bad frame indication flag
271 Word16 prev_bf, // i : previous bad frame indication flag
272 Word16 pdfi, // i : potential degraded bad frame ind flag
273 Word16 prev_pdf, // i : prev pot. degraded bad frame ind flag
274 Word16 inBackgroundNoise, // i : background noise decision
275 Word16 voicedHangover // i : # of frames after last voiced frame
278 //---------------------------------------------------------*
279 * Compute mixed cb gain, used to make cb gain more *
280 * smooth in background noise for modes 5.15, 5.9 and 6.7 *
281 * states that needs to be updated by all *
282 *---------------------------------------------------------
284 Word16 cbGainMix, diff, tmp_diff, bgMix, cbGainMean;
286 Word16 tmp[M], tmp1, tmp2, shift1, shift2, shift;
288 // set correct cbGainMix for MR74, MR795, MR122
289 cbGainMix = gain_code;
291 *-------------------------------------------------------*
292 * Store list of CB gain needed in the CB gain *
294 *-------------------------------------------------------*
295 for (i = 0; i < (L_CBGAINHIST-1); i++)
297 st->cbGainHistory[i] = st->cbGainHistory[i+1];
299 st->cbGainHistory[L_CBGAINHIST-1] = gain_code;
301 // compute lsp difference
302 for (i = 0; i < M; i++) {
303 tmp1 = abs_s(sub(lspAver[i], lsp[i])); // Q15
304 shift1 = sub(norm_s(tmp1), 1); // Qn
305 tmp1 = shl(tmp1, shift1); // Q15+Qn
306 shift2 = norm_s(lspAver[i]); // Qm
307 tmp2 = shl(lspAver[i], shift2); // Q15+Qm
308 tmp[i] = div_s(tmp1, tmp2); // Q15+(Q15+Qn)-(Q15+Qm)
309 shift = sub(add(2, shift1), shift2);
312 tmp[i] = shr(tmp[i], shift); // Q15+Qn-Qm-Qx=Q13
316 tmp[i] = shl(tmp[i], negate(shift)); // Q15+Qn-Qm-Qx=Q13
321 for (i = 1; i < M; i++) {
322 diff = add(diff, tmp[i]); // Q13
326 if (sub(diff, 5325) > 0) // 0.65 in Q11
328 st->hangVar = add(st->hangVar, 1);
335 if (sub(st->hangVar, 10) > 0)
337 st->hangCount = 0; // Speech period, reset hangover variable
340 // Compute mix constant (bgMix)
341 bgMix = 8192; // 1 in Q13
342 if ((sub(mode, MR67) <= 0) || (sub(mode, MR102) == 0))
343 // MR475, MR515, MR59, MR67, MR102
345 // if errors and presumed noise make smoothing probability stronger
346 if (((((pdfi != 0) && (prev_pdf != 0)) || (bfi != 0) || (prev_bf != 0)) &&
347 (sub(voicedHangover, 1) > 0) && (inBackgroundNoise != 0) &&
348 ((sub(mode, MR475) == 0) ||
349 (sub(mode, MR515) == 0) ||
350 (sub(mode, MR59) == 0)) ))
352 // bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25;
353 tmp_diff = sub(diff, 4506); // 0.55 in Q13
355 // max(0.0, diff-0.55)
366 if (sub(2048, tmp1) < 0)
372 bgMix = shl(tmp1, 2);
377 // bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25;
378 tmp_diff = sub(diff, 3277); // 0.4 in Q13
380 // max(0.0, diff-0.40)
391 if (sub(2048, tmp1) < 0)
397 bgMix = shl(tmp1, 2);
401 if ((sub(st->hangCount, 40) < 0) || (sub(diff, 5325) > 0)) // 0.65 in Q13
403 bgMix = 8192; // disable mix if too short time since
406 // Smoothen the cb gain trajectory
407 // smoothing depends on mix constant bgMix
408 L_sum = L_mult(6554, st->cbGainHistory[2]); // 0.2 in Q15; L_sum in Q17
409 for (i = 3; i < L_CBGAINHIST; i++)
411 L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i]);
413 cbGainMean = pv_round(L_sum); // Q1
415 // more smoothing in error and bg noise (NB no DFI used here)
416 if (((bfi != 0) || (prev_bf != 0)) && (inBackgroundNoise != 0) &&
417 ((sub(mode, MR475) == 0) ||
418 (sub(mode, MR515) == 0) ||
419 (sub(mode, MR59) == 0)) )
421 L_sum = L_mult(4681, st->cbGainHistory[0]); // 0.143 in Q15; L_sum in Q17
422 for (i = 1; i < L_CBGAINHIST; i++)
424 L_sum = L_mac(L_sum, 4681, st->cbGainHistory[i]);
426 cbGainMean = pv_round(L_sum); // Q1
429 // cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean;
430 L_sum = L_mult(bgMix, cbGainMix); // L_sum in Q15
431 L_sum = L_mac(L_sum, 8192, cbGainMean);
432 L_sum = L_msu(L_sum, bgMix, cbGainMean);
433 cbGainMix = pv_round(L_shl(L_sum, 2)); // Q1
436 st->hangCount = add(st->hangCount, 1);
440 ------------------------------------------------------------------------------
441 RESOURCES USED [optional]
443 When the code is written for a specific target processor the
444 the resources used should be documented below.
446 HEAP MEMORY USED: x bytes
448 STACK MEMORY USED: x bytes
450 CLOCK CYCLES: (cycle count equation for this function) + (variable
451 used to represent cycle count for each subroutine
453 where: (cycle count variable) = cycle count for [subroutine
456 ------------------------------------------------------------------------------
458 [State any special notes, constraints or cautions for users of this function]
460 ------------------------------------------------------------------------------
463 Word16 Cb_gain_average(
464 Cb_gain_averageState *st, /* i/o : State variables for CB gain averaging */
465 enum Mode mode, /* i : AMR mode */
466 Word16 gain_code, /* i : CB gain Q1 */
467 Word16 lsp[], /* i : The LSP for the current frame Q15 */
468 Word16 lspAver[], /* i : The average of LSP for 8 frames Q15 */
469 Word16 bfi, /* i : bad frame indication flag */
470 Word16 prev_bf, /* i : previous bad frame indication flag */
471 Word16 pdfi, /* i : potential degraded bad frame ind flag */
472 Word16 prev_pdf, /* i : prev pot. degraded bad frame ind flag */
473 Word16 inBackgroundNoise, /* i : background noise decision */
474 Word16 voicedHangover, /* i : # of frames after last voiced frame */
492 /*---------------------------------------------------------*
493 * Compute mixed cb gain, used to make cb gain more *
494 * smooth in background noise for modes 5.15, 5.9 and 6.7 *
495 * states that needs to be updated by all *
496 *---------------------------------------------------------*/
498 /* set correct cbGainMix for MR74, MR795, MR122 */
499 cbGainMix = gain_code;
501 /*-------------------------------------------------------*
502 * Store list of CB gain needed in the CB gain *
504 *-------------------------------------------------------*/
505 for (i = 0; i < (L_CBGAINHIST - 1); i++)
507 st->cbGainHistory[i] = st->cbGainHistory[i+1];
509 st->cbGainHistory[L_CBGAINHIST-1] = gain_code;
513 /* compute lsp difference */
514 for (i = 0; i < M; i++)
516 tmp1 = abs_s(sub(*(lspAver + i), *(lsp + i), pOverflow));
518 shift1 = sub(norm_s(tmp1), 1, pOverflow); /* Qn */
519 tmp1 = shl(tmp1, shift1, pOverflow); /* Q15+Qn */
520 shift2 = norm_s(*(lspAver + i)); /* Qm */
521 tmp2 = shl(*(lspAver + i), shift2, pOverflow); /* Q15+Qm */
522 tmp[i] = div_s(tmp1, tmp2); /* Q15+(Q15+Qn)-(Q15+Qm) */
524 shift = 2 + shift1 - shift2;
528 *(tmp + i) = shr(*(tmp + i), shift, pOverflow);
529 /* Q15+Qn-Qm-Qx=Q13 */
533 *(tmp + i) = shl(*(tmp + i), negate(shift), pOverflow);
534 /* Q15+Qn-Qm-Qx=Q13 */
537 diff = add(diff, *(tmp + i), pOverflow); /* Q13 */
540 /* Compute hangover */
542 if (diff > 5325) /* 0.65 in Q11 */
552 if (st->hangVar > 10)
554 /* Speech period, reset hangover variable */
558 /* Compute mix constant (bgMix) */
559 bgMix = 8192; /* 1 in Q13 */
561 if ((mode <= MR67) || (mode == MR102))
562 /* MR475, MR515, MR59, MR67, MR102 */
564 /* if errors and presumed noise make smoothing probability stronger */
566 if (((((pdfi != 0) && (prev_pdf != 0)) || (bfi != 0) ||
568 && (voicedHangover > 1)
569 && (inBackgroundNoise != 0)
570 && ((mode == MR475) || (mode == MR515) ||
573 /* bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25; */
574 tmp_diff = sub(diff, 4506, pOverflow); /* 0.55 in Q13 */
578 /* bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25; */
579 tmp_diff = sub(diff, 3277, pOverflow); /* 0.4 in Q13 */
582 /* max(0.0, diff-0.55) or */
583 /* max(0.0, diff-0.40) */
593 /* min(0.25, tmp1) */
600 bgMix = shl(tmp1, 2, pOverflow);
603 if ((st->hangCount < 40) || (diff > 5325)) /* 0.65 in Q13 */
605 /* disable mix if too short time since */
609 /* Smoothen the cb gain trajectory */
610 /* smoothing depends on mix constant bgMix */
611 L_sum = L_mult(6554, st->cbGainHistory[2], pOverflow);
612 /* 0.2 in Q15; L_sum in Q17 */
614 for (i = 3; i < L_CBGAINHIST; i++)
616 L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i], pOverflow);
618 cbGainMean = pv_round(L_sum, pOverflow); /* Q1 */
620 /* more smoothing in error and bg noise (NB no DFI used here) */
622 if (((bfi != 0) || (prev_bf != 0)) && (inBackgroundNoise != 0)
623 && ((mode == MR475) || (mode == MR515)
626 /* 0.143 in Q15; L_sum in Q17 */
627 L_sum = L_mult(4681, st->cbGainHistory[0], pOverflow);
628 for (i = 1; i < L_CBGAINHIST; i++)
631 L_mac(L_sum, 4681, st->cbGainHistory[i], pOverflow);
633 cbGainMean = pv_round(L_sum, pOverflow); /* Q1 */
636 /* cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean; */
638 L_sum = L_mult(bgMix, cbGainMix, pOverflow);
639 L_sum = L_mac(L_sum, 8192, cbGainMean, pOverflow);
640 L_sum = L_msu(L_sum, bgMix, cbGainMean, pOverflow);
641 cbGainMix = pv_round(L_shl(L_sum, 2, pOverflow), pOverflow); /* Q1 */