blob: e44e4bc9d292b7d9d8d4998f1f9b9f083514242a [file] [log] [blame]
/* ------------------------------------------------------------------
* 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 <stdlib.h>
#include <string.h>
#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 <xn y1> <y1 y1>
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 <xn y1> <y1 y1> */
/* 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;
}