gain_q.cpp revision b841f14f8e51f2365945281fbfa54ef6a1b1b5a6
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/gain_q.c
35 Functions:
36
37     Date: 02/05/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: Removed everything associated with gc_pred_init
46 and gc_pred_exit.  gc_pred_exit was simply removed -- gc_pred_init
47 was replaced with calls to gc_pred_reset.  This is because the gc_pred
48 related structures are no longer dynamically allocated via malloc.
49
50 Description:  For gainQuant()
51              1. Replaced gc_pred_copy() with memcpy.
52              2. Eliminated unused include file gc_pred.h.
53
54 Description:  Replaced OSCL mem type functions and eliminated include
55               files that now are chosen by OSCL definitions
56
57 Description:  Replaced "int" and/or "char" with OSCL defined types.
58
59 Description:
60
61------------------------------------------------------------------------------
62 MODULE DESCRIPTION
63
64    Quantazation of gains
65------------------------------------------------------------------------------
66*/
67
68/*----------------------------------------------------------------------------
69; INCLUDES
70----------------------------------------------------------------------------*/
71#include <stdlib.h>
72#include <string.h>
73
74#include "gain_q.h"
75#include "typedef.h"
76#include "basic_op.h"
77#include "qua_gain.h"
78#include "cnst.h"
79#include "mode.h"
80#include "g_code.h"
81#include "q_gain_c.h"
82#include "calc_en.h"
83#include "qgain795.h"
84#include "qgain475.h"
85#include "set_zero.h"
86
87
88/*----------------------------------------------------------------------------
89; MACROS
90; Define module specific macros here
91----------------------------------------------------------------------------*/
92
93/*----------------------------------------------------------------------------
94; DEFINES
95; Include all pre-processor statements here. Include conditional
96; compile variables also.
97----------------------------------------------------------------------------*/
98#define NPRED 4  /* number of prediction taps */
99
100/*----------------------------------------------------------------------------
101; LOCAL FUNCTION DEFINITIONS
102; Function Prototype declaration
103----------------------------------------------------------------------------*/
104
105/*----------------------------------------------------------------------------
106; LOCAL VARIABLE DEFINITIONS
107; Variable declaration - defined here and used outside this module
108----------------------------------------------------------------------------*/
109
110/*
111------------------------------------------------------------------------------
112 FUNCTION NAME: gainQuant_init
113------------------------------------------------------------------------------
114 INPUT AND OUTPUT DEFINITIONS
115
116 Inputs:
117    st -- double pointer to gainQuantState
118
119 Outputs:
120    st -- double ponter to gainQuantState
121
122 Returns:
123    -1 if an error occurs during memory initialization
124     0 if OK
125
126 Global Variables Used:
127    None
128
129 Local Variables Needed:
130    None
131
132------------------------------------------------------------------------------
133 FUNCTION DESCRIPTION
134
135    Allocates state memory and initializes state memory
136
137------------------------------------------------------------------------------
138 REQUIREMENTS
139
140 None
141
142------------------------------------------------------------------------------
143 REFERENCES
144
145 gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
146
147------------------------------------------------------------------------------
148 PSEUDO-CODE
149
150
151------------------------------------------------------------------------------
152 RESOURCES USED [optional]
153
154 When the code is written for a specific target processor the
155 the resources used should be documented below.
156
157 HEAP MEMORY USED: x bytes
158
159 STACK MEMORY USED: x bytes
160
161 CLOCK CYCLES: (cycle count equation for this function) + (variable
162                used to represent cycle count for each subroutine
163                called)
164     where: (cycle count variable) = cycle count for [subroutine
165                                     name]
166
167------------------------------------------------------------------------------
168 CAUTION [optional]
169 [State any special notes, constraints or cautions for users of this function]
170
171------------------------------------------------------------------------------
172*/
173
174Word16 gainQuant_init(gainQuantState **state)
175{
176    gainQuantState* s;
177
178    if (state == (gainQuantState **) NULL)
179    {
180        /* fprintf(stderr, "gainQuant_init: invalid parameter\n"); */
181        return -1;
182    }
183    *state = NULL;
184
185    /* allocate memory */
186    if ((s = (gainQuantState *) malloc(sizeof(gainQuantState))) == NULL)
187    {
188        /* fprintf(stderr, "gainQuant_init: can not malloc state structure\n"); */
189        return -1;
190    }
191
192    s->gain_idx_ptr = NULL;
193
194    s->adaptSt = NULL;
195
196    /* Init sub states */
197    if (gc_pred_reset(&s->gc_predSt)
198            || gc_pred_reset(&s->gc_predUnqSt)
199            || gain_adapt_init(&s->adaptSt))
200    {
201        gainQuant_exit(&s);
202        return -1;
203    }
204
205    gainQuant_reset(s);
206    *state = s;
207
208    return 0;
209}
210
211/*
212------------------------------------------------------------------------------
213 FUNCTION NAME: gainQuant_reset
214------------------------------------------------------------------------------
215 INPUT AND OUTPUT DEFINITIONS
216
217 Inputs:
218    st -- double pointer to gainQuantState
219
220 Outputs:
221    st -- double ponter to gainQuantState
222
223 Returns:
224    -1 if an error occurs
225     0 if OK
226
227 Global Variables Used:
228    None
229
230 Local Variables Needed:
231    None
232
233------------------------------------------------------------------------------
234 FUNCTION DESCRIPTION
235
236    Initializes state memory to zero
237------------------------------------------------------------------------------
238 REQUIREMENTS
239
240 None
241
242------------------------------------------------------------------------------
243 REFERENCES
244
245 gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
246
247------------------------------------------------------------------------------
248 PSEUDO-CODE
249
250
251------------------------------------------------------------------------------
252 RESOURCES USED [optional]
253
254 When the code is written for a specific target processor the
255 the resources used should be documented below.
256
257 HEAP MEMORY USED: x bytes
258
259 STACK MEMORY USED: x bytes
260
261 CLOCK CYCLES: (cycle count equation for this function) + (variable
262                used to represent cycle count for each subroutine
263                called)
264     where: (cycle count variable) = cycle count for [subroutine
265                                     name]
266
267------------------------------------------------------------------------------
268 CAUTION [optional]
269 [State any special notes, constraints or cautions for users of this function]
270
271------------------------------------------------------------------------------
272*/
273
274Word16 gainQuant_reset(gainQuantState *state)
275{
276
277    if (state == (gainQuantState *) NULL)
278    {
279        /* fprintf(stderr, "gainQuant_reset: invalid parameter\n"); */
280        return -1;
281    }
282
283    state->sf0_exp_gcode0 = 0;
284    state->sf0_frac_gcode0 = 0;
285    state->sf0_exp_target_en = 0;
286    state->sf0_frac_target_en = 0;
287
288    Set_zero(state->sf0_exp_coeff, 5);
289    Set_zero(state->sf0_frac_coeff, 5);
290    state->gain_idx_ptr = NULL;
291
292    gc_pred_reset(&(state->gc_predSt));
293    gc_pred_reset(&(state->gc_predUnqSt));
294    gain_adapt_reset(state->adaptSt);
295
296    return 0;
297}
298
299/*
300------------------------------------------------------------------------------
301 FUNCTION NAME: gainQuant_exit
302------------------------------------------------------------------------------
303 INPUT AND OUTPUT DEFINITIONS
304
305 Inputs:
306    st -- double pointer to gainQuantState
307
308 Outputs:
309    None
310
311 Returns:
312    None
313
314 Global Variables Used:
315    None
316
317 Local Variables Needed:
318    None
319
320------------------------------------------------------------------------------
321 FUNCTION DESCRIPTION
322
323    The memory used for state memory is freed
324------------------------------------------------------------------------------
325 REQUIREMENTS
326
327 None
328
329------------------------------------------------------------------------------
330 REFERENCES
331
332 gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
333
334------------------------------------------------------------------------------
335 PSEUDO-CODE
336
337
338------------------------------------------------------------------------------
339 RESOURCES USED [optional]
340
341 When the code is written for a specific target processor the
342 the resources used should be documented below.
343
344 HEAP MEMORY USED: x bytes
345
346 STACK MEMORY USED: x bytes
347
348 CLOCK CYCLES: (cycle count equation for this function) + (variable
349                used to represent cycle count for each subroutine
350                called)
351     where: (cycle count variable) = cycle count for [subroutine
352                                     name]
353
354------------------------------------------------------------------------------
355 CAUTION [optional]
356 [State any special notes, constraints or cautions for users of this function]
357
358------------------------------------------------------------------------------
359*/
360
361void gainQuant_exit(gainQuantState **state)
362{
363    if (state == NULL || *state == NULL)
364        return;
365
366    gain_adapt_exit(&(*state)->adaptSt);
367
368    /* deallocate memory */
369    free(*state);
370    *state = NULL;
371
372    return;
373}
374
375
376
377/*
378------------------------------------------------------------------------------
379 FUNCTION NAME: gainQuant
380------------------------------------------------------------------------------
381 INPUT AND OUTPUT DEFINITIONS
382
383 Inputs:
384    st   -- pointer to gainQuantState
385    mode -- enum Mode -- coder mode
386    res  -- Word16 array -- LP residual,                 Q0
387    exc  -- Word16 array -- LTP excitation (unfiltered), Q0
388    code -- Word16 array -- CB innovation (unfiltered),  Q13
389                            (unsharpened for MR475)
390    xn  -- Word16 array -- Target vector.
391    xn2 -- Word16 array -- Target vector.
392    y1  -- Word16 array -- Adaptive codebook.
393    Y2  -- Word16 array -- Filtered innovative vector.
394    g_coeff -- Word16 array -- Correlations <xn y1> <y1 y1>
395                               Compute in G_pitch().
396
397    even_subframe -- Word16 -- even subframe indicator flag
398    gp_limit -- Word16 -- pitch gain limit
399    gain_pit -- Word16 Pointer -- Pitch gain.
400
401 Outputs:
402    st -- pointer to gainQuantState
403    sf0_gain_pit -- Word16 Pointer -- Pitch gain sf 0.   MR475
404    sf0_gain_cod -- Word16 Pointer -- Code gain sf 0.    MR475
405    gain_pit -- Word16 Pointer -- Pitch gain.
406    gain_cod -- Word16 Pointer -- Code gain.
407                                  MR475: gain_* unquantized in even
408                                  subframes, quantized otherwise
409
410    anap -- Word16 Double Pointer -- Index of quantization
411
412    pOverflow -- Flag Pointer -- overflow indicator
413
414 Returns:
415    Zero
416
417 Global Variables Used:
418    None
419
420 Local Variables Needed:
421    None
422
423------------------------------------------------------------------------------
424 FUNCTION DESCRIPTION
425
426    Quantazation of gains
427
428------------------------------------------------------------------------------
429 REQUIREMENTS
430
431 None
432
433------------------------------------------------------------------------------
434 REFERENCES
435
436 gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
437
438------------------------------------------------------------------------------
439 PSEUDO-CODE
440
441
442------------------------------------------------------------------------------
443 RESOURCES USED [optional]
444
445 When the code is written for a specific target processor the
446 the resources used should be documented below.
447
448 HEAP MEMORY USED: x bytes
449
450 STACK MEMORY USED: x bytes
451
452 CLOCK CYCLES: (cycle count equation for this function) + (variable
453                used to represent cycle count for each subroutine
454                called)
455     where: (cycle count variable) = cycle count for [subroutine
456                                     name]
457
458------------------------------------------------------------------------------
459 CAUTION [optional]
460 [State any special notes, constraints or cautions for users of this function]
461
462------------------------------------------------------------------------------
463*/
464
465
466
467void gainQuant(
468    gainQuantState *st,   /* i/o : State struct                      */
469    enum Mode mode,       /* i   : coder mode                        */
470    Word16 res[],         /* i   : LP residual,                 Q0   */
471    Word16 exc[],         /* i   : LTP excitation (unfiltered), Q0   */
472    Word16 code[],        /* i   : CB innovation (unfiltered),  Q13  */
473    /*       (unsharpened for MR475)           */
474    Word16 xn[],          /* i   : Target vector.                    */
475    Word16 xn2[],         /* i   : Target vector.                    */
476    Word16 y1[],          /* i   : Adaptive codebook.                */
477    Word16 Y2[],          /* i   : Filtered innovative vector.       */
478    Word16 g_coeff[],     /* i   : Correlations <xn y1> <y1 y1>      */
479    /*       Compute in G_pitch().             */
480    Word16 even_subframe, /* i   : even subframe indicator flag      */
481    Word16 gp_limit,      /* i   : pitch gain limit                  */
482    Word16 *sf0_gain_pit, /* o   : Pitch gain sf 0.   MR475          */
483    Word16 *sf0_gain_cod, /* o   : Code gain sf 0.    MR475          */
484    Word16 *gain_pit,     /* i/o : Pitch gain.                       */
485    Word16 *gain_cod,     /* o   : Code gain.                        */
486    /*       MR475: gain_* unquantized in even */
487    /*       subframes, quantized otherwise    */
488    Word16 **anap,        /* o   : Index of quantization             */
489    Flag   *pOverflow     /* o   : overflow indicator                */
490)
491{
492    Word16 exp_gcode0;
493    Word16 frac_gcode0;
494    Word16 qua_ener_MR122;
495    Word16 qua_ener;
496    Word16 frac_coeff[5];
497    Word16 exp_coeff[5];
498    Word16 exp_en;
499    Word16 frac_en;
500    Word16 cod_gain_exp;
501    Word16 cod_gain_frac;
502    Word16 temp;
503
504    if (mode == MR475)
505    {
506        if (even_subframe != 0)
507        {
508            /* save position in output parameter stream and current
509               state of codebook gain predictor */
510            st->gain_idx_ptr = (*anap)++;
511
512//            gc_pred_copy(&(st->gc_predSt), &(st->gc_predUnqSt));
513
514            memcpy(st->gc_predUnqSt.past_qua_en,
515                        st->gc_predSt.past_qua_en,
516                        NPRED*sizeof(Word16));
517            memcpy(st->gc_predUnqSt.past_qua_en_MR122,
518                        st->gc_predSt.past_qua_en_MR122,
519                        NPRED*sizeof(Word16));
520
521
522            /* predict codebook gain (using "unquantized" predictor)*/
523            /* (note that code[] is unsharpened in MR475)           */
524            gc_pred(
525                &(st->gc_predUnqSt),
526                mode,
527                code,
528                &st->sf0_exp_gcode0,
529                &st->sf0_frac_gcode0,
530                &exp_en,
531                &frac_en,
532                pOverflow);
533
534            /* calculate energy coefficients for quantization
535               and store them in state structure (will be used
536               in next subframe when real quantizer is run) */
537            calc_filt_energies(
538                mode,
539                xn,
540                xn2,
541                y1,
542                Y2,
543                g_coeff,
544                st->sf0_frac_coeff,
545                st->sf0_exp_coeff,
546                &cod_gain_frac,
547                &cod_gain_exp,
548                pOverflow);
549
550            /* store optimum codebook gain (Q1) */
551            temp =
552                add(
553                    cod_gain_exp,
554                    1,
555                    pOverflow);
556
557            *gain_cod =
558                shl(
559                    cod_gain_frac,
560                    temp,
561                    pOverflow);
562
563            calc_target_energy(
564                xn,
565                &st->sf0_exp_target_en,
566                &st->sf0_frac_target_en,
567                pOverflow);
568
569            /* calculate optimum codebook gain and update
570               "unquantized" predictor                    */
571            MR475_update_unq_pred(
572                &(st->gc_predUnqSt),
573                st->sf0_exp_gcode0,
574                st->sf0_frac_gcode0,
575                cod_gain_exp,
576                cod_gain_frac,
577                pOverflow);
578
579            /* the real quantizer is not run here... */
580        }
581        else
582        {
583            /* predict codebook gain (using "unquantized" predictor) */
584            /* (note that code[] is unsharpened in MR475)            */
585            gc_pred(
586                &(st->gc_predUnqSt),
587                mode,
588                code,
589                &exp_gcode0,
590                &frac_gcode0,
591                &exp_en,
592                &frac_en,
593                pOverflow);
594
595            /* calculate energy coefficients for quantization */
596            calc_filt_energies(
597                mode,
598                xn,
599                xn2,
600                y1,
601                Y2,
602                g_coeff,
603                frac_coeff,
604                exp_coeff,
605                &cod_gain_frac,
606                &cod_gain_exp,
607                pOverflow);
608
609            calc_target_energy(
610                xn,
611                &exp_en,
612                &frac_en,
613                pOverflow);
614
615            /* run real (4-dim) quantizer and update real gain predictor */
616            *st->gain_idx_ptr =
617                MR475_gain_quant(
618                    &(st->gc_predSt),
619                    st->sf0_exp_gcode0,
620                    st->sf0_frac_gcode0,
621                    st->sf0_exp_coeff,
622                    st->sf0_frac_coeff,
623                    st->sf0_exp_target_en,
624                    st->sf0_frac_target_en,
625                    code,
626                    exp_gcode0,
627                    frac_gcode0,
628                    exp_coeff,
629                    frac_coeff,
630                    exp_en,
631                    frac_en,
632                    gp_limit,
633                    sf0_gain_pit,
634                    sf0_gain_cod,
635                    gain_pit,
636                    gain_cod,
637                    pOverflow);
638        }
639    }
640    else
641    {
642        /*-------------------------------------------------------------------*
643         *  predict codebook gain and quantize                               *
644         *  (also compute normalized CB innovation energy for MR795)         *
645         *-------------------------------------------------------------------*/
646        gc_pred(
647            &(st->gc_predSt),
648            mode,
649            code,
650            &exp_gcode0,
651            &frac_gcode0,
652            &exp_en,
653            &frac_en,
654            pOverflow);
655
656        if (mode == MR122)
657        {
658            *gain_cod =
659                G_code(
660                    xn2,
661                    Y2,
662                    pOverflow);
663
664            *(*anap)++ =
665                q_gain_code(
666                    mode,
667                    exp_gcode0,
668                    frac_gcode0,
669                    gain_cod,
670                    &qua_ener_MR122,
671                    &qua_ener,
672                    pOverflow);
673        }
674        else
675        {
676            /* calculate energy coefficients for quantization */
677            calc_filt_energies(
678                mode,
679                xn,
680                xn2,
681                y1,
682                Y2,
683                g_coeff,
684                frac_coeff,
685                exp_coeff,
686                &cod_gain_frac,
687                &cod_gain_exp,
688                pOverflow);
689
690            if (mode == MR795)
691            {
692                MR795_gain_quant(
693                    st->adaptSt,
694                    res,
695                    exc,
696                    code,
697                    frac_coeff,
698                    exp_coeff,
699                    exp_en,
700                    frac_en,
701                    exp_gcode0,
702                    frac_gcode0,
703                    L_SUBFR,
704                    cod_gain_frac,
705                    cod_gain_exp,
706                    gp_limit,
707                    gain_pit,
708                    gain_cod,
709                    &qua_ener_MR122,
710                    &qua_ener,
711                    anap,
712                    pOverflow);
713            }
714            else
715            {
716                *(*anap)++ =
717                    Qua_gain(
718                        mode,
719                        exp_gcode0,
720                        frac_gcode0,
721                        frac_coeff,
722                        exp_coeff,
723                        gp_limit,
724                        gain_pit,
725                        gain_cod,
726                        &qua_ener_MR122,
727                        &qua_ener,
728                        pOverflow);
729            }
730        }
731
732        /*------------------------------------------------------------------*
733         *  update table of past quantized energies                         *
734         *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                         *
735         *  st->past_qua_en(Q10) = 20 * Log10(qua_gain_code) / constant     *
736         *                       = Log2(qua_gain_code)                      *
737         *                       = qua_ener                                 *
738         *                                           constant = 20*Log10(2) *
739         *------------------------------------------------------------------*/
740        gc_pred_update(
741            &(st->gc_predSt),
742            qua_ener_MR122,
743            qua_ener);
744    }
745
746    return;
747}
748