Initialize Tizen 2.3
[external/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / dec / src / bgnscd.cpp
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  Filename: bgnscd.cpp
33  Functions:
34            Bgn_scd_reset
35            Bgn_scd
36
37 ------------------------------------------------------------------------------
38  MODULE DESCRIPTION
39
40  Background noise source characteristic detector (SCD)
41
42 ------------------------------------------------------------------------------
43 */
44
45
46 /*----------------------------------------------------------------------------
47 ; INCLUDES
48 ----------------------------------------------------------------------------*/
49 #include    "bgnscd.h"
50 #include    "typedef.h"
51 #include    "basic_op.h"
52 #include    "cnst.h"
53 #include    "gmed_n.h"
54 #include    "sqrt_l.h"
55 #include    "oscl_mem.h"
56
57 /*----------------------------------------------------------------------------
58 ; MACROS
59 ; Define module specific macros here
60 ----------------------------------------------------------------------------*/
61
62
63 /*----------------------------------------------------------------------------
64 ; DEFINES
65 ; Include all pre-processor statements here. Include conditional
66 ; compile variables also.
67 ----------------------------------------------------------------------------*/
68 #define TRUE  1
69 #define FALSE 0
70
71 /*----------------------------------------------------------------------------
72 ; LOCAL FUNCTION DEFINITIONS
73 ; Function Prototype declaration
74 ----------------------------------------------------------------------------*/
75
76 /*----------------------------------------------------------------------------
77 ; LOCAL VARIABLE DEFINITIONS
78 ; Variable declaration - defined here and used outside this module
79 ----------------------------------------------------------------------------*/
80
81
82 /*
83 ------------------------------------------------------------------------------
84  FUNCTION NAME: Bgn_scd_reset
85 ------------------------------------------------------------------------------
86  INPUT AND OUTPUT DEFINITIONS
87
88  Inputs:
89     state = points to memory of type Bgn_scdState.
90
91  Outputs:
92     The memory of type Bgn_scdState pointed to by state is set to all
93         zeros.
94
95  Returns:
96     Returns 0 if memory was successfully initialized,
97         otherwise returns -1.
98
99  Global Variables Used:
100     None.
101
102  Local Variables Needed:
103     None.
104
105 ------------------------------------------------------------------------------
106  FUNCTION DESCRIPTION
107
108  Resets state memory.
109
110 ------------------------------------------------------------------------------
111  REQUIREMENTS
112
113  None
114
115 ------------------------------------------------------------------------------
116  REFERENCES
117
118  bgnscd.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
119
120 ------------------------------------------------------------------------------
121  PSEUDO-CODE
122
123 Word16 Bgn_scd_reset (Bgn_scdState *state)
124 {
125    if (state == (Bgn_scdState *) NULL){
126       fprintf(stderr, "Bgn_scd_reset: invalid parameter\n");
127       return -1;
128    }
129
130    // Static vectors to zero
131    Set_zero (state->frameEnergyHist, L_ENERGYHIST);
132
133    // Initialize hangover handling
134    state->bgHangover = 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
146 Word16  Bgn_scd_reset(Bgn_scdState *state)
147 {
148     if (state == (Bgn_scdState *) NULL)
149     {
150         /* fprintf(stderr, "Bgn_scd_reset: invalid parameter\n");  */
151         return(-1);
152     }
153
154     /* Static vectors to zero */
155     oscl_memset(state->frameEnergyHist, 0, L_ENERGYHIST*sizeof(Word16));
156
157     /* Initialize hangover handling */
158     state->bgHangover = 0;
159
160     return(0);
161 }
162
163 /****************************************************************************/
164
165 /*
166 ------------------------------------------------------------------------------
167  FUNCTION NAME: Bgn_scd
168 ------------------------------------------------------------------------------
169  INPUT AND OUTPUT DEFINITIONS
170
171  Inputs:
172     st = pointer to state variables of type Bgn_scdState
173     ltpGainHist[] = LTP gain history (Word16)
174     speech[] = synthesis speech frame (Word16)
175     voicedHangover = pointer to # of frames after last voiced frame (Word16)
176     pOverflow      = pointer to overflow indicator (Flag)
177
178  Outputs:
179     st = function updates the state variables of type Bgn_scdState
180         pointed to by st.
181     voicedHangover = function updates the # of frames after last voiced
182         frame pointed to by voicedHangover.
183     pOverflow = 1 if the basic math function L_add() results in saturation.
184                   else pOverflow is zero.
185
186  Returns:
187     inbgNoise = flag if background noise is present (Word16)
188
189  Global Variables Used:
190     None.
191
192  Local Variables Needed:
193     None.
194
195 ------------------------------------------------------------------------------
196  FUNCTION DESCRIPTION
197
198  Characterize synthesis speech and detect background noise.
199
200 ------------------------------------------------------------------------------
201  REQUIREMENTS
202
203  None
204
205 ------------------------------------------------------------------------------
206  REFERENCES
207
208  bgnscd.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
209
210 ------------------------------------------------------------------------------
211  PSEUDO-CODE
212
213 Word16 Bgn_scd (Bgn_scdState *st,      // i : State variables for bgn SCD
214                 Word16 ltpGainHist[],  // i : LTP gain history
215                 Word16 speech[],       // o : synthesis speech frame
216                 Word16 *voicedHangover // o : # of frames after last
217                                               voiced frame
218                 )
219 {
220    Word16 i;
221    Word16 prevVoiced, inbgNoise;
222    Word16 temp;
223    Word16 ltpLimit, frameEnergyMin;
224    Word16 currEnergy, noiseFloor, maxEnergy, maxEnergyLastPart;
225    Word32 s;
226
227    // Update the inBackgroundNoise flag (valid for use in next frame if BFI)
228    // it now works as a energy detector floating on top
229    // not as good as a VAD.
230
231    currEnergy = 0;
232    s = (Word32) 0;
233
234    for (i = 0; i < L_FRAME; i++)
235    {
236        s = L_mac (s, speech[i], speech[i]);
237    }
238
239    s = L_shl(s, 2);
240
241    currEnergy = extract_h (s);
242
243    frameEnergyMin = 32767;
244
245    for (i = 0; i < L_ENERGYHIST; i++)
246    {
247       if (sub(st->frameEnergyHist[i], frameEnergyMin) < 0)
248          frameEnergyMin = st->frameEnergyHist[i];
249    }
250
251    noiseFloor = shl (frameEnergyMin, 4); // Frame Energy Margin of 16
252
253    maxEnergy = st->frameEnergyHist[0];
254    for (i = 1; i < L_ENERGYHIST-4; i++)
255    {
256       if ( sub (maxEnergy, st->frameEnergyHist[i]) < 0)
257       {
258          maxEnergy = st->frameEnergyHist[i];
259       }
260    }
261
262    maxEnergyLastPart = st->frameEnergyHist[2*L_ENERGYHIST/3];
263    for (i = 2*L_ENERGYHIST/3+1; i < L_ENERGYHIST; i++)
264    {
265       if ( sub (maxEnergyLastPart, st->frameEnergyHist[i] ) < 0)
266       {
267          maxEnergyLastPart = st->frameEnergyHist[i];
268       }
269    }
270
271    inbgNoise = 0;        // false
272
273    // Do not consider silence as noise
274    // Do not consider continuous high volume as noise
275    // Or if the current noise level is very low
276    // Mark as noise if under current noise limit
277    // OR if the maximum energy is below the upper limit
278
279    if ( (sub(maxEnergy, LOWERNOISELIMIT) > 0) &&
280         (sub(currEnergy, FRAMEENERGYLIMIT) < 0) &&
281         (sub(currEnergy, LOWERNOISELIMIT) > 0) &&
282         ( (sub(currEnergy, noiseFloor) < 0) ||
283           (sub(maxEnergyLastPart, UPPERNOISELIMIT) < 0)))
284    {
285       if (sub(add(st->bgHangover, 1), 30) > 0)
286       {
287          st->bgHangover = 30;
288       } else
289       {
290          st->bgHangover = add(st->bgHangover, 1);
291       }
292    }
293    else
294    {
295       st->bgHangover = 0;
296    }
297
298    // make final decision about frame state , act somewhat cautiosly
299    if (sub(st->bgHangover,1) > 0)
300       inbgNoise = 1;       // true
301
302    for (i = 0; i < L_ENERGYHIST-1; i++)
303    {
304       st->frameEnergyHist[i] = st->frameEnergyHist[i+1];
305    }
306    st->frameEnergyHist[L_ENERGYHIST-1] = currEnergy;
307
308    // prepare for voicing decision; tighten the threshold after some
309       time in noise
310    ltpLimit = 13926;             // 0.85  Q14
311    if (sub(st->bgHangover, 8) > 0)
312    {
313       ltpLimit = 15565;          // 0.95  Q14
314    }
315    if (sub(st->bgHangover, 15) > 0)
316    {
317       ltpLimit = 16383;          // 1.00  Q14
318    }
319
320    // weak sort of voicing indication.
321    prevVoiced = 0;        // false
322
323    if (sub(gmed_n(&ltpGainHist[4], 5), ltpLimit) > 0)
324    {
325       prevVoiced = 1;     // true
326    }
327    if (sub(st->bgHangover, 20) > 0) {
328       if (sub(gmed_n(ltpGainHist, 9), ltpLimit) > 0)
329       {
330          prevVoiced = 1;  // true
331       }
332       else
333       {
334          prevVoiced = 0;  // false
335       }
336    }
337
338    if (prevVoiced)
339    {
340       *voicedHangover = 0;
341    }
342    else
343    {
344       temp = add(*voicedHangover, 1);
345       if (sub(temp, 10) > 0)
346       {
347          *voicedHangover = 10;
348       }
349       else
350       {
351          *voicedHangover = temp;
352       }
353    }
354
355    return inbgNoise;
356 }
357
358 ------------------------------------------------------------------------------
359  CAUTION [optional]
360  [State any special notes, constraints or cautions for users of this function]
361
362 ------------------------------------------------------------------------------
363 */
364
365 Word16  Bgn_scd(Bgn_scdState *st,       /* i : State variables for bgn SCD  */
366                 Word16 ltpGainHist[],  /* i : LTP gain history             */
367                 Word16 speech[],       /* o : synthesis speech frame       */
368                 Word16 *voicedHangover,/* o : # of frames after last
369                                                voiced frame                 */
370                 Flag   *pOverflow
371                )
372 {
373     Word16  i;
374     Word16  prevVoiced, inbgNoise;
375     Word16  temp;
376     Word16  ltpLimit, frameEnergyMin;
377     Word16  currEnergy, noiseFloor, maxEnergy, maxEnergyLastPart;
378     Word32  s, L_temp;
379
380
381     /* Update the inBackgroundNoise flag (valid for use in next frame if BFI)   */
382     /* it now works as a energy detector floating on top                        */
383     /* not as good as a VAD.                                                    */
384
385     s = (Word32) 0;
386
387     for (i = L_FRAME - 1; i >= 0; i--)
388     {
389         L_temp = ((Word32) speech[i]) * speech[i];
390         if (L_temp != (Word32) 0x40000000L)
391         {
392             L_temp = L_temp << 1;
393         }
394         else
395         {
396             L_temp = MAX_32;
397         }
398         s = L_add(s, L_temp, pOverflow);
399     }
400
401     /* s is a sum of squares, so don't need to check for neg overflow */
402     if (s > (Word32)0x1fffffffL)
403     {
404         currEnergy = MAX_16;
405     }
406     else
407     {
408         currEnergy = (Word16)(s >> 14);
409     }
410
411     frameEnergyMin = 32767;
412     for (i = L_ENERGYHIST - 1; i >= 0; i--)
413     {
414         if (st->frameEnergyHist[i] < frameEnergyMin)
415         {
416             frameEnergyMin = st->frameEnergyHist[i];
417         }
418     }
419
420     /* Frame Energy Margin of 16 */
421     L_temp = (Word32)frameEnergyMin << 4;
422     if (L_temp != (Word32)((Word16) L_temp))
423     {
424         if (L_temp > 0)
425         {
426             noiseFloor = MAX_16;
427         }
428         else
429         {
430             noiseFloor = MIN_16;
431         }
432     }
433     else
434     {
435         noiseFloor = (Word16)(L_temp);
436     }
437
438     maxEnergy = st->frameEnergyHist[0];
439     for (i = L_ENERGYHIST - 5; i >= 1; i--)
440     {
441         if (maxEnergy < st->frameEnergyHist[i])
442         {
443             maxEnergy = st->frameEnergyHist[i];
444         }
445     }
446
447     maxEnergyLastPart = st->frameEnergyHist[2*L_ENERGYHIST/3];
448     for (i = 2 * L_ENERGYHIST / 3 + 1; i < L_ENERGYHIST; i++)
449     {
450         if (maxEnergyLastPart < st->frameEnergyHist[i])
451         {
452             maxEnergyLastPart = st->frameEnergyHist[i];
453         }
454     }
455
456     /* Do not consider silence as noise */
457     /* Do not consider continuous high volume as noise */
458     /* Or if the current noise level is very low */
459     /* Mark as noise if under current noise limit */
460     /* OR if the maximum energy is below the upper limit */
461
462     if ((maxEnergy > LOWERNOISELIMIT) &&
463             (currEnergy < FRAMEENERGYLIMIT) &&
464             (currEnergy > LOWERNOISELIMIT) &&
465             ((currEnergy < noiseFloor) ||
466              (maxEnergyLastPart < UPPERNOISELIMIT)))
467     {
468         if ((st->bgHangover + 1) > 30)
469         {
470             st->bgHangover = 30;
471         }
472         else
473         {
474             st->bgHangover += 1;
475         }
476     }
477     else
478     {
479         st->bgHangover = 0;
480     }
481
482     /* make final decision about frame state , act somewhat cautiosly */
483
484     if (st->bgHangover > 1)
485     {
486         inbgNoise = TRUE;
487     }
488     else
489     {
490         inbgNoise = FALSE;
491     }
492
493     for (i = 0; i < L_ENERGYHIST - 1; i++)
494     {
495         st->frameEnergyHist[i] = st->frameEnergyHist[i+1];
496     }
497     st->frameEnergyHist[L_ENERGYHIST-1] = currEnergy;
498
499     /* prepare for voicing decision; tighten the threshold after some
500        time in noise */
501
502     if (st->bgHangover > 15)
503     {
504         ltpLimit = 16383;       /* 1.00  Q14 */
505     }
506     else if (st->bgHangover > 8)
507     {
508         ltpLimit = 15565;       /* 0.95  Q14 */
509     }
510     else
511     {
512         ltpLimit = 13926;       /* 0.85  Q14 */
513     }
514
515     /* weak sort of voicing indication. */
516     prevVoiced = FALSE;
517
518     if (gmed_n(&ltpGainHist[4], 5) > ltpLimit)
519     {
520         prevVoiced = TRUE;
521     }
522
523     if (st->bgHangover > 20)
524     {
525         if (gmed_n(ltpGainHist, 9) > ltpLimit)
526         {
527             prevVoiced = TRUE;
528         }
529         else
530         {
531             prevVoiced = FALSE;
532         }
533     }
534
535
536     if (prevVoiced)
537     {
538         *voicedHangover = 0;
539     }
540     else
541     {
542         temp = *voicedHangover + 1;
543
544         if (temp > 10)
545         {
546             *voicedHangover = 10;
547         }
548         else
549         {
550             *voicedHangover = temp;
551         }
552     }
553
554     return(inbgNoise);
555 }