6123 lines
157 KiB
C
Executable File
6123 lines
157 KiB
C
Executable File
/*
|
||
* ===================================================================
|
||
* TS 26.104
|
||
* REL-5 V5.4.0 2004-03
|
||
* REL-6 V6.1.0 2004-03
|
||
* 3GPP AMR Floating-point Speech Codec
|
||
* ===================================================================
|
||
*
|
||
*/
|
||
|
||
/*
|
||
* sp_dec.c
|
||
*
|
||
*
|
||
* Project:
|
||
* AMR Floating-Point Codec
|
||
*
|
||
* Contains:
|
||
* This module contains all the functions needed decoding AMR
|
||
* encoder parameters to 16-bit speech samples
|
||
*
|
||
*/
|
||
/*
|
||
* include files
|
||
*/
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <memory.h>
|
||
#include <math.h>
|
||
#include "sp_dec.h"
|
||
#include "rom_dec.h"
|
||
|
||
/*
|
||
* Declare structure types
|
||
*/
|
||
enum DTXStateType
|
||
{
|
||
SPEECH = 0, DTX, DTX_MUTE
|
||
};
|
||
|
||
/*
|
||
* Decoder memory structure
|
||
*/
|
||
typedef struct
|
||
{
|
||
/* history vector of past synthesis speech energy */
|
||
Word32 frameEnergyHist[L_ENERGYHIST];
|
||
|
||
|
||
/* state flags */
|
||
Word16 bgHangover; /* counter; number of frames after last speech frame */
|
||
|
||
|
||
}Bgn_scdState;
|
||
typedef struct
|
||
{
|
||
Word32 hangCount; /* counter; */
|
||
/* history vector of past synthesis speech energy */
|
||
Word32 cbGainHistory[L_CBGAINHIST];
|
||
Word16 hangVar; /* counter; */
|
||
|
||
}Cb_gain_averageState;
|
||
typedef struct
|
||
{
|
||
Word32 lsp_meanSave[M]; /* Averaged LSPs saved for efficiency */
|
||
|
||
|
||
}lsp_avgState;
|
||
typedef struct
|
||
{
|
||
Word32 past_r_q[M]; /* Past quantized prediction error, Q15 */
|
||
Word32 past_lsf_q[M]; /* Past dequantized lsfs, Q15 */
|
||
|
||
|
||
}D_plsfState;
|
||
typedef struct
|
||
{
|
||
Word32 pbuf[5];
|
||
Word32 past_gain_pit;
|
||
Word32 prev_gp;
|
||
|
||
|
||
}ec_gain_pitchState;
|
||
typedef struct
|
||
{
|
||
Word32 gbuf[5];
|
||
Word32 past_gain_code;
|
||
Word32 prev_gc;
|
||
|
||
|
||
}ec_gain_codeState;
|
||
typedef struct
|
||
{
|
||
/*
|
||
* normal MA predictor memory, Q10
|
||
* (contains 20*log10(quaErr))
|
||
*/
|
||
Word32 past_qua_en[4];
|
||
|
||
|
||
/*
|
||
* MA predictor memory for MR122 mode, Q10
|
||
* (contains log2(quaErr))
|
||
*/
|
||
Word32 past_qua_en_MR122[4];
|
||
|
||
|
||
}gc_predState;
|
||
typedef struct
|
||
{
|
||
Word32 gainMem[PHDGAINMEMSIZE];
|
||
Word32 prevCbGain;
|
||
Word32 prevState;
|
||
Word16 lockFull;
|
||
Word16 onset;
|
||
|
||
|
||
}ph_dispState;
|
||
typedef struct
|
||
{
|
||
enum DTXStateType dtxGlobalState; /* contains previous state */
|
||
|
||
Word32 log_en;
|
||
Word32 old_log_en;
|
||
Word32 pn_seed_rx;
|
||
Word32 lsp[M];
|
||
Word32 lsp_old[M];
|
||
Word32 lsf_hist[M * DTX_HIST_SIZE];
|
||
Word32 lsf_hist_mean[M * DTX_HIST_SIZE];
|
||
Word32 log_en_hist[DTX_HIST_SIZE];
|
||
Word32 true_sid_period_inv;
|
||
Word16 since_last_sid;
|
||
Word16 lsf_hist_ptr;
|
||
Word16 log_pg_mean;
|
||
Word16 log_en_hist_ptr;
|
||
Word16 log_en_adjust;
|
||
Word16 dtxHangoverCount;
|
||
Word16 decAnaElapsedCount;
|
||
Word16 sid_frame;
|
||
Word16 valid_data;
|
||
Word16 dtxHangoverAdded;
|
||
|
||
|
||
/* updated in main decoder */
|
||
Word16 data_updated; /* marker to know if CNI data is ever renewed */
|
||
|
||
|
||
}dtx_decState;
|
||
typedef struct
|
||
{
|
||
Word32 past_gain;
|
||
|
||
|
||
}agcState;
|
||
typedef struct
|
||
{
|
||
/* Excitation vector */
|
||
Word32 old_exc[L_SUBFR + PIT_MAX + L_INTERPOL];
|
||
Word32 *exc;
|
||
Word32 lsp_old[M];
|
||
|
||
|
||
/* Filter's memory */
|
||
Word32 mem_syn[M];
|
||
|
||
|
||
/* pitch sharpening */
|
||
Word32 sharp;
|
||
Word32 old_T0;
|
||
|
||
|
||
/* Variable holding received ltpLag, used in background noise and BFI */
|
||
Word32 T0_lagBuff;
|
||
|
||
|
||
/* Variables for the source characteristic detector (SCD) */
|
||
Word32 inBackgroundNoise;
|
||
Word32 voicedHangover;
|
||
Word32 ltpGainHistory[9];
|
||
|
||
|
||
/* Memories for bad frame handling */
|
||
Word32 excEnergyHist[9];
|
||
Word16 prev_bf;
|
||
Word16 prev_pdf;
|
||
Word16 state;
|
||
Word16 nodataSeed;
|
||
|
||
|
||
Bgn_scdState * background_state;
|
||
Cb_gain_averageState * Cb_gain_averState;
|
||
lsp_avgState * lsp_avg_st;
|
||
D_plsfState * lsfState;
|
||
ec_gain_pitchState * ec_gain_p_st;
|
||
ec_gain_codeState * ec_gain_c_st;
|
||
gc_predState * pred_state;
|
||
ph_dispState * ph_disp_st;
|
||
dtx_decState * dtxDecoderState;
|
||
}Decoder_amrState;
|
||
typedef struct
|
||
{
|
||
Word32 res2[L_SUBFR];
|
||
Word32 mem_syn_pst[M];
|
||
Word32 synth_buf[M + L_FRAME];
|
||
Word32 preemph_state_mem_pre;
|
||
agcState * agc_state;
|
||
}Post_FilterState;
|
||
typedef struct
|
||
{
|
||
Word32 y2_hi;
|
||
Word32 y2_lo;
|
||
Word32 y1_hi;
|
||
Word32 y1_lo;
|
||
Word32 x0;
|
||
Word32 x1;
|
||
|
||
|
||
}Post_ProcessState;
|
||
typedef struct
|
||
{
|
||
Decoder_amrState * decoder_amrState;
|
||
Post_FilterState * post_state;
|
||
Post_ProcessState * postHP_state;
|
||
}Speech_Decode_FrameState;
|
||
|
||
|
||
/*
|
||
* CodAmrReset
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state B: state structure
|
||
* mode I: AMR mode
|
||
*
|
||
* Function:
|
||
* Resets state memory
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Decoder_amr_reset( Decoder_amrState *state, enum Mode mode )
|
||
{
|
||
Word32 i;
|
||
|
||
/* Cb_gain_average_reset */
|
||
memset(state->Cb_gain_averState->cbGainHistory, 0, L_CBGAINHIST << 2);
|
||
state->Cb_gain_averState->hangVar = 0;
|
||
state->Cb_gain_averState->hangCount= 0;
|
||
|
||
/* Initialize static pointer */
|
||
state->exc = state->old_exc + PIT_MAX + L_INTERPOL;
|
||
|
||
/* Static vectors to zero */
|
||
memset( state->old_exc, 0, ( PIT_MAX + L_INTERPOL )<<2 );
|
||
|
||
if ( mode != MRDTX )
|
||
memset( state->mem_syn, 0, M <<2 );
|
||
|
||
/* initialize pitch sharpening */
|
||
state->sharp = SHARPMIN;
|
||
state->old_T0 = 40;
|
||
|
||
/* Initialize state->lsp_old [] */
|
||
if ( mode != MRDTX ) {
|
||
state->lsp_old[0] = 30000;
|
||
state->lsp_old[1] = 26000;
|
||
state->lsp_old[2] = 21000;
|
||
state->lsp_old[3] = 15000;
|
||
state->lsp_old[4] = 8000;
|
||
state->lsp_old[5] = 0;
|
||
state->lsp_old[6] = -8000;
|
||
state->lsp_old[7] = -15000;
|
||
state->lsp_old[8] = -21000;
|
||
state->lsp_old[9] = -26000;
|
||
}
|
||
|
||
/* Initialize memories of bad frame handling */
|
||
state->prev_bf = 0;
|
||
state->prev_pdf = 0;
|
||
state->state = 0;
|
||
state->T0_lagBuff = 40;
|
||
state->inBackgroundNoise = 0;
|
||
state->voicedHangover = 0;
|
||
|
||
if ( mode != MRDTX )
|
||
memset( state->excEnergyHist, 0, 9 <<2 );
|
||
memset( state->ltpGainHistory, 0, 9 <<2 );
|
||
|
||
if ( mode != MRDTX ) {
|
||
state->lsp_avg_st->lsp_meanSave[0] = 1384;
|
||
state->lsp_avg_st->lsp_meanSave[1] = 2077;
|
||
state->lsp_avg_st->lsp_meanSave[2] = 3420;
|
||
state->lsp_avg_st->lsp_meanSave[3] = 5108;
|
||
state->lsp_avg_st->lsp_meanSave[4] = 6742;
|
||
state->lsp_avg_st->lsp_meanSave[5] = 8122;
|
||
state->lsp_avg_st->lsp_meanSave[6] = 9863;
|
||
state->lsp_avg_st->lsp_meanSave[7] = 11092;
|
||
state->lsp_avg_st->lsp_meanSave[8] = 12714;
|
||
state->lsp_avg_st->lsp_meanSave[9] = 13701;
|
||
}
|
||
memset( state->lsfState->past_r_q, 0, M <<2 );
|
||
|
||
/* Past dequantized lsfs */
|
||
state->lsfState->past_lsf_q[0] = 1384;
|
||
state->lsfState->past_lsf_q[1] = 2077;
|
||
state->lsfState->past_lsf_q[2] = 3420;
|
||
state->lsfState->past_lsf_q[3] = 5108;
|
||
state->lsfState->past_lsf_q[4] = 6742;
|
||
state->lsfState->past_lsf_q[5] = 8122;
|
||
state->lsfState->past_lsf_q[6] = 9863;
|
||
state->lsfState->past_lsf_q[7] = 11092;
|
||
state->lsfState->past_lsf_q[8] = 12714;
|
||
state->lsfState->past_lsf_q[9] = 13701;
|
||
|
||
for ( i = 0; i < 5; i++ )
|
||
state->ec_gain_p_st->pbuf[i] = 1640;
|
||
state->ec_gain_p_st->past_gain_pit = 0;
|
||
state->ec_gain_p_st->prev_gp = 16384;
|
||
|
||
for ( i = 0; i < 5; i++ )
|
||
state->ec_gain_c_st->gbuf[i] = 1;
|
||
state->ec_gain_c_st->past_gain_code = 0;
|
||
state->ec_gain_c_st->prev_gc = 1;
|
||
|
||
if ( mode != MRDTX ) {
|
||
for ( i = 0; i < NPRED; i++ ) {
|
||
state->pred_state->past_qua_en[i] = MIN_ENERGY;
|
||
state->pred_state->past_qua_en_MR122[i] = MIN_ENERGY_MR122;
|
||
}
|
||
}
|
||
state->nodataSeed = 21845;
|
||
|
||
/* Static vectors to zero */
|
||
memset( state->background_state->frameEnergyHist, 0, L_ENERGYHIST <<2 );
|
||
|
||
/* Initialize hangover handling */
|
||
state->background_state->bgHangover = 0;
|
||
|
||
/* phDispReset */
|
||
memset( state->ph_disp_st->gainMem, 0, PHDGAINMEMSIZE <<2 );
|
||
state->ph_disp_st->prevState = 0;
|
||
state->ph_disp_st->prevCbGain = 0;
|
||
state->ph_disp_st->lockFull = 0;
|
||
state->ph_disp_st->onset = 0; /* assume no onset in start */
|
||
|
||
if ( mode != MRDTX ) {
|
||
state->dtxDecoderState->since_last_sid = 0;
|
||
state->dtxDecoderState->true_sid_period_inv = 8192;
|
||
state->dtxDecoderState->log_en = 3500;
|
||
state->dtxDecoderState->old_log_en = 3500;
|
||
|
||
/* low level noise for better performance in DTX handover cases*/
|
||
state->dtxDecoderState->pn_seed_rx = PN_INITIAL_SEED;
|
||
|
||
/* Initialize state->lsp [] */
|
||
state->dtxDecoderState->lsp[0] = 30000;
|
||
state->dtxDecoderState->lsp[1] = 26000;
|
||
state->dtxDecoderState->lsp[2] = 21000;
|
||
state->dtxDecoderState->lsp[3] = 15000;
|
||
state->dtxDecoderState->lsp[4] = 8000;
|
||
state->dtxDecoderState->lsp[5] = 0;
|
||
state->dtxDecoderState->lsp[6] = -8000;
|
||
state->dtxDecoderState->lsp[7] = -15000;
|
||
state->dtxDecoderState->lsp[8] = -21000;
|
||
state->dtxDecoderState->lsp[9] = -26000;
|
||
|
||
/* Initialize state->lsp_old [] */
|
||
state->dtxDecoderState->lsp_old[0] = 30000;
|
||
state->dtxDecoderState->lsp_old[1] = 26000;
|
||
state->dtxDecoderState->lsp_old[2] = 21000;
|
||
state->dtxDecoderState->lsp_old[3] = 15000;
|
||
state->dtxDecoderState->lsp_old[4] = 8000;
|
||
state->dtxDecoderState->lsp_old[5] = 0;
|
||
state->dtxDecoderState->lsp_old[6] = -8000;
|
||
state->dtxDecoderState->lsp_old[7] = -15000;
|
||
state->dtxDecoderState->lsp_old[8] = -21000;
|
||
state->dtxDecoderState->lsp_old[9] = -26000;
|
||
state->dtxDecoderState->lsf_hist_ptr = 0;
|
||
state->dtxDecoderState->log_pg_mean = 0;
|
||
state->dtxDecoderState->log_en_hist_ptr = 0;
|
||
|
||
/* initialize decoder lsf history */
|
||
state->dtxDecoderState->lsf_hist[0] = 1384;
|
||
state->dtxDecoderState->lsf_hist[1] = 2077;
|
||
state->dtxDecoderState->lsf_hist[2] = 3420;
|
||
state->dtxDecoderState->lsf_hist[3] = 5108;
|
||
state->dtxDecoderState->lsf_hist[4] = 6742;
|
||
state->dtxDecoderState->lsf_hist[5] = 8122;
|
||
state->dtxDecoderState->lsf_hist[6] = 9863;
|
||
state->dtxDecoderState->lsf_hist[7] = 11092;
|
||
state->dtxDecoderState->lsf_hist[8] = 12714;
|
||
state->dtxDecoderState->lsf_hist[9] = 13701;
|
||
|
||
for ( i = 1; i < DTX_HIST_SIZE; i++ ) {
|
||
memcpy( &state->dtxDecoderState->lsf_hist[M * i], &state->
|
||
dtxDecoderState->lsf_hist[0], M <<2 );
|
||
}
|
||
memset( state->dtxDecoderState->lsf_hist_mean, 0, M * DTX_HIST_SIZE <<2 );
|
||
|
||
/* initialize decoder log frame energy */
|
||
for ( i = 0; i < DTX_HIST_SIZE; i++ ) {
|
||
state->dtxDecoderState->log_en_hist[i] = state->dtxDecoderState->log_en
|
||
;
|
||
}
|
||
state->dtxDecoderState->log_en_adjust = 0;
|
||
state->dtxDecoderState->dtxHangoverCount = DTX_HANG_CONST;
|
||
state->dtxDecoderState->decAnaElapsedCount = 31;
|
||
state->dtxDecoderState->sid_frame = 0;
|
||
state->dtxDecoderState->valid_data = 0;
|
||
state->dtxDecoderState->dtxHangoverAdded = 0;
|
||
state->dtxDecoderState->dtxGlobalState = DTX;
|
||
state->dtxDecoderState->data_updated = 0;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* rx_dtx_handler
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->dtxGlobalState I: DTX state
|
||
* st->since_last_sid B: Frames after last SID frame
|
||
* st->data_updated I: SID update flag
|
||
* st->decAnaElapsedCount B: state machine that synch with the GSMEFR txDtx machine
|
||
* st->dtxHangoverAdded B: DTX hangover
|
||
* st->sid_frame O: SID frame indicator
|
||
* st->valid_data O: Vaild data indicator
|
||
* frame_type O: Frame type
|
||
*
|
||
* Function:
|
||
* Find the new DTX state
|
||
*
|
||
* Returns:
|
||
* DTXStateType DTX, DTX_MUTE or SPEECH
|
||
*/
|
||
static enum DTXStateType rx_dtx_handler( dtx_decState *st, enum RXFrameType frame_type )
|
||
{
|
||
enum DTXStateType newState;
|
||
enum DTXStateType encState;
|
||
|
||
/* DTX if SID frame or previously in DTX{_MUTE} and (NO_RX OR BAD_SPEECH) */
|
||
if ( table_SID[frame_type] | ( ( st->dtxGlobalState != SPEECH ) &
|
||
table_speech_bad[frame_type] ) ) {
|
||
newState = DTX;
|
||
|
||
/* stay in mute for these input types */
|
||
if ( ( st->dtxGlobalState == DTX_MUTE ) & table_mute[frame_type] ) {
|
||
newState = DTX_MUTE;
|
||
}
|
||
|
||
/*
|
||
* evaluate if noise parameters are too old
|
||
* since_last_sid is reset when CN parameters have been updated
|
||
*/
|
||
st->since_last_sid += 1;
|
||
|
||
/* no update of sid parameters in DTX for a long while */
|
||
if ((frame_type != RX_SID_UPDATE) & ( st->since_last_sid > DTX_MAX_EMPTY_THRESH )) {
|
||
newState = DTX_MUTE;
|
||
}
|
||
}
|
||
else {
|
||
newState = SPEECH;
|
||
st->since_last_sid = 0;
|
||
}
|
||
|
||
/*
|
||
* reset the decAnaElapsed Counter when receiving CNI data the first
|
||
* time, to robustify counter missmatch after handover
|
||
* this might delay the bwd CNI analysis in the new decoder slightly.
|
||
*/
|
||
if ( ( st->data_updated == 0 ) & ( frame_type == RX_SID_UPDATE ) ) {
|
||
st->decAnaElapsedCount = 0;
|
||
}
|
||
|
||
/*
|
||
* update the SPE-SPD DTX hangover synchronization
|
||
* to know when SPE has added dtx hangover
|
||
*/
|
||
st->decAnaElapsedCount += 1;
|
||
st->dtxHangoverAdded = 0;
|
||
encState = SPEECH;
|
||
|
||
if ( table_DTX[frame_type] ) {
|
||
encState = DTX;
|
||
if( ( frame_type == RX_NO_DATA ) & ( newState == SPEECH ) ) {
|
||
encState = SPEECH;
|
||
}
|
||
}
|
||
|
||
if ( encState == SPEECH ) {
|
||
st->dtxHangoverCount = DTX_HANG_CONST;
|
||
}
|
||
else {
|
||
if ( st->decAnaElapsedCount > DTX_ELAPSED_FRAMES_THRESH ) {
|
||
st->dtxHangoverAdded = 1;
|
||
st->decAnaElapsedCount = 0;
|
||
st->dtxHangoverCount = 0;
|
||
}
|
||
else if ( st->dtxHangoverCount == 0 ) {
|
||
st->decAnaElapsedCount = 0;
|
||
}
|
||
else {
|
||
st->dtxHangoverCount -= 1;
|
||
}
|
||
}
|
||
|
||
if ( newState != SPEECH ) {
|
||
/*
|
||
* DTX or DTX_MUTE
|
||
* CN data is not in a first SID, first SIDs are marked as SID_BAD
|
||
* but will do backwards analysis if a hangover period has been added
|
||
* according to the state machine above
|
||
*/
|
||
st->sid_frame = 0;
|
||
st->valid_data = 0;
|
||
|
||
if ( frame_type == RX_SID_FIRST ) {
|
||
st->sid_frame = 1;
|
||
}
|
||
else if ( frame_type == RX_SID_UPDATE ) {
|
||
st->sid_frame = 1;
|
||
st->valid_data = 1;
|
||
}
|
||
else if ( frame_type == RX_SID_BAD ) {
|
||
st->sid_frame = 1;
|
||
|
||
/* use old data */
|
||
st->dtxHangoverAdded = 0;
|
||
}
|
||
}
|
||
|
||
/* newState is used by both SPEECH AND DTX synthesis routines */
|
||
return newState;
|
||
}
|
||
|
||
|
||
/*
|
||
* Lsf_lsp
|
||
*
|
||
*
|
||
* Parameters:
|
||
* lsf I: vector of LSFs
|
||
* lsp O: vector of LSPs
|
||
*
|
||
* Function:
|
||
* Transformation lsf to lsp, order M
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Lsf_lsp( Word32 lsf[], Word32 lsp[] )
|
||
{
|
||
Word32 i, ind, offset, tmp;
|
||
|
||
|
||
for ( i = 0; i < M; i++ ) {
|
||
/* ind = b8-b15 of lsf[i] */
|
||
ind = lsf[i] >> 8;
|
||
|
||
/* offset = b0-b7 of lsf[i] */
|
||
offset = lsf[i] & 0x00ff;
|
||
|
||
/* lsp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 256 */
|
||
tmp = ( ( cos_table[ind+1]-cos_table[ind] )*offset ) << 1;
|
||
lsp[i] = cos_table[ind] + ( tmp >> 9 );
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* D_plsf_3
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->past_lsf_q I: Past dequantized LFSs
|
||
* st->past_r_q B: past quantized residual
|
||
* mode I: AMR mode
|
||
* bfi B: bad frame indicator
|
||
* indice I: quantization indices of 3 submatrices, Q0
|
||
* lsp1_q O: quantized 1st LSP vector
|
||
*
|
||
* Function:
|
||
* Decodes the LSP parameters using the received quantization indices.
|
||
* 1st order MA prediction and split by 3 vector quantization (split-VQ)
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void D_plsf_3( D_plsfState *st, enum Mode mode, Word16 bfi, Word16 *
|
||
indice, Word32 *lsp1_q )
|
||
{
|
||
Word32 lsf1_r[M], lsf1_q[M];
|
||
Word32 i, index, temp;
|
||
const Word32 *p_cb1, *p_cb2, *p_cb3, *p_dico;
|
||
|
||
|
||
/* if bad frame */
|
||
if ( bfi != 0 ) {
|
||
/* use the past LSFs slightly shifted towards their mean */
|
||
for ( i = 0; i < M; i++ ) {
|
||
/* lsfi_q[i] = ALPHA*past_lsf_q[i] + ONE_ALPHA*meanLsf[i]; */
|
||
lsf1_q[i] = ( ( st->past_lsf_q[i] * ALPHA ) >> 15 ) + ( ( mean_lsf_3[i]
|
||
* ONE_ALPHA ) >> 15 );
|
||
}
|
||
|
||
/* estimate past quantized residual to be used in next frame */
|
||
if ( mode != MRDTX ) {
|
||
for ( i = 0; i < M; i++ ) {
|
||
/* temp = meanLsf[i] + pastR2_q[i] * pred_fac; */
|
||
temp = mean_lsf_3[i] + ( ( st->past_r_q[i] * pred_fac[i] ) >> 15 );
|
||
st->past_r_q[i] = lsf1_q[i] - temp;
|
||
}
|
||
}
|
||
else {
|
||
for ( i = 0; i < M; i++ ) {
|
||
/* temp = meanLsf[i] + pastR2_q[i]; */
|
||
temp = mean_lsf_3[i] + st->past_r_q[i];
|
||
st->past_r_q[i] = lsf1_q[i] - temp;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* if good LSFs received */
|
||
else {
|
||
if ( ( mode == MR475 ) | ( mode == MR515 ) ) {
|
||
/* MR475, MR515 */
|
||
p_cb1 = dico1_lsf_3;
|
||
p_cb2 = dico2_lsf_3;
|
||
p_cb3 = mr515_3_lsf;
|
||
}
|
||
else if ( mode == MR795 ) {
|
||
/* MR795 */
|
||
p_cb1 = mr795_1_lsf;
|
||
p_cb2 = dico2_lsf_3;
|
||
p_cb3 = dico3_lsf_3;
|
||
}
|
||
else {
|
||
/* MR59, MR67, MR74, MR102, MRDTX */
|
||
p_cb1 = dico1_lsf_3;
|
||
p_cb2 = dico2_lsf_3;
|
||
p_cb3 = dico3_lsf_3;
|
||
}
|
||
|
||
/* decode prediction residuals from 3 received indices */
|
||
index = *indice++;
|
||
p_dico = &p_cb1[index + index + index];
|
||
index = *indice++;
|
||
lsf1_r[0] = *p_dico++;
|
||
lsf1_r[1] = *p_dico++;
|
||
lsf1_r[2] = *p_dico++;
|
||
|
||
if ( ( mode == MR475 ) | ( mode == MR515 ) ) {
|
||
/* MR475, MR515 only using every second entry */
|
||
index = index << 1;
|
||
}
|
||
p_dico = &p_cb2[index + index + index];
|
||
index = *indice++;
|
||
lsf1_r[3] = *p_dico++;
|
||
lsf1_r[4] = *p_dico++;
|
||
lsf1_r[5] = *p_dico++;
|
||
p_dico = &p_cb3[index << 2];
|
||
lsf1_r[6] = *p_dico++;
|
||
lsf1_r[7] = *p_dico++;
|
||
lsf1_r[8] = *p_dico++;
|
||
lsf1_r[9] = *p_dico++;
|
||
|
||
/* Compute quantized LSFs and update the past quantized residual */
|
||
if ( mode != MRDTX ) {
|
||
for ( i = 0; i < M; i++ ) {
|
||
lsf1_q[i] = lsf1_r[i] + ( mean_lsf_3[i] + ( ( st->past_r_q[i] *
|
||
pred_fac[i] ) >> 15 ) );
|
||
}
|
||
memcpy( st->past_r_q, lsf1_r, M <<2 );
|
||
}
|
||
else {
|
||
for ( i = 0; i < M; i++ ) {
|
||
lsf1_q[i] = lsf1_r[i] + ( mean_lsf_3[i] + st->past_r_q[i] );
|
||
}
|
||
memcpy( st->past_r_q, lsf1_r, M <<2 );
|
||
}
|
||
}
|
||
|
||
/* verification that LSFs has minimum distance of LSF_GAP Hz */
|
||
temp = LSF_GAP;
|
||
|
||
for ( i = 0; i < M; i++ ) {
|
||
if ( lsf1_q[i] < temp ) {
|
||
lsf1_q[i] = temp;
|
||
}
|
||
temp = lsf1_q[i] + LSF_GAP;
|
||
}
|
||
memcpy( st->past_lsf_q, lsf1_q, M <<2 );
|
||
|
||
/* convert LSFs to the cosine domain */
|
||
Lsf_lsp( lsf1_q, lsp1_q );
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* pseudonoise
|
||
*
|
||
*
|
||
* Parameters:
|
||
* shift_reg B: Old CN generator shift register state
|
||
* no_bits I: Number of bits
|
||
*
|
||
* Function:
|
||
* pseudonoise
|
||
*
|
||
* Returns:
|
||
* noise_bits
|
||
*/
|
||
static Word32 pseudonoise( Word32 *shift_reg, Word32 no_bits )
|
||
{
|
||
Word32 noise_bits, Sn, i;
|
||
Word32 s_reg;
|
||
|
||
|
||
s_reg = *shift_reg;
|
||
noise_bits = 0;
|
||
|
||
for ( i = 0; i < no_bits; i++ ) {
|
||
/* State n == 31 */
|
||
Sn = s_reg & 0x00000001L;
|
||
|
||
/* State n == 3 */
|
||
if ( s_reg & 0x10000000L ) {
|
||
Sn = Sn ^ 0x1L;
|
||
}
|
||
else {
|
||
Sn = Sn ^ 0x0L;
|
||
}
|
||
noise_bits = ( noise_bits << 1 ) | ( s_reg & 1 );
|
||
s_reg = s_reg >> 1;
|
||
|
||
if ( Sn & 1 ) {
|
||
s_reg = s_reg | 0x40000000L;
|
||
}
|
||
}
|
||
*shift_reg = s_reg;
|
||
return noise_bits;
|
||
}
|
||
|
||
|
||
/*
|
||
* Lsp_lsf
|
||
*
|
||
*
|
||
* Parameters:
|
||
* lsp I: LSP vector (range: -1<=val<1)
|
||
* lsf O: LSF vector Old CN generator shift register state
|
||
*
|
||
* Function:
|
||
* Transformation lsp to lsf, LPC order M
|
||
* lsf[i] = arccos(lsp[i])/(2*pi)
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Lsp_lsf( Word32 lsp[], Word32 lsf[] )
|
||
{
|
||
Word32 i, ind = 63; /* begin at end of table -1 */
|
||
|
||
|
||
for ( i = M - 1; i >= 0; i-- ) {
|
||
/* find value in table that is just greater than lsp[i] */
|
||
while ( cos_table[ind] < lsp[i] ) {
|
||
ind--;
|
||
}
|
||
lsf[i] = ( ( ( ( lsp[i] - cos_table[ind] ) * acos_slope[ind] ) + 0x800 )
|
||
>> 12 ) + ( ind << 8 );
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Reorder_lsf
|
||
*
|
||
*
|
||
* Parameters:
|
||
* lsf B: vector of LSFs (range: 0<=val<=0.5)
|
||
* min_dist I: minimum required distance
|
||
*
|
||
* Function:
|
||
* Make sure that the LSFs are properly ordered and to keep a certain minimum
|
||
* distance between adjacent LSFs. LPC order = M.
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Reorder_lsf( Word32 *lsf, Word32 min_dist )
|
||
{
|
||
Word32 lsf_min, i;
|
||
|
||
|
||
lsf_min = min_dist;
|
||
|
||
for ( i = 0; i < M; i++ ) {
|
||
if ( lsf[i] < lsf_min ) {
|
||
lsf[i] = lsf_min;
|
||
}
|
||
lsf_min = lsf[i] + min_dist;
|
||
}
|
||
}
|
||
|
||
/* VC5.0 Global optimization does not work with this function */
|
||
#if _MSC_VER == 1100
|
||
#pragma optimize( "g", off )
|
||
#endif
|
||
/*
|
||
* Get_lsp_pol
|
||
*
|
||
*
|
||
* Parameters:
|
||
* lsp I: line spectral frequencies
|
||
* f O: polynomial F1(z) or F2(z)
|
||
*
|
||
* Function:
|
||
* Find the polynomial F1(z) or F2(z) from the LSPs.
|
||
*
|
||
* F1(z) = product ( 1 - 2 lsp[i] z^-1 + z^-2 )
|
||
* i=0,2,4,6,8
|
||
* F2(z) = product ( 1 - 2 lsp[i] z^-1 + z^-2 )
|
||
* i=1,3,5,7,9
|
||
*
|
||
* where lsp[] is the LSP vector in the cosine domain.
|
||
*
|
||
* The expansion is performed using the following recursion:
|
||
*
|
||
* f[0] = 1
|
||
* b = -2.0 * lsp[0]
|
||
* f[1] = b
|
||
* for i=2 to 5 do
|
||
* b = -2.0 * lsp[2*i-2];
|
||
* f[i] = b*f[i-1] + 2.0*f[i-2];
|
||
* for j=i-1 down to 2 do
|
||
* f[j] = f[j] + b*f[j-1] + f[j-2];
|
||
* f[1] = f[1] + b;
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Get_lsp_pol( Word32 *lsp, Word32 *f )
|
||
{
|
||
volatile Word32 f0, f1, f2, f3, f4, f5;
|
||
Word32 l1, l2, l3, l4;
|
||
|
||
|
||
/* f[0] = 1.0; */
|
||
f0 = 16777216L;
|
||
|
||
/* f1 = *lsp * -1024; */
|
||
f1 = -lsp[0] << 10;
|
||
l1 = lsp[2];
|
||
l2 = lsp[4];
|
||
l3 = lsp[6];
|
||
l4 = lsp[8];
|
||
f2 = f0 << 1;
|
||
f2 -= ( ( ( f1 >> 16 ) * l1 ) + ( ( ( f1 & 0xFFFE ) * l1 ) >> 16 ) ) << 2;
|
||
f1 -= l1 << 10;
|
||
f3 = f1 << 1;
|
||
f3 -= ( ( ( f2 >> 16 ) * l2 ) + ( ( ( f2 & 0xFFFE ) * l2 ) >> 16 ) ) << 2;
|
||
f2 += f0;
|
||
f2 -= ( ( ( f1 >> 16 ) * l2 ) + ( ( ( f1 & 0xFFFE ) * l2 ) >> 16 ) ) << 2;
|
||
f1 -= l2 << 10;
|
||
f4 = f2 << 1;
|
||
f4 -= ( ( ( f3 >> 16 ) * l3 ) + ( ( ( f3 & 0xFFFE ) * l3 ) >> 16 ) ) << 2;
|
||
f3 += f1;
|
||
f3 -= ( ( ( f2 >> 16 ) * l3 ) + ( ( ( f2 & 0xFFFE ) * l3 ) >> 16 ) ) << 2;
|
||
f2 += f0;
|
||
f2 -= ( ( ( f1 >> 16 ) * l3 ) + ( ( ( f1 & 0xFFFE ) * l3 ) >> 16 ) ) << 2;
|
||
f1 -= l3 << 10;
|
||
f5 = f3 << 1;
|
||
f5 -= ( ( ( f4 >> 16 ) * l4 ) + ( ( ( f4 & 0xFFFE ) * l4 ) >> 16 ) ) << 2;
|
||
f4 += f2;
|
||
f4 -= ( ( ( f3 >> 16 ) * l4 ) + ( ( ( f3 & 0xFFFE ) * l4 ) >> 16 ) ) << 2;
|
||
f3 += f1;
|
||
f3 -= ( ( ( f2 >> 16 ) * l4 ) + ( ( ( f2 & 0xFFFE ) * l4 ) >> 16 ) ) << 2;
|
||
f2 += f0;
|
||
f2 -= ( ( ( f1 >> 16 ) * l4 ) + ( ( ( f1 & 0xFFFE ) * l4 ) >> 16 ) ) << 2;
|
||
f1 -= l4 << 10;
|
||
f[0] = f0;
|
||
f[1] = f1;
|
||
f[2] = f2;
|
||
f[3] = f3;
|
||
f[4] = f4;
|
||
f[5] = f5;
|
||
return;
|
||
}
|
||
#if _MSC_VER == 1100
|
||
#pragma optimize( "", on )
|
||
#endif
|
||
|
||
|
||
/*
|
||
* Lsp_Az
|
||
*
|
||
*
|
||
* Parameters:
|
||
* lsp I: Line spectral frequencies
|
||
* a O: Predictor coefficients
|
||
*
|
||
* Function:
|
||
* Converts from the line spectral pairs (LSP) to LP coefficients,
|
||
* for a 10th order filter.
|
||
*
|
||
* Find the coefficients of F1(z) and F2(z)
|
||
* Multiply F1(z) by 1+z^{-1} and F2(z) by 1-z^{-1}
|
||
* A(z) = ( F1(z) + F2(z) ) / 2
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Lsp_Az( Word32 lsp[], Word32 a[] )
|
||
{
|
||
Word32 f1[6], f2[6];
|
||
Word32 T0, i, j;
|
||
|
||
|
||
Get_lsp_pol( &lsp[0], f1 );
|
||
Get_lsp_pol( &lsp[1], f2 );
|
||
|
||
for ( i = 5; i > 0; i-- ) {
|
||
f1[i] += f1[i - 1];
|
||
f2[i] -= f2[i - 1];
|
||
}
|
||
a[0] = 4096;
|
||
|
||
for ( i = 1, j = 10; i <= 5; i++, j-- ) {
|
||
T0 = f1[i] + f2[i];
|
||
a[i] = (Word16)(T0 >> 13); /* emulate fixed point bug */
|
||
if ( ( T0 & 4096 ) != 0 ) {
|
||
a[i]++;
|
||
}
|
||
T0 = f1[i] - f2[i];
|
||
a[j] = (Word16)(T0 >> 13); /* emulate fixed point bug */
|
||
|
||
if ( ( T0 & 4096 ) != 0 ) {
|
||
a[j]++;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* A_Refl
|
||
*
|
||
*
|
||
* Parameters:
|
||
* a I: Directform coefficients
|
||
* refl O: Reflection coefficients
|
||
*
|
||
* Function:
|
||
* Converts from the directform coefficients to reflection coefficients
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void A_Refl( Word32 a[], Word32 refl[] )
|
||
{
|
||
/* local variables */
|
||
int normShift;
|
||
Word32 aState[M], bState[M];
|
||
Word32 normProd, acc, temp, mult, scale, i, j;
|
||
|
||
|
||
/* initialize states */
|
||
memcpy( aState, a, M <<2 );
|
||
|
||
/* backward Levinson recursion */
|
||
for ( i = M - 1; i >= 0; i-- ) {
|
||
if ( labs( aState[i] ) >= 4096 ) {
|
||
goto ExitRefl;
|
||
}
|
||
refl[i] = aState[i] << 3;
|
||
temp = ( refl[i] * refl[i] ) << 1;
|
||
acc = ( MAX_32 - temp );
|
||
normShift=0;
|
||
if (acc != 0){
|
||
temp = acc;
|
||
while (!(temp & 0x40000000))
|
||
{
|
||
normShift++;
|
||
temp = temp << 1;
|
||
}
|
||
}
|
||
else{
|
||
normShift = 0;
|
||
}
|
||
scale = 15 - normShift;
|
||
acc = ( acc << normShift );
|
||
temp = ( acc + ( Word32 )0x00008000L );
|
||
|
||
if ( temp > 0 ) {
|
||
normProd = temp >> 16;
|
||
mult = 0x20000000L / normProd;
|
||
}
|
||
else
|
||
mult = 16384;
|
||
|
||
for ( j = 0; j < i; j++ ) {
|
||
acc = aState[j] << 16;
|
||
acc -= ( refl[i] * aState[i - j - 1] ) << 1;
|
||
temp = ( acc + ( Word32 )0x00008000L ) >> 16;
|
||
temp = ( mult * temp ) << 1;
|
||
|
||
if ( scale > 0 ) {
|
||
if ( ( temp & ( ( Word32 )1 << ( scale - 1 ) ) ) != 0 ) {
|
||
temp = ( temp >> scale ) + 1;
|
||
}
|
||
else
|
||
temp = ( temp >> scale );
|
||
}
|
||
else
|
||
temp = ( temp >> scale );
|
||
|
||
if ( labs( temp ) > 32767 ) {
|
||
goto ExitRefl;
|
||
}
|
||
bState[j] = temp;
|
||
}
|
||
memcpy( aState, bState, i <<2 );
|
||
}
|
||
return;
|
||
ExitRefl:
|
||
memset( refl, 0, M <<2 );
|
||
}
|
||
|
||
|
||
/*
|
||
* Log2_norm
|
||
*
|
||
*
|
||
* Parameters:
|
||
* x I: input value
|
||
* exp I: exponent
|
||
* exponent O: Integer part of Log2. (range: 0<=val<=30)
|
||
* fraction O: Fractional part of Log2. (range: 0<=val<1)
|
||
*
|
||
* Function:
|
||
* Computes log2
|
||
*
|
||
* Computes log2(L_x, exp), where L_x is positive and
|
||
* normalized, and exp is the normalisation exponent
|
||
* If L_x is negative or zero, the result is 0.
|
||
*
|
||
* The function Log2(L_x) is approximated by a table and linear
|
||
* interpolation. The following steps are used to compute Log2(L_x)
|
||
*
|
||
* exponent = 30-normExponent
|
||
* i = bit25-b31 of L_x; 32<=i<=63 (because of normalization).
|
||
* a = bit10-b24
|
||
* i -=32
|
||
* fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Log2_norm( Word32 x, Word32 exp, Word32 *exponent, Word32 *
|
||
fraction )
|
||
{
|
||
Word32 y, i, a;
|
||
|
||
|
||
if ( x <= 0 ) {
|
||
*exponent = 0;
|
||
*fraction = 0;
|
||
return;
|
||
}
|
||
|
||
/* Extract b25-b31 */
|
||
i = x >> 25;
|
||
i = i - 32;
|
||
|
||
/* Extract b10-b24 of fraction */
|
||
a = x >> 9;
|
||
a = a & 0xFFFE; /* 2a */
|
||
|
||
/* fraction */
|
||
y = ( log2_table[i] << 16 ) - a * ( log2_table[i] - log2_table[i + 1] );
|
||
*fraction = y >> 16;
|
||
*exponent = 30 - exp;
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Log2
|
||
*
|
||
*
|
||
* Parameters:
|
||
* x I: input value
|
||
* exponent O: Integer part of Log2. (range: 0<=val<=30)
|
||
* fraction O: Fractional part of Log2. (range: 0<=val<1)
|
||
*
|
||
* Function:
|
||
* Computes log2(L_x)
|
||
* If x is negative or zero, the result is 0.
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Log2( Word32 x, Word32 *exponent, Word32 *fraction )
|
||
{
|
||
int tmp, exp=0;
|
||
|
||
if (x != 0){
|
||
tmp = x;
|
||
while (!((tmp & 0x80000000) ^ ((tmp & 0x40000000) << 1)))
|
||
{
|
||
exp++;
|
||
tmp = tmp << 1;
|
||
}
|
||
}
|
||
Log2_norm( x <<exp, exp, exponent, fraction );
|
||
}
|
||
|
||
|
||
/*
|
||
* Pow2
|
||
*
|
||
*
|
||
* Parameters:
|
||
* exponent I: Integer part. (range: 0<=val<=30)
|
||
* fraction O: Fractional part. (range: 0.0<=val<1.0)
|
||
*
|
||
* Function:
|
||
* pow(2.0, exponent.fraction)
|
||
*
|
||
* The function Pow2(L_x) is approximated by a table and linear interpolation.
|
||
*
|
||
* i = bit10-b15 of fraction, 0 <= i <= 31
|
||
* a = biT0-b9 of fraction
|
||
* x = table[i]<<16 - (table[i] - table[i+1]) * a * 2
|
||
* x = L_x >> (30-exponent) (with rounding)
|
||
*
|
||
* Returns:
|
||
* result (range: 0<=val<=0x7fffffff)
|
||
*/
|
||
static Word32 Pow2( Word32 exponent, Word32 fraction )
|
||
{
|
||
Word32 i, a, tmp, x, exp;
|
||
|
||
|
||
/* Extract b10-b16 of fraction */
|
||
i = fraction >> 10;
|
||
|
||
/* Extract b0-b9 of fraction */
|
||
a = ( fraction << 5 ) & 0x7fff;
|
||
|
||
/* table[i] << 16 */
|
||
x = pow2_table[i] << 16;
|
||
|
||
/* table[i] - table[i+1] */
|
||
tmp = pow2_table[i] - pow2_table[i + 1];
|
||
|
||
/* L_x -= tmp*a*2 */
|
||
x -= ( tmp * a ) << 1;
|
||
|
||
if ( exponent >= -1 ) {
|
||
exp = ( 30 - exponent );
|
||
|
||
/* Rounding */
|
||
if ( ( x & ( ( Word32 )1 << ( exp - 1 ) ) ) != 0 ) {
|
||
x = ( x >> exp ) + 1;
|
||
}
|
||
else
|
||
x = x >> exp;
|
||
}
|
||
else
|
||
x = 0;
|
||
return( x );
|
||
}
|
||
|
||
|
||
/*
|
||
* Build_CN_code
|
||
*
|
||
*
|
||
* Parameters:
|
||
* seed B: Old CN generator shift register state
|
||
* cod O: Generated CN fixed codebook vector
|
||
*
|
||
* Function:
|
||
* Generate CN fixed codebook vector
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Build_CN_code( Word32 *seed, Word32 cod[] )
|
||
{
|
||
Word32 i, j, k;
|
||
|
||
|
||
memset( cod, 0, L_SUBFR <<2 );
|
||
|
||
for ( k = 0; k < 10; k++ ) {
|
||
i = pseudonoise( seed, 2 ); /* generate pulse position */
|
||
i = ( i * 20 ) >> 1;
|
||
i = ( i + k );
|
||
j = pseudonoise( seed, 1 ); /* generate sign */
|
||
|
||
if ( j > 0 ) {
|
||
cod[i] = 4096;
|
||
}
|
||
else {
|
||
cod[i] = -4096;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Build_CN_param
|
||
*
|
||
*
|
||
* Parameters:
|
||
* seed B: Old CN generator shift register state
|
||
* nParam I: number of params
|
||
* paramSizeTable I: size of params
|
||
* parm O: CN Generated params
|
||
*
|
||
* Function:
|
||
* Generate parameters for comfort noise generation
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Build_CN_param( Word16 *seed, enum Mode mode, Word16 parm[] )
|
||
{
|
||
Word32 i;
|
||
const Word32 *p;
|
||
|
||
|
||
*seed = ( Word16 )( ( *seed * 31821 ) + 13849L );
|
||
p = &window_200_40[ * seed & 0x7F];
|
||
|
||
switch ( mode ) {
|
||
case MR122:
|
||
for ( i = 0; i < PRMNO_MR122; i++ ) {
|
||
parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR122[i] ) );
|
||
}
|
||
break;
|
||
|
||
case MR102:
|
||
for ( i = 0; i < PRMNO_MR102; i++ ) {
|
||
parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR102[i] ) );
|
||
}
|
||
break;
|
||
|
||
case MR795:
|
||
for ( i = 0; i < PRMNO_MR795; i++ ) {
|
||
parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR795[i] ) );
|
||
}
|
||
break;
|
||
|
||
case MR74:
|
||
for ( i = 0; i < PRMNO_MR74; i++ ) {
|
||
parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR74[i] ) );
|
||
}
|
||
break;
|
||
|
||
case MR67:
|
||
for ( i = 0; i < PRMNO_MR67; i++ ) {
|
||
parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR67[i] ) );
|
||
}
|
||
break;
|
||
|
||
case MR59:
|
||
for ( i = 0; i < PRMNO_MR59; i++ ) {
|
||
parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR59[i] ) );
|
||
}
|
||
break;
|
||
|
||
case MR515:
|
||
for ( i = 0; i < PRMNO_MR515; i++ ) {
|
||
parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR515[i] ) );
|
||
}
|
||
break;
|
||
|
||
case MR475:
|
||
for ( i = 0; i < PRMNO_MR475; i++ ) {
|
||
parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR475[i] ) );
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* Syn_filt
|
||
*
|
||
*
|
||
* Parameters:
|
||
* a I: prediction coefficients [M+1]
|
||
* x I: input signal
|
||
* y O: output signal
|
||
* lg I: size of filtering
|
||
* mem B: memory associated with this filtering
|
||
* update I: 0=no update, 1=update of memory.
|
||
*
|
||
* Function:
|
||
* Perform synthesis filtering through 1/A(z).
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static Word32 Syn_filt( Word32 a[], Word32 x[], Word32 y[], Word32 lg, Word32 mem[]
|
||
, Word32 update )
|
||
{
|
||
Word32 tmp[50]; /* malloc is slow */
|
||
Word32 s, a0, overflow = 0;
|
||
Word32 *yy, *yy_limit;
|
||
|
||
|
||
/* Copy mem[] to yy[] */
|
||
memcpy( tmp, mem, 40 );
|
||
yy = tmp + M;
|
||
yy_limit = yy + lg;
|
||
a0 = a[0];
|
||
|
||
/* Do the filtering. */
|
||
while ( yy < yy_limit ) {
|
||
|
||
s = *x++ * a0;
|
||
s -= yy[-1] * a[1];
|
||
s -= yy[-2] * a[2];
|
||
s -= yy[-3] * a[3];
|
||
s -= yy[-4] * a[4];
|
||
s -= yy[-5] * a[5];
|
||
s -= yy[-6] * a[6];
|
||
s -= yy[-7] * a[7];
|
||
s -= yy[-8] * a[8];
|
||
s -= yy[-9] * a[9];
|
||
s -= yy[-10] * a[10];
|
||
if ( labs( s ) < 0x7ffffff )
|
||
*yy = ( s + 0x800L ) >> 12;
|
||
else if ( s > 0 ) {
|
||
*yy = 32767;
|
||
overflow = 1;
|
||
}
|
||
else {
|
||
*yy = -32768;
|
||
overflow = 1;
|
||
}
|
||
yy++;
|
||
}
|
||
memcpy( y, &tmp[M], lg <<2 );
|
||
|
||
/* Update of memory if update==1 */
|
||
if ( update ) {
|
||
memcpy( mem, &y[lg - M], 40 );
|
||
}
|
||
return overflow;
|
||
}
|
||
|
||
/*
|
||
* Syn_filt_overflow
|
||
*
|
||
*
|
||
* Parameters:
|
||
* a I: prediction coefficients [M+1]
|
||
* x I: input signal
|
||
* y O: output signal
|
||
* lg I: size of filtering
|
||
* mem B: memory associated with this filtering
|
||
* update I: 0=no update, 1=update of memory.
|
||
*
|
||
* Function:
|
||
* Perform synthesis filtering through 1/A(z).
|
||
* Saturate after every multiplication.
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Syn_filt_overflow( Word32 a[], Word32 x[], Word32 y[], Word32 lg, Word32 mem[]
|
||
, Word32 update )
|
||
{
|
||
Word32 tmp[50]; /* malloc is slow */
|
||
Word32 i, j, s, a0;
|
||
Word32 *yy;
|
||
|
||
|
||
/* Copy mem[] to yy[] */
|
||
memcpy( tmp, mem, 40 );
|
||
yy = tmp + M;
|
||
a0 = a[0];
|
||
|
||
/* Do the filtering. */
|
||
for ( i = 0; i < lg; i++ ) {
|
||
s = x[i] * a0;
|
||
|
||
for ( j = 1; j <= M; j++ ) {
|
||
s -= a[j] * yy[ - j];
|
||
if (s > 1073741823){
|
||
s = 1073741823;
|
||
}
|
||
else if ( s < -1073741824) {
|
||
s = -1073741824;
|
||
}
|
||
}
|
||
|
||
if ( labs( s ) < 0x7FFE800 )
|
||
*yy = ( s + 0x800L ) >> 12;
|
||
else if ( s > 0 ) {
|
||
*yy = 32767;
|
||
}
|
||
else {
|
||
*yy = -32768;
|
||
}
|
||
yy++;
|
||
}
|
||
memcpy( y, &tmp[M], lg <<2 );
|
||
|
||
/* Update of memory if update==1 */
|
||
if ( update ) {
|
||
memcpy( mem, &y[lg - M], 40 );
|
||
}
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* dtx_dec
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st B: DTX state struct
|
||
* mem_syn I: AMR decoder state
|
||
* lsfState B: LSF state struct
|
||
* pred_state->past_qua_en O: table of past quantized energies
|
||
* pred_state->past_qua_en_MR122 O: table of past quantized energies MR122
|
||
* averState->hangVar O:
|
||
* averState->hangCount O: hangover variable
|
||
* new_state I: new DTX state
|
||
* mode I: AMR mode
|
||
* parm I: vector of synthesis parameters
|
||
* synth O: synthesised speech
|
||
* A_t O: decoded LP filter in 4 subframes
|
||
*
|
||
* Function:
|
||
* DTX
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void dtx_dec( dtx_decState *st, Word32 *mem_syn, D_plsfState *lsfState,
|
||
gc_predState *pred_state, Cb_gain_averageState *averState, enum
|
||
DTXStateType new_state, enum Mode mode, Word16 parm[], Word32 synth[],
|
||
Word32 A_t[] )
|
||
{
|
||
Word32 ex[L_SUBFR], acoeff[11], acoeff_variab[M + 1], lsp_int[M];
|
||
Word32 refl[M], lsf[M], lsf_int[M], lsf_int_variab[M], lsp_int_variab[M];
|
||
Word32 i, j, int_fac, log_en_int, pred_err, log_pg_e, log_pg_m, log_pg;
|
||
Word32 negative, lsf_mean, lsf_variab_index, lsf_variab_factor, ptr;
|
||
Word16 log_en_index, log_en_int_e, log_en_int_m, level, ma_pred_init,
|
||
tmp_int_length;
|
||
|
||
|
||
if ( ( st->dtxHangoverAdded != 0 ) & ( st->sid_frame != 0 ) ) {
|
||
/*
|
||
* sidFirst after dtx hangover period
|
||
* or sidUpd after dtxhangover
|
||
*/
|
||
/* set log_en_adjust to correct value */
|
||
st->log_en_adjust = dtx_log_en_adjust[mode];
|
||
ptr = st->lsf_hist_ptr + M;
|
||
|
||
if ( ptr == 80 ) {
|
||
ptr = 0;
|
||
}
|
||
memcpy( &st->lsf_hist[ptr], &st->lsf_hist[st->lsf_hist_ptr], M <<2 );
|
||
ptr = st->log_en_hist_ptr + 1;
|
||
|
||
if ( ptr == DTX_HIST_SIZE ) {
|
||
ptr = 0;
|
||
}
|
||
st->log_en_hist[ptr] = st->log_en_hist[st->log_en_hist_ptr]; /* Q11 */
|
||
|
||
/*
|
||
* compute mean log energy and lsp
|
||
* from decoded signal (SID_FIRST)
|
||
*/
|
||
st->log_en = 0;
|
||
memset( lsf, 0, M <<2 );
|
||
|
||
/* average energy and lsp */
|
||
for ( i = 0; i < DTX_HIST_SIZE; i++ ) {
|
||
st->log_en = st->log_en + ( st->log_en_hist[i] >> 3 );
|
||
|
||
for ( j = 0; j < M; j++ ) {
|
||
lsf[j] += st->lsf_hist[i * M + j];
|
||
}
|
||
}
|
||
|
||
for ( j = 0; j < M; j++ ) {
|
||
lsf[j] = lsf[j] >> 3; /* divide by 8 */
|
||
}
|
||
Lsf_lsp( lsf, st->lsp );
|
||
|
||
/*
|
||
* make log_en speech coder mode independent
|
||
* added again later before synthesis
|
||
*/
|
||
st->log_en = st->log_en - st->log_en_adjust;
|
||
|
||
/* compute lsf variability vector */
|
||
memcpy( st->lsf_hist_mean, st->lsf_hist, 80 <<2 );
|
||
|
||
for ( i = 0; i < M; i++ ) {
|
||
lsf_mean = 0;
|
||
|
||
/* compute mean lsf */
|
||
for ( j = 0; j < 8; j++ ) {
|
||
lsf_mean += st->lsf_hist_mean[i + j * M];
|
||
}
|
||
lsf_mean = lsf_mean >> 3;
|
||
|
||
/*
|
||
* subtract mean and limit to within reasonable limits
|
||
* moreover the upper lsf's are attenuated
|
||
*/
|
||
for ( j = 0; j < 8; j++ ) {
|
||
/* subtract mean */
|
||
st->lsf_hist_mean[i + j * M] = st->lsf_hist_mean[i + j * M] -
|
||
lsf_mean;
|
||
|
||
/* attenuate deviation from mean, especially for upper lsf's */
|
||
st->lsf_hist_mean[i + j * M] = ( st->lsf_hist_mean[i + j * M] *
|
||
lsf_hist_mean_scale[i] ) >> 15;
|
||
|
||
/* limit the deviation */
|
||
if ( st->lsf_hist_mean[i + j * M] < 0 ) {
|
||
negative = 1;
|
||
}
|
||
else {
|
||
negative = 0;
|
||
}
|
||
st->lsf_hist_mean[i + j * M] = labs( st->lsf_hist_mean[i + j * M] );
|
||
|
||
/* apply soft limit */
|
||
if ( st->lsf_hist_mean[i + j * M] > 655 ) {
|
||
st->lsf_hist_mean[i + j * M] = 655 + ( ( st->lsf_hist_mean[i + j
|
||
* M] - 655 ) >> 2 );
|
||
}
|
||
|
||
/* apply hard limit */
|
||
if ( st->lsf_hist_mean[i + j * M] > 1310 ) {
|
||
st->lsf_hist_mean[i + j * M] = 1310;
|
||
}
|
||
|
||
if ( negative != 0 ) {
|
||
st->lsf_hist_mean[i + j * M] = -st->lsf_hist_mean[i + j * M];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( st->sid_frame != 0 ) {
|
||
/*
|
||
* Set old SID parameters, always shift
|
||
* even if there is no new valid_data
|
||
*/
|
||
memcpy( st->lsp_old, st->lsp, M <<2 );
|
||
st->old_log_en = st->log_en;
|
||
|
||
if ( st->valid_data != 0 ) /* new data available (no CRC) */ {
|
||
/* Compute interpolation factor, since the division only works
|
||
* for values of since_last_sid < 32 we have to limit the
|
||
* interpolation to 32 frames
|
||
*/
|
||
tmp_int_length = st->since_last_sid;
|
||
st->since_last_sid = 0;
|
||
|
||
if ( tmp_int_length > 32 ) {
|
||
tmp_int_length = 32;
|
||
}
|
||
|
||
if ( tmp_int_length >= 2 ) {
|
||
st->true_sid_period_inv = 0x2000000 / ( tmp_int_length
|
||
<< 10 );
|
||
}
|
||
else {
|
||
st->true_sid_period_inv = 16384; /* 0.5 it Q15 */
|
||
}
|
||
memcpy( lsfState->past_r_q, &past_rq_init[parm[0] * M], M <<2 );
|
||
D_plsf_3( lsfState, MRDTX, 0, &parm[1], st->lsp );
|
||
|
||
/* reset for next speech frame */
|
||
memset( lsfState->past_r_q, 0, M <<2 );
|
||
log_en_index = parm[4];
|
||
|
||
/* Q11 and divide by 4 */
|
||
st->log_en = ( Word16 )( log_en_index << 9 );
|
||
|
||
/* Subtract 2.5 in Q11 */
|
||
st->log_en = ( Word16 )( st->log_en - 5120 );
|
||
|
||
/* Index 0 is reserved for silence */
|
||
if ( log_en_index == 0 ) {
|
||
st->log_en = MIN_16;
|
||
}
|
||
|
||
/*
|
||
* no interpolation at startup after coder reset
|
||
* or when SID_UPD has been received right after SPEECH
|
||
*/
|
||
if ( ( st->data_updated == 0 ) || ( st->dtxGlobalState == SPEECH ) ) {
|
||
memcpy( st->lsp_old, st->lsp, M <<2 );
|
||
st->old_log_en = st->log_en;
|
||
}
|
||
} /* endif valid_data */
|
||
|
||
/* initialize gain predictor memory of other modes */
|
||
ma_pred_init = ( Word16 )( ( st->log_en >> 1 ) - 9000 );
|
||
|
||
if ( ma_pred_init > 0 ) {
|
||
ma_pred_init = 0;
|
||
}
|
||
|
||
if ( ma_pred_init < - 14436 ) {
|
||
ma_pred_init = -14436;
|
||
}
|
||
pred_state->past_qua_en[0] = ma_pred_init;
|
||
pred_state->past_qua_en[1] = ma_pred_init;
|
||
pred_state->past_qua_en[2] = ma_pred_init;
|
||
pred_state->past_qua_en[3] = ma_pred_init;
|
||
|
||
/* past_qua_en for other modes than MR122 */
|
||
ma_pred_init = ( Word16 )( ( 5443*ma_pred_init ) >> 15 );
|
||
|
||
/* scale down by factor 20*log10(2) in Q15 */
|
||
pred_state->past_qua_en_MR122[0] = ma_pred_init;
|
||
pred_state->past_qua_en_MR122[1] = ma_pred_init;
|
||
pred_state->past_qua_en_MR122[2] = ma_pred_init;
|
||
pred_state->past_qua_en_MR122[3] = ma_pred_init;
|
||
} /* endif sid_frame */
|
||
|
||
/*
|
||
* CN generation
|
||
* recompute level adjustment factor Q11
|
||
* st->log_en_adjust = 0.9*st->log_en_adjust +
|
||
* 0.1*dtx_log_en_adjust[mode]);
|
||
*/
|
||
st->log_en_adjust = ( Word16 )( ( ( st->log_en_adjust * 29491 ) >> 15 ) + ( (
|
||
( dtx_log_en_adjust[mode] << 5 ) * 3277 ) >> 20 ) );
|
||
|
||
/* Interpolate SID info */
|
||
/* Q10 */
|
||
if ( st->since_last_sid > 30 )
|
||
int_fac = 32767;
|
||
else
|
||
int_fac = ( Word16 )( (st->since_last_sid + 1) << 10 );
|
||
|
||
/* Q10 * Q15 -> Q10 */
|
||
int_fac = ( int_fac * st->true_sid_period_inv ) >> 15;
|
||
|
||
/* Maximize to 1.0 in Q10 */
|
||
if ( int_fac > 1024 ) {
|
||
int_fac = 1024;
|
||
}
|
||
|
||
/* Q10 -> Q14 */
|
||
int_fac = ( Word16 )( int_fac << 4 );
|
||
|
||
/* Q14 * Q11->Q26 */
|
||
log_en_int = ( int_fac * st->log_en ) << 1;
|
||
|
||
for ( i = 0; i < M; i++ ) {
|
||
/* Q14 * Q15 -> Q14 */
|
||
lsp_int[i] = ( int_fac * st->lsp[i] ) >> 15;
|
||
}
|
||
|
||
/* 1-k in Q14 */
|
||
int_fac = 16384 - int_fac;
|
||
|
||
/* (Q14 * Q11 -> Q26) + Q26 -> Q26 */
|
||
log_en_int += ( int_fac * st->old_log_en ) << 1;
|
||
|
||
for ( i = 0; i < M; i++ ) {
|
||
/* Q14 + (Q14 * Q15 -> Q14) -> Q14 */
|
||
lsp_int[i] = lsp_int[i] + ( ( int_fac * st->lsp_old[i] ) >> 15 );
|
||
|
||
/* Q14 -> Q15 */
|
||
lsp_int[i] = lsp_int[i] << 1;
|
||
}
|
||
|
||
/* compute the amount of lsf variability */
|
||
/* -0.6 in Q12 */
|
||
lsf_variab_factor = st->log_pg_mean - 2457;
|
||
|
||
/* *0.3 Q12*Q15 -> Q12 */
|
||
lsf_variab_factor = 4096 - ( ( lsf_variab_factor * 9830 ) >> 15 );
|
||
|
||
/* limit to values between 0..1 in Q12 */
|
||
if ( lsf_variab_factor >= 4096 ) {
|
||
lsf_variab_factor = 32767;
|
||
}
|
||
else if ( lsf_variab_factor < 0 ) {
|
||
lsf_variab_factor = 0;
|
||
}
|
||
else
|
||
lsf_variab_factor = lsf_variab_factor << 3; /* -> Q15 */
|
||
|
||
/* get index of vector to do variability with */
|
||
lsf_variab_index = pseudonoise( &st->pn_seed_rx, 3 );
|
||
|
||
/* convert to lsf */
|
||
Lsp_lsf( lsp_int, lsf_int );
|
||
|
||
/* apply lsf variability */
|
||
memcpy( lsf_int_variab, lsf_int, M <<2 );
|
||
|
||
for ( i = 0; i < M; i++ ) {
|
||
lsf_int_variab[i] = lsf_int_variab[i] + ( ( lsf_variab_factor * st->
|
||
lsf_hist_mean[i + lsf_variab_index * M] ) >> 15 );
|
||
}
|
||
|
||
/* make sure that LSP's are ordered */
|
||
Reorder_lsf( lsf_int, LSF_GAP );
|
||
Reorder_lsf( lsf_int_variab, LSF_GAP );
|
||
|
||
/* copy lsf to speech decoders lsf state */
|
||
memcpy( lsfState->past_lsf_q, lsf_int, M <<2 );
|
||
|
||
/* convert to lsp */
|
||
Lsf_lsp( lsf_int, lsp_int );
|
||
Lsf_lsp( lsf_int_variab, lsp_int_variab );
|
||
|
||
/* Compute acoeffs Q12 acoeff is used for level
|
||
* normalization and Post_Filter, acoeff_variab is
|
||
* used for synthesis filter
|
||
* by doing this we make sure that the level
|
||
* in high frequenncies does not jump up and down
|
||
*/
|
||
Lsp_Az( lsp_int, acoeff );
|
||
Lsp_Az( lsp_int_variab, acoeff_variab );
|
||
|
||
/* For use in Post_Filter */
|
||
memcpy( &A_t[0], acoeff, MP1 <<2 );
|
||
memcpy( &A_t[MP1], acoeff, MP1 <<2 );
|
||
memcpy( &A_t[MP1 <<1], acoeff, MP1 <<2 );
|
||
memcpy( &A_t[MP1 + MP1 + MP1], acoeff, MP1 <<2 );
|
||
|
||
/* Compute reflection coefficients Q15 */
|
||
A_Refl( &acoeff[1], refl );
|
||
|
||
/* Compute prediction error in Q15 */
|
||
/* 0.99997 in Q15 */
|
||
pred_err = MAX_16;
|
||
|
||
for ( i = 0; i < M; i++ ) {
|
||
pred_err = ( pred_err * ( MAX_16 - ( ( refl[i] * refl[i] ) >> 15 ) ) ) >>
|
||
15;
|
||
}
|
||
|
||
/* compute logarithm of prediction gain */
|
||
Log2( pred_err, &log_pg_e, &log_pg_m );
|
||
|
||
/* convert exponent and mantissa to Word16 Q12 */
|
||
/* Q12 */
|
||
log_pg = ( log_pg_e - 15 ) << 12;
|
||
/* saturate */
|
||
if (log_pg < -32768) {
|
||
log_pg = -32768;
|
||
}
|
||
log_pg = ( -( log_pg + ( log_pg_m >> 3 ) ) ) >> 1;
|
||
st->log_pg_mean = ( Word16 )( ( ( 29491*st->log_pg_mean ) >> 15 ) + ( ( 3277
|
||
* log_pg ) >> 15 ) );
|
||
|
||
/* Compute interpolated log energy */
|
||
/* Q26 -> Q16 */
|
||
log_en_int = log_en_int >> 10;
|
||
|
||
/* Add 4 in Q16 */
|
||
log_en_int += 262144L;
|
||
|
||
/* subtract prediction gain */
|
||
log_en_int = log_en_int - ( log_pg << 4 );
|
||
|
||
/* adjust level to speech coder mode */
|
||
log_en_int += st->log_en_adjust << 5;
|
||
log_en_int_e = ( Word16 )( log_en_int >> 16 );
|
||
log_en_int_m = ( Word16 )( ( log_en_int - ( log_en_int_e << 16 ) ) >> 1 );
|
||
|
||
/* Q4 */
|
||
level = ( Word16 )( Pow2( log_en_int_e, log_en_int_m ) );
|
||
|
||
for ( i = 0; i < 4; i++ ) {
|
||
/* Compute innovation vector */
|
||
Build_CN_code( &st->pn_seed_rx, ex );
|
||
|
||
for ( j = 0; j < L_SUBFR; j++ ) {
|
||
ex[j] = ( level * ex[j] ) >> 15;
|
||
}
|
||
|
||
/* Synthesize */
|
||
Syn_filt( acoeff_variab, ex, &synth[i * L_SUBFR], L_SUBFR, mem_syn, 1 );
|
||
} /* next i */
|
||
|
||
/* reset codebook averaging variables */
|
||
averState->hangVar = 20;
|
||
averState->hangCount = 0;
|
||
|
||
if ( new_state == DTX_MUTE ) {
|
||
/*
|
||
* mute comfort noise as it has been quite a long time since
|
||
* last SID update was performed
|
||
*/
|
||
Word32 num, denom;
|
||
|
||
|
||
tmp_int_length = st->since_last_sid;
|
||
|
||
if ( tmp_int_length > 32 ) {
|
||
tmp_int_length = 32;
|
||
}
|
||
|
||
if ( tmp_int_length == 1 ) {
|
||
st->true_sid_period_inv = MAX_16;
|
||
}
|
||
else {
|
||
num = 1024;
|
||
denom = ( tmp_int_length << 10 );
|
||
st->true_sid_period_inv = 0;
|
||
|
||
for ( i = 0; i < 15; i++ ) {
|
||
st->true_sid_period_inv <<= 1;
|
||
num <<= 1;
|
||
|
||
if ( num >= denom ) {
|
||
num = num - denom;
|
||
st->true_sid_period_inv += 1;
|
||
}
|
||
}
|
||
}
|
||
st->since_last_sid = 0;
|
||
memcpy( st->lsp_old, st->lsp, M << 2 );
|
||
st->old_log_en = st->log_en;
|
||
|
||
/* subtract 1/8 in Q11 i.e -6/8 dB */
|
||
st->log_en = st->log_en - 256;
|
||
if (st->log_en < -32768) st->log_en = -32768;
|
||
}
|
||
|
||
/*
|
||
* reset interpolation length timer
|
||
* if data has been updated.
|
||
*/
|
||
if ( ( st->sid_frame != 0 ) & ( ( st->valid_data != 0 ) || ( ( st->valid_data
|
||
== 0 ) & ( st->dtxHangoverAdded != 0 ) ) ) ) {
|
||
st->since_last_sid = 0;
|
||
st->data_updated = 1;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* lsp_avg
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->lsp_meanSave B: LSP averages
|
||
* lsp I: LSPs
|
||
*
|
||
* Function:
|
||
* Calculate the LSP averages
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void lsp_avg( lsp_avgState *st, Word32 *lsp )
|
||
{
|
||
Word32 i, tmp;
|
||
|
||
|
||
for ( i = 0; i < M; i++ ) {
|
||
/* mean = 0.84*mean */
|
||
tmp = ( st->lsp_meanSave[i] << 16 );
|
||
tmp -= ( EXPCONST * st->lsp_meanSave[i] ) << 1;
|
||
|
||
/* Add 0.16 of newest LSPs to mean */
|
||
tmp += ( EXPCONST * lsp[i] ) << 1;
|
||
|
||
/* Save means */
|
||
tmp += 0x00008000L;
|
||
st->lsp_meanSave[i] = tmp >> 16;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Int_lpc_1and3
|
||
*
|
||
*
|
||
* Parameters:
|
||
* lsp_old I: LSP vector at the 4th subfr. of past frame [M]
|
||
* lsp_mid I: LSP vector at the 2nd subframe of present frame [M]
|
||
* lsp_new I: LSP vector at the 4th subframe of present frame [M]
|
||
* Az O: interpolated LP parameters in subframes 1 and 3
|
||
* [AZ_SIZE]
|
||
*
|
||
* Function:
|
||
* Interpolates the LSPs and converts to LPC parameters
|
||
* to get a different LP filter in each subframe.
|
||
*
|
||
* The 20 ms speech frame is divided into 4 subframes.
|
||
* The LSPs are quantized and transmitted at the 2nd and
|
||
* 4th subframes (twice per frame) and interpolated at the
|
||
* 1st and 3rd subframe.
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Int_lpc_1and3( Word32 lsp_old[], Word32 lsp_mid[], Word32 lsp_new[],
|
||
Word32 Az[] )
|
||
{
|
||
Word32 lsp[M];
|
||
Word32 i;
|
||
|
||
|
||
/* lsp[i] = lsp_mid[i] * 0.5 + lsp_old[i] * 0.5 */
|
||
for ( i = 0; i < 10; i++ ) {
|
||
lsp[i] = ( lsp_mid[i] >> 1 ) + ( lsp_old[i] >> 1 );
|
||
}
|
||
|
||
/* Subframe 1 */
|
||
Lsp_Az( lsp, Az );
|
||
Az += MP1;
|
||
|
||
/* Subframe 2 */
|
||
Lsp_Az( lsp_mid, Az );
|
||
Az += MP1;
|
||
|
||
for ( i = 0; i < 10; i++ ) {
|
||
lsp[i] = ( lsp_mid[i] >> 1 ) + ( lsp_new[i] >> 1 );
|
||
}
|
||
|
||
/* Subframe 3 */
|
||
Lsp_Az( lsp, Az );
|
||
Az += MP1;
|
||
|
||
/* Subframe 4 */
|
||
Lsp_Az( lsp_new, Az );
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Int_lpc_1to3
|
||
*
|
||
*
|
||
* Parameters:
|
||
* lsp_old I: LSP vector at the 4th subframe of past frame [M]
|
||
* lsp_new I: LSP vector at the 4th subframe of present frame [M]
|
||
* Az O: interpolated LP parameters in all subframes
|
||
* [AZ_SIZE]
|
||
*
|
||
* Function:
|
||
* Interpolates the LSPs and converts to LPC parameters to get a different
|
||
* LP filter in each subframe.
|
||
*
|
||
* The 20 ms speech frame is divided into 4 subframes.
|
||
* The LSPs are quantized and transmitted at the 4th
|
||
* subframes (once per frame) and interpolated at the
|
||
* 1st, 2nd and 3rd subframe.
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Int_lpc_1to3( Word32 lsp_old[], Word32 lsp_new[], Word32 Az[] )
|
||
{
|
||
Word32 lsp[M];
|
||
Word32 i;
|
||
|
||
|
||
for ( i = 0; i < 10; i++ ) {
|
||
lsp[i] = ( lsp_new[i] >> 2 ) + ( lsp_old[i] - ( lsp_old[i] >> 2 ) );
|
||
}
|
||
|
||
/* Subframe 1 */
|
||
Lsp_Az( lsp, Az );
|
||
Az += MP1;
|
||
|
||
for ( i = 0; i < 10; i++ ) {
|
||
lsp[i] = ( lsp_old[i] >> 1 ) + ( lsp_new[i] >> 1 );
|
||
}
|
||
|
||
/* Subframe 2 */
|
||
Lsp_Az( lsp, Az );
|
||
Az += MP1;
|
||
|
||
for ( i = 0; i < 10; i++ ) {
|
||
lsp[i] = ( lsp_old[i] >> 2 ) + ( lsp_new[i] - ( lsp_new[i] >> 2 ) );
|
||
}
|
||
|
||
/* Subframe 3 */
|
||
Lsp_Az( lsp, Az );
|
||
Az += MP1;
|
||
|
||
/* Subframe 4 */
|
||
Lsp_Az( lsp_new, Az );
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* D_plsf_5
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->past_lsf_q I: Past dequantized LFSs
|
||
* st->past_r_q B: past quantized residual
|
||
* bfi B: bad frame indicator
|
||
* indice I: quantization indices of 3 submatrices, Q0
|
||
* lsp1_q O: quantized 1st LSP vector
|
||
* lsp2_q O: quantized 2nd LSP vector
|
||
*
|
||
* Function:
|
||
* Decodes the 2 sets of LSP parameters in a frame
|
||
* using the received quantization indices.
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void D_plsf_5( D_plsfState *st, Word16 bfi, Word16 *indice, Word32 *lsp1_q
|
||
, Word32 *lsp2_q )
|
||
{
|
||
Word32 lsf1_r[M], lsf2_r[M], lsf1_q[M], lsf2_q[M];
|
||
Word32 i, temp1, temp2, sign;
|
||
const Word32 *p_dico;
|
||
|
||
|
||
/* if bad frame */
|
||
if ( bfi != 0 ) {
|
||
/* use the past LSFs slightly shifted towards their mean */
|
||
for ( i = 0; i < M; i += 2 ) {
|
||
/* lsfi_q[i] = ALPHA*st->past_lsf_q[i] + ONE_ALPHA*meanLsf[i]; */
|
||
lsf1_q[i] = ( ( st->past_lsf_q[i] * ALPHA_122 ) >> 15 ) + ( ( mean_lsf_5[i]
|
||
* ONE_ALPHA_122 ) >> 15 );
|
||
lsf1_q[i + 1] = ( ( st->past_lsf_q[i + 1] * ALPHA_122 ) >> 15 ) + ( (
|
||
mean_lsf_5[i + 1] * ONE_ALPHA_122 ) >> 15 );
|
||
}
|
||
memcpy( lsf2_q, lsf1_q, M <<2 );
|
||
|
||
/* estimate past quantized residual to be used in next frame */
|
||
for ( i = 0; i < M; i += 2 ) {
|
||
/* temp = meanLsf[i] + st->past_r_q[i] * LSPPpred_facMR122; */
|
||
temp1 = mean_lsf_5[i] + ( ( st->past_r_q[i] * LSP_PRED_FAC_MR122 ) >>
|
||
15 );
|
||
temp2 = mean_lsf_5[i + 1] +( ( st->past_r_q[i + 1] *LSP_PRED_FAC_MR122
|
||
) >> 15 );
|
||
st->past_r_q[i] = lsf2_q[i] - temp1;
|
||
st->past_r_q[i + 1] = lsf2_q[i + 1] -temp2;
|
||
}
|
||
}
|
||
|
||
/* if good LSFs received */
|
||
else {
|
||
/* decode prediction residuals from 5 received indices */
|
||
p_dico = &dico1_lsf_5[indice[0] << 2];
|
||
lsf1_r[0] = *p_dico++;
|
||
lsf1_r[1] = *p_dico++;
|
||
lsf2_r[0] = *p_dico++;
|
||
lsf2_r[1] = *p_dico++;
|
||
p_dico = &dico2_lsf_5[indice[1] << 2];
|
||
lsf1_r[2] = *p_dico++;
|
||
lsf1_r[3] = *p_dico++;
|
||
lsf2_r[2] = *p_dico++;
|
||
lsf2_r[3] = *p_dico++;
|
||
sign = ( Word16 )( indice[2] & 1 );
|
||
i = indice[2] >> 1;
|
||
p_dico = &dico3_lsf_5[i << 2];
|
||
|
||
if ( sign == 0 ) {
|
||
lsf1_r[4] = *p_dico++;
|
||
lsf1_r[5] = *p_dico++;
|
||
lsf2_r[4] = *p_dico++;
|
||
lsf2_r[5] = *p_dico++;
|
||
}
|
||
else {
|
||
lsf1_r[4] = ( Word16 )( -( *p_dico++ ) );
|
||
lsf1_r[5] = ( Word16 )( -( *p_dico++ ) );
|
||
lsf2_r[4] = ( Word16 )( -( *p_dico++ ) );
|
||
lsf2_r[5] = ( Word16 )( -( *p_dico++ ) );
|
||
}
|
||
p_dico = &dico4_lsf_5[( indice[3]<<2 )];
|
||
lsf1_r[6] = *p_dico++;
|
||
lsf1_r[7] = *p_dico++;
|
||
lsf2_r[6] = *p_dico++;
|
||
lsf2_r[7] = *p_dico++;
|
||
p_dico = &dico5_lsf_5[( indice[4]<<2 )];
|
||
lsf1_r[8] = *p_dico++;
|
||
lsf1_r[9] = *p_dico++;
|
||
lsf2_r[8] = *p_dico++;
|
||
lsf2_r[9] = *p_dico++;
|
||
|
||
/* Compute quantized LSFs and update the past quantized residual */
|
||
for ( i = 0; i < M; i++ ) {
|
||
temp1 = mean_lsf_5[i] + ( ( st->past_r_q[i] * LSP_PRED_FAC_MR122 ) >>
|
||
15 );
|
||
lsf1_q[i] = lsf1_r[i] + temp1;
|
||
lsf2_q[i] = lsf2_r[i] + temp1;
|
||
st->past_r_q[i] = lsf2_r[i];
|
||
}
|
||
}
|
||
|
||
/* verification that LSFs have minimum distance of LSF_GAP Hz */
|
||
Reorder_lsf( lsf1_q, LSF_GAP );
|
||
Reorder_lsf( lsf2_q, LSF_GAP );
|
||
memcpy( st->past_lsf_q, lsf2_q, M <<2 );
|
||
|
||
/* convert LSFs to the cosine domain */
|
||
Lsf_lsp( lsf1_q, lsp1_q );
|
||
Lsf_lsp( lsf2_q, lsp2_q );
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Dec_lag3
|
||
*
|
||
*
|
||
* Parameters:
|
||
* index I: received pitch index
|
||
* t0_min I: minimum of search range
|
||
* t0_max I: maximum of search range
|
||
* i_subfr I: subframe flag
|
||
* T0_prev I: integer pitch delay of last subframe used
|
||
* in 2nd and 4th subframes
|
||
* T0 O: integer part of pitch lag
|
||
* T0_frac O : fractional part of pitch lag
|
||
* flag4 I : flag for encoding with 4 bits
|
||
* Function:
|
||
* Decoding of fractional pitch lag with 1/3 resolution.
|
||
* Extract the integer and fraction parts of the pitch lag from
|
||
* the received adaptive codebook index.
|
||
*
|
||
* The fractional lag in 1st and 3rd subframes is encoded with 8 bits
|
||
* while that in 2nd and 4th subframes is relatively encoded with 4, 5
|
||
* and 6 bits depending on the mode.
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Dec_lag3( Word32 index, Word32 t0_min, Word32 t0_max, Word32 i_subfr
|
||
, Word32 T0_prev, Word32 *T0, Word32 *T0_frac, Word32 flag4 )
|
||
{
|
||
Word32 i, tmp_lag;
|
||
|
||
|
||
/* if 1st or 3rd subframe */
|
||
if ( i_subfr == 0 ) {
|
||
if ( index < 197 ) {
|
||
*T0 = ( ( ( index + 2 ) * 10923 ) >> 15 ) + 19;
|
||
i = *T0 + *T0 + *T0;
|
||
*T0_frac = ( index - i ) + 58;
|
||
}
|
||
else {
|
||
*T0 = index - 112;
|
||
*T0_frac = 0;
|
||
}
|
||
}
|
||
|
||
/* 2nd or 4th subframe */
|
||
else {
|
||
if ( flag4 == 0 ) {
|
||
/* 'normal' decoding: either with 5 or 6 bit resolution */
|
||
i = ( ( ( index + 2 ) * 10923 ) >> 15 ) - 1;
|
||
*T0 = i + t0_min;
|
||
i = i + i + i;
|
||
*T0_frac = ( index - 2 ) - i;
|
||
}
|
||
else {
|
||
/* decoding with 4 bit resolution */
|
||
tmp_lag = T0_prev;
|
||
|
||
if ( ( tmp_lag - t0_min ) > 5 )
|
||
tmp_lag = t0_min + 5;
|
||
|
||
if ( ( t0_max - tmp_lag ) > 4 )
|
||
tmp_lag = t0_max - 4;
|
||
|
||
if ( index < 4 ) {
|
||
i = ( tmp_lag - 5 );
|
||
*T0 = i + index;
|
||
*T0_frac = 0;
|
||
}
|
||
else {
|
||
if ( index < 12 ) {
|
||
i = ( ( ( index - 5 ) * 10923 ) >> 15 ) - 1;
|
||
*T0 = i + tmp_lag;
|
||
i = i + i + i;
|
||
*T0_frac = ( index - 9 ) - i;
|
||
}
|
||
else {
|
||
i = ( index - 12 ) + tmp_lag;
|
||
*T0 = i + 1;
|
||
*T0_frac = 0;
|
||
}
|
||
}
|
||
} /* end if (decoding with 4 bit resolution) */
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Pred_lt_3or6_40
|
||
*
|
||
*
|
||
* Parameters:
|
||
* exc B: excitation buffer
|
||
* T0 I: integer pitch lag
|
||
* frac I: fraction of lag
|
||
* flag3 I: if set, upsampling rate = 3 (6 otherwise)
|
||
*
|
||
* Function:
|
||
* Compute the result of long term prediction with fractional
|
||
* interpolation of resolution 1/3 or 1/6. (Interpolated past excitation).
|
||
*
|
||
* Once the fractional pitch lag is determined,
|
||
* the adaptive codebook vector v(n) is computed by interpolating
|
||
* the past excitation signal u(n) at the given integer delay k
|
||
* and phase (fraction) :
|
||
*
|
||
* 9 9
|
||
* v(n) = SUM[ u(n-k-i) * b60(t+i*6) ] + SUM[ u(n-k+1+i) * b60(6-t+i*6) ],
|
||
* i=0 i=0
|
||
* n = 0, ...,39, t = 0, ...,5.
|
||
*
|
||
* The interpolation filter b60 is based on a Hamming windowed sin(x)/x
|
||
* function truncated at <20> 59 and padded with zeros at <20> 60 (b60(60)=0)).
|
||
* The filter has a cut-off frequency (-3 dB) at 3 600 Hz in
|
||
* the over-sampled domain.
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Pred_lt_3or6_40( Word32 exc[], Word32 T0, Word32 frac, Word32 flag3 )
|
||
{
|
||
Word32 s, i;
|
||
Word32 *x0, *x1, *x2;
|
||
const Word32 *c1, *c2;
|
||
|
||
|
||
x0 = &exc[ - T0];
|
||
frac = -frac;
|
||
|
||
if ( flag3 != 0 ) {
|
||
frac <<= 1; /* inter_3l[k] = inter6[2*k] -> k' = 2*k */
|
||
}
|
||
|
||
if ( frac < 0 ) {
|
||
frac += 6;
|
||
x0--;
|
||
}
|
||
c1 = &inter6[frac];
|
||
c2 = &inter6[6 - frac];
|
||
|
||
for ( i = 0; i < 40; i++ ) {
|
||
x1 = x0++;
|
||
x2 = x0;
|
||
s = x1[0] * c1[0];
|
||
s += x1[ - 1] * c1[6];
|
||
s += x1[ - 2] * c1[12];
|
||
s += x1[ - 3] * c1[18];
|
||
s += x1[ - 4] * c1[24];
|
||
s += x1[ - 5] * c1[30];
|
||
s += x1[ - 6] * c1[36];
|
||
s += x1[ - 7] * c1[42];
|
||
s += x1[ - 8] * c1[48];
|
||
s += x1[ - 9] * c1[54];
|
||
s += x2[0] * c2[0];
|
||
s += x2[1] * c2[6];
|
||
s += x2[2] * c2[12];
|
||
s += x2[3] * c2[18];
|
||
s += x2[4] * c2[24];
|
||
s += x2[5] * c2[30];
|
||
s += x2[6] * c2[36];
|
||
s += x2[7] * c2[42];
|
||
s += x2[8] * c2[48];
|
||
s += x2[9] * c2[54];
|
||
exc[i] = ( s + 0x4000 ) >> 15;
|
||
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* Dec_lag6
|
||
*
|
||
*
|
||
* Parameters:
|
||
* index I: received pitch index
|
||
* pit_min I: minimum pitch lag
|
||
* pit_max I: maximum pitch lag
|
||
* i_subfr I: subframe flag
|
||
* T0 B: integer part of pitch lag
|
||
* T0_frac O : fractional part of pitch lag
|
||
*
|
||
* Function:
|
||
* Decoding of fractional pitch lag with 1/6 resolution.
|
||
* Extract the integer and fraction parts of the pitch lag from
|
||
* the received adaptive codebook index.
|
||
*
|
||
* The fractional lag in 1st and 3rd subframes is encoded with 9 bits
|
||
* while that in 2nd and 4th subframes is relatively encoded with 6 bits.
|
||
* Note that in relative encoding only 61 values are used. If the
|
||
* decoder receives 61, 62, or 63 as the relative pitch index, it means
|
||
* that a transmission error occurred. In this case, the pitch lag from
|
||
* previous subframe (actually from previous frame) is used.
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Dec_lag6( Word32 index, Word32 pit_min, Word32 pit_max, Word32
|
||
i_subfr, Word32 *T0, Word32 *T0_frac )
|
||
{
|
||
Word32 t0_min, t0_max, i;
|
||
|
||
|
||
/* if 1st or 3rd subframe */
|
||
if ( i_subfr == 0 ) {
|
||
if ( index < 463 ) {
|
||
/* T0 = (index+5)/6 + 17 */
|
||
*T0 = ( index + 5 ) / 6 + 17;
|
||
i = *T0 + *T0 + *T0;
|
||
|
||
/* *T0_frac = index - T0*6 + 105 */
|
||
*T0_frac = ( index - ( i + i ) ) + 105;
|
||
}
|
||
else {
|
||
*T0 = index - 368;
|
||
*T0_frac = 0;
|
||
}
|
||
}
|
||
|
||
/* second or fourth subframe */
|
||
else {
|
||
/* find t0_min and t0_max for 2nd (or 4th) subframe */
|
||
t0_min = *T0 - 5;
|
||
|
||
if ( t0_min < pit_min ) {
|
||
t0_min = pit_min;
|
||
}
|
||
t0_max = t0_min + 9;
|
||
|
||
if ( t0_max > pit_max ) {
|
||
t0_max = pit_max;
|
||
t0_min = t0_max - 9;
|
||
}
|
||
|
||
/* i = (index+5)/6 - 1 */
|
||
i = ( index + 5 ) / 6 - 1;
|
||
*T0 = i + t0_min;
|
||
i = i + i + i;
|
||
*T0_frac = ( index - 3 ) - ( i + i );
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* decompress10
|
||
*
|
||
*
|
||
* Parameters:
|
||
* MSBs I: MSB part of the index
|
||
* LSBs I: LSB part of the index
|
||
* index1 I: index for first pos in posIndex
|
||
* index2 I: index for second pos in posIndex
|
||
* index3 I: index for third pos in posIndex
|
||
* pos_indx O: position of 3 pulses (decompressed)
|
||
* Function:
|
||
* Decompression of the linear codeword
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void decompress10( Word32 MSBs, Word32 LSBs, Word32 index1, Word32 index2
|
||
, Word32 index3, Word32 pos_indx[] )
|
||
{
|
||
Word32 divMSB;
|
||
|
||
if (MSBs > 124)
|
||
{
|
||
MSBs = 124;
|
||
}
|
||
/*
|
||
* pos_indx[index1] = ((MSBs-25*(MSBs/25))%5)*2 + (LSBs-4*(LSBs/4))%2;
|
||
* pos_indx[index2] = ((MSBs-25*(MSBs/25))/5)*2 + (LSBs-4*(LSBs/4))/2;
|
||
* pos_indx[index3] = (MSBs/25)*2 + LSBs/4;
|
||
*/
|
||
divMSB = MSBs / 25;
|
||
pos_indx[index1] = ( ( ( MSBs - 25 * ( divMSB ) ) % 5 ) << 1 ) + ( LSBs & 0x1
|
||
);
|
||
pos_indx[index2] = ( ( ( MSBs - 25 * ( divMSB ) ) / 5 ) << 1 ) + ( ( LSBs &
|
||
0x2 ) >> 1 );
|
||
pos_indx[index3] = ( divMSB << 1 ) + ( LSBs >> 2 );
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* decompress_codewords
|
||
*
|
||
*
|
||
* Parameters:
|
||
* indx I: position of 8 pulses (compressed)
|
||
* pos_indx O: position index of 8 pulses (position only)
|
||
*
|
||
* Function:
|
||
* Decompression of the linear codewords to 4+three indeces
|
||
* one bit from each pulse is made robust to errors by
|
||
* minimizing the phase shift of a bit error.
|
||
*
|
||
* i0,i4,i1 => one index (7+3) bits, 3 LSBs more robust
|
||
* i2,i6,i5 => one index (7+3) bits, 3 LSBs more robust
|
||
* i3,i7 => one index (5+2) bits, 2-3 LSbs more robust
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void decompress_codewords( Word16 indx[], Word32 pos_indx[] )
|
||
{
|
||
Word32 ia, ib, MSBs, LSBs, MSBs0_24, tmp;
|
||
|
||
|
||
/*
|
||
* First index: 10x10x10 -> 2x5x2x5x2x5-> 125x2x2x2 -> 7+1x3 bits
|
||
* MSBs = indx[NB_TRACK]/8;
|
||
* LSBs = indx[NB_TRACK]%8;
|
||
*/
|
||
MSBs = *indx >> 3;
|
||
LSBs = *indx & 0x7;
|
||
decompress10( MSBs, LSBs, 0, 4, 1, pos_indx );
|
||
|
||
/*
|
||
* Second index: 10x10x10 -> 2x5x2x5x2x5-> 125x2x2x2 -> 7+1x3 bits
|
||
* MSBs = indx[NB_TRACK+1]/8;
|
||
* LSBs = indx[NB_TRACK+1]%8;
|
||
*/
|
||
MSBs = indx[1] >> 3;
|
||
LSBs = indx[1] & 0x7;
|
||
decompress10( MSBs, LSBs, 2, 6, 5, pos_indx );
|
||
|
||
/*
|
||
* Third index: 10x10 -> 2x5x2x5-> 25x2x2 -> 5+1x2 bits
|
||
* MSBs = indx[NB_TRACK+2]/4;
|
||
* LSBs = indx[NB_TRACK+2]%4;
|
||
* MSBs0_24 = (MSBs*25+12)/32;
|
||
* if ((MSBs0_24/5)%2==1)
|
||
* pos_indx[3] = (4-(MSBs0_24%5))*2 + LSBs%2;
|
||
* else
|
||
* pos_indx[3] = (MSBs0_24%5)*2 + LSBs%2;
|
||
* pos_indx[7] = (MSBs0_24/5)*2 + LSBs/2;
|
||
*/
|
||
MSBs = indx[2] >> 2;
|
||
LSBs = indx[2] & 0x3;
|
||
MSBs0_24 = ( ( ( MSBs * 25 ) + 12 ) >> 5 );
|
||
tmp = ( MSBs0_24 * 6554 ) >> 15;
|
||
ia = tmp & 0x1;
|
||
ib = ( MSBs0_24 - ( tmp * 5 ) );
|
||
|
||
if ( ia == 1 ) {
|
||
ib = 4 - ib;
|
||
}
|
||
pos_indx[3] = ( ib << 1 ) + ( LSBs & 0x1 );
|
||
pos_indx[7] = ( tmp << 1 ) + ( LSBs >> 1 );
|
||
}
|
||
|
||
|
||
/*
|
||
* decode_2i40_9bits
|
||
*
|
||
*
|
||
* Parameters:
|
||
* subNr I: subframe number
|
||
* sign I: signs of 2 pulses
|
||
* index I: Positions of the 2 pulses
|
||
* cod O: algebraic (fixed) codebook excitation
|
||
*
|
||
* Function:
|
||
* Algebraic codebook decoder
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void decode_2i40_9bits( Word32 subNr, Word32 sign, Word32 index, Word32
|
||
cod[] )
|
||
{
|
||
Word32 pos[2];
|
||
Word32 i, j, k;
|
||
|
||
|
||
/* Decode the positions */
|
||
/* table bit is the MSB */
|
||
j = ( index & 64 ) >> 6;
|
||
i = index & 7;
|
||
|
||
/* pos0 =i*5+startPos[j*8+subNr*2] */
|
||
i = ( i + ( i << 2 ) );
|
||
k = startPos[( j <<3 )+( subNr << 1 )];
|
||
pos[0] = i + k;
|
||
index = index >> 3;
|
||
i = index & 7;
|
||
|
||
/* pos1 =i*5+startPos[j*8+subNr*2+1] */
|
||
i = ( i + ( i << 2 ) );
|
||
k = startPos[( ( j <<3 )+ ( subNr <<1 ) ) + 1];
|
||
pos[1] = ( Word16 )( i + k );
|
||
|
||
/* decode the signs and build the codeword */
|
||
memset( cod, 0, L_SUBFR <<2 );
|
||
|
||
for ( j = 0; j < 2; j++ ) {
|
||
i = sign & 1;
|
||
sign = sign >> 1;
|
||
|
||
if ( i != 0 ) {
|
||
cod[pos[j]] = 8191; /* +1.0 */
|
||
}
|
||
else {
|
||
cod[pos[j]] = -8192; /* -1.0 */
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* decode_2i40_11bits
|
||
*
|
||
*
|
||
* Parameters:
|
||
* sign I: signs of 2 pulses
|
||
* index I: Positions of the 2 pulses
|
||
* cod O: algebraic (fixed) codebook excitation
|
||
*
|
||
* Function:
|
||
* Algebraic codebook decoder
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void decode_2i40_11bits( Word32 sign, Word32 index, Word32 cod[] )
|
||
{
|
||
Word32 pos[2];
|
||
Word32 i, j;
|
||
|
||
|
||
/* Decode the positions */
|
||
j = index & 1;
|
||
index = index >> 1;
|
||
i = index & 7;
|
||
|
||
/* pos0 =i*5+1+j*2 */
|
||
i = ( i + ( i << 2 ) );
|
||
i = ( i + 1 );
|
||
j = ( j << 1 );
|
||
pos[0] = i + j;
|
||
index = index >> 3;
|
||
j = index & 3;
|
||
index = index >> 2;
|
||
i = index & 7;
|
||
|
||
if ( j == 3 ) {
|
||
/* pos1 =i*5+4 */
|
||
i = ( i + ( i << 2 ) );
|
||
pos[1] = i + 4;
|
||
}
|
||
else {
|
||
/* pos1 =i*5+j */
|
||
i = ( i + ( i << 2 ) );
|
||
pos[1] = i + j;
|
||
}
|
||
|
||
/* decode the signs and build the codeword */
|
||
memset( cod, 0, L_SUBFR <<2 );
|
||
|
||
for ( j = 0; j < 2; j++ ) {
|
||
i = sign & 1;
|
||
sign = sign >> 1;
|
||
|
||
if ( i != 0 ) {
|
||
cod[pos[j]] = 8191; /* +1.0 */
|
||
}
|
||
else {
|
||
cod[pos[j]] = -8192; /* -1.0 */
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* decode_3i40_14bits
|
||
*
|
||
*
|
||
* Parameters:
|
||
* sign I: signs of 3 pulses
|
||
* index I: Positions of the 3 pulses
|
||
* cod O: algebraic (fixed) codebook excitation
|
||
*
|
||
* Function:
|
||
* Algebraic codebook decoder
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void decode_3i40_14bits( Word32 sign, Word32 index, Word32 cod[] )
|
||
{
|
||
Word32 pos[3];
|
||
Word32 i, j;
|
||
|
||
|
||
/* Decode the positions */
|
||
i = index & 7;
|
||
|
||
/* pos0 =i*5 */
|
||
pos[0] = i + ( i << 2 );
|
||
index = index >> 3;
|
||
j = index & 1;
|
||
index = index >> 1;
|
||
i = index & 7;
|
||
|
||
/* pos1 =i*5+1+j*2 */
|
||
i = ( i + ( i << 2 ) );
|
||
i = ( i + 1 );
|
||
j = ( j << 1 );
|
||
pos[1] = i + j;
|
||
index = index >> 3;
|
||
j = index & 1;
|
||
index = index >> 1;
|
||
i = index & 7;
|
||
|
||
/* pos2 =i*5+2+j*2 */
|
||
i = ( i + ( i << 2 ) );
|
||
i = ( i + 2 );
|
||
j = ( j << 1 );
|
||
pos[2] = i + j;
|
||
|
||
/* decode the signs and build the codeword */
|
||
memset( cod, 0, L_SUBFR <<2 );
|
||
|
||
for ( j = 0; j < 3; j++ ) {
|
||
i = sign & 1;
|
||
sign = sign >> 1;
|
||
|
||
if ( i > 0 ) {
|
||
cod[pos[j]] = 8191; /* +1.0 */
|
||
}
|
||
else {
|
||
cod[pos[j]] = -8192; /* -1.0 */
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* decode_3i40_14bits
|
||
*
|
||
*
|
||
* Parameters:
|
||
* sign I: signs of 4 pulses
|
||
* index I: Positions of the 4 pulses
|
||
* cod O: algebraic (fixed) codebook excitation
|
||
*
|
||
* Function:
|
||
* Algebraic codebook decoder
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void decode_4i40_17bits( Word32 sign, Word32 index, Word32 cod[] )
|
||
{
|
||
Word32 pos[4];
|
||
Word32 i, j;
|
||
|
||
|
||
/* Decode the positions */
|
||
i = index & 7;
|
||
i = dgray[i];
|
||
|
||
/* pos0 =i*5 */
|
||
pos[0] = i + ( i << 2 );
|
||
index = index >> 3;
|
||
i = index & 7;
|
||
i = dgray[i];
|
||
|
||
/* pos1 =i*5+1 */
|
||
i = ( i + ( i << 2 ) );
|
||
pos[1] = i + 1;
|
||
index = index >> 3;
|
||
i = index & 7;
|
||
i = dgray[i];
|
||
|
||
/* pos2 =i*5+1 */
|
||
i = ( i + ( i << 2 ) );
|
||
pos[2] = i + 2;
|
||
index = index >> 3;
|
||
j = index & 1;
|
||
index = index >> 1;
|
||
i = index & 7;
|
||
i = dgray[i];
|
||
|
||
/* pos3 =i*5+3+j */
|
||
i = ( i + ( i << 2 ) );
|
||
i = ( i + 3 );
|
||
pos[3] = i + j;
|
||
|
||
/* decode the signs and build the codeword */
|
||
memset( cod, 0, L_SUBFR <<2 );
|
||
|
||
for ( j = 0; j < 4; j++ ) {
|
||
i = sign & 1;
|
||
sign = sign >> 1;
|
||
|
||
if ( i != 0 ) {
|
||
cod[pos[j]] = 8191;
|
||
}
|
||
else {
|
||
cod[pos[j]] = -8192;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* decode_8i40_31bits
|
||
*
|
||
*
|
||
* Parameters:
|
||
* index I: index of 8 pulses (sign+position)
|
||
* cod O: algebraic (fixed) codebook excitation
|
||
*
|
||
* Function:
|
||
* Algebraic codebook decoder
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void decode_8i40_31bits( Word16 index[], Word32 cod[] )
|
||
{
|
||
Word32 linear_codewords[8];
|
||
Word32 i, j, pos1, pos2, sign;
|
||
|
||
|
||
memset( cod, 0, L_CODE <<2 );
|
||
decompress_codewords( &index[NB_TRACK_MR102], linear_codewords );
|
||
|
||
/* decode the positions and signs of pulses and build the codeword */
|
||
for ( j = 0; j < NB_TRACK_MR102; j++ ) {
|
||
/* compute index i */
|
||
i = linear_codewords[j];
|
||
i <<= 2;
|
||
|
||
/* position of pulse "j" */
|
||
pos1 = i + j;
|
||
|
||
if ( index[j] == 0 ) {
|
||
sign = POS_CODE; /* +1.0 */
|
||
}
|
||
else {
|
||
sign = -NEG_CODE; /* -1.0 */
|
||
}
|
||
|
||
/* compute index i */
|
||
i = linear_codewords[j + 4];
|
||
i = i << 2;
|
||
|
||
/* position of pulse "j+4" */
|
||
pos2 = i + j;
|
||
cod[pos1] = sign;
|
||
|
||
if ( pos2 < pos1 ) {
|
||
sign = -( sign );
|
||
}
|
||
cod[pos2] = cod[pos2] + sign;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* decode_10i40_35bits
|
||
*
|
||
*
|
||
* Parameters:
|
||
* index I: index of 10 pulses (sign+position)
|
||
* cod O: algebraic (fixed) codebook excitation
|
||
*
|
||
* Function:
|
||
* Algebraic codebook decoder
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void decode_10i40_35bits( Word16 index[], Word32 cod[] )
|
||
{
|
||
Word32 i, j, pos1, pos2, sign, tmp;
|
||
|
||
|
||
memset( cod, 0, L_CODE <<2 );
|
||
|
||
/* decode the positions and signs of pulses and build the codeword */
|
||
for ( j = 0; j < 5; j++ ) {
|
||
/* compute index i */
|
||
tmp = index[j];
|
||
i = tmp & 7;
|
||
i = dgray[i];
|
||
i = ( i * 5 );
|
||
|
||
/* position of pulse "j" */
|
||
pos1 = ( i + j );
|
||
i = ( tmp >> 3 ) & 1;
|
||
|
||
if ( i == 0 ) {
|
||
sign = 4096; /* +1.0 */
|
||
}
|
||
else {
|
||
sign = -4096; /* -1.0 */
|
||
}
|
||
|
||
/* compute index i */
|
||
i = index[j + 5] & 7;
|
||
i = dgray[i];
|
||
i = i * 5;
|
||
|
||
/* position of pulse "j+5" */
|
||
pos2 = ( i + j );
|
||
cod[pos1] = sign;
|
||
|
||
if ( pos2 < pos1 ) {
|
||
sign = -( sign );
|
||
}
|
||
cod[pos2] = cod[pos2] + sign;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* gmed_n
|
||
*
|
||
*
|
||
* Parameters:
|
||
* ind I: values
|
||
* n I: The number of gains (odd)
|
||
*
|
||
* Function:
|
||
* Calculates N-point median.
|
||
*
|
||
* Returns:
|
||
* index of the median value
|
||
*/
|
||
static Word32 gmed_n( Word32 ind[], Word32 n )
|
||
{
|
||
Word32 tmp[NMAX], tmp2[NMAX];
|
||
Word32 max, medianIndex, i, j, ix = 0;
|
||
|
||
|
||
for ( i = 0; i < n; i++ ) {
|
||
tmp2[i] = ind[i];
|
||
}
|
||
|
||
for ( i = 0; i < n; i++ ) {
|
||
max = -32767;
|
||
|
||
for ( j = 0; j < n; j++ ) {
|
||
if ( tmp2[j] >= max ) {
|
||
max = tmp2[j];
|
||
ix = j;
|
||
}
|
||
}
|
||
tmp2[ix] = -32768;
|
||
tmp[i] = ix;
|
||
}
|
||
medianIndex = tmp[( n >>1 )];
|
||
return( ind[medianIndex] );
|
||
}
|
||
|
||
|
||
/*
|
||
* ec_gain_pitch
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->pbuf I: last five gains
|
||
* st->past_gain_pit I: past gain
|
||
* state I: state of the state machine
|
||
* gain_pitch O: pitch gain
|
||
*
|
||
* Function:
|
||
* Calculates pitch from previous values.
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void ec_gain_pitch( ec_gain_pitchState *st, Word16 state, Word32 *
|
||
gain_pitch )
|
||
{
|
||
Word32 tmp;
|
||
|
||
|
||
/* calculate median of last five gains */
|
||
tmp = gmed_n( st->pbuf, 5 );
|
||
|
||
/* new gain = minimum(median, past_gain) * pdown[state] */
|
||
if ( tmp > st->past_gain_pit ) {
|
||
tmp = st->past_gain_pit;
|
||
}
|
||
*gain_pitch = ( tmp * pdown[state] ) >> 15;
|
||
}
|
||
|
||
|
||
/*
|
||
* d_gain_pitch
|
||
*
|
||
*
|
||
* Parameters:
|
||
* mode I: AMR mode
|
||
* index I: index of quantization
|
||
*
|
||
* Function:
|
||
* Decodes the pitch gain using the received index
|
||
*
|
||
* Returns:
|
||
* gain
|
||
*/
|
||
static Word32 d_gain_pitch( enum Mode mode, Word32 index )
|
||
{
|
||
Word32 gain;
|
||
|
||
|
||
if ( mode == MR122 ) {
|
||
/* clear 2 LSBits */
|
||
gain = ( qua_gain_pitch[index] >> 2 ) << 2;
|
||
}
|
||
else {
|
||
gain = qua_gain_pitch[index];
|
||
}
|
||
return gain;
|
||
}
|
||
|
||
|
||
/*
|
||
* ec_gain_pitch_update
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->prev_gp B: previous pitch gain
|
||
* st->past_gain_pit O: past gain
|
||
* st->pbuf B: past gain buffer
|
||
* bfi I: bad frame indicator
|
||
* prev_bf I: previous frame was bad
|
||
* gain_pitch B: pitch gain
|
||
*
|
||
* Function:
|
||
* Update the pitch gain concealment state
|
||
* Limit gain_pitch if the previous frame was bad
|
||
*
|
||
* Returns:
|
||
* gain
|
||
*/
|
||
static void ec_gain_pitch_update( ec_gain_pitchState *st, Word32 bfi,
|
||
Word32 prev_bf, Word32 *gain_pitch )
|
||
{
|
||
if ( bfi == 0 ) {
|
||
if ( prev_bf != 0 ) {
|
||
if ( *gain_pitch > st->prev_gp ) {
|
||
*gain_pitch = st->prev_gp;
|
||
}
|
||
}
|
||
st->prev_gp = *gain_pitch;
|
||
}
|
||
st->past_gain_pit = *gain_pitch;
|
||
|
||
/* if (st->past_gain_pit > 1.0) */
|
||
if ( st->past_gain_pit > 16384 ) {
|
||
st->past_gain_pit = 16384;
|
||
}
|
||
st->pbuf[0] = st->pbuf[1];
|
||
st->pbuf[1] = st->pbuf[2];
|
||
st->pbuf[2] = st->pbuf[3];
|
||
st->pbuf[3] = st->pbuf[4];
|
||
st->pbuf[4] = st->past_gain_pit;
|
||
}
|
||
|
||
|
||
/*
|
||
* gc_pred (366)
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->past_qua_en I: MA predictor
|
||
* st->past_qua_en_MR122 I: MA predictor MR122
|
||
* mode I: AMR mode
|
||
* code I: innovative codebook vector
|
||
* exp_gcode0 O: predicted gain factor (exponent)
|
||
* frac_gcode0 O: predicted gain factor (fraction)
|
||
* exp_en I: innovation energy (MR795) (exponent)
|
||
* frac_en I: innovation energy (MR795) (fraction)
|
||
*
|
||
* Function:
|
||
* MA prediction of the innovation energy
|
||
*
|
||
* Mean removed innovation energy (dB) in subframe n
|
||
* N-1
|
||
* E(n) = 10*log(gc*gc * SUM[(code(i) * code(i)]/N) - EMean
|
||
* i=0
|
||
* N=40
|
||
*
|
||
* Mean innovation energy (dB)
|
||
* N-1
|
||
* Ei(n) = 10*log(SUM[(code(i) * code(i)]/N)
|
||
* i=0
|
||
*
|
||
* Predicted energy
|
||
* 4
|
||
* Ep(n) = SUM[b(i) * R(n-i)]
|
||
* i=1
|
||
* b = [0.68 0.58 0.34 0.19]
|
||
* R(k) is quantified prediction error at subframe k
|
||
*
|
||
* E_Mean = 36 dB (MR122)
|
||
*
|
||
* Predicted gain gc is found by
|
||
*
|
||
* gc = POW[10, 0.05 * (Ep(n) + EMean - Ei)]
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void gc_pred( gc_predState *st, enum Mode mode, Word32 *code, Word32 *
|
||
exp_gcode0, Word32 *frac_gcode0, Word32 *exp_en, Word32 *frac_en )
|
||
{
|
||
Word32 exp, frac, ener_code = 0, i = 0;
|
||
|
||
|
||
/* energy of code:
|
||
* ener_code = sum(code[i]^2)
|
||
*/
|
||
while ( i < L_SUBFR ) {
|
||
ener_code += code[i] * code[i];
|
||
i++;
|
||
}
|
||
|
||
if ( ( 0x3fffffff <= ener_code ) | ( ener_code < 0 ) )
|
||
ener_code = MAX_32;
|
||
else
|
||
ener_code <<= 1;
|
||
|
||
if ( mode == MR122 ) {
|
||
Word32 ener;
|
||
|
||
|
||
/* ener_code = ener_code / lcode; lcode = 40; 1/40 = 26214 Q20 */
|
||
ener_code = ( ( ener_code + 0x00008000L ) >> 16 ) * 52428;
|
||
|
||
/* 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 = ( ( exp - 30 ) << 16 ) + ( frac << 1 );
|
||
|
||
/* Q16 for log(), ->Q17 for 1/2 log() */
|
||
/*
|
||
* predicted energy:
|
||
* ener(Q24) = (Emean + sum{pred[i]*pastEn[i]})/constant
|
||
* = MEAN_ENER + sum(pred[i]*past_qua_en[i])
|
||
* constant = 20*Log10(2)
|
||
*/
|
||
ener = 0;
|
||
i = 0;
|
||
|
||
while ( i < 4 ) {
|
||
ener += st->past_qua_en_MR122[i] * pred_MR122[i];
|
||
i++;
|
||
}
|
||
ener <<= 1;
|
||
ener += MEAN_ENER_MR122;
|
||
|
||
/*
|
||
* predicted codebook gain
|
||
|
||
* gc0 = Pow10( (ener*constant - ener_code*constant) / 20 )
|
||
* = Pow2(ener-ener_code)
|
||
* = Pow2(int(d)+frac(d))
|
||
*/
|
||
ener = ( ener - ener_code ) >> 1; /* Q16 */
|
||
*exp_gcode0 = ener >> 16;
|
||
*frac_gcode0 = ( ener >> 1 ) - ( *exp_gcode0 << 15 );
|
||
}
|
||
|
||
/* all modes except 12.2 */
|
||
else {
|
||
Word32 tmp, gcode0;
|
||
int exp_code;
|
||
|
||
|
||
/*
|
||
* Compute: meansEner - 10log10(ener_code/ LSufr)
|
||
*/
|
||
exp_code=0;
|
||
if (ener_code != 0){
|
||
while (!(ener_code & 0x40000000))
|
||
{
|
||
exp_code++;
|
||
ener_code = ener_code << 1;
|
||
}
|
||
}
|
||
|
||
/* Log2 = log2 + 27 */
|
||
Log2_norm( ener_code, exp_code, &exp, &frac );
|
||
|
||
/* fact = 10/log2(10) = 3.01 = 24660 Q13 */
|
||
/* Q0.Q15 * Q13 -> Q14 */
|
||
tmp = ( exp * ( -49320 ) ) + ( ( ( frac * ( -24660 ) ) >> 15 ) << 1 );
|
||
|
||
/*
|
||
* tmp = meansEner - 10log10(ener_code/L_SUBFR)
|
||
* = meansEner - 10log10(ener_code) + 10log10(L_SUBFR)
|
||
* = K - fact * Log2(ener_code)
|
||
* = K - fact * log2(ener_code) - fact*27
|
||
*
|
||
* ==> K = meansEner + fact*27 + 10log10(L_SUBFR)
|
||
*
|
||
* meansEner = 33 = 540672 Q14 (MR475, MR515, MR59)
|
||
* meansEner = 28.75 = 471040 Q14 (MR67)
|
||
* meansEner = 30 = 491520 Q14 (MR74)
|
||
* meansEner = 36 = 589824 Q14 (MR795)
|
||
* meansEner = 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 */
|
||
tmp += 2134784; /* Q14 */
|
||
}
|
||
else if ( mode == MR795 ) {
|
||
/* mean = 36 dB */
|
||
tmp += 2183936; /* Q14 */
|
||
|
||
/*
|
||
* 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 = ener_code >> 16;
|
||
*exp_en = -11 - exp_code;
|
||
}
|
||
else if ( mode == MR74 ) {
|
||
/* mean = 30 dB */
|
||
tmp += 2085632; /* Q14 */
|
||
}
|
||
else if ( mode == MR67 ) {
|
||
/* mean = 28.75 dB */
|
||
tmp += 2065152; /* Q14 */
|
||
}
|
||
else /* MR59, MR515, MR475 */ {
|
||
/* mean = 33 dB */
|
||
tmp += 2134784; /* Q14 */
|
||
}
|
||
|
||
/*
|
||
* Compute gcode0
|
||
* = Sum(i=0,3) pred[i]*past_qua_en[i] - ener_code + meanEner
|
||
*/
|
||
tmp = tmp << 9; /* Q23 */
|
||
|
||
/* Q13 * Q10 -> Q23 */
|
||
i = 0;
|
||
|
||
while ( i < 4 ) {
|
||
tmp += pred[i] * st->past_qua_en[i];
|
||
i++;
|
||
}
|
||
gcode0 = tmp >> 15; /* 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) */
|
||
/* For IS641 bitexactness */
|
||
if ( mode == MR74 ) {
|
||
/* Q8 * Q15 -> Q24 */
|
||
tmp = gcode0 * 10878;
|
||
}
|
||
else {
|
||
/* Q8 * Q15 -> Q24 */
|
||
tmp = gcode0 * 10886;
|
||
}
|
||
tmp = tmp >> 9; /* -> Q15 */
|
||
|
||
/* -> Q0.Q15 */
|
||
*exp_gcode0 = tmp >> 15;
|
||
*frac_gcode0 = tmp - ( *exp_gcode0 * 32768 );
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* gc_pred_update
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->past_qua_en B: MA predictor
|
||
* st->past_qua_en_MR122 B: MA predictor MR122
|
||
* qua_ener_MR122 I: quantized energy for update (log2(quaErr))
|
||
* qua_ener I: quantized energy for update (20*log10(quaErr))
|
||
*
|
||
* Function:
|
||
* Update MA predictor with last quantized energy
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void gc_pred_update( gc_predState *st, Word32 qua_ener_MR122,
|
||
Word32 qua_ener )
|
||
{
|
||
Word32 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 (quaErr), Q10 */
|
||
st->past_qua_en[0] = qua_ener; /* 20*log10(quaErr), Q10 */
|
||
}
|
||
|
||
|
||
/*
|
||
* Dec_gain
|
||
*
|
||
*
|
||
* Parameters:
|
||
* pred_state->past_qua_en B: MA predictor
|
||
* pred_state->past_qua_en_MR122 B: MA predictor MR122
|
||
* mode I: AMR mode
|
||
* index I: index of quantization
|
||
* code I: Innovative vector
|
||
* evenSubfr I: Flag for even subframes
|
||
* gain_pit O: Pitch gain
|
||
* gain_cod O: Code gain
|
||
*
|
||
* Function:
|
||
* Decode the pitch and codebook gains
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Dec_gain( gc_predState *pred_state, enum Mode mode, Word32 index,
|
||
Word32 code[], Word32 evenSubfr, Word32 *gain_pit, Word32 *gain_cod )
|
||
{
|
||
Word32 frac, gcode0, exp, qua_ener, qua_ener_MR122, g_code, tmp;
|
||
const Word32 *p;
|
||
|
||
|
||
/* Read the quantized gains (table depends on mode) */
|
||
index = index << 2;
|
||
|
||
if ( ( mode == MR102 ) || ( mode == MR74 ) || ( mode == MR67 ) ) {
|
||
p = &table_gain_highrates[index];
|
||
*gain_pit = *p++;
|
||
g_code = *p++;
|
||
qua_ener_MR122 = *p++;
|
||
qua_ener = *p;
|
||
}
|
||
else {
|
||
if ( mode == MR475 ) {
|
||
index = index + ( ( 1 - evenSubfr ) << 1 );
|
||
p = &table_gain_MR475[index];
|
||
*gain_pit = *p++;
|
||
g_code = *p++;
|
||
|
||
/*
|
||
* calculate predictor update values (not stored in 4.75
|
||
* quantizer table to save space):
|
||
* qua_ener = log2(g)
|
||
* qua_ener_MR122 = 20*log10(g)
|
||
*/
|
||
/* Log2(x Q12) = log2(x) + 12 */
|
||
Log2( g_code, &exp, &frac );
|
||
exp = exp - 12;
|
||
tmp = frac >> 5;
|
||
|
||
if ( ( frac & ( ( Word16 )1 << 4 ) ) != 0 ) {
|
||
tmp++;
|
||
}
|
||
qua_ener_MR122 = tmp + ( exp << 10 );
|
||
|
||
/* 24660 Q12 ~= 6.0206 = 20*log10(2) */
|
||
tmp = exp * 49320;
|
||
tmp += ( ( ( frac * 24660 ) >> 15 ) << 1 );
|
||
|
||
/* Q12 * Q0 = Q13 -> Q10 */
|
||
qua_ener = ( ( tmp << 13 ) + 0x00008000L ) >> 16;
|
||
}
|
||
else {
|
||
p = &table_gain_lowrates[index];
|
||
*gain_pit = *p++;
|
||
g_code = *p++;
|
||
qua_ener_MR122 = *p++;
|
||
qua_ener = *p;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* predict codebook gain
|
||
* gc0 = Pow2(int(d)+frac(d))
|
||
* = 2^exp + 2^frac
|
||
* gcode0 (Q14) = 2^14*2^frac = gc0 * 2^(14-exp)
|
||
*/
|
||
gc_pred( pred_state, mode, code, &exp, &frac, NULL, NULL );
|
||
gcode0 = Pow2( 14, frac );
|
||
|
||
/*
|
||
* read quantized gains, update table of past quantized energies
|
||
* st->past_qua_en(Q10) = 20 * Log10(gFac) / constant
|
||
* = Log2(gFac)
|
||
* = qua_ener
|
||
* constant = 20*Log10(2)
|
||
*/
|
||
if ( exp < 11 ) {
|
||
*gain_cod = ( g_code * gcode0 ) >> ( 25 - exp );
|
||
}
|
||
else {
|
||
tmp = ( ( g_code * gcode0 ) << ( exp - 9 ) );
|
||
|
||
if ( ( tmp >> ( exp - 9 ) ) != ( g_code * gcode0 ) ) {
|
||
*gain_cod = 0x7FFF;
|
||
}
|
||
else {
|
||
*gain_cod = tmp >> 16;
|
||
}
|
||
}
|
||
|
||
/* update table of past quantized energies */
|
||
gc_pred_update( pred_state, qua_ener_MR122, qua_ener );
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* gc_pred_average_limited
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->past_qua_en I: MA predictor
|
||
* st->past_qua_en_MR122 I: MA predictor MR122
|
||
* ener_avg_MR122 O: everaged quantized energy (log2(quaErr))
|
||
* ener_avg O: averaged quantized energy (20*log10(quaErr))
|
||
*
|
||
* Function:
|
||
* Compute average limited quantized energy
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void gc_pred_average_limited( gc_predState *st, Word32 *ener_avg_MR122,
|
||
Word32 *ener_avg )
|
||
{
|
||
Word32 av_pred_en, i;
|
||
|
||
|
||
/* do average in MR122 mode (log2() domain) */
|
||
av_pred_en = 0;
|
||
|
||
for ( i = 0; i < NPRED; i++ ) {
|
||
av_pred_en = ( av_pred_en + st->past_qua_en_MR122[i] );
|
||
}
|
||
|
||
/* av_pred_en = 0.25*av_pred_en */
|
||
av_pred_en = ( av_pred_en * 8192 ) >> 15;
|
||
|
||
/* 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 = ( Word16 )av_pred_en;
|
||
|
||
/* do average for other modes (20*log10() domain) */
|
||
av_pred_en = 0;
|
||
|
||
for ( i = 0; i < NPRED; i++ ) {
|
||
av_pred_en = ( av_pred_en + st->past_qua_en[i] );
|
||
if (av_pred_en < -32768)
|
||
av_pred_en = -32768;
|
||
else if (av_pred_en > 32767)
|
||
av_pred_en = 32767;
|
||
}
|
||
|
||
/* av_pred_en = 0.25*av_pred_en */
|
||
av_pred_en = ( av_pred_en * 8192 ) >> 15;
|
||
|
||
*ener_avg = av_pred_en;
|
||
}
|
||
|
||
|
||
/*
|
||
* ec_gain_code
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->gbuf I: last five gains
|
||
* st->past_gain_code I: past gain
|
||
* pred_state B: MA predictor state
|
||
* state I: state of the state machine
|
||
* gain_code O: decoded innovation gain
|
||
*
|
||
* Function:
|
||
* Conceal the codebook gain
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void ec_gain_code( ec_gain_codeState *st, gc_predState *pred_state,
|
||
Word16 state, Word32 *gain_code )
|
||
{
|
||
Word32 tmp, qua_ener_MR122, qua_ener;
|
||
|
||
|
||
/* calculate median of last five gain values */
|
||
tmp = gmed_n( st->gbuf, 5 );
|
||
|
||
/* new gain = minimum(median, past_gain) * cdown[state] */
|
||
if ( tmp > st->past_gain_code ) {
|
||
tmp = st->past_gain_code;
|
||
}
|
||
tmp = ( tmp * cdown[state] ) >> 15;
|
||
*gain_code = tmp;
|
||
|
||
/*
|
||
* update table of past quantized energies with average of
|
||
* current values
|
||
*/
|
||
gc_pred_average_limited( pred_state, &qua_ener_MR122, &qua_ener );
|
||
gc_pred_update( pred_state, qua_ener_MR122, qua_ener );
|
||
}
|
||
|
||
|
||
/*
|
||
* ec_gain_code_update
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->gbuf B: last five gains
|
||
* st->past_gain_code O: past gain
|
||
* st->prev_gc B previous gain
|
||
* bfi I: bad indicator
|
||
* prev_bf I: previous frame bad indicator
|
||
* gain_code O: decoded innovation gain
|
||
*
|
||
* Function:
|
||
* Update the codebook gain concealment state
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void ec_gain_code_update( ec_gain_codeState *st, Word16 bfi,
|
||
Word16 prev_bf, Word32 *gain_code )
|
||
{
|
||
/* limit gain_code by previous good gain if previous frame was bad */
|
||
if ( bfi == 0 ) {
|
||
if ( prev_bf != 0 ) {
|
||
if ( *gain_code > st->prev_gc ) {
|
||
*gain_code = st->prev_gc;
|
||
}
|
||
}
|
||
st->prev_gc = *gain_code;
|
||
}
|
||
|
||
/* update EC states: previous gain, gain buffer */
|
||
st->past_gain_code = *gain_code;
|
||
st->gbuf[0] = st->gbuf[1];
|
||
st->gbuf[1] = st->gbuf[2];
|
||
st->gbuf[2] = st->gbuf[3];
|
||
st->gbuf[3] = st->gbuf[4];
|
||
st->gbuf[4] = *gain_code;
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* d_gain_code
|
||
*
|
||
*
|
||
* Parameters:
|
||
* pred_state B: MA predictor state
|
||
* mode I: AMR mode (MR795 or MR122)
|
||
* index I: received quantization index
|
||
* code I: innovation codevector
|
||
* gain_code O: decoded innovation gain
|
||
*
|
||
* Function:
|
||
* Decode the fixed codebook gain using the received index
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void d_gain_code( gc_predState *pred_state, enum Mode mode, Word32 index,
|
||
Word32 code[], Word32 *gain_code )
|
||
{
|
||
Word32 g_code0, exp, frac, qua_ener_MR122, qua_ener;
|
||
Word32 exp_inn_en, frac_inn_en, tmp, tmp2, i;
|
||
const Word32 *p;
|
||
|
||
|
||
/*
|
||
* Decode codebook gain
|
||
*/
|
||
gc_pred( pred_state, mode, code, &exp, &frac, &exp_inn_en, &frac_inn_en );
|
||
p = &qua_gain_code[( ( index + index )+ index )];
|
||
|
||
/* Different scalings between MR122 and the other modes */
|
||
if ( mode == MR122 ) {
|
||
/* predicted gain */
|
||
g_code0 = Pow2( exp, frac );
|
||
|
||
if ( g_code0 <= 2047 )
|
||
g_code0 = g_code0 << 4;
|
||
else
|
||
g_code0 = 32767;
|
||
*gain_code = ( ( g_code0 * *p++ ) >> 15 ) << 1;
|
||
if (*gain_code & 0xFFFF8000)
|
||
*gain_code = 32767;
|
||
|
||
}
|
||
else {
|
||
g_code0 = Pow2( 14, frac );
|
||
tmp = ( *p++ * g_code0 ) << 1;
|
||
exp = 9 - exp;
|
||
|
||
if ( exp > 0 ) {
|
||
tmp = tmp >> exp;
|
||
}
|
||
else {
|
||
for (i = exp; i < 0; i++) {
|
||
tmp2 = tmp << 1;
|
||
if ((tmp ^ tmp2) & 0x80000000) {
|
||
tmp = (tmp & 0x80000000) ? 0x80000000 : 0x7FFFFFFF;
|
||
break;
|
||
}
|
||
else {
|
||
tmp = tmp2;
|
||
}
|
||
}
|
||
}
|
||
*gain_code = tmp >> 16;
|
||
if (*gain_code & 0xFFFF8000)
|
||
*gain_code = 32767;
|
||
}
|
||
|
||
/*
|
||
* update table of past quantized energies
|
||
*/
|
||
qua_ener_MR122 = *p++;
|
||
qua_ener = *p++;
|
||
gc_pred_update( pred_state, qua_ener_MR122, qua_ener );
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Int_lsf
|
||
*
|
||
*
|
||
* Parameters:
|
||
* lsf_old I: LSF vector at the 4th subframe of past frame
|
||
* lsf_new I: LSF vector at the 4th subframe of present frame
|
||
* i_subfr I: current subframe
|
||
* lsf_out O: interpolated LSF parameters for current subframe
|
||
*
|
||
* Function:
|
||
* Interpolates the LSFs for selected subframe
|
||
*
|
||
* The LSFs are interpolated at the 1st, 2nd and 3rd
|
||
* ubframe and only forwarded at the 4th subframe.
|
||
*
|
||
* sf1: 3/4 F0 + 1/4 F1
|
||
* sf2: 1/2 F0 + 1/2 F1
|
||
* sf3: 1/4 F0 + 3/4 F1
|
||
* sf4: F1
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Int_lsf( Word32 lsf_old[], Word32 lsf_new[], int i_subfr, Word32
|
||
lsf_out[] )
|
||
{
|
||
Word32 i;
|
||
|
||
|
||
switch ( i_subfr ) {
|
||
case 0:
|
||
for ( i = 0; i < 10; i++ ) {
|
||
lsf_out[i] = lsf_old[i] - ( lsf_old[i] >> 2 ) + ( lsf_new[i] >> 2 );
|
||
}
|
||
break;
|
||
|
||
case 40:
|
||
for ( i = 0; i < 10; i++ ) {
|
||
lsf_out[i] = ( lsf_old[i] >> 1 ) + ( lsf_new[i] >> 1 );
|
||
}
|
||
break;
|
||
|
||
case 80:
|
||
for ( i = 0; i < 10; i++ ) {
|
||
lsf_out[i] = ( lsf_old[i] >> 2 ) - ( lsf_new[i] >> 2 ) +
|
||
lsf_new[i];
|
||
}
|
||
break;
|
||
|
||
case 120:
|
||
memcpy( lsf_out, lsf_new, M <<2 );
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* Cb_gain_average
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->cbGainHistory B: codebook gain history
|
||
* st->hangCount B: hangover counter
|
||
* mode I: AMR mode
|
||
* gain_code I: codebook gain
|
||
* lsp I: The LSP for the current frame
|
||
* lspAver I: The average of LSP for 8 frames
|
||
* bfi I: bad frame indication
|
||
* prev_bf I: previous bad frame indication
|
||
* pdfi I: potential degraded bad frame indication
|
||
* prev_pdf I: previous potential degraded bad frame indication
|
||
* inBackgroundNoise I: background noise decision
|
||
* voicedHangover I: number of frames after last voiced frame
|
||
*
|
||
* Function:
|
||
* The mixed codebook gain, used to make codebook gain more smooth in background
|
||
*
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static Word32 Cb_gain_average( Cb_gain_averageState *st, enum Mode mode, Word32
|
||
gain_code, Word32 lsp[], Word32 lspAver[], Word16 bfi, Word16 prev_bf,
|
||
Word16 pdfi, Word16 prev_pdf, Word32 inBackgroundNoise, Word32
|
||
voicedHangover )
|
||
{
|
||
Word32 tmp[M];
|
||
Word32 i, cbGainMix, tmp_diff, bgMix, cbGainMean, sum, diff, tmp1, tmp2;
|
||
int shift1, shift2, shift;
|
||
|
||
|
||
/* set correct cbGainMix for MR74, MR795, MR122 */
|
||
cbGainMix = gain_code;
|
||
|
||
/*
|
||
* Store list of CB gain needed in the CB gain averaging *
|
||
*/
|
||
st->cbGainHistory[0] = st->cbGainHistory[1];
|
||
st->cbGainHistory[1] = st->cbGainHistory[2];
|
||
st->cbGainHistory[2] = st->cbGainHistory[3];
|
||
st->cbGainHistory[3] = st->cbGainHistory[4];
|
||
st->cbGainHistory[4] = st->cbGainHistory[5];
|
||
st->cbGainHistory[5] = st->cbGainHistory[6];
|
||
st->cbGainHistory[6] = gain_code;
|
||
|
||
/* compute lsp difference */
|
||
for ( i = 0; i < M; i++ ) {
|
||
tmp1 = labs( lspAver[i]- lsp[i] );
|
||
shift1 = 0;
|
||
if (tmp1 != 0){
|
||
while (!(tmp1 & 0x2000))
|
||
{
|
||
shift1++;
|
||
tmp1 = tmp1 << 1;
|
||
}
|
||
}
|
||
tmp2 = lspAver[i];
|
||
shift2 = 0;
|
||
if (tmp2 != 0){
|
||
while (!(tmp2 & 0x4000))
|
||
{
|
||
shift2++;
|
||
tmp2 = tmp2 << 1;
|
||
}
|
||
}
|
||
tmp[i] = ( tmp1 << 15 ) / tmp2;
|
||
shift = 2 + shift1 - shift2;
|
||
|
||
if ( shift >= 0 ) {
|
||
tmp[i] = tmp[i] >> shift;
|
||
}
|
||
else {
|
||
tmp[i] = tmp[i] << -( shift );
|
||
}
|
||
}
|
||
diff = *tmp + tmp[1] + tmp[2] + tmp[3] + tmp[4] + tmp[5] + tmp[6] + tmp[7] +
|
||
tmp[8] + tmp[9];
|
||
|
||
/* saturate */
|
||
if ( diff > 32767 ) {
|
||
diff = 32767;
|
||
}
|
||
|
||
/* Compute hangover */
|
||
st->hangVar += 1;
|
||
|
||
if ( diff <= 5325 ) {
|
||
st->hangVar = 0;
|
||
}
|
||
|
||
if ( st->hangVar > 10 ) {
|
||
/* Speech period, reset hangover variable */
|
||
st->hangCount = 0;
|
||
}
|
||
|
||
/* Compute mix constant (bgMix) */
|
||
bgMix = 8192;
|
||
|
||
/* MR475, MR515, MR59, MR67, MR102 */
|
||
if ( ( mode <= MR67 ) | ( mode == MR102 ) ) {
|
||
/* disable mix if too short time since */
|
||
if ( ( st->hangCount >= 40 ) & ( diff <= 5325 ) ) /* 0.65 in Q13 */ {
|
||
/* if errors and presumed noise make smoothing probability stronger */
|
||
if ( ( ( ( ( pdfi != 0 ) & ( prev_pdf != 0 ) ) | ( bfi != 0 ) | (
|
||
prev_bf != 0 ) ) & ( ( voicedHangover > 1 ) ) & (
|
||
inBackgroundNoise != 0 ) & ( mode < MR67 ) ) ) {
|
||
/* bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25; */
|
||
tmp_diff = diff - 4506; /* 0.55 in Q13 */
|
||
|
||
/* max(0.0, diff-0.55) */
|
||
tmp1 = 0;
|
||
|
||
if ( tmp_diff > 0 ) {
|
||
tmp1 = tmp_diff;
|
||
}
|
||
|
||
/* min(0.25, tmp1) */
|
||
if ( 2048 >= tmp1 ) {
|
||
bgMix = tmp1 << 2;
|
||
}
|
||
}
|
||
else {
|
||
/* bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25; */
|
||
tmp_diff = diff - 3277; /* 0.4 in Q13 */
|
||
|
||
/* max(0.0, diff-0.40) */
|
||
tmp1 = 0;
|
||
|
||
if ( tmp_diff > 0 ) {
|
||
tmp1 = tmp_diff;
|
||
}
|
||
|
||
/* min(0.25, tmp1) */
|
||
if ( 2048 >= tmp1 ) {
|
||
bgMix = tmp1 << 2;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Smoothen the cb gain trajectory
|
||
* smoothing depends on mix constant bgMix
|
||
*/
|
||
sum = st->cbGainHistory[2] + st->cbGainHistory[3] + st->cbGainHistory[4] +
|
||
st->cbGainHistory[5] + st->cbGainHistory[6];
|
||
|
||
if ( sum > 163822 ) {
|
||
cbGainMean = 32767;
|
||
}
|
||
else {
|
||
cbGainMean = ( 3277 * sum + 0x00002000L ) >> 14; /* Q1 */
|
||
}
|
||
|
||
/* more smoothing in error and bg noise (NB no DFI used here) */
|
||
if ( ( ( bfi != 0 ) | ( prev_bf != 0 ) ) & ( inBackgroundNoise != 0 ) & (
|
||
mode < MR67 ) ) {
|
||
sum = 9362 * ( st->cbGainHistory[0] + st->cbGainHistory[1] + st->
|
||
cbGainHistory[2] + st->cbGainHistory[3] + st->cbGainHistory[4] +
|
||
st->cbGainHistory[5] + st->cbGainHistory[6] );
|
||
cbGainMean = ( sum + 0x00008000L ) >> 16; /* Q1 */
|
||
}
|
||
|
||
/* cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean; */
|
||
sum = bgMix * cbGainMix; /* sum in Q14 */
|
||
sum += cbGainMean << 13;
|
||
sum -= bgMix * cbGainMean;
|
||
cbGainMix = ( sum + 0x00001000L ) >> 13;
|
||
|
||
/* Q1 */
|
||
}
|
||
st->hangCount += 1;
|
||
if (st->hangCount & 0x80000000)
|
||
st->hangCount = 40;
|
||
return cbGainMix;
|
||
}
|
||
|
||
|
||
/*
|
||
* ph_disp
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state->gainMem B: LTP gain memory
|
||
* state->prevCbGain B: Codebook gain memory
|
||
* mode I: AMR mode
|
||
* x B: LTP excitation signal -> total excitation signal
|
||
* cbGain I: Codebook gain
|
||
* ltpGain I: LTP gain
|
||
* inno B: Innovation vector
|
||
* pitch_fac I: pitch factor used to scale the LTP excitation
|
||
* tmp_shift I: shift factor applied to sum of scaled LTP ex & innov.
|
||
* before rounding
|
||
*
|
||
* Function:
|
||
* Adaptive phase dispersion; forming of total excitation
|
||
*
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void ph_disp( ph_dispState *state, enum Mode mode, Word32 x[],
|
||
Word32 cbGain, Word32 ltpGain, Word32 inno[],
|
||
Word32 pitch_fac, Word32 tmp_shift)
|
||
{
|
||
Word32 inno_sav[L_SUBFR], ps_poss[L_SUBFR];
|
||
Word32 i, i1, impNr, temp1, temp2, j, nze, nPulse, ppos;
|
||
const Word32 *ph_imp; /* Pointer to phase dispersion filter */
|
||
|
||
|
||
/* Update LTP gain memory */
|
||
state->gainMem[4] = state->gainMem[3];
|
||
state->gainMem[3] = state->gainMem[2];
|
||
state->gainMem[2] = state->gainMem[1];
|
||
state->gainMem[1] = state->gainMem[0];
|
||
state->gainMem[0] = ltpGain;
|
||
|
||
/* basic adaption of phase dispersion */
|
||
/* no dispersion */
|
||
impNr = 2;
|
||
|
||
/* if (ltpGain < 0.9) */
|
||
if ( ltpGain < PHDTHR2LTP ) {
|
||
/* maximum dispersion */
|
||
impNr = 0;
|
||
|
||
/* if (ltpGain > 0.6 */
|
||
if ( ltpGain > PHDTHR1LTP ) {
|
||
/* medium dispersion */
|
||
impNr = 1;
|
||
}
|
||
}
|
||
|
||
/* onset indicator */
|
||
/* onset = (cbGain > onFact * cbGainMem[0]) */
|
||
temp1 = ( ( state->prevCbGain * ONFACTPLUS1 ) + 0x1000 ) >> 13;
|
||
|
||
if ( cbGain > temp1 ) {
|
||
state->onset = ONLENGTH;
|
||
}
|
||
else {
|
||
if ( state->onset > 0 ) {
|
||
state->onset--;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* if not onset, check ltpGain buffer and use max phase dispersion if
|
||
* half or more of the ltpGain-parameters say so
|
||
*/
|
||
if ( state->onset == 0 ) {
|
||
/* Check LTP gain memory and set filter accordingly */
|
||
i1 = 0;
|
||
|
||
for ( i = 0; i < PHDGAINMEMSIZE; i++ ) {
|
||
if ( state->gainMem[i] < PHDTHR1LTP ) {
|
||
i1++;
|
||
}
|
||
}
|
||
|
||
if ( i1 > 2 ) {
|
||
impNr = 0;
|
||
}
|
||
}
|
||
|
||
/* Restrict decrease in phase dispersion to one step if not onset */
|
||
if ( ( impNr > ( state->prevState + 1 ) ) & ( state->onset == 0 ) ) {
|
||
impNr--;
|
||
}
|
||
|
||
/* if onset, use one step less phase dispersion */
|
||
if ( ( impNr<2 )&( state->onset>0 ) ) {
|
||
impNr++;
|
||
}
|
||
|
||
/* disable for very low levels */
|
||
if ( cbGain < 10 ) {
|
||
impNr = 2;
|
||
}
|
||
|
||
if ( state->lockFull == 1 ) {
|
||
impNr = 0;
|
||
}
|
||
|
||
/* update static memory */
|
||
state->prevState = impNr;
|
||
state->prevCbGain = cbGain;
|
||
|
||
/*
|
||
* do phase dispersion for all modes but 12.2 and 7.4;
|
||
* don't modify the innovation if impNr >=2 (= no phase disp)
|
||
*/
|
||
if ( ( mode != MR122 ) & ( mode != MR102 ) & ( mode != MR74 ) & ( impNr < 2 )
|
||
) {
|
||
/*
|
||
* track pulse positions, save innovation,
|
||
* and initialize new innovation
|
||
*/
|
||
nze = 0;
|
||
|
||
for ( i = 0; i < L_SUBFR; i++ ) {
|
||
if ( inno[i] != 0 ) {
|
||
ps_poss[nze] = i;
|
||
nze++;
|
||
}
|
||
}
|
||
memcpy( inno_sav, inno, L_SUBFR <<2 );
|
||
memset( inno, 0, L_SUBFR <<2 );
|
||
|
||
/* Choose filter corresponding to codec mode and dispersion criterium */
|
||
ph_imp = ph_imp_mid;
|
||
|
||
if ( impNr == 0 ) {
|
||
ph_imp = ph_imp_low;
|
||
}
|
||
|
||
if ( mode == MR795 ) {
|
||
ph_imp = ph_imp_mid_MR795;
|
||
|
||
if ( impNr == 0 ) {
|
||
ph_imp = ph_imp_low_MR795;
|
||
}
|
||
}
|
||
|
||
/* Do phase dispersion of innovation */
|
||
for ( nPulse = 0; nPulse < nze; nPulse++ ) {
|
||
ppos = ps_poss[nPulse];
|
||
|
||
/* circular convolution with impulse response */
|
||
j = 0;
|
||
|
||
for ( i = ppos; i < L_SUBFR; i++ ) {
|
||
/* inno[i1] += inno_sav[ppos] * ph_imp[i1-ppos] */
|
||
temp1 = ( inno_sav[ppos] * ph_imp[j++] ) >> 15;
|
||
inno[i] = inno[i] + temp1;
|
||
}
|
||
|
||
for ( i = 0; i < ppos; i++ ) {
|
||
/* inno[i] += inno_sav[ppos] * ph_imp[L_SUBFR-ppos+i] */
|
||
temp1 = ( inno_sav[ppos] * ph_imp[j++] ) >> 15;
|
||
inno[i] = inno[i] + temp1;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* compute total excitation for synthesis part of decoder
|
||
* (using modified innovation if phase dispersion is active)
|
||
*/
|
||
for ( i = 0; i < L_SUBFR; i++ ) {
|
||
/* x[i] = gain_pit*x[i] + cbGain*code[i]; */
|
||
temp1 = x[i] * pitch_fac + inno[i] * cbGain;
|
||
temp2 = temp1 << tmp_shift;
|
||
x[i] = ( temp2 + 0x4000 ) >> 15;
|
||
if (labs(x[i]) > 32767)
|
||
{
|
||
if ((temp1 ^ temp2) & 0x80000000) {
|
||
x[i] = (temp1 & 0x80000000) ? -32768: 32767;
|
||
}
|
||
else {
|
||
x[i] = (temp2 & 0x80000000) ? -32768: 32767;
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* sqrt_l_exp
|
||
*
|
||
*
|
||
* Parameters:
|
||
* x I: input value
|
||
* exp O: right shift to be applied to result
|
||
*
|
||
* Function:
|
||
* Sqrt with exponent value.
|
||
*
|
||
* y = sqrt(x)
|
||
* x = f * 2^-e, 0.5 <= f < 1 (normalization)
|
||
* y = sqrt(f) * 2^(-e/2)
|
||
*
|
||
* a) e = 2k --> y = sqrt(f) * 2^-k
|
||
* (k = e div 2, 0.707 <= sqrt(f) < 1)
|
||
* b) e = 2k+1 --> y = sqrt(f/2) * 2^-k
|
||
* (k = e div 2, 0.5 <= sqrt(f/2) < 0.707)
|
||
*
|
||
*
|
||
* Returns:
|
||
* y output value
|
||
*/
|
||
static Word32 sqrt_l_exp( Word32 x, Word32 *exp )
|
||
{
|
||
Word32 y, a, i, tmp;
|
||
int e;
|
||
|
||
|
||
if ( x <= ( Word32 )0 ) {
|
||
*exp = 0;
|
||
return( Word32 )0;
|
||
}
|
||
e=0;
|
||
if (x != 0){
|
||
tmp = x;
|
||
while (!(tmp & 0x40000000))
|
||
{
|
||
e++;
|
||
tmp = tmp << 1;
|
||
}
|
||
}
|
||
e = e & 0xFFFE;
|
||
x = ( x << e );
|
||
*exp = ( Word16 )e;
|
||
x = ( x >> 9 );
|
||
i = ( Word16 )( x >> 16 );
|
||
x = ( x >> 1 );
|
||
a = x & ( Word16 )0x7fff;
|
||
i = ( i - 16 );
|
||
y = ( sqrt_table[i] << 16 );
|
||
tmp = ( sqrt_table[i] - sqrt_table[i + 1] );
|
||
y -= ( tmp * a ) << 1;
|
||
return( y );
|
||
}
|
||
|
||
|
||
/*
|
||
* Ex_ctrl
|
||
*
|
||
*
|
||
* Parameters:
|
||
* excitation B: Current subframe excitation
|
||
* excEnergy I: Exc. Energy, sqrt(totEx*totEx)
|
||
* exEnergyHist I: History of subframe energies
|
||
* voicedHangover I: number of frames after last voiced frame
|
||
* prevBFI I: Set i previous bad frame indicators
|
||
* carefulFlag I: Restrict dymamic in scaling
|
||
*
|
||
* Function:
|
||
* Charaterice synthesis speech and detect background noise
|
||
*
|
||
* Returns:
|
||
* background noise decision; 0 = no bgn, 1 = bgn
|
||
*/
|
||
static Word16 Ex_ctrl( Word32 excitation[], Word32 excEnergy, Word32
|
||
exEnergyHist[], Word32 voicedHangover, Word16 prevBFI, Word16 carefulFlag
|
||
)
|
||
{
|
||
Word32 i, testEnergy, scaleFactor, avgEnergy, prevEnergy, T0;
|
||
int exp;
|
||
|
||
|
||
/* get target level */
|
||
avgEnergy = gmed_n( exEnergyHist, 9 );
|
||
prevEnergy = ( exEnergyHist[7] + exEnergyHist[8] ) >> 1;
|
||
|
||
if ( exEnergyHist[8] < prevEnergy ) {
|
||
prevEnergy = exEnergyHist[8];
|
||
}
|
||
|
||
/* upscaling to avoid too rapid energy rises for some cases */
|
||
if ( ( excEnergy<avgEnergy )&( excEnergy>5 ) ) {
|
||
/* testEnergy = 4*prevEnergy; */
|
||
testEnergy = prevEnergy << 2;
|
||
|
||
if ( ( voicedHangover < 7 ) || prevBFI != 0 ) {
|
||
/* testEnergy = 3*prevEnergy */
|
||
testEnergy = testEnergy - prevEnergy;
|
||
}
|
||
|
||
if ( avgEnergy > testEnergy ) {
|
||
avgEnergy = testEnergy;
|
||
}
|
||
|
||
/* scaleFactor=avgEnergy/excEnergy in Q0 */
|
||
exp=0;
|
||
if (excEnergy != 0){
|
||
while (!(excEnergy & 0x4000))
|
||
{
|
||
exp++;
|
||
excEnergy = excEnergy << 1;
|
||
}
|
||
}
|
||
excEnergy = 536838144 / excEnergy;
|
||
T0 = ( avgEnergy * excEnergy ) << 1;
|
||
T0 = ( T0 >> ( 20 - exp ) );
|
||
|
||
if ( T0 > 32767 ) {
|
||
/* saturate */
|
||
T0 = 32767;
|
||
}
|
||
scaleFactor = T0;
|
||
|
||
/* test if scaleFactor > 3.0 */
|
||
if ( ( carefulFlag != 0 ) & ( scaleFactor > 3072 ) ) {
|
||
scaleFactor = 3072;
|
||
}
|
||
|
||
/* scale the excitation by scaleFactor */
|
||
for ( i = 0; i < L_SUBFR; i++ ) {
|
||
T0 = ( scaleFactor * excitation[i] ) << 1;
|
||
T0 = ( T0 >> 11 );
|
||
excitation[i] = T0;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*
|
||
* Inv_sqrt
|
||
*
|
||
*
|
||
* Parameters:
|
||
* x I: input value
|
||
*
|
||
* Function:
|
||
* 1/sqrt(x)
|
||
*
|
||
* Returns:
|
||
* y 1/sqrt(x)
|
||
*/
|
||
static Word32 Inv_sqrt( Word32 x )
|
||
{
|
||
int i, a, tmp, exp;
|
||
Word32 y;
|
||
|
||
|
||
if ( x <= ( Word32 )0 )
|
||
return( ( Word32 )0x3fffffffL );
|
||
exp=0;
|
||
while (!(x & 0x40000000))
|
||
{
|
||
exp++;
|
||
x = x << 1;
|
||
}
|
||
|
||
/* x is normalized */
|
||
exp = ( 30 - exp );
|
||
|
||
/* If exponent even -> shift right */
|
||
if ( ( exp & 1 ) == 0 ) {
|
||
x = ( x >> 1 );
|
||
}
|
||
exp = ( exp >> 1 );
|
||
exp = ( exp + 1 );
|
||
x = ( x >> 9 );
|
||
|
||
/* Extract b25-b31 */
|
||
i = ( Word16 )( x >> 16 );
|
||
|
||
/* Extract b10-b24 */
|
||
x = ( x >> 1 );
|
||
a = x & ( Word16 )0x7fff;
|
||
i = ( i - 16 );
|
||
|
||
/* table[i] << 16 */
|
||
y = inv_sqrt_table[i] << 16;
|
||
|
||
/* table[i] - table[i+1]) */
|
||
tmp = ( inv_sqrt_table[i] - inv_sqrt_table[i + 1] );
|
||
|
||
/* y -= tmp*a*2 */
|
||
y -= ( tmp * a ) << 1;
|
||
|
||
/* denormalization */
|
||
y = ( y >> exp );
|
||
return( y );
|
||
}
|
||
|
||
|
||
/*
|
||
* energy_old
|
||
*
|
||
*
|
||
* Parameters:
|
||
* in I: input value
|
||
*
|
||
* Function:
|
||
* Energy of signal
|
||
*
|
||
* Returns:
|
||
* Energy
|
||
*/
|
||
static Word32 energy_old( Word32 in[] )
|
||
{
|
||
Word32 temp, i, sum = 0;
|
||
|
||
|
||
for ( i = 0; i < L_SUBFR; i += 8 ) {
|
||
temp = in[i] >> 2;
|
||
sum += temp * temp;
|
||
temp = in[i + 1] >> 2;
|
||
sum += temp * temp;
|
||
temp = in[i + 2] >> 2;
|
||
sum += temp * temp;
|
||
temp = in[i + 3] >> 2;
|
||
sum += temp * temp;
|
||
temp = in[i + 4] >> 2;
|
||
sum += temp * temp;
|
||
temp = in[i + 5] >> 2;
|
||
sum += temp * temp;
|
||
temp = in[i + 6] >> 2;
|
||
sum += temp * temp;
|
||
temp = in[i + 7] >> 2;
|
||
sum += temp * temp;
|
||
}
|
||
|
||
if ( sum & 0xC0000000 ) {
|
||
return 0x7FFFFFFF;
|
||
}
|
||
return( sum << 1 );
|
||
}
|
||
|
||
|
||
/*
|
||
* energy_new
|
||
*
|
||
*
|
||
* Parameters:
|
||
* in I: input value
|
||
*
|
||
* Function:
|
||
* Energy of signal
|
||
*
|
||
* Returns:
|
||
* Energy
|
||
*/
|
||
static Word32 energy_new( Word32 in[] )
|
||
{
|
||
Word32 i, s = 0, overflow = 0;
|
||
|
||
s += in[0] * in[0];
|
||
for ( i = 1; i < L_SUBFR; i += 3 ) {
|
||
s += in[i] * in[i];
|
||
s += in[i + 1] *in[i + 1];
|
||
s += in[i + 2] * in[i + 2];
|
||
|
||
|
||
if ( s & 0xC0000000 ) {
|
||
overflow = 1;
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* check for overflow */
|
||
if ( overflow ) {
|
||
s = energy_old( in );
|
||
}
|
||
else {
|
||
s = ( s >> 3 );
|
||
}
|
||
return s;
|
||
}
|
||
|
||
|
||
/*
|
||
* agc2
|
||
*
|
||
*
|
||
* Parameters:
|
||
* sig_in I: Post_Filter input signal
|
||
* sig_out B: Post_Filter output signal
|
||
*
|
||
* Function:
|
||
* Scales the excitation on a subframe basis
|
||
*
|
||
* Returns:
|
||
* Energy
|
||
*/
|
||
static void agc2( Word32 *sig_in, Word32 *sig_out )
|
||
{
|
||
Word32 s;
|
||
int i, exp;
|
||
Word16 gain_in, gain_out, g0;
|
||
|
||
|
||
/* calculate gain_out with exponent */
|
||
s = energy_new( sig_out );
|
||
|
||
if ( s == 0 ) {
|
||
return;
|
||
}
|
||
exp=0;
|
||
while (!(s & 0x20000000))
|
||
{
|
||
exp++;
|
||
s = s << 1;
|
||
}
|
||
|
||
gain_out = ( Word16 )( ( s + 0x00008000L ) >> 16 );
|
||
|
||
/* calculate gain_in with exponent */
|
||
s = energy_new( sig_in );
|
||
|
||
if ( s == 0 ) {
|
||
g0 = 0;
|
||
}
|
||
else {
|
||
i = 0;
|
||
while (!(s & 0x40000000))
|
||
{
|
||
i++;
|
||
s = s << 1;
|
||
}
|
||
|
||
if ( s < 0x7fff7fff )
|
||
gain_in = ( Word16 )( ( s + 0x00008000L ) >> 16 );
|
||
else
|
||
gain_in = 32767;
|
||
exp = ( exp - i );
|
||
|
||
/*
|
||
* g0 = sqrt(gain_in/gain_out);
|
||
*/
|
||
/* s = gain_out / gain_in */
|
||
s = ( gain_out << 15 ) / gain_in;
|
||
s = ( s << 7 );
|
||
|
||
if ( exp > 0 )
|
||
s = ( s >> exp );
|
||
else
|
||
s = ( s << ( -exp ) );
|
||
s = Inv_sqrt( s );
|
||
g0 = ( Word16 )( ( ( s << 9 ) + 0x00008000L ) >> 16 );
|
||
}
|
||
|
||
/* sig_out(n) = gain(n) * sig_out(n) */
|
||
for ( i = 0; i < L_SUBFR; i++ ) {
|
||
sig_out[i] = ( sig_out[i] * g0 ) >> 12;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Bgn_scd
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->frameEnergyHist B: Frame Energy memory
|
||
* st->bgHangover B: Background hangover counter
|
||
* ltpGainHist I: LTP gain history
|
||
* speech I: synthesis speech frame
|
||
* voicedHangover O: number of frames after last voiced frame
|
||
*
|
||
* Function:
|
||
* Charaterice synthesis speech and detect background noise
|
||
*
|
||
* Returns:
|
||
* inbgNoise background noise decision; 0 = no bgn, 1 = bgn
|
||
*/
|
||
static Word16 Bgn_scd( Bgn_scdState *st, Word32 ltpGainHist[], Word32 speech[],
|
||
Word32 *voicedHangover )
|
||
{
|
||
Word32 temp, ltpLimit, frame_energyMin, currEnergy, noiseFloor, maxEnergy,
|
||
maxEnergyLastPart, s, i;
|
||
Word16 prevVoiced, inbgNoise;
|
||
|
||
|
||
/*
|
||
* Update the inBackgroundNoise flag (valid for use in next frame if BFI)
|
||
* it now works as a energy detector floating on top
|
||
* not as good as a VAD.
|
||
*/
|
||
s = 0;
|
||
|
||
for ( i = 0; i < L_FRAME; i++ ) {
|
||
s += speech[i] * speech[i];
|
||
}
|
||
|
||
if ( (s < 0xFFFFFFF) & (s >= 0) )
|
||
currEnergy = s >> 13;
|
||
else
|
||
currEnergy = 32767;
|
||
frame_energyMin = 32767;
|
||
|
||
for ( i = 0; i < L_ENERGYHIST; i++ ) {
|
||
if ( st->frameEnergyHist[i] < frame_energyMin )
|
||
frame_energyMin = st->frameEnergyHist[i];
|
||
}
|
||
|
||
/* Frame Energy Margin of 16 */
|
||
noiseFloor = frame_energyMin << 4;
|
||
maxEnergy = st->frameEnergyHist[0];
|
||
|
||
for ( i = 1; i < L_ENERGYHIST - 4; i++ ) {
|
||
if ( maxEnergy < st->frameEnergyHist[i] ) {
|
||
maxEnergy = st->frameEnergyHist[i];
|
||
}
|
||
}
|
||
maxEnergyLastPart = st->frameEnergyHist[2 * L_ENERGYHIST / 3];
|
||
|
||
for ( i = 2 * L_ENERGYHIST / 3 + 1; i < L_ENERGYHIST; i++ ) {
|
||
if ( maxEnergyLastPart < st->frameEnergyHist[i] ) {
|
||
maxEnergyLastPart = st->frameEnergyHist[i];
|
||
}
|
||
}
|
||
|
||
/* false */
|
||
inbgNoise = 0;
|
||
|
||
/*
|
||
* Do not consider silence as noise
|
||
* Do not consider continuous high volume as noise
|
||
* Or if the current noise level is very low
|
||
* Mark as noise if under current noise limit
|
||
* OR if the maximum energy is below the upper limit
|
||
*/
|
||
if ( ( maxEnergy> LOWERNOISELIMIT )&( currEnergy<FRAMEENERGYLIMIT )&(
|
||
currEnergy>LOWERNOISELIMIT ) & ( ( currEnergy < noiseFloor ) || (
|
||
maxEnergyLastPart < UPPERNOISELIMIT ) ) ) {
|
||
if ( ( st->bgHangover + 1 ) > 30 ) {
|
||
st->bgHangover = 30;
|
||
}
|
||
else {
|
||
st->bgHangover += 1;
|
||
}
|
||
}
|
||
else {
|
||
st->bgHangover = 0;
|
||
}
|
||
|
||
/* make final decision about frame state, act somewhat cautiosly */
|
||
if ( st->bgHangover > 1 )
|
||
inbgNoise = 1; /* true */
|
||
|
||
for ( i = 0; i < L_ENERGYHIST - 1; i++ ) {
|
||
st->frameEnergyHist[i] = st->frameEnergyHist[i + 1];
|
||
}
|
||
st->frameEnergyHist[L_ENERGYHIST - 1] = currEnergy;
|
||
|
||
/*
|
||
* prepare for voicing decision;
|
||
* tighten the threshold after some time in noise
|
||
*/
|
||
ltpLimit = 13926; /* 0.85 Q14 */
|
||
|
||
if ( st->bgHangover > 8 ) {
|
||
ltpLimit = 15565; /* 0.95 Q14 */
|
||
}
|
||
|
||
if ( st->bgHangover > 15 ) {
|
||
ltpLimit = 16383; /* 1.00 Q14 */
|
||
}
|
||
|
||
/* weak sort of voicing indication. */
|
||
prevVoiced = 0; /* false */
|
||
|
||
if ( gmed_n( <pGainHist[4], 5 ) > ltpLimit ) {
|
||
prevVoiced = 1; /* true */
|
||
}
|
||
|
||
if ( st->bgHangover > 20 ) {
|
||
if ( gmed_n( ltpGainHist, 9 ) > ltpLimit ) {
|
||
prevVoiced = 1; /* true */
|
||
}
|
||
else {
|
||
prevVoiced = 0; /* false */
|
||
}
|
||
}
|
||
|
||
if ( prevVoiced ) {
|
||
*voicedHangover = 0;
|
||
}
|
||
else {
|
||
temp = *voicedHangover + 1;
|
||
|
||
if ( temp > 10 ) {
|
||
*voicedHangover = 10;
|
||
}
|
||
else {
|
||
*voicedHangover = temp;
|
||
}
|
||
}
|
||
return inbgNoise;
|
||
}
|
||
|
||
|
||
/*
|
||
* dtx_dec_activity_update
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->lsf_hist_ptr B: LSF history pointer
|
||
* st->lsf_hist B: LSF history
|
||
* lsf I: lsf
|
||
* frame I: noise frame
|
||
*
|
||
* Function:
|
||
* Update lsp history and compute log energy.
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void dtx_dec_activity_update( dtx_decState *st, Word32 lsf[], Word32
|
||
frame[] )
|
||
{
|
||
Word32 frame_en;
|
||
Word32 log_en_e, log_en_m, log_en, i;
|
||
|
||
|
||
/* update lsp history */
|
||
st->lsf_hist_ptr += M;
|
||
|
||
if ( st->lsf_hist_ptr == 80 ) {
|
||
st->lsf_hist_ptr = 0;
|
||
}
|
||
memcpy( &st->lsf_hist[st->lsf_hist_ptr], lsf, M <<2 );
|
||
|
||
/* compute log energy based on frame energy */
|
||
frame_en = 0; /* Q0 */
|
||
|
||
for ( i = 0; (i < L_FRAME); i ++ ) {
|
||
frame_en += frame[i] * frame[i];
|
||
if (frame_en & 0x80000000)
|
||
break;
|
||
}
|
||
|
||
log_en = (frame_en & 0xC0000000) ? 0x7FFFFFFE: (Word32)frame_en << 1;
|
||
|
||
Log2( log_en , &log_en_e, &log_en_m );
|
||
|
||
/* convert exponent and mantissa to Word16 Q10 */
|
||
log_en = log_en_e << 10; /* Q10 */
|
||
log_en = log_en + ( log_en_m >> 5 );
|
||
|
||
/* divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193 */
|
||
log_en = log_en - 8521;
|
||
|
||
/*
|
||
* insert into log energy buffer, no division by two as
|
||
* log_en in decoder is Q11
|
||
*/
|
||
st->log_en_hist_ptr += 1;
|
||
|
||
if ( st->log_en_hist_ptr == DTX_HIST_SIZE ) {
|
||
st->log_en_hist_ptr = 0;
|
||
}
|
||
st->log_en_hist[st->log_en_hist_ptr] = log_en; /* Q11 */
|
||
}
|
||
|
||
|
||
/*
|
||
* Decoder_amr
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st B: State variables
|
||
* mode I: AMR mode
|
||
* parm I: vector of synthesis parameters
|
||
* frame_type I: received frame type
|
||
* synth O: synthesis speech
|
||
* A_t O: decoded LP filter in 4 subframes
|
||
*
|
||
* Function:
|
||
* Speech decoder routine
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Decoder_amr( Decoder_amrState *st, enum Mode mode, Word16 parm[],
|
||
enum RXFrameType frame_type, Word32 synth[], Word32 A_t[] )
|
||
{
|
||
/* LSPs */
|
||
Word32 lsp_new[M];
|
||
Word32 lsp_mid[M];
|
||
|
||
|
||
/* LSFs */
|
||
Word32 prev_lsf[M];
|
||
Word32 lsf_i[M];
|
||
|
||
|
||
/* Algebraic codevector */
|
||
Word32 code[L_SUBFR];
|
||
|
||
|
||
/* excitation */
|
||
Word32 excp[L_SUBFR];
|
||
Word32 exc_enhanced[L_SUBFR];
|
||
|
||
|
||
/* Scalars */
|
||
Word32 i, i_subfr, overflow, T0_frac, index, temp, temp2, subfrNr, excEnergy;
|
||
Word32 gain_code, gain_code_mix, pit_sharp, pit_flag, pitch_fac, t0_min, t0_max;
|
||
Word32 gain_pit = 0, evenSubfr = 0, T0 = 0, index_mr475 = 0;
|
||
Word32 *Az; /* Pointer on A_t */
|
||
Word16 flag4, carefulFlag;
|
||
Word16 delta_frc_low, delta_frc_range, tmp_shift;
|
||
Word16 bfi = 0, pdfi = 0;
|
||
/* bad frame indication flag, potential degraded bad frame flag */
|
||
|
||
|
||
enum DTXStateType newDTXState; /* SPEECH , DTX, DTX_MUTE */
|
||
|
||
/* find the new DTX state SPEECH OR DTX */
|
||
newDTXState = rx_dtx_handler( st->dtxDecoderState, frame_type );
|
||
|
||
/* DTX actions */
|
||
if ( newDTXState != SPEECH ) {
|
||
Decoder_amr_reset( st, MRDTX );
|
||
dtx_dec( st->dtxDecoderState, st->mem_syn, st->lsfState, st->pred_state,
|
||
st->Cb_gain_averState, newDTXState, mode, parm, synth, A_t );
|
||
|
||
/* update average lsp */
|
||
Lsf_lsp( st->lsfState->past_lsf_q, st->lsp_old );
|
||
lsp_avg( st->lsp_avg_st, st->lsfState->past_lsf_q );
|
||
goto theEnd;
|
||
}
|
||
|
||
/* SPEECH action state machine */
|
||
if ( table_speech_bad[frame_type] ) {
|
||
bfi = 1;
|
||
|
||
if ( frame_type != RX_SPEECH_BAD ) {
|
||
Build_CN_param( &st->nodataSeed, mode, parm );
|
||
}
|
||
}
|
||
else if ( frame_type == RX_SPEECH_DEGRADED ) {
|
||
pdfi = 1;
|
||
}
|
||
|
||
if ( bfi != 0 ) {
|
||
st->state += 1;
|
||
}
|
||
else if ( st->state == 6 ) {
|
||
st->state = 5;
|
||
}
|
||
else {
|
||
st->state = 0;
|
||
}
|
||
|
||
if ( st->state > 6 ) {
|
||
st->state = 6;
|
||
}
|
||
|
||
/*
|
||
* If this frame is the first speech frame after CNI period,
|
||
* set the BFH state machine to an appropriate state depending
|
||
* on whether there was DTX muting before start of speech or not
|
||
* If there was DTX muting, the first speech frame is muted.
|
||
* If there was no DTX muting, the first speech frame is not
|
||
* muted. The BFH state machine starts from state 5, however, to
|
||
* keep the audible noise resulting from a SID frame which is
|
||
* erroneously interpreted as a good speech frame as small as
|
||
* possible (the decoder output in this case is quickly muted)
|
||
*/
|
||
if ( st->dtxDecoderState->dtxGlobalState == DTX ) {
|
||
st->state = 5;
|
||
st->prev_bf = 0;
|
||
}
|
||
else if ( st->dtxDecoderState->dtxGlobalState == DTX_MUTE ) {
|
||
st->state = 5;
|
||
st->prev_bf = 1;
|
||
}
|
||
|
||
/* save old LSFs for CB gain smoothing */
|
||
memcpy( prev_lsf, st->lsfState->past_lsf_q, M <<2 );
|
||
|
||
/*
|
||
* decode LSF parameters and generate interpolated lpc coefficients
|
||
* for the 4 subframes
|
||
*/
|
||
if ( mode != MR122 ) {
|
||
D_plsf_3( st->lsfState, mode, bfi, parm, lsp_new );
|
||
|
||
/* Advance synthesis parameters pointer */
|
||
parm += 3;
|
||
Int_lpc_1to3( st->lsp_old, lsp_new, A_t );
|
||
}
|
||
else {
|
||
D_plsf_5( st->lsfState, bfi, parm, lsp_mid, lsp_new );
|
||
|
||
/* Advance synthesis parameters pointer */
|
||
parm += 5;
|
||
Int_lpc_1and3( st->lsp_old, lsp_mid, lsp_new, A_t );
|
||
}
|
||
|
||
/* update the LSPs for the next frame */
|
||
memcpy( st->lsp_old, lsp_new, M <<2 );
|
||
|
||
/*
|
||
* Loop for every subframe in the analysis frame
|
||
*
|
||
* The subframe size is L_SUBFR and the loop is repeated
|
||
* L_FRAME/L_SUBFR times *
|
||
* - decode the pitch delay
|
||
* - decode algebraic code
|
||
* - decode pitch and codebook gains
|
||
* - find the excitation and compute synthesis speech
|
||
*/
|
||
/* pointer to interpolated LPC parameters */
|
||
Az = A_t;
|
||
evenSubfr = 0;
|
||
subfrNr = -1;
|
||
|
||
for ( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) {
|
||
subfrNr += 1;
|
||
evenSubfr = 1 - evenSubfr;
|
||
|
||
/* flag for first and 3th subframe */
|
||
pit_flag = i_subfr;
|
||
|
||
if ( i_subfr == L_FRAME_BY2 ) {
|
||
if ( ( mode != MR475 ) & ( mode != MR515 ) ) {
|
||
pit_flag = 0;
|
||
}
|
||
}
|
||
|
||
/* pitch index */
|
||
index = *parm++;
|
||
|
||
/*
|
||
* decode pitch lag and find adaptive codebook vector.
|
||
*/
|
||
if ( mode != MR122 ) {
|
||
/*
|
||
* flag4 indicates encoding with 4 bit resolution;
|
||
* this is needed for mode MR475, MR515, MR59 and MR67
|
||
*/
|
||
flag4 = 0;
|
||
|
||
if ( ( mode == MR475 ) || ( mode == MR515 ) || ( mode == MR59 ) || (
|
||
mode == MR67 ) ) {
|
||
flag4 = 1;
|
||
}
|
||
|
||
/*
|
||
* get ranges for the t0_min and t0_max
|
||
* only needed in delta decoding
|
||
*/
|
||
delta_frc_low = 5;
|
||
delta_frc_range = 9;
|
||
|
||
if ( mode == MR795 ) {
|
||
delta_frc_low = 10;
|
||
delta_frc_range = 19;
|
||
}
|
||
t0_min = st->old_T0 - delta_frc_low;
|
||
|
||
if ( t0_min < PIT_MIN ) {
|
||
t0_min = PIT_MIN;
|
||
}
|
||
t0_max = t0_min + delta_frc_range;
|
||
|
||
if ( t0_max > PIT_MAX ) {
|
||
t0_max = PIT_MAX;
|
||
t0_min = t0_max - delta_frc_range;
|
||
}
|
||
Dec_lag3( index, t0_min, t0_max, pit_flag, st->old_T0, &T0, &T0_frac,
|
||
flag4 );
|
||
st->T0_lagBuff = T0;
|
||
|
||
if ( bfi != 0 ) {
|
||
if ( st->old_T0 < PIT_MAX ) {
|
||
/* Graceful pitch degradation */
|
||
st->old_T0 += 1;
|
||
}
|
||
T0 = st->old_T0;
|
||
T0_frac = 0;
|
||
|
||
if ( ( st->inBackgroundNoise != 0 ) & ( st->voicedHangover > 4 ) & (
|
||
( mode == MR475 ) || ( mode == MR515 ) || ( mode == MR59 ) ) )
|
||
{
|
||
T0 = st->T0_lagBuff;
|
||
}
|
||
}
|
||
Pred_lt_3or6_40( st->exc, T0, T0_frac, 1 );
|
||
}
|
||
else {
|
||
Dec_lag6( index, PIT_MIN_MR122, PIT_MAX, pit_flag, &T0, &T0_frac );
|
||
|
||
if ( ( bfi != 0 ) || ( ( pit_flag != 0 ) & ( index > 60 ) ) ) {
|
||
st->T0_lagBuff = T0;
|
||
T0 = st->old_T0;
|
||
T0_frac = 0;
|
||
}
|
||
Pred_lt_3or6_40( st->exc, T0, T0_frac, 0 );
|
||
}
|
||
|
||
/*
|
||
* (MR122 only: Decode pitch gain.)
|
||
* Decode innovative codebook.
|
||
* set pitch sharpening factor
|
||
*/
|
||
/* MR475, MR515 */
|
||
if ( ( mode == MR475 ) || ( mode == MR515 ) ) {
|
||
/* index of position */
|
||
index = *parm++;
|
||
|
||
/* signs */
|
||
i = *parm++;
|
||
decode_2i40_9bits( subfrNr, i, index, code );
|
||
pit_sharp = st->sharp << 1;
|
||
}
|
||
|
||
/* MR59 */
|
||
else if ( mode == MR59 ) {
|
||
/* index of position */
|
||
index = *parm++;
|
||
|
||
/* signs */
|
||
i = *parm++;
|
||
decode_2i40_11bits( i, index, code );
|
||
pit_sharp = st->sharp << 1;
|
||
}
|
||
|
||
/* MR67 */
|
||
else if ( mode == MR67 ) {
|
||
/* index of position */
|
||
index = *parm++;
|
||
|
||
/* signs */
|
||
i = *parm++;
|
||
decode_3i40_14bits( i, index, code );
|
||
pit_sharp = st->sharp << 1;
|
||
}
|
||
|
||
/* MR74, MR795 */
|
||
else if ( mode <= MR795 ) {
|
||
/* index of position */
|
||
index = *parm++;
|
||
|
||
/* signs */
|
||
i = *parm++;
|
||
decode_4i40_17bits( i, index, code );
|
||
pit_sharp = st->sharp << 1;
|
||
}
|
||
|
||
/* MR102 */
|
||
else if ( mode == MR102 ) {
|
||
decode_8i40_31bits( parm, code );
|
||
parm += 7;
|
||
pit_sharp = st->sharp << 1;
|
||
}
|
||
|
||
/* MR122 */
|
||
else {
|
||
index = *parm++;
|
||
|
||
if ( bfi != 0 ) {
|
||
ec_gain_pitch( st->ec_gain_p_st, st->state, &gain_pit );
|
||
}
|
||
else {
|
||
gain_pit = d_gain_pitch( mode, index );
|
||
}
|
||
ec_gain_pitch_update( st->ec_gain_p_st, bfi, st->prev_bf, &gain_pit );
|
||
decode_10i40_35bits( parm, code );
|
||
parm += 10;
|
||
|
||
/*
|
||
* pit_sharp = gain_pit;
|
||
* if (pit_sharp > 1.0) pit_sharp = 1.0;
|
||
*/
|
||
pit_sharp = gain_pit;
|
||
|
||
if ( pit_sharp > 16383 )
|
||
pit_sharp = 32767;
|
||
else
|
||
pit_sharp *= 2;
|
||
}
|
||
|
||
/*
|
||
* Add the pitch contribution to code[].
|
||
*/
|
||
for ( i = T0; i < L_SUBFR; i++ ) {
|
||
temp = ( code[i - T0] * pit_sharp ) >> 15;
|
||
code[i] = code[i] + temp;
|
||
}
|
||
|
||
/*
|
||
* Decode codebook gain (MR122) or both pitch
|
||
* gain and codebook gain (all others)
|
||
* Update pitch sharpening "sharp" with quantized gain_pit
|
||
*/
|
||
if ( mode == MR475 ) {
|
||
/* read and decode pitch and code gain */
|
||
if ( evenSubfr != 0 ) {
|
||
/* index of gain(s) */
|
||
index_mr475 = *parm++;
|
||
}
|
||
|
||
if ( bfi == 0 ) {
|
||
Dec_gain( st->pred_state, mode, index_mr475, code, evenSubfr, &
|
||
gain_pit, &gain_code );
|
||
}
|
||
else {
|
||
ec_gain_pitch( st->ec_gain_p_st, st->state, &gain_pit );
|
||
ec_gain_code( st->ec_gain_c_st, st->pred_state, st->state, &
|
||
gain_code );
|
||
}
|
||
ec_gain_pitch_update( st->ec_gain_p_st, bfi, st->prev_bf, &gain_pit );
|
||
ec_gain_code_update( st->ec_gain_c_st, bfi, st->prev_bf, &gain_code );
|
||
pit_sharp = gain_pit;
|
||
|
||
if ( pit_sharp > SHARPMAX ) {
|
||
pit_sharp = SHARPMAX;
|
||
}
|
||
}
|
||
else if ( ( mode <= MR74 ) || ( mode == MR102 ) ) {
|
||
/* read and decode pitch and code gain */
|
||
/* index of gain(s) */
|
||
index = *parm++;
|
||
|
||
if ( bfi == 0 ) {
|
||
Dec_gain( st->pred_state, mode, index, code, evenSubfr, &gain_pit, &
|
||
gain_code );
|
||
}
|
||
else {
|
||
ec_gain_pitch( st->ec_gain_p_st, st->state, &gain_pit );
|
||
ec_gain_code( st->ec_gain_c_st, st->pred_state, st->state, &
|
||
gain_code );
|
||
}
|
||
ec_gain_pitch_update( st->ec_gain_p_st, bfi, st->prev_bf, &gain_pit );
|
||
ec_gain_code_update( st->ec_gain_c_st, bfi, st->prev_bf, &gain_code );
|
||
pit_sharp = gain_pit;
|
||
|
||
if ( pit_sharp > SHARPMAX ) {
|
||
pit_sharp = SHARPMAX;
|
||
}
|
||
|
||
if ( mode == MR102 ) {
|
||
if ( st->old_T0 > ( L_SUBFR + 5 ) ) {
|
||
pit_sharp = pit_sharp >> 2;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
/* read and decode pitch gain */
|
||
/* index of gain(s) */
|
||
index = *parm++;
|
||
|
||
if ( mode == MR795 ) {
|
||
/* decode pitch gain */
|
||
if ( bfi != 0 ) {
|
||
ec_gain_pitch( st->ec_gain_p_st, st->state, &gain_pit );
|
||
}
|
||
else {
|
||
gain_pit = d_gain_pitch( mode, index );
|
||
}
|
||
ec_gain_pitch_update( st->ec_gain_p_st, bfi, st->prev_bf, &gain_pit
|
||
);
|
||
|
||
/* read and decode code gain */
|
||
index = *parm++;
|
||
|
||
if ( bfi == 0 ) {
|
||
d_gain_code( st->pred_state, mode, index, code, &gain_code );
|
||
}
|
||
else {
|
||
ec_gain_code( st->ec_gain_c_st, st->pred_state, st->state, &
|
||
gain_code );
|
||
}
|
||
ec_gain_code_update( st->ec_gain_c_st, bfi, st->prev_bf, &gain_code
|
||
);
|
||
pit_sharp = gain_pit;
|
||
|
||
if ( pit_sharp > SHARPMAX ) {
|
||
pit_sharp = SHARPMAX;
|
||
}
|
||
}
|
||
else { /* MR122 */
|
||
|
||
if ( bfi == 0 ) {
|
||
d_gain_code( st->pred_state, mode, index, code, &gain_code );
|
||
}
|
||
else {
|
||
ec_gain_code( st->ec_gain_c_st, st->pred_state, st->state, &
|
||
gain_code );
|
||
}
|
||
ec_gain_code_update( st->ec_gain_c_st, bfi, st->prev_bf, &gain_code
|
||
);
|
||
pit_sharp = gain_pit;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* store pitch sharpening for next subframe
|
||
* (for modes which use the previous pitch gain for
|
||
* pitch sharpening in the search phase)
|
||
* do not update sharpening in even subframes for MR475
|
||
*/
|
||
if ( ( mode != MR475 ) || evenSubfr == 0 ) {
|
||
st->sharp = gain_pit;
|
||
|
||
if ( st->sharp > SHARPMAX ) {
|
||
st->sharp = SHARPMAX;
|
||
}
|
||
}
|
||
|
||
if ( pit_sharp > 16383 )
|
||
pit_sharp = 32767;
|
||
else
|
||
pit_sharp *= 2;
|
||
|
||
if ( pit_sharp > 16384 ) {
|
||
for ( i = 0; i < L_SUBFR; i++ ) {
|
||
temp = ( st->exc[i] * pit_sharp ) >> 15;
|
||
temp2 = ( temp * gain_pit ) << 1;
|
||
|
||
if ( mode == MR122 ) {
|
||
temp2 = ( temp2 >> 1 );
|
||
}
|
||
excp[i] = ( temp2 + 0x00008000L ) >> 16;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Store list of LTP gains needed in the source
|
||
* characteristic detector (SCD)
|
||
*/
|
||
if ( bfi == 0 ) {
|
||
for (i = 0; i < 8; i++){
|
||
st->ltpGainHistory[i] = st->ltpGainHistory[i+1];
|
||
}
|
||
st->ltpGainHistory[8] = gain_pit;
|
||
}
|
||
|
||
|
||
/*
|
||
* Limit gain_pit if in background noise and BFI
|
||
* for MR475, MR515, MR59
|
||
*/
|
||
if ( ( st->prev_bf != 0 || bfi != 0 ) & ( st->inBackgroundNoise != 0 ) & (
|
||
( mode == MR475 ) || ( mode == MR515 ) || ( mode == MR59 ) ) ) {
|
||
/* if (gain_pit > 0.75) in Q14*/
|
||
if ( gain_pit > 12288 )
|
||
/* gain_pit = (gain_pit-0.75)/2.0 + 0.75; */
|
||
gain_pit = ( ( gain_pit - 12288 ) >> 1 ) + 12288;
|
||
|
||
/* if (gain_pit > 0.90) in Q14*/
|
||
if ( gain_pit > 14745 ) {
|
||
gain_pit = 14745;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Calculate CB mixed gain
|
||
*/
|
||
Int_lsf( prev_lsf, st->lsfState->past_lsf_q, i_subfr, lsf_i );
|
||
gain_code_mix = Cb_gain_average( st->Cb_gain_averState, mode, gain_code,
|
||
lsf_i, st->lsp_avg_st->lsp_meanSave, bfi, st->prev_bf, pdfi, st->
|
||
prev_pdf, st->inBackgroundNoise, st->voicedHangover );
|
||
|
||
/* make sure that MR74, MR795, MR122 have original codeGain*/
|
||
/* MR74, MR795, MR122 */
|
||
if ( ( mode > MR67 ) & ( mode != MR102 ) ) {
|
||
gain_code_mix = gain_code;
|
||
}
|
||
|
||
/*
|
||
* Find the total excitation.
|
||
* Find synthesis speech corresponding to st->exc[].
|
||
*/
|
||
/* MR475, MR515, MR59, MR67, MR74, MR795, MR102*/
|
||
if ( mode <= MR102 ) {
|
||
pitch_fac = gain_pit;
|
||
tmp_shift = 1;
|
||
}
|
||
|
||
/* MR122 */
|
||
else {
|
||
pitch_fac = gain_pit >> 1;
|
||
tmp_shift = 2;
|
||
}
|
||
|
||
/*
|
||
* copy unscaled LTP excitation to exc_enhanced (used in phase
|
||
* dispersion below) and compute total excitation for LTP feedback
|
||
*/
|
||
memcpy( exc_enhanced, st->exc, L_SUBFR <<2 );
|
||
|
||
for ( i = 0; i < L_SUBFR; i++ ) {
|
||
/* st->exc[i] = gain_pit*st->exc[i] + gain_code*code[i]; */
|
||
temp = ( st->exc[i] * pitch_fac ) + ( code[i] * gain_code );
|
||
temp2 = ( temp << tmp_shift );
|
||
if (((temp2 >> 1) ^ temp2) & 0x40000000) {
|
||
if ((temp ^ temp2) & 0x80000000) {
|
||
temp2 = (temp & 0x80000000) ? (-1073741824L) : 1073725439;
|
||
}
|
||
else {
|
||
temp2 = (temp2 & 0x80000000) ? (-1073741824L) : 1073725439;
|
||
}
|
||
}
|
||
st->exc[i] = ( temp2 + 0x00004000L ) >> 15;
|
||
}
|
||
/*
|
||
* Adaptive phase dispersion
|
||
*/
|
||
|
||
/* free phase dispersion adaption */
|
||
st->ph_disp_st->lockFull = 0;
|
||
|
||
if ( ( ( mode == MR475 ) || ( mode == MR515 ) || ( mode == MR59 ) ) & ( st
|
||
->voicedHangover > 3 ) & ( st->inBackgroundNoise != 0 ) & ( bfi != 0
|
||
) ) {
|
||
/*
|
||
* Always Use full Phase Disp.
|
||
* if error in bg noise
|
||
*/
|
||
st->ph_disp_st->lockFull = 1;
|
||
}
|
||
|
||
/*
|
||
* apply phase dispersion to innovation (if enabled) and
|
||
* compute total excitation for synthesis part
|
||
*/
|
||
ph_disp( st->ph_disp_st, mode, exc_enhanced, gain_code_mix, gain_pit, code
|
||
, pitch_fac, tmp_shift );
|
||
|
||
/*
|
||
* The Excitation control module are active during BFI.
|
||
* Conceal drops in signal energy if in bg noise.
|
||
*/
|
||
temp2 = 0;
|
||
|
||
for ( i = 0; i < L_SUBFR; i++ ) {
|
||
temp2 += ( exc_enhanced[i] * exc_enhanced[i] );
|
||
}
|
||
|
||
if ( temp2 > 0x3FFFFFFF ) {
|
||
excEnergy = 11584;
|
||
}
|
||
else {
|
||
temp2 = sqrt_l_exp( temp2, &temp );
|
||
temp2 = ( temp2 >> ( ( temp >> 1 ) + 15 ) );
|
||
excEnergy = temp2 >> 2;
|
||
}
|
||
|
||
if ( ( ( mode == MR475 ) || ( mode == MR515 ) || ( mode == MR59 ) ) & ( st
|
||
->voicedHangover > 5 ) & ( st->inBackgroundNoise != 0 ) & ( st->
|
||
state < 4 ) & ( ( ( pdfi != 0 ) & ( st->prev_pdf != 0 ) ) || bfi !=
|
||
0 || st->prev_bf != 0 ) ) {
|
||
carefulFlag = 0;
|
||
|
||
if ( ( pdfi != 0 ) & ( bfi == 0 ) ) {
|
||
carefulFlag = 1;
|
||
}
|
||
Ex_ctrl( exc_enhanced, excEnergy, st->excEnergyHist, st->voicedHangover
|
||
, st->prev_bf, carefulFlag );
|
||
}
|
||
|
||
if ( ( st->inBackgroundNoise != 0 ) & ( bfi != 0 || st->prev_bf != 0 ) & (
|
||
st->state < 4 ) ) {; /* do nothing! */
|
||
}
|
||
else {
|
||
/* Update energy history for all modes */
|
||
for (i = 0; i < 8; i++){
|
||
st->excEnergyHist[i] = st->excEnergyHist[i+1];
|
||
}
|
||
st->excEnergyHist[8] = excEnergy;
|
||
}
|
||
|
||
/*
|
||
* Excitation control module end.
|
||
*/
|
||
if ( pit_sharp > 16384 ) {
|
||
for ( i = 0; i < L_SUBFR; i++ ) {
|
||
excp[i] = excp[i] + exc_enhanced[i];
|
||
if (labs(excp[i]) > 32767)
|
||
excp[i] = (excp[i] & 0x80000000) ? -32768 : 32767;
|
||
}
|
||
agc2( exc_enhanced, excp );
|
||
overflow = Syn_filt( Az, excp, &synth[i_subfr], L_SUBFR, st->mem_syn, 0
|
||
);
|
||
}
|
||
else {
|
||
overflow = Syn_filt( Az, exc_enhanced, &synth[i_subfr], L_SUBFR, st->
|
||
mem_syn, 0 );
|
||
}
|
||
|
||
if ( overflow ) {
|
||
for ( i = 0; i < PIT_MAX + L_INTERPOL + L_SUBFR; i++ ) {
|
||
st->old_exc[i] = st->old_exc[i] >> 2;
|
||
}
|
||
|
||
for ( i = 0; i < L_SUBFR; i++ ) {
|
||
exc_enhanced[i] = exc_enhanced[i] >> 2;
|
||
}
|
||
Syn_filt_overflow( Az, exc_enhanced, &synth[i_subfr], L_SUBFR, st->mem_syn, 1 );
|
||
}
|
||
else {
|
||
memcpy( st->mem_syn, &synth[i_subfr + 30], 40 );
|
||
}
|
||
|
||
/*
|
||
* Update signal for next frame.
|
||
* -> shift to the left by L_SUBFR st->exc[]
|
||
*/
|
||
memcpy( &st->old_exc[0], &st->old_exc[L_SUBFR], ( PIT_MAX + L_INTERPOL )<<
|
||
2 );
|
||
|
||
/* interpolated LPC parameters for next subframe */
|
||
Az += MP1;
|
||
|
||
/* store T0 for next subframe */
|
||
st->old_T0 = T0;
|
||
}
|
||
|
||
/*
|
||
* Call the Source Characteristic Detector which updates
|
||
* st->inBackgroundNoise and st->voicedHangover.
|
||
*/
|
||
st->inBackgroundNoise = Bgn_scd( st->background_state, &( st->ltpGainHistory[
|
||
0] ), &( synth[0] ), &( st->voicedHangover ) );
|
||
dtx_dec_activity_update( st->dtxDecoderState, st->lsfState->past_lsf_q, synth
|
||
);
|
||
|
||
/* store bfi for next subframe */
|
||
st->prev_bf = bfi;
|
||
st->prev_pdf = pdfi;
|
||
|
||
/*
|
||
* Calculate the LSF averages on the eight
|
||
* previous frames
|
||
*/
|
||
lsp_avg( st->lsp_avg_st, st->lsfState->past_lsf_q );
|
||
theEnd:
|
||
st->dtxDecoderState->dtxGlobalState = newDTXState;
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Residu40
|
||
*
|
||
*
|
||
* Parameters:
|
||
* a I: prediction coefficients
|
||
* x I: speech signal
|
||
* y O: residual signal
|
||
*
|
||
* Function:
|
||
* The LP residual is computed by filtering the input
|
||
* speech through the LP inverse filter a(z)
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Residu40( Word32 a[], Word32 x[], Word32 y[] )
|
||
{
|
||
Word32 s, i, j;
|
||
|
||
|
||
for ( i = 0; i < 40; i++ ) {
|
||
s = a[0] * x[i] + a[1] * x[i - 1] + a[2] * x[i - 2] + a[3] * x[i - 3];
|
||
s += a[4] * x[i - 4] + a[5] * x[i - 5] + a[6] * x[i - 6] + a[7] * x[i - 7]
|
||
;
|
||
s += a[8] * x[i - 8] + a[9] * x[i - 9] + a[10] * x[i - 10];
|
||
y[i] = ( s + 0x800 ) >> 12;
|
||
if (abs(y[i]) > 32767){
|
||
/* go to safe mode */
|
||
for (i = 0; i < 40; i++) {
|
||
s = a[0] * x[i];
|
||
for (j = 1; j <= 10; j++) {
|
||
s += a[j] * x[i - j];
|
||
if (s > 1073741823){
|
||
s = 1073741823;
|
||
}
|
||
else if ( s < -1073741824) {
|
||
s = -1073741824;
|
||
}
|
||
}
|
||
y[i] = ( s + 0x800 ) >> 12;
|
||
if (abs(y[i]) > 32767)
|
||
y[i] = (y[i] & 0x80000000) ? -32768 : 32767;
|
||
}
|
||
return;
|
||
}
|
||
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* agc
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st->past_gain B: gain memory
|
||
* sig_in I: Post_Filter input signal
|
||
* sig_out B: Post_Filter output signal
|
||
* agc_fac I: AGC factor
|
||
*
|
||
* Function:
|
||
* Scales the Post_Filter output on a subframe basis
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void agc( agcState *st, Word32 *sig_in, Word32 *sig_out, Word16 agc_fac )
|
||
{
|
||
Word32 s, gain_in, gain_out, g0, gain;
|
||
int exp, i;
|
||
|
||
|
||
/* calculate gain_out with exponent */
|
||
s = energy_new( sig_out );
|
||
|
||
if ( s == 0 ) {
|
||
st->past_gain = 0;
|
||
return;
|
||
}
|
||
exp=0;
|
||
i = s;
|
||
while (!(i & 0x40000000))
|
||
{
|
||
exp++;
|
||
i = i << 1;
|
||
}
|
||
exp -=1;
|
||
if (exp & 0x80000000) {
|
||
s >>= 1;
|
||
}
|
||
else {
|
||
s <<= exp;
|
||
}
|
||
gain_out = ( s + 0x00008000L ) >> 16;
|
||
|
||
/* calculate gain_in with exponent */
|
||
s = energy_new( sig_in );
|
||
|
||
if ( s == 0 ) {
|
||
g0 = 0;
|
||
}
|
||
else {
|
||
i=0;
|
||
while (!(s & 0x40000000))
|
||
{
|
||
i++;
|
||
s = s << 1;
|
||
}
|
||
s = s + 0x00008000L;
|
||
|
||
if ( s >= 0 )
|
||
gain_in = s >> 16;
|
||
else
|
||
gain_in = 32767;
|
||
exp = ( exp - i );
|
||
|
||
/*
|
||
* g0 = (1-agc_fac) * sqrt(gain_in/gain_out);
|
||
*/
|
||
/* s = gain_out / gain_in */
|
||
s = ( gain_out << 15 ) / gain_in;
|
||
exp = 7 - exp;
|
||
|
||
if ( exp > 0 ){
|
||
if (exp > 31)
|
||
{
|
||
if(s){
|
||
s = 2147483647;
|
||
}
|
||
}
|
||
else {
|
||
s = s << exp ;
|
||
}
|
||
}
|
||
else
|
||
s = ( s >> ( -exp ) );
|
||
if (s < 0)
|
||
s = 2147483647;
|
||
s = Inv_sqrt( s );
|
||
i = ( ( s << 9 ) + 0x00008000L ) >> 16;
|
||
if (i & 0xFFFF8000)
|
||
i = 32767;
|
||
|
||
/* g0 = i * (1-agc_fac) */
|
||
g0 = ( i * ( 32767 - agc_fac ) ) >> 15;
|
||
}
|
||
|
||
/*
|
||
* compute gain[n] = agc_fac * gain[n-1] + (1-agc_fac) * sqrt(gain_in/gain_out)
|
||
* sig_out[n] = gain[n] * sig_out[n]
|
||
*/
|
||
gain = st->past_gain;
|
||
|
||
for ( i = 0; i < L_SUBFR; i++ ) {
|
||
gain = ( gain * agc_fac ) >> 15;
|
||
gain = gain + g0;
|
||
sig_out[i] = ( sig_out[i] * gain ) >> 12;
|
||
if (labs(sig_out[i]) > 32767)
|
||
sig_out[i] = (sig_out[i] & 0x8000000) ? -32768 : 32767;
|
||
}
|
||
st->past_gain = gain;
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Post_Filter
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st B: post filter states
|
||
* mode I: AMR mode
|
||
* syn B: synthesis speech
|
||
* Az_4 I: interpolated LPC parameters in all subfr.
|
||
*
|
||
* Function:
|
||
* Post_Filtering of synthesis speech.
|
||
*
|
||
* inverse filtering of syn[] through A(z/0.7) to get res2[]
|
||
* tilt compensation filtering; 1 - MU*k*z^-1
|
||
* synthesis filtering through 1/A(z/0.75)
|
||
* adaptive gain control
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Post_Filter( Post_FilterState *st, enum Mode mode, Word32 *syn,
|
||
Word32 *Az_4 )
|
||
{
|
||
Word32 h[22], Ap3[MP1], Ap4[MP1]; /* bandwidth expanded LP parameters */
|
||
Word32 tmp, i_subfr, i, temp1, temp2, overflow = 0;
|
||
Word32 *Az, *p1, *p2, *syn_work = &st->synth_buf[M];
|
||
const Word32 *pgamma3 = &gamma3[0];
|
||
const Word32 *pgamma4 = &gamma4_gamma3_MR122[0];
|
||
|
||
|
||
/*
|
||
* Post filtering
|
||
*/
|
||
memcpy( syn_work, syn, L_FRAME <<2 );
|
||
Az = Az_4;
|
||
|
||
if ( ( mode == MR122 ) || ( mode == MR102 ) ) {
|
||
pgamma3 = &gamma4_gamma3_MR122[0];
|
||
pgamma4 = &gamma4_MR122[0];
|
||
}
|
||
|
||
for ( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) {
|
||
/* Find weighted filter coefficients Ap3[] and Ap[4] */
|
||
Ap3[0] = Az[0];
|
||
Ap4[0] = Az[0];
|
||
|
||
for ( i = 1; i <= 10; i++ ) {
|
||
Ap3[i] = ( Az[i] * pgamma3[i - 1] +0x4000 ) >> 15;
|
||
Ap4[i] = ( Az[i] * pgamma4[i - 1] +0x4000 ) >> 15;
|
||
}
|
||
|
||
/* filtering of synthesis speech by A(z/0.7) to find res2[] */
|
||
Residu40( Ap3, &syn_work[i_subfr], st->res2 );
|
||
|
||
/* tilt compensation filter */
|
||
/* impulse response of A(z/0.7)/A(z/0.75) */
|
||
memcpy( h, Ap3, MP1 <<2 );
|
||
memset( &h[M +1], 0, ( 22 - M - 1 )<<2 );
|
||
Syn_filt( Ap4, h, h, 22, &h[M +1], 0 );
|
||
|
||
/* 1st correlation of h[] */
|
||
tmp = 16777216 + h[1] * h[1];
|
||
|
||
for ( i = 2; i < 22; i++ ) {
|
||
tmp += h[i] * h[i];
|
||
if (tmp > 0x3FFF8000)
|
||
break;
|
||
}
|
||
temp1 = tmp >> 15;
|
||
if (temp1 & 0xFFFF8000)
|
||
temp1 = 32767;
|
||
|
||
tmp = h[0] * h[1];
|
||
|
||
for ( i = 1; i < 21; i++ ) {
|
||
tmp += h[i] * h[i + 1];
|
||
if (abs(tmp) > 1073741823)
|
||
tmp = 1073741823;
|
||
}
|
||
temp2 = tmp >> 15;
|
||
|
||
if ( temp2 <= 0 ) {
|
||
temp2 = 0;
|
||
}
|
||
else {
|
||
tmp = temp2 * 26214;
|
||
temp2 = ( tmp & 0xffff8000 ) / temp1;
|
||
}
|
||
|
||
/* preemphasis */
|
||
p1 = st->res2 + 39;
|
||
p2 = p1 - 1;
|
||
tmp = *p1;
|
||
|
||
do {
|
||
*p1 = *p1 - ( ( temp2 * *p2-- ) >> 15 );
|
||
if (abs(*p1) > 32767) {
|
||
*p1 = (*p1 & 0x80000000) ? -32768 : 32767;
|
||
}
|
||
p1--;
|
||
*p1 = *p1 - ( ( temp2 * *p2-- ) >> 15 );
|
||
if (abs(*p1) > 32767) {
|
||
*p1 = (*p1 & 0x80000000) ? -32768 : 32767;
|
||
}
|
||
p1--;
|
||
*p1 = *p1 - ( ( temp2 * *p2-- ) >> 15 );
|
||
if (abs(*p1) > 32767) {
|
||
*p1 = (*p1 & 0x80000000) ? -32768 : 32767;
|
||
}
|
||
p1--;
|
||
} while( p1 > st->res2 );
|
||
*p1 = *p1 - ( ( temp2 * st->preemph_state_mem_pre ) >> 15 );
|
||
if (abs(*p1) > 32767) {
|
||
*p1 = (*p1 & 0x80000000) ? -32768 : 32767;
|
||
}
|
||
st->preemph_state_mem_pre = tmp;
|
||
|
||
/* filtering through 1/A(z/0.75) */
|
||
overflow = Syn_filt( Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 0 );
|
||
if (overflow){
|
||
Syn_filt_overflow( Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1 );
|
||
overflow = 0;
|
||
}
|
||
else {
|
||
memcpy(st->mem_syn_pst, &syn[i_subfr + 30], 40);
|
||
}
|
||
|
||
/* scale output to input */
|
||
agc( st->agc_state, &syn_work[i_subfr], &syn[i_subfr], AGC_FAC );
|
||
Az += MP1;
|
||
}
|
||
|
||
/* update syn_work[] buffer */
|
||
memcpy( &syn_work[- M], &syn_work[L_FRAME - M], M <<2 );
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Post_Process
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st B: post filter states
|
||
* signal B: signal
|
||
*
|
||
* Function:
|
||
* Postprocessing of input speech.
|
||
*
|
||
* 2nd order high pass filtering with cut off frequency at 60 Hz.
|
||
* Multiplication of output by two.
|
||
*
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
static void Post_Process( Post_ProcessState *st, Word32 signal[] )
|
||
{
|
||
Word32 x2, tmp, i = 0;
|
||
Word32 mask = 0x40000000;
|
||
|
||
do {
|
||
x2 = st->x1;
|
||
st->x1 = st->x0;
|
||
st->x0 = signal[i];
|
||
|
||
/*
|
||
* y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b140[2]*x[i-2]/2
|
||
* + a[1]*y[i-1] + a[2] * y[i-2];
|
||
*/
|
||
tmp = ( st->y1_hi * 15836) + ( ( ( st->y1_lo * 15836 ) & ( Word32 )0xffff8000 ) >> 15);
|
||
tmp += (st->y2_hi * -7667) + ( ( ( st->y2_lo * ( -7667 ) ) & ( Word32 )0xffff8000 ) >> 15);
|
||
tmp += st->x0 * 7699;
|
||
tmp += st->x1 * -15398;
|
||
if ( ( (tmp >> 1) ^ tmp ) & mask)
|
||
tmp = (tmp & 0x80000000) ? -1073741824 : 1073741823;
|
||
|
||
tmp += x2 * 7699;
|
||
if ( ( (tmp >> 1) ^ tmp ) & mask)
|
||
tmp = (tmp & 0x80000000) ? -1073741824 : 1073741823;
|
||
|
||
tmp = tmp << 1;
|
||
if ( ( (tmp >> 1) ^ tmp ) & mask)
|
||
tmp = (tmp & 0x80000000) ? -1073741824 : 1073741823;
|
||
|
||
tmp = tmp << 1;
|
||
if ( ( (tmp >> 1) ^ tmp ) & mask)
|
||
tmp = (tmp & 0x80000000) ? -1073741824 : 1073741823;
|
||
|
||
if ( labs( tmp ) < 536862720 ) {
|
||
signal[i++] = ( tmp + 0x00002000L ) >> 14;
|
||
}
|
||
else if ( tmp > 0 ) {
|
||
signal[i++] = 32767;
|
||
}
|
||
else {
|
||
signal[i++] = -32768;
|
||
}
|
||
st->y2_hi = st->y1_hi;
|
||
st->y2_lo = st->y1_lo;
|
||
st->y1_hi = tmp >> 15;
|
||
st->y1_lo = ( ( tmp << 1 ) - ( st->y1_hi << 16 ) ) >> 1;
|
||
} while( i < 160 );
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Speech_Decode_Frame
|
||
*
|
||
*
|
||
* Parameters:
|
||
* st B: decoder memory
|
||
* mode I: AMR mode
|
||
* parm I: speech parameters
|
||
* frame_type I: Frame type
|
||
* synth O: synthesis speech
|
||
|
||
* Function:
|
||
* Decode one frame
|
||
*
|
||
* Returns:
|
||
* void
|
||
*/
|
||
void Speech_Decode_Frame( void *st, enum Mode mode, Word16 *parm, enum
|
||
RXFrameType frame_type, Word16 *synth )
|
||
{
|
||
Word32 Az_dec[AZ_SIZE]; /* Decoded Az for post-filter in 4 subframes*/
|
||
Word32 synth_speech[L_FRAME];
|
||
Word32 i;
|
||
|
||
/* Synthesis */
|
||
Decoder_amr( ( ( Speech_Decode_FrameState * ) st )->decoder_amrState, mode,
|
||
parm, frame_type, synth_speech, Az_dec );
|
||
Post_Filter( ( ( Speech_Decode_FrameState * ) st )->post_state, mode,
|
||
synth_speech, Az_dec );
|
||
|
||
/* post HP filter, and 15->16 bits */
|
||
Post_Process( ( ( Speech_Decode_FrameState * ) st )->postHP_state,
|
||
synth_speech );
|
||
|
||
for ( i = 0; i < L_FRAME; i++ ) {
|
||
#ifndef NO13BIT
|
||
/* Truncate to 13 bits */
|
||
synth[i] = ( Word16 )( synth_speech[i] & 0xfff8 );
|
||
#else
|
||
synth[i] = ( Word16 )( synth_speech[i]);
|
||
#endif
|
||
}
|
||
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Decoder_amr_exit
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state I: state structure
|
||
*
|
||
* Function:
|
||
* The memory used for state memory is freed
|
||
*
|
||
* Returns:
|
||
* Void
|
||
*/
|
||
static void Decoder_amr_exit( Decoder_amrState **state )
|
||
{
|
||
if ( state == NULL || *state == NULL )
|
||
return;
|
||
free( ( *state )->lsfState );
|
||
free( ( *state )->ec_gain_p_st );
|
||
free( ( *state )->ec_gain_c_st );
|
||
free( ( *state )->pred_state );
|
||
free( ( *state )->background_state );
|
||
free( ( *state )->ph_disp_st );
|
||
free( ( *state )->Cb_gain_averState );
|
||
free( ( *state )->lsp_avg_st );
|
||
free( ( *state )->dtxDecoderState );
|
||
|
||
/* deallocate memory */
|
||
free( *state );
|
||
*state = NULL;
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Post_Filter_exit
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state I: state structure
|
||
*
|
||
* Function:
|
||
* The memory used for state memory is freed
|
||
*
|
||
* Returns:
|
||
* Void
|
||
*/
|
||
static void Post_Filter_exit( Post_FilterState **state )
|
||
{
|
||
if ( state == NULL || *state == NULL )
|
||
return;
|
||
free( ( *state )->agc_state );
|
||
|
||
/* deallocate memory */
|
||
free( *state );
|
||
*state = NULL;
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Post_Process_reset
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state B: state structure
|
||
*
|
||
* Function:
|
||
* Resets state memory
|
||
*
|
||
* Returns:
|
||
* -1 failure
|
||
*/
|
||
static int Post_Process_reset( Post_ProcessState *state )
|
||
{
|
||
if ( ( Post_ProcessState * )state == NULL ) {
|
||
fprintf( stderr, "Post_Process_reset: invalid parameter\n" );
|
||
return-1;
|
||
}
|
||
state->y2_hi = 0;
|
||
state->y2_lo = 0;
|
||
state->y1_hi = 0;
|
||
state->y1_lo = 0;
|
||
state->x0 = 0;
|
||
state->x1 = 0;
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*
|
||
* Post_Process_exit
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state I: state structure
|
||
*
|
||
* Function:
|
||
* The memory used for state memory is freed
|
||
*
|
||
* Returns:
|
||
* Void
|
||
*/
|
||
static void Post_Process_exit( Post_ProcessState **state )
|
||
{
|
||
if ( state == NULL || *state == NULL )
|
||
return;
|
||
|
||
/* deallocate memory */
|
||
free( *state );
|
||
*state = NULL;
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Decoder_amr_init
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state O: state structure
|
||
*
|
||
* Function:
|
||
* Allocates state memory and initializes state memory
|
||
*
|
||
* Returns:
|
||
* success = 0
|
||
*/
|
||
static int Decoder_amr_init( Decoder_amrState **state )
|
||
{
|
||
Decoder_amrState * s;
|
||
|
||
if ( ( Decoder_amrState * )state == NULL ) {
|
||
fprintf( stderr, "Decoder_amr_init: invalid parameter\n" );
|
||
return-1;
|
||
}
|
||
*state = NULL;
|
||
|
||
/* allocate memory */
|
||
if ( ( s = ( Decoder_amrState * ) malloc( sizeof( Decoder_amrState ) ) ) ==
|
||
NULL ) {
|
||
fprintf( stderr, "Decoder_amr_init: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
|
||
/* DPlsf_init */
|
||
/* allocate memory */
|
||
if ( ( s->lsfState = ( D_plsfState * ) malloc( sizeof( D_plsfState ) ) ) ==
|
||
NULL ) {
|
||
fprintf( stderr, "DPlsf_init: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
|
||
/* ecGainPitchInit */
|
||
/* allocate memory */
|
||
if ( ( s->ec_gain_p_st = ( ec_gain_pitchState * ) malloc( sizeof(
|
||
ec_gain_pitchState ) ) ) == NULL ) {
|
||
fprintf( stderr, "ecGainPitchInit: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
|
||
/* ecGainCodeInit */
|
||
/* allocate memory */
|
||
if ( ( s->ec_gain_c_st = ( ec_gain_codeState * ) malloc( sizeof(
|
||
ec_gain_codeState ) ) ) == NULL ) {
|
||
fprintf( stderr, "ecGainCodeInit: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
|
||
/* gcPredInit */
|
||
/* allocate memory */
|
||
if ( ( s->pred_state = ( gc_predState * ) malloc( sizeof( gc_predState ) ) )
|
||
== NULL ) {
|
||
fprintf( stderr, "gcPredInit: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
|
||
/* Cb_gain_averageInit */
|
||
/* allocate memory */
|
||
if ( ( s->Cb_gain_averState = ( Cb_gain_averageState * ) malloc( sizeof(
|
||
Cb_gain_averageState ) ) ) == NULL ) {
|
||
fprintf( stderr, "Cb_gain_averageInit: can not malloc state structure\n" )
|
||
;
|
||
return-1;
|
||
}
|
||
memset( s->Cb_gain_averState->cbGainHistory, 0, L_CBGAINHIST <<2 );
|
||
|
||
/* Initialize hangover handling */
|
||
s->Cb_gain_averState->hangVar = 0;
|
||
s->Cb_gain_averState->hangCount = 0;
|
||
|
||
/* lsp_avgInit */
|
||
/* allocate memory */
|
||
if ( ( s->lsp_avg_st = ( lsp_avgState * ) malloc( sizeof( lsp_avgState ) ) )
|
||
== NULL ) {
|
||
fprintf( stderr, "lsp_avgInit: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
|
||
/* Bgn_scdInit */
|
||
/* allocate memory */
|
||
if ( ( s->background_state = ( Bgn_scdState * ) malloc( sizeof( Bgn_scdState
|
||
) ) ) == NULL ) {
|
||
fprintf( stderr, "Bgn_scdInit: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
|
||
/* phDispInit */
|
||
/* allocate memory */
|
||
if ( ( s->ph_disp_st = ( ph_dispState * ) malloc( sizeof( ph_dispState ) ) )
|
||
== NULL ) {
|
||
fprintf( stderr, "phDispInit: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
|
||
/* dtxDecInit */
|
||
/* allocate memory */
|
||
if ( ( s->dtxDecoderState = ( dtx_decState * ) malloc( sizeof( dtx_decState )
|
||
) ) == NULL ) {
|
||
fprintf( stderr, "dtxDecInit: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
Decoder_amr_reset( s, 0 );
|
||
*state = s;
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*
|
||
* Post_Filter_reset
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state B: state structure
|
||
*
|
||
* Function:
|
||
* Resets state memory
|
||
*
|
||
* Returns:
|
||
* -1 failure
|
||
*/
|
||
static int Post_Filter_reset( Post_FilterState *state )
|
||
{
|
||
if ( ( Post_FilterState * )state == NULL ) {
|
||
fprintf( stderr, "Post_Filter_reset: invalid parameter\n" );
|
||
return-1;
|
||
}
|
||
state->preemph_state_mem_pre = 0;
|
||
state->agc_state->past_gain = 4096;
|
||
memset( state->mem_syn_pst, 0, M <<2 );
|
||
memset( state->res2, 0, L_SUBFR <<2 );
|
||
memset( state->synth_buf, 0, ( L_FRAME + M )<<2 );
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*
|
||
* Post_Filter_init
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state O: state structure
|
||
*
|
||
* Function:
|
||
* Allocates state memory and initializes state memory
|
||
*
|
||
* Returns:
|
||
* success = 0
|
||
*/
|
||
static int Post_Filter_init( Post_FilterState **state )
|
||
{
|
||
Post_FilterState * s;
|
||
|
||
if ( ( Post_FilterState * )state == NULL ) {
|
||
fprintf( stderr, "F057:invalid parameter\n" );
|
||
return-1;
|
||
}
|
||
*state = NULL;
|
||
|
||
/* allocate memory */
|
||
if ( ( s = ( Post_FilterState * ) malloc( sizeof( Post_FilterState ) ) ) ==
|
||
NULL ) {
|
||
fprintf( stderr, "F057:can not malloc filter structure\n" );
|
||
return-1;
|
||
}
|
||
s->agc_state = NULL;
|
||
|
||
/* allocate memory */
|
||
if ( ( s->agc_state = ( agcState * ) malloc( sizeof( agcState ) ) ) == NULL )
|
||
{
|
||
fprintf( stderr, "agcInit: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
Post_Filter_reset( s );
|
||
*state = s;
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*
|
||
* Post_Process_init
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state O: state structure
|
||
*
|
||
* Function:
|
||
* Allocates state memory and initializes state memory
|
||
*
|
||
* Returns:
|
||
* success = 0
|
||
*/
|
||
static int Post_Process_init( Post_ProcessState **state )
|
||
{
|
||
Post_ProcessState * s;
|
||
|
||
if ( ( Post_ProcessState * )state == NULL ) {
|
||
fprintf( stderr, "Post_Process_init: invalid parameter\n" );
|
||
return-1;
|
||
}
|
||
*state = NULL;
|
||
|
||
/* allocate memory */
|
||
if ( ( s = ( Post_ProcessState * ) malloc( sizeof( Post_ProcessState ) ) ) ==
|
||
NULL ) {
|
||
fprintf( stderr, "Post_Process_init: can not malloc state structure\n" );
|
||
return-1;
|
||
}
|
||
Post_Process_reset( s );
|
||
*state = s;
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*
|
||
* Speech_Decode_Frame_exit
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state I: state structure
|
||
*
|
||
* Function:
|
||
* The memory used for state memory is freed
|
||
*
|
||
* Returns:
|
||
* Void
|
||
*/
|
||
void Speech_Decode_Frame_exit( void **st )
|
||
{
|
||
if ( (( Speech_Decode_FrameState * )( st )) == NULL )
|
||
return;
|
||
Decoder_amr_exit( &( ( ( Speech_Decode_FrameState * ) st )->decoder_amrState
|
||
) );
|
||
Post_Filter_exit( &( ( ( Speech_Decode_FrameState * ) st )->post_state ) );
|
||
Post_Process_exit( &( ( ( Speech_Decode_FrameState * ) st )->postHP_state ) )
|
||
;
|
||
|
||
/* deallocate memory */
|
||
free( (( Speech_Decode_FrameState * )st) );
|
||
return;
|
||
}
|
||
|
||
|
||
/*
|
||
* Speech_Decode_Frame_reset
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state B: state structure
|
||
*
|
||
* Function:
|
||
* Resets state memory
|
||
*
|
||
* Returns:
|
||
* -1 = failure
|
||
*/
|
||
int Speech_Decode_Frame_reset( void **st )
|
||
{
|
||
Speech_Decode_FrameState * state;
|
||
|
||
if ( st == NULL || *st == NULL )
|
||
return (-1);
|
||
state = ( Speech_Decode_FrameState * )st;
|
||
Decoder_amr_reset( state->decoder_amrState, ( enum Mode ) 0 );
|
||
Post_Filter_reset( state->post_state );
|
||
Post_Process_reset( state->postHP_state );
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*
|
||
* Speech_Decode_Frame_init
|
||
*
|
||
*
|
||
* Parameters:
|
||
* state O: state structure
|
||
*
|
||
* Function:
|
||
* Allocates state memory and initializes state memory
|
||
*
|
||
* Returns:
|
||
* success = 0
|
||
*/
|
||
void * Speech_Decode_Frame_init( )
|
||
{
|
||
Speech_Decode_FrameState * s;
|
||
|
||
/* allocate memory */
|
||
if ( ( s = ( Speech_Decode_FrameState * ) malloc( sizeof(
|
||
Speech_Decode_FrameState ) ) ) == NULL ) {
|
||
fprintf( stderr, "Speech_Decode_Frame_init: can not malloc state "
|
||
"structure\n" );
|
||
return NULL;
|
||
}
|
||
s->decoder_amrState = NULL;
|
||
s->post_state = NULL;
|
||
s->postHP_state = NULL;
|
||
|
||
if ( Decoder_amr_init( &s->decoder_amrState ) || Post_Filter_init( &s->
|
||
post_state ) || Post_Process_init( &s->postHP_state ) ) {
|
||
Speech_Decode_Frame_exit( ( void ** )( &s ) );
|
||
return NULL;
|
||
}
|
||
return s;
|
||
}
|