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/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
159Word16 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
245Word16 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
330void 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
409void 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