ref: 69c20d751aafe341e65c0304dbf4f2b6a584e38f
dir: /amr-wb/dec_main.c/
/*------------------------------------------------------------------------*
* DEC_MAIN.C *
*------------------------------------------------------------------------*
* Performs the main decoder routine *
*------------------------------------------------------------------------*/
/*___________________________________________________________________________
| |
| Fixed-point C simulation of AMR WB ACELP coding algorithm with 20 ms |
| speech frames for wideband speech signals. |
|___________________________________________________________________________|
*/
#include <stdio.h>
#include <stdlib.h>
#include "typedef.h"
#include "basic_op.h"
#include "oper_32b.h"
#include "cnst.h"
#include "acelp.h"
#include "dec_main.h"
#include "bits.h"
#include "count.h"
#include "math_op.h"
#include "main.h"
/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */
static Word16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767};
/* High Band encoding */
static const Word16 HP_gain[16] =
{
3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264,
11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728
};
/* isp tables for initialization */
static Word16 isp_init[M] =
{
32138, 30274, 27246, 23170, 18205, 12540, 6393, 0,
-6393, -12540, -18205, -23170, -27246, -30274, -32138, 1475
};
static Word16 isf_init[M] =
{
1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192,
9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840
};
static void synthesis(
Word16 Aq[], /* A(z) : quantized Az */
Word16 exc[], /* (i) : excitation at 12kHz */
Word16 Q_new, /* (i) : scaling performed on exc */
Word16 synth16k[], /* (o) : 16kHz synthesis signal */
Word16 prms, /* (i) : parameter */
Word16 HfIsf[],
Word16 nb_bits,
Word16 newDTXState,
Decoder_State * st, /* (i/o) : State structure */
Word16 bfi /* (i) : bad frame indicator */
);
/*-----------------------------------------------------------------*
* Funtion init_decoder *
* ~~~~~~~~~~~~ *
* ->Initialization of variables for the decoder section. *
*-----------------------------------------------------------------*/
void Init_decoder(void **spd_state)
{
/* Decoder states */
Decoder_State *st;
*spd_state = NULL;
/*-------------------------------------------------------------------------*
* Memory allocation for coder state. *
*-------------------------------------------------------------------------*/
test();
if ((st = (Decoder_State *) malloc(sizeof(Decoder_State))) == NULL)
{
printf("Can not malloc Decoder_State structure!\n");
return;
}
st->dtx_decSt = NULL;
dtx_dec_init(&st->dtx_decSt, isf_init);
Reset_decoder((void *) st, 1);
*spd_state = (void *) st;
return;
}
void Reset_decoder(void *st, int reset_all)
{
Word16 i;
Decoder_State *dec_state;
dec_state = (Decoder_State *) st;
Set_zero(dec_state->old_exc, PIT_MAX + L_INTERPOL);
Set_zero(dec_state->past_isfq, M);
dec_state->old_T0_frac = 0; move16(); /* old pitch value = 64.0 */
dec_state->old_T0 = 64; move16();
dec_state->first_frame = 1; move16();
dec_state->L_gc_thres = 0; move16();
dec_state->tilt_code = 0; move16();
Init_Phase_dispersion(dec_state->disp_mem);
/* scaling memories for excitation */
dec_state->Q_old = Q_MAX; move16();
dec_state->Qsubfr[3] = Q_MAX; move16();
dec_state->Qsubfr[2] = Q_MAX; move16();
dec_state->Qsubfr[1] = Q_MAX; move16();
dec_state->Qsubfr[0] = Q_MAX; move16();
if (reset_all != 0)
{
/* routines initialization */
Init_D_gain2(dec_state->dec_gain);
Init_Oversamp_16k(dec_state->mem_oversamp);
Init_HP50_12k8(dec_state->mem_sig_out);
Init_Filt_6k_7k(dec_state->mem_hf);
Init_Filt_7k(dec_state->mem_hf3);
Init_HP400_12k8(dec_state->mem_hp400);
Init_Lagconc(dec_state->lag_hist);
/* isp initialization */
Copy(isp_init, dec_state->ispold, M);
Copy(isf_init, dec_state->isfold, M);
for (i = 0; i < L_MEANBUF; i++)
Copy(isf_init, &dec_state->isf_buf[i * M], M);
/* variable initialization */
dec_state->mem_deemph = 0; move16();
dec_state->seed = 21845; move16(); /* init random with 21845 */
dec_state->seed2 = 21845; move16();
dec_state->seed3 = 21845; move16();
dec_state->state = 0; move16();
dec_state->prev_bfi = 0; move16();
/* Static vectors to zero */
Set_zero(dec_state->mem_syn_hf, M16k);
Set_zero(dec_state->mem_syn_hi, M);
Set_zero(dec_state->mem_syn_lo, M);
dtx_dec_reset(dec_state->dtx_decSt, isf_init);
dec_state->vad_hist = 0; move16();
}
return;
}
void Close_decoder(void *spd_state)
{
dtx_dec_exit(&(((Decoder_State *) spd_state)->dtx_decSt));
free(spd_state);
return;
}
/*-----------------------------------------------------------------*
* Funtion decoder *
* ~~~~~~~ *
* ->Main decoder routine. *
* *
*-----------------------------------------------------------------*/
void decoder(
int mode, /* input : used mode */
Word16 prms[], /* input : parameter vector */
Word16 synth16k[], /* output: synthesis speech */
Word16 * frame_length, /* output: lenght of the frame */
void *spd_state, /* i/o : State structure */
int frame_type /* input : received frame type */
)
{
/* Decoder states */
Decoder_State *st;
/* Excitation vector */
Word16 old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL];
Word16 *exc;
/* LPC coefficients */
Word16 *p_Aq; /* ptr to A(z) for the 4 subframes */
Word16 Aq[NB_SUBFR * (M + 1)]; /* A(z) quantized for the 4 subframes */
Word16 ispnew[M]; /* immittance spectral pairs at 4nd sfr */
Word16 isf[M]; /* ISF (frequency domain) at 4nd sfr */
Word16 code[L_SUBFR]; /* algebraic codevector */
Word16 code2[L_SUBFR]; /* algebraic codevector */
Word16 exc2[L_FRAME]; /* excitation vector */
Word16 fac, stab_fac, voice_fac, Q_new = 0;
Word32 L_tmp, L_gain_code;
/* Scalars */
Word16 i, j, i_subfr, index, ind[8], max, tmp;
Word16 T0, T0_frac, pit_flag, T0_max, select, T0_min = 0;
Word16 gain_pit, gain_code, gain_code_lo;
Word16 newDTXState, bfi, unusable_frame, nb_bits;
Word16 vad_flag;
Word16 pit_sharp;
Word16 excp[L_SUBFR];
Word16 isf_tmp[M];
Word16 HfIsf[M16k];
Word16 corr_gain = 0;
st = (Decoder_State *) spd_state;
/* mode verification */
nb_bits = nb_of_bits[mode]; move16();
*frame_length = L_FRAME16k; move16();
/* find the new DTX state SPEECH OR DTX */
newDTXState = rx_dtx_handler(st->dtx_decSt, frame_type);
test();
if (sub(newDTXState, SPEECH) != 0)
{
dtx_dec(st->dtx_decSt, exc2, newDTXState, isf, &prms);
}
/* SPEECH action state machine */
test();test();
if ((sub(frame_type, RX_SPEECH_BAD) == 0) ||
(sub(frame_type, RX_SPEECH_PROBABLY_DEGRADED) == 0))
{
/* bfi only for lsf, gains and pitch period */
bfi = 1; move16();
unusable_frame = 0; move16();
} else if ((sub(frame_type, RX_NO_DATA) == 0) ||
(sub(frame_type, RX_SPEECH_LOST) == 0))
{
/* bfi for all index, bits are not usable */
bfi = 1; move16();
unusable_frame = 1; move16();
} else
{
bfi = 0; move16();
unusable_frame = 0; move16();
}
test();
if (bfi != 0)
{
st->state = add(st->state, 1); move16();
test();
if (sub(st->state, 6) > 0)
{
st->state = 6; move16();
}
} else
{
st->state = shr(st->state, 1); move16();
}
/* 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) */
test();test();
if (sub(st->dtx_decSt->dtxGlobalState, DTX) == 0)
{
st->state = 5; move16();
st->prev_bfi = 0; move16();
} else if (sub(st->dtx_decSt->dtxGlobalState, DTX_MUTE) == 0)
{
st->state = 5; move16();
st->prev_bfi = 1; move16();
}
test();
if (sub(newDTXState, SPEECH) == 0)
{
vad_flag = Serial_parm(1, &prms);
test();
if (bfi == 0)
{
test();
if (vad_flag == 0)
{
st->vad_hist = add(st->vad_hist, 1); move16();
} else
{
st->vad_hist = 0; move16();
}
}
}
/*----------------------------------------------------------------------*
* DTX-CNG *
*----------------------------------------------------------------------*/
test();
if (sub(newDTXState, SPEECH) != 0) /* CNG mode */
{
/* increase slightly energy of noise below 200 Hz */
/* Convert ISFs to the cosine domain */
Isf_isp(isf, ispnew, M);
Isp_Az(ispnew, Aq, M, 1);
Copy(st->isfold, isf_tmp, M);
for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
{
j = shr(i_subfr, 6);
for (i = 0; i < M; i++)
{
L_tmp = L_mult(isf_tmp[i], sub(32767, interpol_frac[j]));
L_tmp = L_mac(L_tmp, isf[i], interpol_frac[j]);
HfIsf[i] = round(L_tmp); move16();
}
synthesis(Aq, &exc2[i_subfr], 0, &synth16k[i_subfr * 5 / 4], (short) 1, HfIsf, nb_bits, newDTXState, st, bfi);
}
/* reset speech coder memories */
Reset_decoder(st, 0);
Copy(isf, st->isfold, M);
st->prev_bfi = bfi; move16();
st->dtx_decSt->dtxGlobalState = newDTXState; move16();
return;
}
/*----------------------------------------------------------------------*
* ACELP *
*----------------------------------------------------------------------*/
/* copy coder memory state into working space (internal memory for DSP) */
Copy(st->old_exc, old_exc, PIT_MAX + L_INTERPOL);
exc = old_exc + PIT_MAX + L_INTERPOL; move16();
/* Decode the ISFs */
test();
if (sub(nb_bits, NBBITS_7k) <= 0)
{
ind[0] = Serial_parm(8, &prms); move16();
ind[1] = Serial_parm(8, &prms); move16();
ind[2] = Serial_parm(7, &prms); move16();
ind[3] = Serial_parm(7, &prms); move16();
ind[4] = Serial_parm(6, &prms); move16();
Dpisf_2s_36b(ind, isf, st->past_isfq, st->isfold, st->isf_buf, bfi, 1);
} else
{
ind[0] = Serial_parm(8, &prms); move16();
ind[1] = Serial_parm(8, &prms); move16();
ind[2] = Serial_parm(6, &prms); move16();
ind[3] = Serial_parm(7, &prms); move16();
ind[4] = Serial_parm(7, &prms); move16();
ind[5] = Serial_parm(5, &prms); move16();
ind[6] = Serial_parm(5, &prms); move16();
Dpisf_2s_46b(ind, isf, st->past_isfq, st->isfold, st->isf_buf, bfi, 1);
}
/* Convert ISFs to the cosine domain */
Isf_isp(isf, ispnew, M);
test();
if (st->first_frame != 0)
{
st->first_frame = 0; move16();
Copy(ispnew, st->ispold, M);
}
/* Find the interpolated ISPs and convert to a[] for all subframes */
Int_isp(st->ispold, ispnew, interpol_frac, Aq);
/* update ispold[] for the next frame */
Copy(ispnew, st->ispold, M);
/* Check stability on isf : distance between old isf and current isf */
L_tmp = 0; move32();
for (i = 0; i < M - 1; i++)
{
tmp = sub(isf[i], st->isfold[i]);
L_tmp = L_mac(L_tmp, tmp, tmp);
}
tmp = extract_h(L_shl(L_tmp, 8));
tmp = mult(tmp, 26214); /* tmp = L_tmp*0.8/256 */
tmp = sub(20480, tmp); /* 1.25 - tmp */
stab_fac = shl(tmp, 1); /* Q14 -> Q15 with saturation */
test();
if (stab_fac < 0)
{
stab_fac = 0; move16();
}
Copy(st->isfold, isf_tmp, M);
Copy(isf, st->isfold, M);
/*------------------------------------------------------------------------*
* 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 and filter mode *
* - decode algebraic code *
* - decode pitch and codebook gains *
* - find voicing factor and tilt of code for next subframe. *
* - find the excitation and compute synthesis speech *
*------------------------------------------------------------------------*/
p_Aq = Aq; move16(); /* pointer to interpolated LPC parameters */
for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
{
pit_flag = i_subfr; move16();
test();test();
if ((sub(i_subfr, 2 * L_SUBFR) == 0) && (sub(nb_bits, NBBITS_7k) > 0))
{
pit_flag = 0; move16();
}
/*-------------------------------------------------*
* - Decode pitch lag *
* Lag indeces received also in case of BFI, *
* so that the parameter pointer stays in sync. *
*-------------------------------------------------*/
test();
if (pit_flag == 0)
{
test();
if (sub(nb_bits, NBBITS_9k) <= 0)
{
index = Serial_parm(8, &prms);
test();
if (sub(index, (PIT_FR1_8b - PIT_MIN) * 2) < 0)
{
T0 = add(PIT_MIN, shr(index, 1));
T0_frac = sub(index, shl(sub(T0, PIT_MIN), 1));
T0_frac = shl(T0_frac, 1);
} else
{
T0 = add(index, PIT_FR1_8b - ((PIT_FR1_8b - PIT_MIN) * 2));
T0_frac = 0; move16();
}
} else
{
index = Serial_parm(9, &prms);
test();test();
if (sub(index, (PIT_FR2 - PIT_MIN) * 4) < 0)
{
T0 = add(PIT_MIN, shr(index, 2));
T0_frac = sub(index, shl(sub(T0, PIT_MIN), 2));
} else if (sub(index, (((PIT_FR2 - PIT_MIN) * 4) + ((PIT_FR1_9b - PIT_FR2) * 2))) < 0)
{
index = sub(index, (PIT_FR2 - PIT_MIN) * 4);
T0 = add(PIT_FR2, shr(index, 1));
T0_frac = sub(index, shl(sub(T0, PIT_FR2), 1));
T0_frac = shl(T0_frac, 1);
} else
{
T0 = add(index, (PIT_FR1_9b - ((PIT_FR2 - PIT_MIN) * 4) - ((PIT_FR1_9b - PIT_FR2) * 2)));
T0_frac = 0; move16();
}
}
/* find T0_min and T0_max for subframe 2 and 4 */
T0_min = sub(T0, 8);
test();
if (sub(T0_min, PIT_MIN) < 0)
{
T0_min = PIT_MIN; move16();
}
T0_max = add(T0_min, 15);
test();
if (sub(T0_max, PIT_MAX) > 0)
{
T0_max = PIT_MAX; move16();
T0_min = sub(T0_max, 15);
}
} else
{ /* if subframe 2 or 4 */
test();
if (sub(nb_bits, NBBITS_9k) <= 0)
{
index = Serial_parm(5, &prms);
T0 = add(T0_min, shr(index, 1));
T0_frac = sub(index, shl(sub(T0, T0_min), 1));
T0_frac = shl(T0_frac, 1);
} else
{
index = Serial_parm(6, &prms);
T0 = add(T0_min, shr(index, 2));
T0_frac = sub(index, shl(sub(T0, T0_min), 2));
}
}
/* check BFI after pitch lag decoding */
test();
if (bfi != 0) /* if frame erasure */
{
lagconc(&(st->dec_gain[17]), st->lag_hist, &T0, &(st->old_T0), &(st->seed3), unusable_frame);
T0_frac = 0; move16();
}
/*-------------------------------------------------*
* - Find the pitch gain, the interpolation filter *
* and the adaptive codebook vector. *
*-------------------------------------------------*/
Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);
test();
if (unusable_frame)
{
select = 1; move16();
} else
{
test();
if (sub(nb_bits, NBBITS_9k) <= 0)
{
select = 0; move16();
} else
{
select = Serial_parm(1, &prms);
}
}
test();
if (select == 0)
{
/* find pitch excitation with lp filter */
for (i = 0; i < L_SUBFR; i++)
{
L_tmp = L_mult(5898, exc[i - 1 + i_subfr]);
L_tmp = L_mac(L_tmp, 20972, exc[i + i_subfr]);
L_tmp = L_mac(L_tmp, 5898, exc[i + 1 + i_subfr]);
code[i] = round(L_tmp); move16();
}
Copy(code, &exc[i_subfr], L_SUBFR);
}
/*-------------------------------------------------------*
* - Decode innovative codebook. *
* - Add the fixed-gain pitch contribution to code[]. *
*-------------------------------------------------------*/
test();test();test();test();test();test();test();test();
if (unusable_frame != 0)
{
/* the innovative code doesn't need to be scaled (see Q_gain2) */
for (i = 0; i < L_SUBFR; i++)
{
code[i] = shr(Random(&(st->seed)), 3); move16();
}
} else if (sub(nb_bits, NBBITS_7k) <= 0)
{
ind[0] = Serial_parm(12, &prms); move16();
DEC_ACELP_2t64_fx(ind[0], code);
} else if (sub(nb_bits, NBBITS_9k) <= 0)
{
for (i = 0; i < 4; i++)
{
ind[i] = Serial_parm(5, &prms); move16();
}
DEC_ACELP_4t64_fx(ind, 20, code);
} else if (sub(nb_bits, NBBITS_12k) <= 0)
{
for (i = 0; i < 4; i++)
{
ind[i] = Serial_parm(9, &prms); move16();
}
DEC_ACELP_4t64_fx(ind, 36, code);
} else if (sub(nb_bits, NBBITS_14k) <= 0)
{
ind[0] = Serial_parm(13, &prms); move16();
ind[1] = Serial_parm(13, &prms); move16();
ind[2] = Serial_parm(9, &prms);move16();
ind[3] = Serial_parm(9, &prms);move16();
DEC_ACELP_4t64_fx(ind, 44, code);
} else if (sub(nb_bits, NBBITS_16k) <= 0)
{
for (i = 0; i < 4; i++)
{
ind[i] = Serial_parm(13, &prms); move16();
}
DEC_ACELP_4t64_fx(ind, 52, code);
} else if (sub(nb_bits, NBBITS_18k) <= 0)
{
for (i = 0; i < 4; i++)
{
ind[i] = Serial_parm(2, &prms); move16();
}
for (i = 4; i < 8; i++)
{
ind[i] = Serial_parm(14, &prms); move16();
}
DEC_ACELP_4t64_fx(ind, 64, code);
} else if (sub(nb_bits, NBBITS_20k) <= 0)
{
ind[0] = Serial_parm(10, &prms); move16();
ind[1] = Serial_parm(10, &prms); move16();
ind[2] = Serial_parm(2, &prms);move16();
ind[3] = Serial_parm(2, &prms);move16();
ind[4] = Serial_parm(10, &prms); move16();
ind[5] = Serial_parm(10, &prms); move16();
ind[6] = Serial_parm(14, &prms); move16();
ind[7] = Serial_parm(14, &prms); move16();
DEC_ACELP_4t64_fx(ind, 72, code);
} else
{
for (i = 0; i < 4; i++)
{
ind[i] = Serial_parm(11, &prms); move16();
}
for (i = 4; i < 8; i++)
{
ind[i] = Serial_parm(11, &prms); move16();
}
DEC_ACELP_4t64_fx(ind, 88, code);
}
tmp = 0; move16();
Preemph(code, st->tilt_code, L_SUBFR, &tmp);
tmp = T0; move16();
test();
if (sub(T0_frac, 2) > 0)
{
tmp = add(tmp, 1);
}
Pit_shrp(code, tmp, PIT_SHARP, L_SUBFR);
/*-------------------------------------------------*
* - Decode codebooks gains. *
*-------------------------------------------------*/
test();
if (sub(nb_bits, NBBITS_9k) <= 0)
{
index = Serial_parm(6, &prms); /* codebook gain index */
D_gain2(index, 6, code, L_SUBFR, &gain_pit, &L_gain_code, bfi, st->prev_bfi, st->state, unusable_frame, st->vad_hist, st->dec_gain);
} else
{
index = Serial_parm(7, &prms); /* codebook gain index */
D_gain2(index, 7, code, L_SUBFR, &gain_pit, &L_gain_code, bfi, st->prev_bfi, st->state, unusable_frame, st->vad_hist, st->dec_gain);
}
/* find best scaling to perform on excitation (Q_new) */
tmp = st->Qsubfr[0];
for (i = 1; i < 4; i++)
{
test();move16();
if (sub(st->Qsubfr[i], tmp) < 0)
{
tmp = st->Qsubfr[i]; move16();
}
}
/* limit scaling (Q_new) to Q_MAX: see cnst.h and syn_filt_32() */
test();
if (sub(tmp, Q_MAX) > 0)
{
tmp = Q_MAX; move16();
}
Q_new = 0; move16();
L_tmp = L_gain_code; move32(); /* L_gain_code in Q16 */
test();test();
while ((L_sub(L_tmp, 0x08000000L) < 0) && (sub(Q_new, tmp) < 0))
{
L_tmp = L_shl(L_tmp, 1);
Q_new = add(Q_new, 1);
test();test();
}
gain_code = round(L_tmp); /* scaled gain_code with Qnew */
Scale_sig(exc + i_subfr - (PIT_MAX + L_INTERPOL),
PIT_MAX + L_INTERPOL + L_SUBFR, sub(Q_new, st->Q_old));
st->Q_old = Q_new; move16();
/*----------------------------------------------------------*
* Update parameters for the next subframe. *
* - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) *
*----------------------------------------------------------*/
test();
if (bfi == 0)
{
/* LTP-Lag history update */
for (i = 4; i > 0; i--)
{
st->lag_hist[i] = st->lag_hist[i - 1]; move16();
}
st->lag_hist[0] = T0; move16();
st->old_T0 = T0; move16();
st->old_T0_frac = 0; move16(); /* Remove fraction in case of BFI */
}
/* find voice factor in Q15 (1=voiced, -1=unvoiced) */
Copy(&exc[i_subfr], exc2, L_SUBFR);
Scale_sig(exc2, L_SUBFR, -3);
/* post processing of excitation elements */
test();
if (sub(nb_bits, NBBITS_9k) <= 0)
{
pit_sharp = shl(gain_pit, 1);
test();
if (sub(pit_sharp, 16384) > 0)
{
for (i = 0; i < L_SUBFR; i++)
{
tmp = mult(exc2[i], pit_sharp);
L_tmp = L_mult(tmp, gain_pit);
L_tmp = L_shr(L_tmp, 1);
excp[i] = round(L_tmp);
move16();
}
}
} else
{
pit_sharp = 0; move16();
}
voice_fac = voice_factor(exc2, -3, gain_pit, code, gain_code, L_SUBFR);
/* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
st->tilt_code = add(shr(voice_fac, 2), 8192); move16();
/*-------------------------------------------------------*
* - Find the total excitation. *
* - Find synthesis speech corresponding to exc[]. *
*-------------------------------------------------------*/
Copy(&exc[i_subfr], exc2, L_SUBFR);
for (i = 0; i < L_SUBFR; i++)
{
L_tmp = L_mult(code[i], gain_code);
L_tmp = L_shl(L_tmp, 5);
L_tmp = L_mac(L_tmp, exc[i + i_subfr], gain_pit);
L_tmp = L_shl(L_tmp, 1);
exc[i + i_subfr] = round(L_tmp); move16();
}
/* find maximum value of excitation for next scaling */
max = 1; move16();
for (i = 0; i < L_SUBFR; i++)
{
tmp = abs_s(exc[i + i_subfr]);
test();
if (sub(tmp, max) > 0)
{
max = tmp; move16();
}
}
/* tmp = scaling possible according to max value of excitation */
tmp = sub(add(norm_s(max), Q_new), 1);
st->Qsubfr[3] = st->Qsubfr[2]; move16();
st->Qsubfr[2] = st->Qsubfr[1]; move16();
st->Qsubfr[1] = st->Qsubfr[0]; move16();
st->Qsubfr[0] = tmp; move16();
/*------------------------------------------------------------*
* phase dispersion to enhance noise in low bit rate *
*------------------------------------------------------------*/
/* L_gain_code in Q16 */
L_Extract(L_gain_code, &gain_code, &gain_code_lo);
test();test();move16();
if (sub(nb_bits, NBBITS_7k) <= 0)
j = 0; /* high dispersion for rate <= 7.5 kbit/s */
else if (sub(nb_bits, NBBITS_9k) <= 0)
j = 1; /* low dispersion for rate <= 9.6 kbit/s */
else
j = 2; /* no dispersion for rate > 9.6 kbit/s */
Phase_dispersion(gain_code, gain_pit, code, j, st->disp_mem);
/*------------------------------------------------------------*
* noise enhancer *
* ~~~~~~~~~~~~~~ *
* - Enhance excitation on noise. (modify gain of code) *
* If signal is noisy and LPC filter is stable, move gain *
* of code 1.5 dB toward gain of code threshold. *
* This decrease by 3 dB noise energy variation. *
*------------------------------------------------------------*/
tmp = sub(16384, shr(voice_fac, 1)); /* 1=unvoiced, 0=voiced */
fac = mult(stab_fac, tmp);
L_tmp = L_gain_code; move32();
test();
if (L_sub(L_tmp, st->L_gc_thres) < 0)
{
L_tmp = L_add(L_tmp, Mpy_32_16(gain_code, gain_code_lo, 6226));
test();
if (L_sub(L_tmp, st->L_gc_thres) > 0)
{
L_tmp = st->L_gc_thres; move32();
}
} else
{
L_tmp = Mpy_32_16(gain_code, gain_code_lo, 27536);
test();
if (L_sub(L_tmp, st->L_gc_thres) < 0)
{
L_tmp = st->L_gc_thres; move32();
}
}
st->L_gc_thres = L_tmp; move32();
L_gain_code = Mpy_32_16(gain_code, gain_code_lo, sub(32767, fac));
L_Extract(L_tmp, &gain_code, &gain_code_lo);
L_gain_code = L_add(L_gain_code, Mpy_32_16(gain_code, gain_code_lo, fac));
/*------------------------------------------------------------*
* pitch enhancer *
* ~~~~~~~~~~~~~~ *
* - Enhance excitation on voice. (HP filtering of code) *
* On voiced signal, filtering of code by a smooth fir HP *
* filter to decrease energy of code in low frequency. *
*------------------------------------------------------------*/
tmp = add(shr(voice_fac, 3), 4096);/* 0.25=voiced, 0=unvoiced */
L_tmp = L_deposit_h(code[0]);
L_tmp = L_msu(L_tmp, code[1], tmp);
code2[0] = round(L_tmp);
move16();
for (i = 1; i < L_SUBFR - 1; i++)
{
L_tmp = L_deposit_h(code[i]);
L_tmp = L_msu(L_tmp, code[i + 1], tmp);
L_tmp = L_msu(L_tmp, code[i - 1], tmp);
code2[i] = round(L_tmp);
move16();
}
L_tmp = L_deposit_h(code[L_SUBFR - 1]);
L_tmp = L_msu(L_tmp, code[L_SUBFR - 2], tmp);
code2[L_SUBFR - 1] = round(L_tmp);
move16();
/* build excitation */
gain_code = round(L_shl(L_gain_code, Q_new));
for (i = 0; i < L_SUBFR; i++)
{
L_tmp = L_mult(code2[i], gain_code);
L_tmp = L_shl(L_tmp, 5);
L_tmp = L_mac(L_tmp, exc2[i], gain_pit);
L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */
exc2[i] = round(L_tmp);
move16();
}
if (sub(nb_bits, NBBITS_9k) <= 0)
{
if (sub(pit_sharp, 16384) > 0)
{
for (i = 0; i < L_SUBFR; i++)
{
excp[i] = add(excp[i], exc2[i]);
move16();
}
agc2(exc2, excp, L_SUBFR);
Copy(excp, exc2, L_SUBFR);
}
}
if (sub(nb_bits, NBBITS_7k) <= 0)
{
j = shr(i_subfr, 6);
for (i = 0; i < M; i++)
{
L_tmp = L_mult(isf_tmp[i], sub(32767, interpol_frac[j]));
L_tmp = L_mac(L_tmp, isf[i], interpol_frac[j]);
HfIsf[i] = round(L_tmp);
}
} else
{
Set_zero(st->mem_syn_hf, M16k - M);
}
if (sub(nb_bits, NBBITS_24k) >= 0)
{
corr_gain = Serial_parm(4, &prms);
synthesis(p_Aq, exc2, Q_new, &synth16k[i_subfr * 5 / 4], corr_gain, HfIsf, nb_bits, newDTXState, st, bfi);
} else
synthesis(p_Aq, exc2, Q_new, &synth16k[i_subfr * 5 / 4], 0, HfIsf, nb_bits, newDTXState, st, bfi);
p_Aq += (M + 1); /* interpolated LPC parameters for next subframe */
}
/*--------------------------------------------------*
* Update signal for next frame. *
* -> save past of exc[]. *
* -> save pitch parameters. *
*--------------------------------------------------*/
Copy(&old_exc[L_FRAME], st->old_exc, PIT_MAX + L_INTERPOL);
Scale_sig(exc, L_FRAME, sub(0, Q_new));
dtx_dec_activity_update(st->dtx_decSt, isf, exc);
st->dtx_decSt->dtxGlobalState = newDTXState; move16();
st->prev_bfi = bfi; move16();
return;
}
/*-----------------------------------------------------*
* Function synthesis() *
* *
* Synthesis of signal at 16kHz with HF extension. *
* *
*-----------------------------------------------------*/
static void synthesis(
Word16 Aq[], /* A(z) : quantized Az */
Word16 exc[], /* (i) : excitation at 12kHz */
Word16 Q_new, /* (i) : scaling performed on exc */
Word16 synth16k[], /* (o) : 16kHz synthesis signal */
Word16 prms, /* (i) : parameter */
Word16 HfIsf[],
Word16 nb_bits,
Word16 newDTXState,
Decoder_State * st, /* (i/o) : State structure */
Word16 bfi /* (i) : bad frame indicator */
)
{
Word16 i, fac, tmp, exp;
Word16 ener, exp_ener;
Word32 L_tmp;
Word16 synth_hi[M + L_SUBFR], synth_lo[M + L_SUBFR];
Word16 synth[L_SUBFR];
Word16 HF[L_SUBFR16k]; /* High Frequency vector */
Word16 Ap[M16k + 1];
Word16 HfA[M16k + 1];
Word16 HF_corr_gain;
Word16 HF_gain_ind;
Word16 gain1, gain2;
Word16 weight1, weight2;
/*------------------------------------------------------------*
* speech synthesis *
* ~~~~~~~~~~~~~~~~ *
* - Find synthesis speech corresponding to exc2[]. *
* - Perform fixed deemphasis and hp 50hz filtering. *
* - Oversampling from 12.8kHz to 16kHz. *
*------------------------------------------------------------*/
Copy(st->mem_syn_hi, synth_hi, M);
Copy(st->mem_syn_lo, synth_lo, M);
Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);
Copy(synth_hi + L_SUBFR, st->mem_syn_hi, M);
Copy(synth_lo + L_SUBFR, st->mem_syn_lo, M);
Deemph_32(synth_hi + M, synth_lo + M, synth, PREEMPH_FAC, L_SUBFR, &(st->mem_deemph));
HP50_12k8(synth, L_SUBFR, st->mem_sig_out);
Oversamp_16k(synth, L_SUBFR, synth16k, st->mem_oversamp);
/*------------------------------------------------------*
* HF noise synthesis *
* ~~~~~~~~~~~~~~~~~~ *
* - Generate HF noise between 5.5 and 7.5 kHz. *
* - Set energy of noise according to synthesis tilt. *
* tilt > 0.8 ==> - 14 dB (voiced) *
* tilt 0.5 ==> - 6 dB (voiced or noise) *
* tilt < 0.0 ==> 0 dB (noise) *
*------------------------------------------------------*/
/* generate white noise vector */
for (i = 0; i < L_SUBFR16k; i++)
{
HF[i] = shr(Random(&(st->seed2)), 3); move16();
}
/* energy of excitation */
Scale_sig(exc, L_SUBFR, -3);
Q_new = sub(Q_new, 3);
ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener));
exp_ener = sub(exp_ener, add(Q_new, Q_new));
/* set energy of white noise to energy of excitation */
tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
test();
if (sub(tmp, ener) > 0)
{
tmp = shr(tmp, 1); /* Be sure tmp < ener */
exp = add(exp, 1);
}
L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */
exp = sub(exp, exp_ener);
Isqrt_n(&L_tmp, &exp);
L_tmp = L_shl(L_tmp, add(exp, 1)); /* L_tmp x 2, L_tmp in Q31 */
tmp = extract_h(L_tmp); /* tmp = 2 x sqrt(ener_exc/ener_hf) */
for (i = 0; i < L_SUBFR16k; i++)
{
HF[i] = mult(HF[i], tmp); move16();
}
/* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */
HP400_12k8(synth, L_SUBFR, st->mem_hp400);
L_tmp = 1L; move32();
for (i = 0; i < L_SUBFR; i++)
L_tmp = L_mac(L_tmp, synth[i], synth[i]);
exp = norm_l(L_tmp);
ener = extract_h(L_shl(L_tmp, exp)); /* ener = r[0] */
L_tmp = 1L; move32();
for (i = 1; i < L_SUBFR; i++)
L_tmp = L_mac(L_tmp, synth[i], synth[i - 1]);
tmp = extract_h(L_shl(L_tmp, exp)); /* tmp = r[1] */
test();
if (tmp > 0)
{
fac = div_s(tmp, ener);
} else
{
fac = 0; move16();
}
/* modify energy of white noise according to synthesis tilt */
gain1 = sub(32767, fac);
gain2 = mult(sub(32767, fac), 20480);
gain2 = shl(gain2, 1);
test();
if (st->vad_hist > 0)
{
weight1 = 0; move16();
weight2 = 32767; move16();
} else
{
weight1 = 32767; move16();
weight2 = 0; move16();
}
tmp = mult(weight1, gain1);
tmp = add(tmp, mult(weight2, gain2));
test();
if (tmp != 0)
{
tmp = add(tmp, 1);
}
test();
if (sub(tmp, 3277) < 0)
{
tmp = 3277; /* 0.1 in Q15 */
move16();
}
test(); test();
if ((sub(nb_bits, NBBITS_24k) >= 0 ) && (bfi == 0))
{
/* HF correction gain */
HF_gain_ind = prms;
HF_corr_gain = HP_gain[HF_gain_ind];
/* HF gain */
for (i = 0; i < L_SUBFR16k; i++)
{
HF[i] = shl(mult(HF[i], HF_corr_gain), 1); move16();
}
} else
{
for (i = 0; i < L_SUBFR16k; i++)
{
HF[i] = mult(HF[i], tmp); move16();
}
}
test();test();
if ((sub(nb_bits, NBBITS_7k) <= 0) && (sub(newDTXState, SPEECH) == 0))
{
Isf_Extrapolation(HfIsf);
Isp_Az(HfIsf, HfA, M16k, 0);
Weight_a(HfA, Ap, 29491, M16k); /* fac=0.9 */
Syn_filt(Ap, M16k, HF, HF, L_SUBFR16k, st->mem_syn_hf, 1);
} else
{
/* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */
Weight_a(Aq, Ap, 19661, M); /* fac=0.6 */
Syn_filt(Ap, M, HF, HF, L_SUBFR16k, st->mem_syn_hf + (M16k - M), 1);
}
/* noise High Pass filtering (1ms of delay) */
Filt_6k_7k(HF, L_SUBFR16k, st->mem_hf);
test();
if (sub(nb_bits, NBBITS_24k) >= 0)
{
/* Low Pass filtering (7 kHz) */
Filt_7k(HF, L_SUBFR16k, st->mem_hf3);
}
/* add filtered HF noise to speech synthesis */
for (i = 0; i < L_SUBFR16k; i++)
{
synth16k[i] = add(synth16k[i], HF[i]); move16();
}
return;
}