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/g_adapt.c
35  Functions:
36 
37      Date: 02/04/2002
38 
39 ------------------------------------------------------------------------------
40  REVISION HISTORY
41 
42  Description: Updated template used to PV coding template.
43  Changed to accept the pOverflow flag for EPOC compatibility.
44 
45  Description:  Replaced OSCL mem type functions and eliminated include
46                files that now are chosen by OSCL definitions
47 
48  Description:  Replaced "int" and/or "char" with OSCL defined types.
49 
50  Description:
51 
52 ------------------------------------------------------------------------------
53  MODULE DESCRIPTION
54 
55 
56 ------------------------------------------------------------------------------
57 */
58 
59 /*----------------------------------------------------------------------------
60 ; INCLUDES
61 ----------------------------------------------------------------------------*/
62 #include <stdlib.h>
63 
64 #include "g_adapt.h"
65 #include "typedef.h"
66 #include "basic_op.h"
67 #include "oper_32b.h"
68 #include "cnst.h"
69 #include "gmed_n.h"
70 
71 /*----------------------------------------------------------------------------
72 ; MACROS
73 ; Define module specific macros here
74 ----------------------------------------------------------------------------*/
75 
76 /*----------------------------------------------------------------------------
77 ; DEFINES
78 ; Include all pre-processor statements here. Include conditional
79 ; compile variables also.
80 ----------------------------------------------------------------------------*/
81 #define LTP_GAIN_THR1 2721 /* 2721 Q13 = 0.3322 ~= 1.0 / (10*log10(2)) */
82 #define LTP_GAIN_THR2 5443 /* 5443 Q13 = 0.6644 ~= 2.0 / (10*log10(2)) */
83 
84 /*----------------------------------------------------------------------------
85 ; LOCAL FUNCTION DEFINITIONS
86 ; Function Prototype declaration
87 ----------------------------------------------------------------------------*/
88 
89 /*----------------------------------------------------------------------------
90 ; LOCAL VARIABLE DEFINITIONS
91 ; Variable declaration - defined here and used outside this module
92 ----------------------------------------------------------------------------*/
93 
94 
95 /*
96 ------------------------------------------------------------------------------
97  FUNCTION NAME: gain_adapt_init
98 ------------------------------------------------------------------------------
99  INPUT AND OUTPUT DEFINITIONS
100 
101  Inputs:
102     st -- double pointer to GainAdaptState
103 
104  Outputs:
105     st -- double ponter to GainAdaptState
106 
107  Returns:
108     -1 if an error occurs during memory initialization
109      0 if OK
110 
111  Global Variables Used:
112     None
113 
114  Local Variables Needed:
115     None
116 
117 ------------------------------------------------------------------------------
118  FUNCTION DESCRIPTION
119 
120     Allocates state memory and initializes state memory
121 
122 ------------------------------------------------------------------------------
123  REQUIREMENTS
124 
125  None
126 
127 ------------------------------------------------------------------------------
128  REFERENCES
129 
130  g_adapt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
131 
132 ------------------------------------------------------------------------------
133  PSEUDO-CODE
134 
135 
136 ------------------------------------------------------------------------------
137  RESOURCES USED [optional]
138 
139  When the code is written for a specific target processor the
140  the resources used should be documented below.
141 
142  HEAP MEMORY USED: x bytes
143 
144  STACK MEMORY USED: x bytes
145 
146  CLOCK CYCLES: (cycle count equation for this function) + (variable
147                 used to represent cycle count for each subroutine
148                 called)
149      where: (cycle count variable) = cycle count for [subroutine
150                                      name]
151 
152 ------------------------------------------------------------------------------
153  CAUTION [optional]
154  [State any special notes, constraints or cautions for users of this function]
155 
156 ------------------------------------------------------------------------------
157 */
158 
gain_adapt_init(GainAdaptState ** st)159 Word16 gain_adapt_init(GainAdaptState **st)
160 {
161     GainAdaptState* s;
162 
163     if (st == (GainAdaptState **) NULL)
164     {
165         /* fprintf(stderr, "gain_adapt_init: invalid parameter\n"); */
166         return -1;
167     }
168     *st = NULL;
169 
170     /* allocate memory */
171     if ((s = (GainAdaptState *) malloc(sizeof(GainAdaptState))) == NULL)
172     {
173         /* fprintf(stderr, "gain_adapt_init: can't malloc state structure\n"); */
174         return -1;
175     }
176     gain_adapt_reset(s);
177     *st = s;
178 
179     return 0;
180 }
181 
182 /*
183 ------------------------------------------------------------------------------
184  FUNCTION NAME: gain_adapt_reset
185 ------------------------------------------------------------------------------
186  INPUT AND OUTPUT DEFINITIONS
187 
188  Inputs:
189     st -- double pointer to GainAdaptState
190 
191  Outputs:
192     st -- double ponter to GainAdaptState
193 
194  Returns:
195     -1 if an error occurs
196      0 if OK
197 
198  Global Variables Used:
199     None
200 
201  Local Variables Needed:
202     None
203 
204 ------------------------------------------------------------------------------
205  FUNCTION DESCRIPTION
206 
207     Initializes state memory to zero
208 ------------------------------------------------------------------------------
209  REQUIREMENTS
210 
211  None
212 
213 ------------------------------------------------------------------------------
214  REFERENCES
215 
216  g_adapt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
217 
218 ------------------------------------------------------------------------------
219  PSEUDO-CODE
220 
221 
222 ------------------------------------------------------------------------------
223  RESOURCES USED [optional]
224 
225  When the code is written for a specific target processor the
226  the resources used should be documented below.
227 
228  HEAP MEMORY USED: x bytes
229 
230  STACK MEMORY USED: x bytes
231 
232  CLOCK CYCLES: (cycle count equation for this function) + (variable
233                 used to represent cycle count for each subroutine
234                 called)
235      where: (cycle count variable) = cycle count for [subroutine
236                                      name]
237 
238 ------------------------------------------------------------------------------
239  CAUTION [optional]
240  [State any special notes, constraints or cautions for users of this function]
241 
242 ------------------------------------------------------------------------------
243 */
244 
gain_adapt_reset(GainAdaptState * st)245 Word16 gain_adapt_reset(GainAdaptState *st)
246 {
247     Word16 i;
248 
249     if (st == (GainAdaptState *) NULL)
250     {
251         /* fprintf(stderr, "gain_adapt_reset: invalid parameter\n"); */
252         return -1;
253     }
254 
255     st->onset = 0;
256     st->prev_alpha = 0;
257     st->prev_gc = 0;
258 
259     for (i = 0; i < LTPG_MEM_SIZE; i++)
260     {
261         st->ltpg_mem[i] = 0;
262     }
263 
264     return 0;
265 }
266 
267 
268 /*
269 ------------------------------------------------------------------------------
270  FUNCTION NAME: gain_adapt_exit
271 ------------------------------------------------------------------------------
272  INPUT AND OUTPUT DEFINITIONS
273 
274  Inputs:
275     st -- double pointer to GainAdaptState
276 
277  Outputs:
278     None
279 
280  Returns:
281     None
282 
283  Global Variables Used:
284     None
285 
286  Local Variables Needed:
287     None
288 
289 ------------------------------------------------------------------------------
290  FUNCTION DESCRIPTION
291 
292     The memory used for state memory is freed
293 ------------------------------------------------------------------------------
294  REQUIREMENTS
295 
296  None
297 
298 ------------------------------------------------------------------------------
299  REFERENCES
300 
301  g_adapt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
302 
303 ------------------------------------------------------------------------------
304  PSEUDO-CODE
305 
306 
307 ------------------------------------------------------------------------------
308  RESOURCES USED [optional]
309 
310  When the code is written for a specific target processor the
311  the resources used should be documented below.
312 
313  HEAP MEMORY USED: x bytes
314 
315  STACK MEMORY USED: x bytes
316 
317  CLOCK CYCLES: (cycle count equation for this function) + (variable
318                 used to represent cycle count for each subroutine
319                 called)
320      where: (cycle count variable) = cycle count for [subroutine
321                                      name]
322 
323 ------------------------------------------------------------------------------
324  CAUTION [optional]
325  [State any special notes, constraints or cautions for users of this function]
326 
327 ------------------------------------------------------------------------------
328 */
329 
gain_adapt_exit(GainAdaptState ** st)330 void gain_adapt_exit(GainAdaptState **st)
331 {
332     if (st == NULL || *st == NULL)
333         return;
334 
335     /* deallocate memory */
336     free(*st);
337     *st = NULL;
338 
339     return;
340 }
341 
342 /*
343 ------------------------------------------------------------------------------
344  FUNCTION NAME: gain_adapt
345 ------------------------------------------------------------------------------
346  INPUT AND OUTPUT DEFINITIONS
347 
348  Inputs:
349     st -- double pointer to GainAdaptState
350     ltpg -- Word16 -- ltp coding gain (log2()), Q13
351     gain_cod -- Word16 -- code gain, Q1
352 
353  Outputs:
354     alpha -- Pointer to Word16 --  gain adaptation factor,   Q15
355     pOverflow -- Pointer to Flag -- overflow indicator
356 
357  Returns:
358     None
359 
360  Global Variables Used:
361     None
362 
363  Local Variables Needed:
364     None
365 
366 ------------------------------------------------------------------------------
367  FUNCTION DESCRIPTION
368 
369  Purpose:    calculate pitch/codebook gain adaptation factor alpha
370              (and update the adaptor state)
371 
372 ------------------------------------------------------------------------------
373  REQUIREMENTS
374 
375  None
376 
377 ------------------------------------------------------------------------------
378  REFERENCES
379 
380  g_adapt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
381 
382 ------------------------------------------------------------------------------
383  PSEUDO-CODE
384 
385 
386 ------------------------------------------------------------------------------
387  RESOURCES USED [optional]
388 
389  When the code is written for a specific target processor the
390  the resources used should be documented below.
391 
392  HEAP MEMORY USED: x bytes
393 
394  STACK MEMORY USED: x bytes
395 
396  CLOCK CYCLES: (cycle count equation for this function) + (variable
397                 used to represent cycle count for each subroutine
398                 called)
399      where: (cycle count variable) = cycle count for [subroutine
400                                      name]
401 
402 ------------------------------------------------------------------------------
403  CAUTION [optional]
404  [State any special notes, constraints or cautions for users of this function]
405 
406 ------------------------------------------------------------------------------
407 */
408 
gain_adapt(GainAdaptState * st,Word16 ltpg,Word16 gain_cod,Word16 * alpha,Flag * pOverflow)409 void gain_adapt(
410     GainAdaptState *st,  /* i  : state struct                  */
411     Word16 ltpg,         /* i  : ltp coding gain (log2()), Q13 */
412     Word16 gain_cod,     /* i  : code gain,                Q1  */
413     Word16 *alpha,       /* o  : gain adaptation factor,   Q15 */
414     Flag   *pOverflow
415 )
416 {
417     Word16 adapt;      /* adaptdation status; 0, 1, or 2       */
418     Word16 result;     /* alpha factor, Q13                    */
419     Word16 filt;       /* median-filtered LTP coding gain, Q13 */
420     Word16 tmp;
421     Word16 i;
422 
423     /* basic adaptation */
424     if (ltpg <= LTP_GAIN_THR1)
425     {
426         adapt = 0;
427     }
428     else
429     {
430         if (ltpg <= LTP_GAIN_THR2)
431         {
432             adapt = 1;
433         }
434         else
435         {
436             adapt = 2;
437         }
438     }
439 
440     /*
441      * // onset indicator
442      * if ((cbGain > onFact * cbGainMem[0]) && (cbGain > 100.0))
443      *     onset = 8;
444      * else
445      *     if (onset)
446      *         onset--;
447      */
448     /* tmp = cbGain / onFact; onFact = 2.0; 200 Q1 = 100.0 */
449     tmp = shr_r(gain_cod, 1, pOverflow);
450 
451     if ((tmp > st->prev_gc) && (gain_cod > 200))
452     {
453         st->onset = 8;
454     }
455     else
456     {
457         if (st->onset != 0)
458         {
459             st->onset = sub(st->onset, 1, pOverflow);
460         }
461     }
462 
463     /*
464      *  // if onset, increase adaptor state
465      *  if (onset && (gainAdapt < 2)) gainAdapt++;
466      */
467     if ((st->onset != 0) && (adapt < 2))
468     {
469         adapt = add(adapt, 1, pOverflow);
470     }
471 
472     st->ltpg_mem[0] = ltpg;
473     filt = gmed_n(st->ltpg_mem, 5);  /* function result */
474 
475     if (adapt == 0)
476     {
477         if (filt > 5443) /* 5443 Q13 = 0.66443... */
478         {
479             result = 0;
480         }
481         else
482         {
483             if (filt < 0)
484             {
485                 result = 16384;  /* 16384 Q15 = 0.5 */
486             }
487             else
488             {   /* result       =   0.5 - 0.75257499*filt     */
489                 /* result (Q15) = 16384 - 24660 * (filt << 2) */
490                 filt = shl(filt, 2, pOverflow);  /* Q15 */
491                 result = mult(24660, filt, pOverflow);
492                 result = sub(16384, result, pOverflow);
493             }
494         }
495     }
496     else
497     {
498         result = 0;
499     }
500     /*
501      *  if (prevAlpha == 0.0) result = 0.5 * (result + prevAlpha);
502      */
503     if (st->prev_alpha == 0)
504     {
505         result = shr(result, 1, pOverflow);
506     }
507 
508     /* store the result */
509     *alpha = result;
510 
511     /* update adapter state memory */
512     st->prev_alpha = result;
513     st->prev_gc = gain_cod;
514 
515     for (i = LTPG_MEM_SIZE - 1; i > 0; i--)
516     {
517         st->ltpg_mem[i] = st->ltpg_mem[i-1];
518     }
519     /* mem[0] is just present for convenience in calling the gmed_n[5]
520      * function above. The memory depth is really LTPG_MEM_SIZE-1.
521      */
522 }
523