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/c_g_aver.c
35 Functions:
36 Cb_gain_average_reset
37 Cb_gain_average
38
39 Date: 03/28/2000
40
41 ------------------------------------------------------------------------------
42 REVISION HISTORY
43
44 Description: Made some changes to the comments to match the comments from
45 other modules.
46
47 Description: Made changes based on comments from the review meeting.
48
49 Description: Synchronized file with UMTS version 3.2.0. Updated coding
50 template.
51
52 Description: Made the following changes per comments from Phase 2/3 review:
53 1. Defined one local variable per line.
54
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.
58
59 Description: Passing in pOverflow to comply with changes needed for EPOC
60 Updated the include files for the module.
61
62 Description: Changed round function name to pv_round to avoid conflict with
63 round function in C standard library.
64
65
66 Description: Replaced OSCL mem type functions and eliminated include
67 files that now are chosen by OSCL definitions
68
69 Description:
70 ------------------------------------------------------------------------------
71 MODULE DESCRIPTION
72
73 This file contains functions that reset and perform
74 codebook gain calculations.
75
76 ------------------------------------------------------------------------------
77 */
78
79
80 /*----------------------------------------------------------------------------
81 ; INCLUDES
82 ----------------------------------------------------------------------------*/
83 #include <string.h>
84
85 #include "c_g_aver.h"
86 #include "typedef.h"
87 #include "mode.h"
88 #include "cnst.h"
89
90 #include "basic_op.h"
91
92 /*----------------------------------------------------------------------------
93 ; MACROS
94 ; Define module specific macros here
95 ----------------------------------------------------------------------------*/
96
97
98 /*----------------------------------------------------------------------------
99 ; DEFINES
100 ; Include all pre-processor statements here. Include conditional
101 ; compile variables also.
102 ----------------------------------------------------------------------------*/
103
104 /*----------------------------------------------------------------------------
105 ; LOCAL FUNCTION DEFINITIONS
106 ; Function Prototype declaration
107 ----------------------------------------------------------------------------*/
108
109 /*----------------------------------------------------------------------------
110 ; LOCAL VARIABLE DEFINITIONS
111 ; Variable declaration - defined here and used outside this module
112 ----------------------------------------------------------------------------*/
113
114 /*
115 ------------------------------------------------------------------------------
116 FUNCTION NAME: Cb_gain_average_reset
117 ------------------------------------------------------------------------------
118 INPUT AND OUTPUT DEFINITIONS
119
120 Inputs:
121 state = pointer to a structure of type Cb_gain_averageState
122
123 Outputs:
124 Structure pointed to by state is initialized to zeros
125
126 Returns:
127 Returns 0 if memory was successfully initialized,
128 otherwise returns -1.
129
130 Global Variables Used:
131 None.
132
133 Local Variables Needed:
134 None.
135
136 ------------------------------------------------------------------------------
137 FUNCTION DESCRIPTION
138
139 Resets state memory
140
141 ------------------------------------------------------------------------------
142 REQUIREMENTS
143
144 None.
145
146 ------------------------------------------------------------------------------
147 REFERENCES
148
149 c_g_aver.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
150
151 ------------------------------------------------------------------------------
152 PSEUDO-CODE
153
154 Word16 Cb_gain_average_reset (Cb_gain_averageState *state)
155 {
156 if (state == (Cb_gain_averageState *) NULL){
157 fprintf(stderr, "Cb_gain_average_reset: invalid parameter\n");
158 return -1;
159 }
160
161 // Static vectors to zero
162 Set_zero (state->cbGainHistory, L_CBGAINHIST);
163
164 // Initialize hangover handling
165 state->hangVar = 0;
166 state->hangCount= 0;
167
168 return 0;
169 }
170
171 ------------------------------------------------------------------------------
172 RESOURCES USED [optional]
173
174 When the code is written for a specific target processor the
175 the resources used should be documented below.
176
177 HEAP MEMORY USED: x bytes
178
179 STACK MEMORY USED: x bytes
180
181 CLOCK CYCLES: (cycle count equation for this function) + (variable
182 used to represent cycle count for each subroutine
183 called)
184 where: (cycle count variable) = cycle count for [subroutine
185 name]
186
187 ------------------------------------------------------------------------------
188 CAUTION [optional]
189 [State any special notes, constraints or cautions for users of this function]
190
191 ------------------------------------------------------------------------------
192 */
193
Cb_gain_average_reset(Cb_gain_averageState * state)194 Word16 Cb_gain_average_reset(Cb_gain_averageState *state)
195 {
196 if (state == (Cb_gain_averageState *) NULL)
197 {
198 /* fprint(stderr, "Cb_gain_average_reset: invalid parameter\n"); */
199 return(-1);
200 }
201
202 /* Static vectors to zero */
203 memset(state->cbGainHistory, 0, L_CBGAINHIST*sizeof(Word16));
204
205 /* Initialize hangover handling */
206 state->hangVar = 0;
207 state->hangCount = 0;
208
209 return(0);
210 }
211
212 /****************************************************************************/
213
214 /*
215 ------------------------------------------------------------------------------
216 FUNCTION NAME: Cb_gain_average
217 ------------------------------------------------------------------------------
218 INPUT AND OUTPUT DEFINITIONS
219
220 Inputs:
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)
233
234 Returns:
235 cbGainMix = codebook gain (Word16)
236
237 Outputs:
238 None.
239
240 Global Variables Used:
241 None.
242
243 Local Variables Needed:
244 None.
245
246 ------------------------------------------------------------------------------
247 FUNCTION DESCRIPTION
248
249 The mix cb gains for MR475, MR515, MR59, MR67, MR102; gain_code other modes
250
251 ------------------------------------------------------------------------------
252 REQUIREMENTS
253
254 None.
255
256 ------------------------------------------------------------------------------
257 REFERENCES
258
259 c_g_aver.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
260
261 ------------------------------------------------------------------------------
262 PSEUDO-CODE
263
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
276 )
277 {
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 *---------------------------------------------------------
283 Word16 i;
284 Word16 cbGainMix, diff, tmp_diff, bgMix, cbGainMean;
285 Word32 L_sum;
286 Word16 tmp[M], tmp1, tmp2, shift1, shift2, shift;
287
288 // set correct cbGainMix for MR74, MR795, MR122
289 cbGainMix = gain_code;
290
291 *-------------------------------------------------------*
292 * Store list of CB gain needed in the CB gain *
293 * averaging *
294 *-------------------------------------------------------*
295 for (i = 0; i < (L_CBGAINHIST-1); i++)
296 {
297 st->cbGainHistory[i] = st->cbGainHistory[i+1];
298 }
299 st->cbGainHistory[L_CBGAINHIST-1] = gain_code;
300
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);
310 if (shift >= 0)
311 {
312 tmp[i] = shr(tmp[i], shift); // Q15+Qn-Qm-Qx=Q13
313 }
314 else
315 {
316 tmp[i] = shl(tmp[i], negate(shift)); // Q15+Qn-Qm-Qx=Q13
317 }
318 }
319
320 diff = tmp[0];
321 for (i = 1; i < M; i++) {
322 diff = add(diff, tmp[i]); // Q13
323 }
324
325 // Compute hangover
326 if (sub(diff, 5325) > 0) // 0.65 in Q11
327 {
328 st->hangVar = add(st->hangVar, 1);
329 }
330 else
331 {
332 st->hangVar = 0;
333 }
334
335 if (sub(st->hangVar, 10) > 0)
336 {
337 st->hangCount = 0; // Speech period, reset hangover variable
338 }
339
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
344 {
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)) ))
351 {
352 // bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25;
353 tmp_diff = sub(diff, 4506); // 0.55 in Q13
354
355 // max(0.0, diff-0.55)
356 if (tmp_diff > 0)
357 {
358 tmp1 = tmp_diff;
359 }
360 else
361 {
362 tmp1 = 0;
363 }
364
365 // min(0.25, tmp1)
366 if (sub(2048, tmp1) < 0)
367 {
368 bgMix = 8192;
369 }
370 else
371 {
372 bgMix = shl(tmp1, 2);
373 }
374 }
375 else
376 {
377 // bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25;
378 tmp_diff = sub(diff, 3277); // 0.4 in Q13
379
380 // max(0.0, diff-0.40)
381 if (tmp_diff > 0)
382 {
383 tmp1 = tmp_diff;
384 }
385 else
386 {
387 tmp1 = 0;
388 }
389
390 // min(0.25, tmp1)
391 if (sub(2048, tmp1) < 0)
392 {
393 bgMix = 8192;
394 }
395 else
396 {
397 bgMix = shl(tmp1, 2);
398 }
399 }
400
401 if ((sub(st->hangCount, 40) < 0) || (sub(diff, 5325) > 0)) // 0.65 in Q13
402 {
403 bgMix = 8192; // disable mix if too short time since
404 }
405
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++)
410 {
411 L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i]);
412 }
413 cbGainMean = pv_round(L_sum); // Q1
414
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)) )
420 {
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++)
423 {
424 L_sum = L_mac(L_sum, 4681, st->cbGainHistory[i]);
425 }
426 cbGainMean = pv_round(L_sum); // Q1
427 }
428
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
434 }
435
436 st->hangCount = add(st->hangCount, 1);
437 return cbGainMix;
438 }
439
440 ------------------------------------------------------------------------------
441 RESOURCES USED [optional]
442
443 When the code is written for a specific target processor the
444 the resources used should be documented below.
445
446 HEAP MEMORY USED: x bytes
447
448 STACK MEMORY USED: x bytes
449
450 CLOCK CYCLES: (cycle count equation for this function) + (variable
451 used to represent cycle count for each subroutine
452 called)
453 where: (cycle count variable) = cycle count for [subroutine
454 name]
455
456 ------------------------------------------------------------------------------
457 CAUTION [optional]
458 [State any special notes, constraints or cautions for users of this function]
459
460 ------------------------------------------------------------------------------
461 */
462
Cb_gain_average(Cb_gain_averageState * st,enum Mode mode,Word16 gain_code,Word16 lsp[],Word16 lspAver[],Word16 bfi,Word16 prev_bf,Word16 pdfi,Word16 prev_pdf,Word16 inBackgroundNoise,Word16 voicedHangover,Flag * pOverflow)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 */
475 Flag *pOverflow
476 )
477 {
478 Word16 i;
479 Word16 cbGainMix;
480 Word16 diff;
481 Word16 tmp_diff;
482 Word16 bgMix;
483 Word16 cbGainMean;
484 Word32 L_sum;
485 Word16 tmp[M];
486 Word16 tmp1;
487 Word16 tmp2;
488 Word16 shift1;
489 Word16 shift2;
490 Word16 shift;
491
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 *---------------------------------------------------------*/
497
498 /* set correct cbGainMix for MR74, MR795, MR122 */
499 cbGainMix = gain_code;
500
501 /*-------------------------------------------------------*
502 * Store list of CB gain needed in the CB gain *
503 * averaging *
504 *-------------------------------------------------------*/
505 for (i = 0; i < (L_CBGAINHIST - 1); i++)
506 {
507 st->cbGainHistory[i] = st->cbGainHistory[i+1];
508 }
509 st->cbGainHistory[L_CBGAINHIST-1] = gain_code;
510
511 diff = 0;
512
513 /* compute lsp difference */
514 for (i = 0; i < M; i++)
515 {
516 tmp1 = abs_s(sub(*(lspAver + i), *(lsp + i), pOverflow));
517 /* Q15 */
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) */
523
524 shift = 2 + shift1 - shift2;
525
526 if (shift >= 0)
527 {
528 *(tmp + i) = shr(*(tmp + i), shift, pOverflow);
529 /* Q15+Qn-Qm-Qx=Q13 */
530 }
531 else
532 {
533 *(tmp + i) = shl(*(tmp + i), negate(shift), pOverflow);
534 /* Q15+Qn-Qm-Qx=Q13 */
535 }
536
537 diff = add(diff, *(tmp + i), pOverflow); /* Q13 */
538 }
539
540 /* Compute hangover */
541
542 if (diff > 5325) /* 0.65 in Q11 */
543 {
544 st->hangVar += 1;
545 }
546 else
547 {
548 st->hangVar = 0;
549 }
550
551
552 if (st->hangVar > 10)
553 {
554 /* Speech period, reset hangover variable */
555 st->hangCount = 0;
556 }
557
558 /* Compute mix constant (bgMix) */
559 bgMix = 8192; /* 1 in Q13 */
560
561 if ((mode <= MR67) || (mode == MR102))
562 /* MR475, MR515, MR59, MR67, MR102 */
563 {
564 /* if errors and presumed noise make smoothing probability stronger */
565
566 if (((((pdfi != 0) && (prev_pdf != 0)) || (bfi != 0) ||
567 (prev_bf != 0))
568 && (voicedHangover > 1)
569 && (inBackgroundNoise != 0)
570 && ((mode == MR475) || (mode == MR515) ||
571 (mode == MR59))))
572 {
573 /* bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25; */
574 tmp_diff = sub(diff, 4506, pOverflow); /* 0.55 in Q13 */
575 }
576 else
577 {
578 /* bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25; */
579 tmp_diff = sub(diff, 3277, pOverflow); /* 0.4 in Q13 */
580 }
581
582 /* max(0.0, diff-0.55) or */
583 /* max(0.0, diff-0.40) */
584 if (tmp_diff > 0)
585 {
586 tmp1 = tmp_diff;
587 }
588 else
589 {
590 tmp1 = 0;
591 }
592
593 /* min(0.25, tmp1) */
594 if (2048 < tmp1)
595 {
596 bgMix = 8192;
597 }
598 else
599 {
600 bgMix = shl(tmp1, 2, pOverflow);
601 }
602
603 if ((st->hangCount < 40) || (diff > 5325)) /* 0.65 in Q13 */
604 {
605 /* disable mix if too short time since */
606 bgMix = 8192;
607 }
608
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 */
613
614 for (i = 3; i < L_CBGAINHIST; i++)
615 {
616 L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i], pOverflow);
617 }
618 cbGainMean = pv_round(L_sum, pOverflow); /* Q1 */
619
620 /* more smoothing in error and bg noise (NB no DFI used here) */
621
622 if (((bfi != 0) || (prev_bf != 0)) && (inBackgroundNoise != 0)
623 && ((mode == MR475) || (mode == MR515)
624 || (mode == MR59)))
625 {
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++)
629 {
630 L_sum =
631 L_mac(L_sum, 4681, st->cbGainHistory[i], pOverflow);
632 }
633 cbGainMean = pv_round(L_sum, pOverflow); /* Q1 */
634 }
635
636 /* cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean; */
637 /* L_sum in Q15 */
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 */
642 }
643
644 st->hangCount += 1;
645
646 return (cbGainMix);
647 }
648
649