blob: 731dc5297ea72fc887abfcf72771e998b32133c3 [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/gc_pred.c
Functions:
gc_pred_reset
gc_pred
gc_pred_update
gc_pred_average_limited
------------------------------------------------------------------------------
MODULE DESCRIPTION
This file contains the functions that perform codebook gain MA prediction.
------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/
#include "gc_pred.h"
#include "basicop_malloc.h"
#include "basic_op.h"
#include "cnst.h"
#include "log2.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 */
/* average innovation energy. */
/* MEAN_ENER = 36.0/constant, constant = 20*Log10(2) */
#define MEAN_ENER_MR122 783741L /* 36/(20*log10(2)) (Q17) */
/* minimum quantized energy: -14 dB */
#define MIN_ENERGY (-14336) /* 14 Q10 */
#define MIN_ENERGY_MR122 (-2381) /* 14 / (20*log10(2)) Q10 */
/*----------------------------------------------------------------------------
; LOCAL FUNCTION DEFINITIONS
; Function Prototype declaration
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; LOCAL VARIABLE DEFINITIONS
; Variable declaration - defined here and used outside this module
----------------------------------------------------------------------------*/
/* MA prediction coefficients (Q13) */
static const Word16 pred[NPRED] = {5571, 4751, 2785, 1556};
/* MA prediction coefficients (Q6) */
static const Word16 pred_MR122[NPRED] = {44, 37, 22, 12};
/*
------------------------------------------------------------------------------
FUNCTION NAME: gc_pred_reset
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
state = pointer to a structure of type gc_predState
Outputs:
past_qua_en field in the structure pointed to by state is initialized
to MIN_ENERGY
past_qua_en_MR122 field in the structure pointed to by state is
initialized to MIN_ENERGY_MR122
Returns:
return_value = 0, if reset was successful; -1, otherwise (int)
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
This function initializes the state memory used by gc_pred to zero.
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
gc_pred.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
int gc_pred_reset (gc_predState *state)
{
Word16 i;
if (state == (gc_predState *) NULL){
fprintf(stderr, "gc_pred_reset: invalid parameter\n");
return -1;
}
for(i = 0; i < NPRED; i++)
{
state->past_qua_en[i] = MIN_ENERGY;
state->past_qua_en_MR122[i] = MIN_ENERGY_MR122;
}
return 0;
}
------------------------------------------------------------------------------
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 gc_pred_reset(gc_predState *state)
{
Word16 i;
if (state == (gc_predState *) NULL)
{
/* fprintf(stderr, "gc_pred_reset: invalid parameter\n"); */
return -1;
}
for (i = 0; i < NPRED; i++)
{
state->past_qua_en[i] = MIN_ENERGY;
state->past_qua_en_MR122[i] = MIN_ENERGY_MR122;
}
return(0);
}
/****************************************************************************/
/*
------------------------------------------------------------------------------
FUNCTION NAME: gc_pred
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st = pointer to a structure of type gc_predState
mode = AMR mode (enum Mode)
code = pointer to the innovative codebook vector; Q12 in MR122 mode,
otherwise, Q13 (Word16)
exp_gcode0 = pointer to the exponent part of predicted gain factor
(Q0) (Word16)
frac_gcode0 = pointer to the fractional part of predicted gain factor
(Q15) (Word16)
exp_en = pointer to the exponent part of the innovation energy; this
is calculated for MR795 mode, Q0 (Word16)
frac_en = pointer to the fractional part of the innovation energy;
this is calculated for MR795 mode, Q15 (Word16)
pOverflow = pointer to overflow (Flag)
Outputs:
store pointed to by exp_gcode0 contains the exponent part of the
recently calculated predicted gain factor
store pointed to by frac_gcode0 contains the fractional part of the
recently calculated predicted gain factor
store pointed to by exp_en contains the exponent part of the
recently calculated innovation energy
store pointed to by frac_en contains the fractional part of the
recently calculated innovation energy
pOverflow = 1 if the math functions called by gc_pred
results in overflow else zero.
Returns:
None
Global Variables Used:
None
Local Variables Needed:
pred = table of MA prediction coefficients (Q13) (Word16)
pred_MR122 = table of MA prediction coefficients (Q6) (Word16)
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
This function performs the MA prediction of the innovation energy (in
dB/(20*log10(2))), with the mean removed.
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
gc_pred.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
The original etsi reference code uses a global flag Overflow. However, in the
actual implementation a pointer to a the overflow flag is passed in.
void
gc_pred(
gc_predState *st, // i/o: State struct
enum Mode mode, // i : AMR mode
Word16 *code, // i : innovative codebook vector (L_SUBFR)
// MR122: Q12, other modes: Q13
Word16 *exp_gcode0, // o : exponent of predicted gain factor, Q0
Word16 *frac_gcode0,// o : fraction of predicted gain factor Q15
Word16 *exp_en, // o : exponent of innovation energy, Q0
// (only calculated for MR795)
Word16 *frac_en // o : fraction of innovation energy, Q15
// (only calculated for MR795)
)
{
Word16 i;
Word32 ener_code;
Word16 exp, frac;
*-------------------------------------------------------------------*
* energy of code: *
* ~~~~~~~~~~~~~~~ *
* ener_code = sum(code[i]^2) *
*-------------------------------------------------------------------*
ener_code = L_mac((Word32) 0, code[0], code[0]);
// MR122: Q12*Q12 -> Q25
// others: Q13*Q13 -> Q27
for (i = 1; i < L_SUBFR; i++)
ener_code = L_mac(ener_code, code[i], code[i]);
if (sub (mode, MR122) == 0)
{
Word32 ener;
// ener_code = ener_code / lcode; lcode = 40; 1/40 = 26214 Q20
ener_code = L_mult (pv_round (ener_code), 26214); // Q9 * Q20 -> Q30
*-------------------------------------------------------------------*
* energy of code: *
* ~~~~~~~~~~~~~~~ *
* ener_code(Q17) = 10 * Log10(energy) / constant *
* = 1/2 * Log2(energy) *
* constant = 20*Log10(2) *
*-------------------------------------------------------------------*
// ener_code = 1/2 * Log2(ener_code); Note: Log2=log2+30
Log2(ener_code, &exp, &frac);
ener_code = L_Comp (sub (exp, 30), frac); // Q16 for log()
// ->Q17 for 1/2 log()
*-------------------------------------------------------------------*
* predicted energy: *
* ~~~~~~~~~~~~~~~~~ *
* ener(Q24) = (Emean + sum{pred[i]*past_en[i]})/constant *
* = MEAN_ENER + sum(pred[i]*past_qua_en[i]) *
* constant = 20*Log10(2) *
*-------------------------------------------------------------------*
ener = MEAN_ENER_MR122; // Q24 (Q17)
for (i = 0; i < NPRED; i++)
{
ener = L_mac (ener, st->past_qua_en_MR122[i], pred_MR122[i]);
// Q10 * Q13 -> Q24
// Q10 * Q6 -> Q17
}
*-------------------------------------------------------------------*
* predicted codebook gain *
* ~~~~~~~~~~~~~~~~~~~~~~~ *
* gc0 = Pow10( (ener*constant - ener_code*constant) / 20 ) *
* = Pow2(ener-ener_code) *
* = Pow2(int(d)+frac(d)) *
* *
* (store exp and frac for pow2()) *
*-------------------------------------------------------------------*
ener = L_shr (L_sub (ener, ener_code), 1); // Q16
L_Extract(ener, exp_gcode0, frac_gcode0);
}
else // all modes except 12.2
{
Word32 L_tmp;
Word16 exp_code, gcode0;
*-----------------------------------------------------------------*
* Compute: means_ener - 10log10(ener_code/ L_sufr) *
*-----------------------------------------------------------------*
exp_code = norm_l (ener_code);
ener_code = L_shl (ener_code, exp_code);
// Log2 = log2 + 27
Log2_norm (ener_code, exp_code, &exp, &frac);
// fact = 10/log2(10) = 3.01 = 24660 Q13
L_tmp = Mpy_32_16(exp, frac, -24660); // Q0.Q15 * Q13 -> Q14
* L_tmp = means_ener - 10log10(ener_code/L_SUBFR)
* = means_ener - 10log10(ener_code) + 10log10(L_SUBFR)
* = K - fact * Log2(ener_code)
* = K - fact * log2(ener_code) - fact*27
*
* ==> K = means_ener + fact*27 + 10log10(L_SUBFR)
*
* means_ener = 33 = 540672 Q14 (MR475, MR515, MR59)
* means_ener = 28.75 = 471040 Q14 (MR67)
* means_ener = 30 = 491520 Q14 (MR74)
* means_ener = 36 = 589824 Q14 (MR795)
* means_ener = 33 = 540672 Q14 (MR102)
* 10log10(L_SUBFR) = 16.02 = 262481.51 Q14
* fact * 27 = 1331640 Q14
* -----------------------------------------
* (MR475, MR515, MR59) K = 2134793.51 Q14 ~= 16678 * 64 * 2
* (MR67) K = 2065161.51 Q14 ~= 32268 * 32 * 2
* (MR74) K = 2085641.51 Q14 ~= 32588 * 32 * 2
* (MR795) K = 2183945.51 Q14 ~= 17062 * 64 * 2
* (MR102) K = 2134793.51 Q14 ~= 16678 * 64 * 2
if (sub (mode, MR102) == 0)
{
// mean = 33 dB
L_tmp = L_mac(L_tmp, 16678, 64); // Q14
}
else if (sub (mode, MR795) == 0)
{
// ener_code = <xn xn> * 2^27*2^exp_code
// frac_en = ener_code / 2^16
// = <xn xn> * 2^11*2^exp_code
// <xn xn> = <xn xn>*2^11*2^exp * 2^exp_en
// := frac_en * 2^exp_en
// ==> exp_en = -11-exp_code;
*frac_en = extract_h (ener_code);
*exp_en = sub (-11, exp_code);
// mean = 36 dB
L_tmp = L_mac(L_tmp, 17062, 64); // Q14
}
else if (sub (mode, MR74) == 0)
{
// mean = 30 dB
L_tmp = L_mac(L_tmp, 32588, 32); // Q14
}
else if (sub (mode, MR67) == 0)
{
// mean = 28.75 dB
L_tmp = L_mac(L_tmp, 32268, 32); // Q14
}
else // MR59, MR515, MR475
{
// mean = 33 dB
L_tmp = L_mac(L_tmp, 16678, 64); // Q14
}
*-----------------------------------------------------------------*
* Compute gcode0. *
* = Sum(i=0,3) pred[i]*past_qua_en[i] - ener_code + mean_ener *
*-----------------------------------------------------------------*
L_tmp = L_shl(L_tmp, 10); // Q24
for (i = 0; i < 4; i++)
L_tmp = L_mac(L_tmp, pred[i], st->past_qua_en[i]);
// Q13 * Q10 -> Q24
gcode0 = extract_h(L_tmp); // Q8
*-----------------------------------------------------------------*
* gcode0 = pow(10.0, gcode0/20) *
* = pow(2, 3.3219*gcode0/20) *
* = pow(2, 0.166*gcode0) *
*-----------------------------------------------------------------*
// 5439 Q15 = 0.165985
// (correct: 1/(20*log10(2)) 0.166096 = 5443 Q15)
if (sub (mode, MR74) == 0) // For IS641 bitexactness
L_tmp = L_mult(gcode0, 5439); // Q8 * Q15 -> Q24
else
L_tmp = L_mult(gcode0, 5443); // Q8 * Q15 -> Q24
L_tmp = L_shr(L_tmp, 8); // -> Q16
L_Extract(L_tmp, exp_gcode0, frac_gcode0); // -> Q0.Q15
}
}
------------------------------------------------------------------------------
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 gc_pred(
gc_predState *st, /* i/o: State struct */
enum Mode mode, /* i : AMR mode */
Word16 *code, /* i : innovative codebook vector (L_SUBFR) */
/* MR122: Q12, other modes: Q13 */
Word16 *exp_gcode0, /* o : exponent of predicted gain factor, Q0 */
Word16 *frac_gcode0,/* o : fraction of predicted gain factor Q15 */
Word16 *exp_en, /* o : exponent of innovation energy, Q0 */
/* (only calculated for MR795) */
Word16 *frac_en, /* o : fraction of innovation energy, Q15 */
/* (only calculated for MR795) */
Flag *pOverflow
)
{
Word16 i;
Word32 L_temp1, L_temp2;
Word32 L_tmp;
Word32 ener_code;
Word32 ener;
Word16 exp, frac;
Word16 exp_code, gcode0;
Word16 tmp;
Word16 *p_code = &code[0];
/*-------------------------------------------------------------------*
* energy of code: *
* ~~~~~~~~~~~~~~~ *
* ener_code = sum(code[i]^2) *
*-------------------------------------------------------------------*/
ener_code = 0;
/* MR122: Q12*Q12 -> Q25 */
/* others: Q13*Q13 -> Q27 */
for (i = L_SUBFR >> 2; i != 0; i--)
{
tmp = *(p_code++);
ener_code += ((Word32) tmp * tmp) >> 3;
tmp = *(p_code++);
ener_code += ((Word32) tmp * tmp) >> 3;
tmp = *(p_code++);
ener_code += ((Word32) tmp * tmp) >> 3;
tmp = *(p_code++);
ener_code += ((Word32) tmp * tmp) >> 3;
}
ener_code <<= 4;
if (ener_code < 0) /* Check for saturation */
{
ener_code = MAX_32;
}
if (mode == MR122)
{
/* ener_code = ener_code / lcode; lcode = 40; 1/40 = 26214 Q20 */
/* Q9 * Q20 -> Q30 */
ener_code = ((Word32)(pv_round(ener_code, pOverflow) * 26214)) << 1;
/*-------------------------------------------------------------*
* energy of code: *
* ~~~~~~~~~~~~~~~ *
* ener_code(Q17) = 10 * Log10(energy) / constant *
* = 1/2 * Log2(energy) *
* constant = 20*Log10(2) *
*-------------------------------------------------------------*/
/* ener_code = 1/2 * Log2(ener_code); Note: Log2=log2+30 */
Log2(ener_code, &exp, &frac, pOverflow);
/* Q16 for log() */
/* ->Q17 for 1/2 log()*/
L_temp1 = (Word32)(exp - 30) << 16;
ener_code = L_temp1 + ((Word32)frac << 1);
/*-------------------------------------------------------------*
* predicted energy: *
* ~~~~~~~~~~~~~~~~~ *
* ener(Q24) = (Emean + sum{pred[i]*past_en[i]})/constant *
* = MEAN_ENER + sum(pred[i]*past_qua_en[i]) *
* constant = 20*Log10(2) *
*-------------------------------------------------------------*/
ener = MEAN_ENER_MR122; /* Q24 (Q17) */
for (i = 0; i < NPRED; i++)
{
L_temp1 = (((Word32) st->past_qua_en_MR122[i]) *
pred_MR122[i]) << 1;
ener = L_add(ener, L_temp1, pOverflow);
/* Q10 * Q13 -> Q24 */
/* Q10 * Q6 -> Q17 */
}
/*---------------------------------------------------------------*
* predicted codebook gain *
* ~~~~~~~~~~~~~~~~~~~~~~~ *
* gc0 = Pow10( (ener*constant - ener_code*constant) / 20 ) *
* = Pow2(ener-ener_code) *
* = Pow2(int(d)+frac(d)) *
* *
* (store exp and frac for pow2()) *
*---------------------------------------------------------------*/
/* Q16 */
L_temp1 = L_sub(ener, ener_code, pOverflow);
*exp_gcode0 = (Word16)(L_temp1 >> 17);
L_temp2 = (Word32) * exp_gcode0 << 15;
L_temp1 >>= 2;
*frac_gcode0 = (Word16)(L_temp1 - L_temp2);
}
else /* all modes except 12.2 */
{
/*-----------------------------------------------------------------*
* Compute: means_ener - 10log10(ener_code/ L_sufr) *
*-----------------------------------------------------------------*/
exp_code = norm_l(ener_code);
ener_code = L_shl(ener_code, exp_code, pOverflow);
/* Log2 = log2 + 27 */
Log2_norm(ener_code, exp_code, &exp, &frac);
/* fact = 10/log2(10) = 3.01 = 24660 Q13 */
/* Q0.Q15 * Q13 -> Q14 */
L_temp2 = (((Word32) exp) * -24660) << 1;
L_tmp = (((Word32) frac) * -24660) >> 15;
/* Sign-extend resulting product */
if (L_tmp & (Word32) 0x00010000L)
{
L_tmp = L_tmp | (Word32) 0xffff0000L;
}
L_tmp = L_tmp << 1;
L_tmp = L_add(L_tmp, L_temp2, pOverflow);
/* L_tmp = means_ener - 10log10(ener_code/L_SUBFR)
* = means_ener - 10log10(ener_code) + 10log10(L_SUBFR)
* = K - fact * Log2(ener_code)
* = K - fact * log2(ener_code) - fact*27
*
* ==> K = means_ener + fact*27 + 10log10(L_SUBFR)
*
* means_ener = 33 = 540672 Q14 (MR475, MR515, MR59)
* means_ener = 28.75 = 471040 Q14 (MR67)
* means_ener = 30 = 491520 Q14 (MR74)
* means_ener = 36 = 589824 Q14 (MR795)
* means_ener = 33 = 540672 Q14 (MR102)
* 10log10(L_SUBFR) = 16.02 = 262481.51 Q14
* fact * 27 = 1331640 Q14
* -----------------------------------------
* (MR475, MR515, MR59) K = 2134793.51 Q14 ~= 16678 * 64 * 2
* (MR67) K = 2065161.51 Q14 ~= 32268 * 32 * 2
* (MR74) K = 2085641.51 Q14 ~= 32588 * 32 * 2
* (MR795) K = 2183945.51 Q14 ~= 17062 * 64 * 2
* (MR102) K = 2134793.51 Q14 ~= 16678 * 64 * 2
*/
if (mode == MR102)
{
/* mean = 33 dB */
L_temp2 = (Word32) 16678 << 7;
L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q14 */
}
else if (mode == MR795)
{
/* ener_code = <xn xn> * 2^27*2^exp_code
frac_en = ener_code / 2^16
= <xn xn> * 2^11*2^exp_code
<xn xn> = <xn xn>*2^11*2^exp * 2^exp_en
: = frac_en * 2^exp_en
==> exp_en = -11-exp_code; */
*frac_en = (Word16)(ener_code >> 16);
*exp_en = sub(-11, exp_code, pOverflow);
/* mean = 36 dB */
L_temp2 = (Word32) 17062 << 7;
L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q14 */
}
else if (mode == MR74)
{
/* mean = 30 dB */
L_temp2 = (Word32) 32588 << 6;
L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q14 */
}
else if (mode == MR67)
{
/* mean = 28.75 dB */
L_temp2 = (Word32) 32268 << 6;
L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q14 */
}
else /* MR59, MR515, MR475 */
{
/* mean = 33 dB */
L_temp2 = (Word32) 16678 << 7;
L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q14 */
}
/*-------------------------------------------------------------*
* Compute gcode0. *
* = Sum(i=0,3) pred[i]*past_qua_en[i] - ener_code + mean_ener *
*--------------------------------------------------------------*/
/* Q24 */
if (L_tmp > (Word32) 0X001fffffL)
{
*pOverflow = 1;
L_tmp = MAX_32;
}
else if (L_tmp < (Word32) 0xffe00000L)
{
*pOverflow = 1;
L_tmp = MIN_32;
}
else
{
L_tmp = L_tmp << 10;
}
for (i = 0; i < 4; i++)
{
L_temp2 = ((((Word32) pred[i]) * st->past_qua_en[i]) << 1);
L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q13 * Q10 -> Q24 */
}
gcode0 = (Word16)(L_tmp >> 16); /* Q8 */
/*-----------------------------------------------------------*
* gcode0 = pow(10.0, gcode0/20) *
* = pow(2, 3.3219*gcode0/20) *
* = pow(2, 0.166*gcode0) *
*-----------------------------------------------------------*/
/* 5439 Q15 = 0.165985 */
/* (correct: 1/(20*log10(2)) 0.166096 = 5443 Q15) */
if (mode == MR74) /* For IS641 bitexactness */
{
L_tmp = (((Word32) gcode0) * 5439) << 1; /* Q8 * Q15 -> Q24 */
}
else
{
L_tmp = (((Word32) gcode0) * 5443) << 1; /* Q8 * Q15 -> Q24 */
}
if (L_tmp < 0)
{
L_tmp = ~((~L_tmp) >> 8);
}
else
{
L_tmp = L_tmp >> 8; /* -> Q16 */
}
*exp_gcode0 = (Word16)(L_tmp >> 16);
if (L_tmp < 0)
{
L_temp1 = ~((~L_tmp) >> 1);
}
else
{
L_temp1 = L_tmp >> 1;
}
L_temp2 = (Word32) * exp_gcode0 << 15;
*frac_gcode0 = (Word16)(L_sub(L_temp1, L_temp2, pOverflow));
/* -> Q0.Q15 */
}
return;
}
/****************************************************************************/
/*
------------------------------------------------------------------------------
FUNCTION NAME: gc_pred_update
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st = pointer to a structure of type gc_predState
qua_ener_MR122 = quantized energy for update (Q10); calculated as
(log2(qua_err)) (Word16)
qua_ener = quantized energy for update (Q10); calculated as
(20*log10(qua_err)) (Word16)
Outputs:
structure pointed to by st contains the calculated quantized energy
for update
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
This function updates the MA predictor with the last quantized energy.
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
gc_pred.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
void gc_pred_update(
gc_predState *st, // i/o: State struct
Word16 qua_ener_MR122, // i : quantized energy for update, Q10
// (log2(qua_err))
Word16 qua_ener // i : quantized energy for update, Q10
// (20*log10(qua_err))
)
{
Word16 i;
for (i = 3; i > 0; i--)
{
st->past_qua_en[i] = st->past_qua_en[i - 1];
st->past_qua_en_MR122[i] = st->past_qua_en_MR122[i - 1];
}
st->past_qua_en_MR122[0] = qua_ener_MR122; // log2 (qua_err), Q10
st->past_qua_en[0] = qua_ener; // 20*log10(qua_err), Q10
}
------------------------------------------------------------------------------
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 gc_pred_update(
gc_predState *st, /* i/o: State struct */
Word16 qua_ener_MR122, /* i : quantized energy for update, Q10 */
/* (log2(qua_err)) */
Word16 qua_ener /* i : quantized energy for update, Q10 */
/* (20*log10(qua_err)) */
)
{
st->past_qua_en[3] = st->past_qua_en[2];
st->past_qua_en_MR122[3] = st->past_qua_en_MR122[2];
st->past_qua_en[2] = st->past_qua_en[1];
st->past_qua_en_MR122[2] = st->past_qua_en_MR122[1];
st->past_qua_en[1] = st->past_qua_en[0];
st->past_qua_en_MR122[1] = st->past_qua_en_MR122[0];
st->past_qua_en_MR122[0] = qua_ener_MR122; /* log2 (qua_err), Q10 */
st->past_qua_en[0] = qua_ener; /* 20*log10(qua_err), Q10 */
return;
}
/****************************************************************************/
/*
------------------------------------------------------------------------------
FUNCTION NAME: gc_pred_average_limited
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st = pointer to a structure of type gc_predState
ener_avg_MR122 = pointer to the averaged quantized energy (Q10);
calculated as (log2(qua_err)) (Word16)
ener_avg = pointer to the averaged quantized energy (Q10); calculated
as (20*log10(qua_err)) (Word16)
pOverflow = pointer to overflow (Flag)
Outputs:
store pointed to by ener_avg_MR122 contains the new averaged quantized
energy
store pointed to by ener_avg contains the new averaged quantized
energy
pOverflow = 1 if the math functions called by gc_pred_average_limited
results in overflow else zero.
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
This function calculates the average of MA predictor state values (with a
lower limit) used in error concealment.
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
gc_pred.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
The original etsi reference code uses a global flag Overflow. However, in the
actual implementation a pointer to a the overflow flag is passed in.
void gc_pred_average_limited(
gc_predState *st, // i: State struct
Word16 *ener_avg_MR122, // o: everaged quantized energy, Q10
// (log2(qua_err))
Word16 *ener_avg // o: averaged quantized energy, Q10
// (20*log10(qua_err))
)
{
Word16 av_pred_en;
Word16 i;
// do average in MR122 mode (log2() domain)
av_pred_en = 0;
for (i = 0; i < NPRED; i++)
{
av_pred_en = add (av_pred_en, st->past_qua_en_MR122[i]);
}
// av_pred_en = 0.25*av_pred_en
av_pred_en = mult (av_pred_en, 8192);
// if (av_pred_en < -14/(20Log10(2))) av_pred_en = ..
if (sub (av_pred_en, MIN_ENERGY_MR122) < 0)
{
av_pred_en = MIN_ENERGY_MR122;
}
*ener_avg_MR122 = av_pred_en;
// do average for other modes (20*log10() domain)
av_pred_en = 0;
for (i = 0; i < NPRED; i++)
{
av_pred_en = add (av_pred_en, st->past_qua_en[i]);
}
// av_pred_en = 0.25*av_pred_en
av_pred_en = mult (av_pred_en, 8192);
// if (av_pred_en < -14) av_pred_en = ..
if (sub (av_pred_en, MIN_ENERGY) < 0)
{
av_pred_en = MIN_ENERGY;
}
*ener_avg = av_pred_en;
}
------------------------------------------------------------------------------
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 gc_pred_average_limited(
gc_predState *st, /* i: State struct */
Word16 *ener_avg_MR122, /* o: everaged quantized energy, Q10 */
/* (log2(qua_err)) */
Word16 *ener_avg, /* o: averaged quantized energy, Q10 */
/* (20*log10(qua_err)) */
Flag *pOverflow
)
{
Word16 av_pred_en;
Word16 i;
/* do average in MR122 mode (log2() domain) */
av_pred_en = 0;
for (i = 0; i < NPRED; i++)
{
av_pred_en =
add(av_pred_en, st->past_qua_en_MR122[i], pOverflow);
}
/* av_pred_en = 0.25*av_pred_en (with sign-extension)*/
if (av_pred_en < 0)
{
av_pred_en = (av_pred_en >> 2) | 0xc000;
}
else
{
av_pred_en >>= 2;
}
/* if (av_pred_en < -14/(20Log10(2))) av_pred_en = .. */
if (av_pred_en < MIN_ENERGY_MR122)
{
av_pred_en = MIN_ENERGY_MR122;
}
*ener_avg_MR122 = av_pred_en;
/* do average for other modes (20*log10() domain) */
av_pred_en = 0;
for (i = 0; i < NPRED; i++)
{
av_pred_en = add(av_pred_en, st->past_qua_en[i], pOverflow);
}
/* av_pred_en = 0.25*av_pred_en (with sign-extension)*/
if (av_pred_en < 0)
{
av_pred_en = (av_pred_en >> 2) | 0xc000;
}
else
{
av_pred_en >>= 2;
}
/* if (av_pred_en < -14) av_pred_en = .. */
if (av_pred_en < MIN_ENERGY)
{
av_pred_en = MIN_ENERGY;
}
*ener_avg = av_pred_en;
}