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 Filename: c_g_aver.cpp
35 Functions:
36 Cb_gain_average_reset
37 Cb_gain_average
38
39 ------------------------------------------------------------------------------
40 MODULE DESCRIPTION
41
42 This file contains functions that reset and perform
43 codebook gain calculations.
44
45 ------------------------------------------------------------------------------
46 */
47
48
49 /*----------------------------------------------------------------------------
50 ; INCLUDES
51 ----------------------------------------------------------------------------*/
52 #include "c_g_aver.h"
53 #include "typedef.h"
54 #include "mode.h"
55 #include "cnst.h"
56
57 #include "basic_op.h"
58 #include "oscl_mem.h"
59
60 /*----------------------------------------------------------------------------
61 ; MACROS
62 ; Define module specific macros here
63 ----------------------------------------------------------------------------*/
64
65
66 /*----------------------------------------------------------------------------
67 ; DEFINES
68 ; Include all pre-processor statements here. Include conditional
69 ; compile variables also.
70 ----------------------------------------------------------------------------*/
71
72 /*----------------------------------------------------------------------------
73 ; LOCAL FUNCTION DEFINITIONS
74 ; Function Prototype declaration
75 ----------------------------------------------------------------------------*/
76
77 /*----------------------------------------------------------------------------
78 ; LOCAL VARIABLE DEFINITIONS
79 ; Variable declaration - defined here and used outside this module
80 ----------------------------------------------------------------------------*/
81
82 /*
83 ------------------------------------------------------------------------------
84 FUNCTION NAME: Cb_gain_average_reset
85 ------------------------------------------------------------------------------
86 INPUT AND OUTPUT DEFINITIONS
87
88 Inputs:
89 state = pointer to a structure of type Cb_gain_averageState
90
91 Outputs:
92 Structure pointed to by state is initialized to zeros
93
94 Returns:
95 Returns 0 if memory was successfully initialized,
96 otherwise returns -1.
97
98 Global Variables Used:
99 None.
100
101 Local Variables Needed:
102 None.
103
104 ------------------------------------------------------------------------------
105 FUNCTION DESCRIPTION
106
107 Resets state memory
108
109 ------------------------------------------------------------------------------
110 REQUIREMENTS
111
112 None.
113
114 ------------------------------------------------------------------------------
115 REFERENCES
116
117 c_g_aver.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
118
119 ------------------------------------------------------------------------------
120 PSEUDO-CODE
121
122 Word16 Cb_gain_average_reset (Cb_gain_averageState *state)
123 {
124 if (state == (Cb_gain_averageState *) NULL){
125 fprintf(stderr, "Cb_gain_average_reset: invalid parameter\n");
126 return -1;
127 }
128
129 // Static vectors to zero
130 Set_zero (state->cbGainHistory, L_CBGAINHIST);
131
132 // Initialize hangover handling
133 state->hangVar = 0;
134 state->hangCount= 0;
135
136 return 0;
137 }
138
139 ------------------------------------------------------------------------------
140 CAUTION [optional]
141 [State any special notes, constraints or cautions for users of this function]
142
143 ------------------------------------------------------------------------------
144 */
145
Cb_gain_average_reset(Cb_gain_averageState * state)146 Word16 Cb_gain_average_reset(Cb_gain_averageState *state)
147 {
148 if (state == (Cb_gain_averageState *) NULL)
149 {
150 /* fprint(stderr, "Cb_gain_average_reset: invalid parameter\n"); */
151 return(-1);
152 }
153
154 /* Static vectors to zero */
155 oscl_memset(state->cbGainHistory, 0, L_CBGAINHIST*sizeof(Word16));
156
157 /* Initialize hangover handling */
158 state->hangVar = 0;
159 state->hangCount = 0;
160
161 return(0);
162 }
163
164 /****************************************************************************/
165
166 /*
167 ------------------------------------------------------------------------------
168 FUNCTION NAME: Cb_gain_average
169 ------------------------------------------------------------------------------
170 INPUT AND OUTPUT DEFINITIONS
171
172 Inputs:
173 st = pointer to structure of type Cb_gain_averageState
174 mode = AMR mode (enum Mode)
175 gain_code = CB gain (Word16)
176 lsp = the LSP for the current frame (Word16)
177 lspAver = the average of LSP for 8 frames (Word16)
178 bfi = bad frame indication flag (Word16)
179 prev_bf = previous bad frame indication flag (Word16)
180 pdfi = potential degraded bad frame ind flag (Word16)
181 prev_pdf = prev pot. degraded bad frame ind flag (Word16)
182 inBackgroundNoise = background noise decision (Word16)
183 voicedHangover = # of frames after last voiced frame (Word16)
184 pOverflow = address of overflow (Flag)
185
186 Returns:
187 cbGainMix = codebook gain (Word16)
188
189 Outputs:
190 None.
191
192 Global Variables Used:
193 None.
194
195 Local Variables Needed:
196 None.
197
198 ------------------------------------------------------------------------------
199 FUNCTION DESCRIPTION
200
201 The mix cb gains for MR475, MR515, MR59, MR67, MR102; gain_code other modes
202
203 ------------------------------------------------------------------------------
204 REQUIREMENTS
205
206 None.
207
208 ------------------------------------------------------------------------------
209 REFERENCES
210
211 c_g_aver.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
212
213 ------------------------------------------------------------------------------
214 PSEUDO-CODE
215
216 Word16 Cb_gain_average (
217 Cb_gain_averageState *st, // i/o : State variables for CB gain avergeing
218 enum Mode mode, // i : AMR mode
219 Word16 gain_code, // i : CB gain Q1
220 Word16 lsp[], // i : The LSP for the current frame Q15
221 Word16 lspAver[], // i : The average of LSP for 8 frames Q15
222 Word16 bfi, // i : bad frame indication flag
223 Word16 prev_bf, // i : previous bad frame indication flag
224 Word16 pdfi, // i : potential degraded bad frame ind flag
225 Word16 prev_pdf, // i : prev pot. degraded bad frame ind flag
226 Word16 inBackgroundNoise, // i : background noise decision
227 Word16 voicedHangover // i : # of frames after last voiced frame
228 )
229 {
230 //---------------------------------------------------------*
231 * Compute mixed cb gain, used to make cb gain more *
232 * smooth in background noise for modes 5.15, 5.9 and 6.7 *
233 * states that needs to be updated by all *
234 *---------------------------------------------------------
235 Word16 i;
236 Word16 cbGainMix, diff, tmp_diff, bgMix, cbGainMean;
237 Word32 L_sum;
238 Word16 tmp[M], tmp1, tmp2, shift1, shift2, shift;
239
240 // set correct cbGainMix for MR74, MR795, MR122
241 cbGainMix = gain_code;
242
243 *-------------------------------------------------------*
244 * Store list of CB gain needed in the CB gain *
245 * averaging *
246 *-------------------------------------------------------*
247 for (i = 0; i < (L_CBGAINHIST-1); i++)
248 {
249 st->cbGainHistory[i] = st->cbGainHistory[i+1];
250 }
251 st->cbGainHistory[L_CBGAINHIST-1] = gain_code;
252
253 // compute lsp difference
254 for (i = 0; i < M; i++) {
255 tmp1 = abs_s(sub(lspAver[i], lsp[i])); // Q15
256 shift1 = sub(norm_s(tmp1), 1); // Qn
257 tmp1 = shl(tmp1, shift1); // Q15+Qn
258 shift2 = norm_s(lspAver[i]); // Qm
259 tmp2 = shl(lspAver[i], shift2); // Q15+Qm
260 tmp[i] = div_s(tmp1, tmp2); // Q15+(Q15+Qn)-(Q15+Qm)
261 shift = sub(add(2, shift1), shift2);
262 if (shift >= 0)
263 {
264 tmp[i] = shr(tmp[i], shift); // Q15+Qn-Qm-Qx=Q13
265 }
266 else
267 {
268 tmp[i] = shl(tmp[i], negate(shift)); // Q15+Qn-Qm-Qx=Q13
269 }
270 }
271
272 diff = tmp[0];
273 for (i = 1; i < M; i++) {
274 diff = add(diff, tmp[i]); // Q13
275 }
276
277 // Compute hangover
278 if (sub(diff, 5325) > 0) // 0.65 in Q11
279 {
280 st->hangVar = add(st->hangVar, 1);
281 }
282 else
283 {
284 st->hangVar = 0;
285 }
286
287 if (sub(st->hangVar, 10) > 0)
288 {
289 st->hangCount = 0; // Speech period, reset hangover variable
290 }
291
292 // Compute mix constant (bgMix)
293 bgMix = 8192; // 1 in Q13
294 if ((sub(mode, MR67) <= 0) || (sub(mode, MR102) == 0))
295 // MR475, MR515, MR59, MR67, MR102
296 {
297 // if errors and presumed noise make smoothing probability stronger
298 if (((((pdfi != 0) && (prev_pdf != 0)) || (bfi != 0) || (prev_bf != 0)) &&
299 (sub(voicedHangover, 1) > 0) && (inBackgroundNoise != 0) &&
300 ((sub(mode, MR475) == 0) ||
301 (sub(mode, MR515) == 0) ||
302 (sub(mode, MR59) == 0)) ))
303 {
304 // bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25;
305 tmp_diff = sub(diff, 4506); // 0.55 in Q13
306
307 // max(0.0, diff-0.55)
308 if (tmp_diff > 0)
309 {
310 tmp1 = tmp_diff;
311 }
312 else
313 {
314 tmp1 = 0;
315 }
316
317 // min(0.25, tmp1)
318 if (sub(2048, tmp1) < 0)
319 {
320 bgMix = 8192;
321 }
322 else
323 {
324 bgMix = shl(tmp1, 2);
325 }
326 }
327 else
328 {
329 // bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25;
330 tmp_diff = sub(diff, 3277); // 0.4 in Q13
331
332 // max(0.0, diff-0.40)
333 if (tmp_diff > 0)
334 {
335 tmp1 = tmp_diff;
336 }
337 else
338 {
339 tmp1 = 0;
340 }
341
342 // min(0.25, tmp1)
343 if (sub(2048, tmp1) < 0)
344 {
345 bgMix = 8192;
346 }
347 else
348 {
349 bgMix = shl(tmp1, 2);
350 }
351 }
352
353 if ((sub(st->hangCount, 40) < 0) || (sub(diff, 5325) > 0)) // 0.65 in Q13
354 {
355 bgMix = 8192; // disable mix if too short time since
356 }
357
358 // Smoothen the cb gain trajectory
359 // smoothing depends on mix constant bgMix
360 L_sum = L_mult(6554, st->cbGainHistory[2]); // 0.2 in Q15; L_sum in Q17
361 for (i = 3; i < L_CBGAINHIST; i++)
362 {
363 L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i]);
364 }
365 cbGainMean = pv_round(L_sum); // Q1
366
367 // more smoothing in error and bg noise (NB no DFI used here)
368 if (((bfi != 0) || (prev_bf != 0)) && (inBackgroundNoise != 0) &&
369 ((sub(mode, MR475) == 0) ||
370 (sub(mode, MR515) == 0) ||
371 (sub(mode, MR59) == 0)) )
372 {
373 L_sum = L_mult(4681, st->cbGainHistory[0]); // 0.143 in Q15; L_sum in Q17
374 for (i = 1; i < L_CBGAINHIST; i++)
375 {
376 L_sum = L_mac(L_sum, 4681, st->cbGainHistory[i]);
377 }
378 cbGainMean = pv_round(L_sum); // Q1
379 }
380
381 // cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean;
382 L_sum = L_mult(bgMix, cbGainMix); // L_sum in Q15
383 L_sum = L_mac(L_sum, 8192, cbGainMean);
384 L_sum = L_msu(L_sum, bgMix, cbGainMean);
385 cbGainMix = pv_round(L_shl(L_sum, 2)); // Q1
386 }
387
388 st->hangCount = add(st->hangCount, 1);
389 return cbGainMix;
390 }
391
392 ------------------------------------------------------------------------------
393 CAUTION [optional]
394 [State any special notes, constraints or cautions for users of this function]
395
396 ------------------------------------------------------------------------------
397 */
398
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)399 Word16 Cb_gain_average(
400 Cb_gain_averageState *st, /* i/o : State variables for CB gain averaging */
401 enum Mode mode, /* i : AMR mode */
402 Word16 gain_code, /* i : CB gain Q1 */
403 Word16 lsp[], /* i : The LSP for the current frame Q15 */
404 Word16 lspAver[], /* i : The average of LSP for 8 frames Q15 */
405 Word16 bfi, /* i : bad frame indication flag */
406 Word16 prev_bf, /* i : previous bad frame indication flag */
407 Word16 pdfi, /* i : potential degraded bad frame ind flag */
408 Word16 prev_pdf, /* i : prev pot. degraded bad frame ind flag */
409 Word16 inBackgroundNoise, /* i : background noise decision */
410 Word16 voicedHangover, /* i : # of frames after last voiced frame */
411 Flag *pOverflow
412 )
413 {
414 Word16 i;
415 Word16 cbGainMix;
416 Word16 diff;
417 Word16 tmp_diff;
418 Word16 bgMix;
419 Word16 cbGainMean;
420 Word32 L_sum;
421 Word16 tmp[M];
422 Word16 tmp1;
423 Word16 tmp2;
424 Word16 shift1;
425 Word16 shift2;
426 Word16 shift;
427
428 /*---------------------------------------------------------*
429 * Compute mixed cb gain, used to make cb gain more *
430 * smooth in background noise for modes 5.15, 5.9 and 6.7 *
431 * states that needs to be updated by all *
432 *---------------------------------------------------------*/
433
434 /* set correct cbGainMix for MR74, MR795, MR122 */
435 cbGainMix = gain_code;
436
437 /*-------------------------------------------------------*
438 * Store list of CB gain needed in the CB gain *
439 * averaging *
440 *-------------------------------------------------------*/
441 for (i = 0; i < (L_CBGAINHIST - 1); i++)
442 {
443 st->cbGainHistory[i] = st->cbGainHistory[i+1];
444 }
445 st->cbGainHistory[L_CBGAINHIST-1] = gain_code;
446
447 diff = 0;
448
449 /* compute lsp difference */
450 for (i = 0; i < M; i++)
451 {
452 tmp1 = abs_s(sub(*(lspAver + i), *(lsp + i), pOverflow));
453 /* Q15 */
454 shift1 = norm_s(tmp1) - 1 ; /* Qn */
455 tmp1 = shl(tmp1, shift1, pOverflow); /* Q15+Qn */
456 shift2 = norm_s(*(lspAver + i)); /* Qm */
457 tmp2 = shl(*(lspAver + i), shift2, pOverflow); /* Q15+Qm */
458 tmp[i] = div_s(tmp1, tmp2); /* Q15+(Q15+Qn)-(Q15+Qm) */
459
460 shift = 2 + shift1 - shift2;
461
462 if (shift >= 0)
463 {
464 *(tmp + i) = shr(*(tmp + i), shift, pOverflow);
465 /* Q15+Qn-Qm-Qx=Q13 */
466 }
467 else
468 {
469 *(tmp + i) = shl(*(tmp + i), negate(shift), pOverflow);
470 /* Q15+Qn-Qm-Qx=Q13 */
471 }
472
473 diff = add_16(diff, *(tmp + i), pOverflow); /* Q13 */
474 }
475
476 /* Compute hangover */
477
478 if (diff > 5325) /* 0.65 in Q11 */
479 {
480 st->hangVar += 1;
481 }
482 else
483 {
484 st->hangVar = 0;
485 }
486
487
488 if (st->hangVar > 10)
489 {
490 /* Speech period, reset hangover variable */
491 st->hangCount = 0;
492 }
493
494 /* Compute mix constant (bgMix) */
495 bgMix = 8192; /* 1 in Q13 */
496
497 if ((mode <= MR67) || (mode == MR102))
498 /* MR475, MR515, MR59, MR67, MR102 */
499 {
500 /* if errors and presumed noise make smoothing probability stronger */
501
502 if (((((pdfi != 0) && (prev_pdf != 0)) || (bfi != 0) ||
503 (prev_bf != 0))
504 && (voicedHangover > 1)
505 && (inBackgroundNoise != 0)
506 && ((mode == MR475) || (mode == MR515) ||
507 (mode == MR59))))
508 {
509 /* bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25; */
510 tmp_diff = diff - 4506; /* 0.55 in Q13 */
511 }
512 else
513 {
514 /* bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25; */
515 tmp_diff = diff - 3277; /* 0.4 in Q13 */
516 }
517
518 /* max(0.0, diff-0.55) or */
519 /* max(0.0, diff-0.40) */
520 if (tmp_diff > 0)
521 {
522 tmp1 = tmp_diff;
523 }
524 else
525 {
526 tmp1 = 0;
527 }
528
529 /* min(0.25, tmp1) */
530 if (2048 < tmp1)
531 {
532 bgMix = 8192;
533 }
534 else
535 {
536 bgMix = shl(tmp1, 2, pOverflow);
537 }
538
539 if ((st->hangCount < 40) || (diff > 5325)) /* 0.65 in Q13 */
540 {
541 /* disable mix if too short time since */
542 bgMix = 8192;
543 }
544
545 /* Smoothen the cb gain trajectory */
546 /* smoothing depends on mix constant bgMix */
547 L_sum = L_mult(6554, st->cbGainHistory[2], pOverflow);
548 /* 0.2 in Q15; L_sum in Q17 */
549
550 for (i = 3; i < L_CBGAINHIST; i++)
551 {
552 L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i], pOverflow);
553 }
554 cbGainMean = pv_round(L_sum, pOverflow); /* Q1 */
555
556 /* more smoothing in error and bg noise (NB no DFI used here) */
557
558 if (((bfi != 0) || (prev_bf != 0)) && (inBackgroundNoise != 0)
559 && ((mode == MR475) || (mode == MR515)
560 || (mode == MR59)))
561 {
562 /* 0.143 in Q15; L_sum in Q17 */
563 L_sum = L_mult(4681, st->cbGainHistory[0], pOverflow);
564 for (i = 1; i < L_CBGAINHIST; i++)
565 {
566 L_sum =
567 L_mac(L_sum, 4681, st->cbGainHistory[i], pOverflow);
568 }
569 cbGainMean = pv_round(L_sum, pOverflow); /* Q1 */
570 }
571
572 /* cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean; */
573 /* L_sum in Q15 */
574 L_sum = L_mult(bgMix, cbGainMix, pOverflow);
575 L_sum = L_mac(L_sum, 8192, cbGainMean, pOverflow);
576 L_sum = L_msu(L_sum, bgMix, cbGainMean, pOverflow);
577 cbGainMix = pv_round(L_shl(L_sum, 2, pOverflow), pOverflow); /* Q1 */
578 }
579
580 st->hangCount += 1;
581
582 return (cbGainMix);
583 }
584
585