/* ------------------------------------------------------------------ * Copyright (C) 1998-2009 PacketVideo * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. * See the License for the specific language governing permissions * and limitations under the License. * ------------------------------------------------------------------- */ /**************************************************************************************** Portions of this file are derived from the following 3GPP standard: 3GPP TS 26.073 ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec Available from http://www.3gpp.org (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC) Permission to distribute, modify and use this file under the standard license terms listed above has been obtained from the copyright holder. ****************************************************************************************/ /* ------------------------------------------------------------------------------ Pathname: ./audio/gsm-amr/c/src/gain_q.c Functions: Date: 02/05/2002 ------------------------------------------------------------------------------ REVISION HISTORY Description: Updated template used to PV coding template. Changed to accept the pOverflow flag for EPOC compatibility. Description: Removed everything associated with gc_pred_init and gc_pred_exit. gc_pred_exit was simply removed -- gc_pred_init was replaced with calls to gc_pred_reset. This is because the gc_pred related structures are no longer dynamically allocated via malloc. Description: For gainQuant() 1. Replaced gc_pred_copy() with memcpy. 2. Eliminated unused include file gc_pred.h. Description: Replaced OSCL mem type functions and eliminated include files that now are chosen by OSCL definitions Description: Replaced "int" and/or "char" with OSCL defined types. Description: ------------------------------------------------------------------------------ MODULE DESCRIPTION Quantazation of gains ------------------------------------------------------------------------------ */ /*---------------------------------------------------------------------------- ; INCLUDES ----------------------------------------------------------------------------*/ #include #include #include "gain_q.h" #include "typedef.h" #include "basic_op.h" #include "qua_gain.h" #include "cnst.h" #include "mode.h" #include "g_code.h" #include "q_gain_c.h" #include "calc_en.h" #include "qgain795.h" #include "qgain475.h" #include "set_zero.h" /*---------------------------------------------------------------------------- ; MACROS ; Define module specific macros here ----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- ; DEFINES ; Include all pre-processor statements here. Include conditional ; compile variables also. ----------------------------------------------------------------------------*/ #define NPRED 4 /* number of prediction taps */ /*---------------------------------------------------------------------------- ; LOCAL FUNCTION DEFINITIONS ; Function Prototype declaration ----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- ; LOCAL VARIABLE DEFINITIONS ; Variable declaration - defined here and used outside this module ----------------------------------------------------------------------------*/ /* ------------------------------------------------------------------------------ FUNCTION NAME: gainQuant_init ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st -- double pointer to gainQuantState Outputs: st -- double ponter to gainQuantState Returns: -1 if an error occurs during memory initialization 0 if OK Global Variables Used: None Local Variables Needed: None ------------------------------------------------------------------------------ FUNCTION DESCRIPTION Allocates state memory and initializes state memory ------------------------------------------------------------------------------ REQUIREMENTS None ------------------------------------------------------------------------------ REFERENCES gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE ------------------------------------------------------------------------------ RESOURCES USED [optional] When the code is written for a specific target processor the the resources used should be documented below. HEAP MEMORY USED: x bytes STACK MEMORY USED: x bytes CLOCK CYCLES: (cycle count equation for this function) + (variable used to represent cycle count for each subroutine called) where: (cycle count variable) = cycle count for [subroutine name] ------------------------------------------------------------------------------ CAUTION [optional] [State any special notes, constraints or cautions for users of this function] ------------------------------------------------------------------------------ */ Word16 gainQuant_init(gainQuantState **state) { gainQuantState* s; if (state == (gainQuantState **) NULL) { /* fprintf(stderr, "gainQuant_init: invalid parameter\n"); */ return -1; } *state = NULL; /* allocate memory */ if ((s = (gainQuantState *) malloc(sizeof(gainQuantState))) == NULL) { /* fprintf(stderr, "gainQuant_init: can not malloc state structure\n"); */ return -1; } s->gain_idx_ptr = NULL; s->adaptSt = NULL; /* Init sub states */ if (gc_pred_reset(&s->gc_predSt) || gc_pred_reset(&s->gc_predUnqSt) || gain_adapt_init(&s->adaptSt)) { gainQuant_exit(&s); return -1; } gainQuant_reset(s); *state = s; return 0; } /* ------------------------------------------------------------------------------ FUNCTION NAME: gainQuant_reset ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st -- double pointer to gainQuantState Outputs: st -- double ponter to gainQuantState Returns: -1 if an error occurs 0 if OK Global Variables Used: None Local Variables Needed: None ------------------------------------------------------------------------------ FUNCTION DESCRIPTION Initializes state memory to zero ------------------------------------------------------------------------------ REQUIREMENTS None ------------------------------------------------------------------------------ REFERENCES gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE ------------------------------------------------------------------------------ RESOURCES USED [optional] When the code is written for a specific target processor the the resources used should be documented below. HEAP MEMORY USED: x bytes STACK MEMORY USED: x bytes CLOCK CYCLES: (cycle count equation for this function) + (variable used to represent cycle count for each subroutine called) where: (cycle count variable) = cycle count for [subroutine name] ------------------------------------------------------------------------------ CAUTION [optional] [State any special notes, constraints or cautions for users of this function] ------------------------------------------------------------------------------ */ Word16 gainQuant_reset(gainQuantState *state) { if (state == (gainQuantState *) NULL) { /* fprintf(stderr, "gainQuant_reset: invalid parameter\n"); */ return -1; } state->sf0_exp_gcode0 = 0; state->sf0_frac_gcode0 = 0; state->sf0_exp_target_en = 0; state->sf0_frac_target_en = 0; Set_zero(state->sf0_exp_coeff, 5); Set_zero(state->sf0_frac_coeff, 5); state->gain_idx_ptr = NULL; gc_pred_reset(&(state->gc_predSt)); gc_pred_reset(&(state->gc_predUnqSt)); gain_adapt_reset(state->adaptSt); return 0; } /* ------------------------------------------------------------------------------ FUNCTION NAME: gainQuant_exit ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st -- double pointer to gainQuantState Outputs: None Returns: None Global Variables Used: None Local Variables Needed: None ------------------------------------------------------------------------------ FUNCTION DESCRIPTION The memory used for state memory is freed ------------------------------------------------------------------------------ REQUIREMENTS None ------------------------------------------------------------------------------ REFERENCES gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE ------------------------------------------------------------------------------ RESOURCES USED [optional] When the code is written for a specific target processor the the resources used should be documented below. HEAP MEMORY USED: x bytes STACK MEMORY USED: x bytes CLOCK CYCLES: (cycle count equation for this function) + (variable used to represent cycle count for each subroutine called) where: (cycle count variable) = cycle count for [subroutine name] ------------------------------------------------------------------------------ CAUTION [optional] [State any special notes, constraints or cautions for users of this function] ------------------------------------------------------------------------------ */ void gainQuant_exit(gainQuantState **state) { if (state == NULL || *state == NULL) return; gain_adapt_exit(&(*state)->adaptSt); /* deallocate memory */ free(*state); *state = NULL; return; } /* ------------------------------------------------------------------------------ FUNCTION NAME: gainQuant ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st -- pointer to gainQuantState mode -- enum Mode -- coder mode res -- Word16 array -- LP residual, Q0 exc -- Word16 array -- LTP excitation (unfiltered), Q0 code -- Word16 array -- CB innovation (unfiltered), Q13 (unsharpened for MR475) xn -- Word16 array -- Target vector. xn2 -- Word16 array -- Target vector. y1 -- Word16 array -- Adaptive codebook. Y2 -- Word16 array -- Filtered innovative vector. g_coeff -- Word16 array -- Correlations Compute in G_pitch(). even_subframe -- Word16 -- even subframe indicator flag gp_limit -- Word16 -- pitch gain limit gain_pit -- Word16 Pointer -- Pitch gain. Outputs: st -- pointer to gainQuantState sf0_gain_pit -- Word16 Pointer -- Pitch gain sf 0. MR475 sf0_gain_cod -- Word16 Pointer -- Code gain sf 0. MR475 gain_pit -- Word16 Pointer -- Pitch gain. gain_cod -- Word16 Pointer -- Code gain. MR475: gain_* unquantized in even subframes, quantized otherwise anap -- Word16 Double Pointer -- Index of quantization pOverflow -- Flag Pointer -- overflow indicator Returns: Zero Global Variables Used: None Local Variables Needed: None ------------------------------------------------------------------------------ FUNCTION DESCRIPTION Quantazation of gains ------------------------------------------------------------------------------ REQUIREMENTS None ------------------------------------------------------------------------------ REFERENCES gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE ------------------------------------------------------------------------------ RESOURCES USED [optional] When the code is written for a specific target processor the the resources used should be documented below. HEAP MEMORY USED: x bytes STACK MEMORY USED: x bytes CLOCK CYCLES: (cycle count equation for this function) + (variable used to represent cycle count for each subroutine called) where: (cycle count variable) = cycle count for [subroutine name] ------------------------------------------------------------------------------ CAUTION [optional] [State any special notes, constraints or cautions for users of this function] ------------------------------------------------------------------------------ */ void gainQuant( gainQuantState *st, /* i/o : State struct */ enum Mode mode, /* i : coder mode */ Word16 res[], /* i : LP residual, Q0 */ Word16 exc[], /* i : LTP excitation (unfiltered), Q0 */ Word16 code[], /* i : CB innovation (unfiltered), Q13 */ /* (unsharpened for MR475) */ Word16 xn[], /* i : Target vector. */ Word16 xn2[], /* i : Target vector. */ Word16 y1[], /* i : Adaptive codebook. */ Word16 Y2[], /* i : Filtered innovative vector. */ Word16 g_coeff[], /* i : Correlations */ /* Compute in G_pitch(). */ Word16 even_subframe, /* i : even subframe indicator flag */ Word16 gp_limit, /* i : pitch gain limit */ Word16 *sf0_gain_pit, /* o : Pitch gain sf 0. MR475 */ Word16 *sf0_gain_cod, /* o : Code gain sf 0. MR475 */ Word16 *gain_pit, /* i/o : Pitch gain. */ Word16 *gain_cod, /* o : Code gain. */ /* MR475: gain_* unquantized in even */ /* subframes, quantized otherwise */ Word16 **anap, /* o : Index of quantization */ Flag *pOverflow /* o : overflow indicator */ ) { Word16 exp_gcode0; Word16 frac_gcode0; Word16 qua_ener_MR122; Word16 qua_ener; Word16 frac_coeff[5]; Word16 exp_coeff[5]; Word16 exp_en; Word16 frac_en; Word16 cod_gain_exp; Word16 cod_gain_frac; Word16 temp; if (mode == MR475) { if (even_subframe != 0) { /* save position in output parameter stream and current state of codebook gain predictor */ st->gain_idx_ptr = (*anap)++; // gc_pred_copy(&(st->gc_predSt), &(st->gc_predUnqSt)); memcpy(st->gc_predUnqSt.past_qua_en, st->gc_predSt.past_qua_en, NPRED*sizeof(Word16)); memcpy(st->gc_predUnqSt.past_qua_en_MR122, st->gc_predSt.past_qua_en_MR122, NPRED*sizeof(Word16)); /* predict codebook gain (using "unquantized" predictor)*/ /* (note that code[] is unsharpened in MR475) */ gc_pred( &(st->gc_predUnqSt), mode, code, &st->sf0_exp_gcode0, &st->sf0_frac_gcode0, &exp_en, &frac_en, pOverflow); /* calculate energy coefficients for quantization and store them in state structure (will be used in next subframe when real quantizer is run) */ calc_filt_energies( mode, xn, xn2, y1, Y2, g_coeff, st->sf0_frac_coeff, st->sf0_exp_coeff, &cod_gain_frac, &cod_gain_exp, pOverflow); /* store optimum codebook gain (Q1) */ temp = add( cod_gain_exp, 1, pOverflow); *gain_cod = shl( cod_gain_frac, temp, pOverflow); calc_target_energy( xn, &st->sf0_exp_target_en, &st->sf0_frac_target_en, pOverflow); /* calculate optimum codebook gain and update "unquantized" predictor */ MR475_update_unq_pred( &(st->gc_predUnqSt), st->sf0_exp_gcode0, st->sf0_frac_gcode0, cod_gain_exp, cod_gain_frac, pOverflow); /* the real quantizer is not run here... */ } else { /* predict codebook gain (using "unquantized" predictor) */ /* (note that code[] is unsharpened in MR475) */ gc_pred( &(st->gc_predUnqSt), mode, code, &exp_gcode0, &frac_gcode0, &exp_en, &frac_en, pOverflow); /* calculate energy coefficients for quantization */ calc_filt_energies( mode, xn, xn2, y1, Y2, g_coeff, frac_coeff, exp_coeff, &cod_gain_frac, &cod_gain_exp, pOverflow); calc_target_energy( xn, &exp_en, &frac_en, pOverflow); /* run real (4-dim) quantizer and update real gain predictor */ *st->gain_idx_ptr = MR475_gain_quant( &(st->gc_predSt), st->sf0_exp_gcode0, st->sf0_frac_gcode0, st->sf0_exp_coeff, st->sf0_frac_coeff, st->sf0_exp_target_en, st->sf0_frac_target_en, code, exp_gcode0, frac_gcode0, exp_coeff, frac_coeff, exp_en, frac_en, gp_limit, sf0_gain_pit, sf0_gain_cod, gain_pit, gain_cod, pOverflow); } } else { /*-------------------------------------------------------------------* * predict codebook gain and quantize * * (also compute normalized CB innovation energy for MR795) * *-------------------------------------------------------------------*/ gc_pred( &(st->gc_predSt), mode, code, &exp_gcode0, &frac_gcode0, &exp_en, &frac_en, pOverflow); if (mode == MR122) { *gain_cod = G_code( xn2, Y2, pOverflow); *(*anap)++ = q_gain_code( mode, exp_gcode0, frac_gcode0, gain_cod, &qua_ener_MR122, &qua_ener, pOverflow); } else { /* calculate energy coefficients for quantization */ calc_filt_energies( mode, xn, xn2, y1, Y2, g_coeff, frac_coeff, exp_coeff, &cod_gain_frac, &cod_gain_exp, pOverflow); if (mode == MR795) { MR795_gain_quant( st->adaptSt, res, exc, code, frac_coeff, exp_coeff, exp_en, frac_en, exp_gcode0, frac_gcode0, L_SUBFR, cod_gain_frac, cod_gain_exp, gp_limit, gain_pit, gain_cod, &qua_ener_MR122, &qua_ener, anap, pOverflow); } else { *(*anap)++ = Qua_gain( mode, exp_gcode0, frac_gcode0, frac_coeff, exp_coeff, gp_limit, gain_pit, gain_cod, &qua_ener_MR122, &qua_ener, pOverflow); } } /*------------------------------------------------------------------* * update table of past quantized energies * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * st->past_qua_en(Q10) = 20 * Log10(qua_gain_code) / constant * * = Log2(qua_gain_code) * * = qua_ener * * constant = 20*Log10(2) * *------------------------------------------------------------------*/ gc_pred_update( &(st->gc_predSt), qua_ener_MR122, qua_ener); } return; }