c_g_aver.cpp revision 4f1efc098cb5791c3e9f483f2af84aef70d2d0a0
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/****************************************************************************************
19Portions 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)
26Permission to distribute, modify and use this file under the standard license
27terms 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
154Word16 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
194Word16  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
264Word16 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
463Word16 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