diff options
Diffstat (limited to 'media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp')
-rw-r--r-- | media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp | 1149 |
1 files changed, 1149 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp new file mode 100644 index 0000000..b8cfefa --- /dev/null +++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp @@ -0,0 +1,1149 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +/**************************************************************************************** +Portions of this file are derived from the following 3GPP standard: + + 3GPP TS 26.173 + ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec + Available from http://www.3gpp.org + +(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC) +Permission to distribute, modify and use this file under the standard license +terms listed above has been obtained from the copyright holder. +****************************************************************************************/ +/* +------------------------------------------------------------------------------ + + + + Filename: pvamrwbdecoder.cpp + + Date: 05/08/2004 + +------------------------------------------------------------------------------ + REVISION HISTORY + + + Description: + +------------------------------------------------------------------------------ + INPUT AND OUTPUT DEFINITIONS + + int16 mode, input : used mode + int16 prms[], input : parameter vector + int16 synth16k[], output: synthesis speech + int16 * frame_length, output: lenght of the frame + void *spd_state, i/o : State structure + int16 frame_type, input : received frame type + int16 ScratchMem[] + +------------------------------------------------------------------------------ + FUNCTION DESCRIPTION + + Performs the main decoder routine AMR WB ACELP coding algorithm with 20 ms + speech frames for wideband speech signals. + + +------------------------------------------------------------------------------ + REQUIREMENTS + + +------------------------------------------------------------------------------ + REFERENCES + +------------------------------------------------------------------------------ + PSEUDO-CODE + +------------------------------------------------------------------------------ +*/ + + +/*---------------------------------------------------------------------------- +; INCLUDES +----------------------------------------------------------------------------*/ + +#include "pv_amr_wb_type_defs.h" +#include "pvamrwbdecoder_mem_funcs.h" +#include "pvamrwbdecoder_basic_op.h" +#include "pvamrwbdecoder_cnst.h" +#include "pvamrwbdecoder_acelp.h" +#include "e_pv_amrwbdec.h" +#include "get_amr_wb_bits.h" +#include "pvamrwb_math_op.h" +#include "pvamrwbdecoder_api.h" +#include "pvamrwbdecoder.h" +#include "synthesis_amr_wb.h" + + +/*---------------------------------------------------------------------------- +; MACROS +; Define module specific macros here +----------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------- +; DEFINES +; Include all pre-processor statements here. Include conditional +; compile variables also. +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; LOCAL STORE/BUFFER/POINTER DEFINITIONS +; Variable declaration - defined here and used outside this module +----------------------------------------------------------------------------*/ + +/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */ +static const int16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767}; + + +/* isp tables for initialization */ + +static const int16 isp_init[M] = +{ + 32138, 30274, 27246, 23170, 18205, 12540, 6393, 0, + -6393, -12540, -18205, -23170, -27246, -30274, -32138, 1475 +}; + +static const int16 isf_init[M] = +{ + 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, + 9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840 +}; + +/*---------------------------------------------------------------------------- +; EXTERNAL FUNCTION REFERENCES +; Declare functions defined elsewhere and referenced in this module +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES +; Declare variables used in this module but defined elsewhere +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; FUNCTION CODE +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + FUNCTION DESCRIPTION pvDecoder_AmrWb_Init + + Initialization of variables for the decoder section. + +----------------------------------------------------------------------------*/ + + + + +void pvDecoder_AmrWb_Init(void **spd_state, void *pt_st, int16 **ScratchMem) +{ + /* Decoder states */ + Decoder_State *st = &(((PV_AmrWbDec *)pt_st)->state); + + *ScratchMem = ((PV_AmrWbDec *)pt_st)->ScratchMem; + /* + * Init dtx decoding + */ + dtx_dec_amr_wb_reset(&(st->dtx_decSt), isf_init); + + pvDecoder_AmrWb_Reset((void *) st, 1); + + *spd_state = (void *) st; + + return; +} + +/*---------------------------------------------------------------------------- +; FUNCTION CODE +----------------------------------------------------------------------------*/ + +void pvDecoder_AmrWb_Reset(void *st, int16 reset_all) +{ + int16 i; + + Decoder_State *dec_state; + + dec_state = (Decoder_State *) st; + + pv_memset((void *)dec_state->old_exc, + 0, + (PIT_MAX + L_INTERPOL)*sizeof(*dec_state->old_exc)); + + pv_memset((void *)dec_state->past_isfq, + 0, + M*sizeof(*dec_state->past_isfq)); + + + dec_state->old_T0_frac = 0; /* old pitch value = 64.0 */ + dec_state->old_T0 = 64; + dec_state->first_frame = 1; + dec_state->L_gc_thres = 0; + dec_state->tilt_code = 0; + + pv_memset((void *)dec_state->disp_mem, + 0, + 8*sizeof(*dec_state->disp_mem)); + + + /* scaling memories for excitation */ + dec_state->Q_old = Q_MAX; + dec_state->Qsubfr[3] = Q_MAX; + dec_state->Qsubfr[2] = Q_MAX; + dec_state->Qsubfr[1] = Q_MAX; + dec_state->Qsubfr[0] = Q_MAX; + + if (reset_all != 0) + { + /* routines initialization */ + + dec_gain2_amr_wb_init(dec_state->dec_gain); + oversamp_12k8_to_16k_init(dec_state->mem_oversamp); + band_pass_6k_7k_init(dec_state->mem_hf); + low_pass_filt_7k_init(dec_state->mem_hf3); + highpass_50Hz_at_12k8_init(dec_state->mem_sig_out); + highpass_400Hz_at_12k8_init(dec_state->mem_hp400); + Init_Lagconc(dec_state->lag_hist); + + /* isp initialization */ + + pv_memcpy((void *)dec_state->ispold, (void *)isp_init, M*sizeof(*isp_init)); + + pv_memcpy((void *)dec_state->isfold, (void *)isf_init, M*sizeof(*isf_init)); + for (i = 0; i < L_MEANBUF; i++) + { + pv_memcpy((void *)&dec_state->isf_buf[i * M], + (void *)isf_init, + M*sizeof(*isf_init)); + } + /* variable initialization */ + + dec_state->mem_deemph = 0; + + dec_state->seed = 21845; /* init random with 21845 */ + dec_state->seed2 = 21845; + dec_state->seed3 = 21845; + + dec_state->state = 0; + dec_state->prev_bfi = 0; + + /* Static vectors to zero */ + + pv_memset((void *)dec_state->mem_syn_hf, + 0, + M16k*sizeof(*dec_state->mem_syn_hf)); + + pv_memset((void *)dec_state->mem_syn_hi, + 0, + M*sizeof(*dec_state->mem_syn_hi)); + + pv_memset((void *)dec_state->mem_syn_lo, + 0, + M*sizeof(*dec_state->mem_syn_lo)); + + + dtx_dec_amr_wb_reset(&(dec_state->dtx_decSt), isf_init); + dec_state->vad_hist = 0; + + } + return; +} + +/*---------------------------------------------------------------------------- +; FUNCTION CODE +----------------------------------------------------------------------------*/ + +int32 pvDecoder_AmrWbMemRequirements() +{ + return(sizeof(PV_AmrWbDec)); +} + + +/*---------------------------------------------------------------------------- +; FUNCTION CODE +----------------------------------------------------------------------------*/ + +/* Main decoder routine. */ + +int32 pvDecoder_AmrWb( + int16 mode, /* input : used mode */ + int16 prms[], /* input : parameter vector */ + int16 synth16k[], /* output: synthesis speech */ + int16 * frame_length, /* output: lenght of the frame */ + void *spd_state, /* i/o : State structure */ + int16 frame_type, /* input : received frame type */ + int16 ScratchMem[] +) +{ + + /* Decoder states */ + Decoder_State *st; + + int16 *ScratchMem2 = &ScratchMem[ L_SUBFR + L_SUBFR16k + ((L_SUBFR + M + M16k +1)<<1)]; + + + /* Excitation vector */ + + + int16 *old_exc = ScratchMem2; + + int16 *Aq = &old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL];/* A(z) quantized for the 4 subframes */ + + int16 *ispnew = &Aq[NB_SUBFR * (M + 1)];/* immittance spectral pairs at 4nd sfr */ + int16 *isf = &ispnew[M]; /* ISF (frequency domain) at 4nd sfr */ + int16 *isf_tmp = &isf[M]; + int16 *code = &isf_tmp[M]; /* algebraic codevector */ + int16 *excp = &code[L_SUBFR]; + int16 *exc2 = &excp[L_SUBFR]; /* excitation vector */ + int16 *HfIsf = &exc2[L_FRAME]; + + + int16 *exc; + + /* LPC coefficients */ + + int16 *p_Aq; /* ptr to A(z) for the 4 subframes */ + + + + int16 fac, stab_fac, voice_fac, Q_new = 0; + int32 L_tmp, L_gain_code; + + /* Scalars */ + + int16 i, j, i_subfr, index, ind[8], tmp; + int32 max; + int16 T0, T0_frac, pit_flag, T0_max, select, T0_min = 0; + int16 gain_pit, gain_code; + int16 newDTXState, bfi, unusable_frame, nb_bits; + int16 vad_flag; + int16 pit_sharp; + + int16 corr_gain = 0; + + st = (Decoder_State *) spd_state; + + /* mode verification */ + + nb_bits = AMR_WB_COMPRESSED[mode]; + + *frame_length = AMR_WB_PCM_FRAME; + + /* find the new DTX state SPEECH OR DTX */ + newDTXState = rx_amr_wb_dtx_handler(&(st->dtx_decSt), frame_type); + + + if (newDTXState != SPEECH) + { + dtx_dec_amr_wb(&(st->dtx_decSt), exc2, newDTXState, isf, &prms); + } + /* SPEECH action state machine */ + + if ((frame_type == RX_SPEECH_BAD) || + (frame_type == RX_SPEECH_PROBABLY_DEGRADED)) + { + /* bfi for all index, bits are not usable */ + bfi = 1; + unusable_frame = 0; + } + else if ((frame_type == RX_NO_DATA) || + (frame_type == RX_SPEECH_LOST)) + { + /* bfi only for lsf, gains and pitch period */ + bfi = 1; + unusable_frame = 1; + } + else + { + bfi = 0; + unusable_frame = 0; + } + + if (bfi != 0) + { + st->state += 1; + + if (st->state > 6) + { + st->state = 6; + } + } + else + { + st->state >>= 1; + } + + /* 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->dtx_decSt.dtxGlobalState == DTX) + { + st->state = 5; + st->prev_bfi = 0; + } + else if (st->dtx_decSt.dtxGlobalState == DTX_MUTE) + { + st->state = 5; + st->prev_bfi = 1; + } + + if (newDTXState == SPEECH) + { + vad_flag = Serial_parm_1bit(&prms); + + if (bfi == 0) + { + if (vad_flag == 0) + { + st->vad_hist = add_int16(st->vad_hist, 1); + } + else + { + st->vad_hist = 0; + } + } + } + /* + * DTX-CNG + */ + + if (newDTXState != SPEECH) /* 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); + + pv_memcpy((void *)isf_tmp, (void *)st->isfold, M*sizeof(*isf_tmp)); + + + for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) + { + j = i_subfr >> 6; + + for (i = 0; i < M; i++) + { + L_tmp = mul_16by16_to_int32(isf_tmp[i], sub_int16(32767, interpol_frac[j])); + L_tmp = mac_16by16_to_int32(L_tmp, isf[i], interpol_frac[j]); + HfIsf[i] = amr_wb_round(L_tmp); + } + + synthesis_amr_wb(Aq, + &exc2[i_subfr], + 0, + &synth16k[i_subfr *5/4], + (short) 1, + HfIsf, + nb_bits, + newDTXState, + st, + bfi, + ScratchMem); + } + + /* reset speech coder memories */ + pvDecoder_AmrWb_Reset(st, 0); + + pv_memcpy((void *)st->isfold, (void *)isf, M*sizeof(*isf)); + + st->prev_bfi = bfi; + st->dtx_decSt.dtxGlobalState = newDTXState; + + return 0; + } + /* + * ACELP + */ + + /* copy coder memory state into working space (internal memory for DSP) */ + + pv_memcpy((void *)old_exc, (void *)st->old_exc, (PIT_MAX + L_INTERPOL)*sizeof(*old_exc)); + + exc = old_exc + PIT_MAX + L_INTERPOL; + + /* Decode the ISFs */ + + if (nb_bits > NBBITS_7k) /* all rates but 6.6 Kbps */ + { + ind[0] = Serial_parm(8, &prms); /* index of 1st ISP subvector */ + ind[1] = Serial_parm(8, &prms); /* index of 2nd ISP subvector */ + ind[2] = Serial_parm(6, &prms); /* index of 3rd ISP subvector */ + ind[3] = Serial_parm(7, &prms); /* index of 4th ISP subvector */ + ind[4] = Serial_parm(7, &prms); /* index of 5th ISP subvector */ + ind[5] = Serial_parm(5, &prms); /* index of 6th ISP subvector */ + ind[6] = Serial_parm(5, &prms); /* index of 7th ISP subvector */ + + Dpisf_2s_46b(ind, isf, st->past_isfq, st->isfold, st->isf_buf, bfi, 1); + } + else + { + ind[0] = Serial_parm(8, &prms); + ind[1] = Serial_parm(8, &prms); + ind[2] = Serial_parm(14, &prms); + ind[3] = ind[2] & 0x007F; + ind[2] >>= 7; + ind[4] = Serial_parm(6, &prms); + + Dpisf_2s_36b(ind, isf, st->past_isfq, st->isfold, st->isf_buf, bfi, 1); + } + + /* Convert ISFs to the cosine domain */ + + Isf_isp(isf, ispnew, M); + + if (st->first_frame != 0) + { + st->first_frame = 0; + pv_memcpy((void *)st->ispold, (void *)ispnew, M*sizeof(*ispnew)); + + } + /* Find the interpolated ISPs and convert to a[] for all subframes */ + interpolate_isp(st->ispold, ispnew, interpol_frac, Aq); + + /* update ispold[] for the next frame */ + pv_memcpy((void *)st->ispold, (void *)ispnew, M*sizeof(*ispnew)); + + /* Check stability on isf : distance between old isf and current isf */ + + L_tmp = 0; + for (i = 0; i < M - 1; i++) + { + tmp = sub_int16(isf[i], st->isfold[i]); + L_tmp = mac_16by16_to_int32(L_tmp, tmp, tmp); + } + tmp = extract_h(shl_int32(L_tmp, 8)); + tmp = mult_int16(tmp, 26214); /* tmp = L_tmp*0.8/256 */ + + tmp = 20480 - tmp; /* 1.25 - tmp */ + stab_fac = shl_int16(tmp, 1); /* Q14 -> Q15 with saturation */ + + if (stab_fac < 0) + { + stab_fac = 0; + } + pv_memcpy((void *)isf_tmp, (void *)st->isfold, M*sizeof(*isf_tmp)); + + pv_memcpy((void *)st->isfold, (void *)isf, M*sizeof(*isf)); + + /* + * 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; /* pointer to interpolated LPC parameters */ + + + /* + * Sub process next 3 subframes + */ + + + for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) + { + pit_flag = i_subfr; + + + if ((i_subfr == 2*L_SUBFR) && (nb_bits > NBBITS_7k)) + { + pit_flag = 0; /* set to 0 for 3rd subframe, <=> is not 6.6 kbps */ + } + /*-------------------------------------------------* + * - Decode pitch lag * + * Lag indeces received also in case of BFI, * + * so that the parameter pointer stays in sync. * + *-------------------------------------------------*/ + + if (pit_flag == 0) + { + + if (nb_bits <= NBBITS_9k) + { + index = Serial_parm(8, &prms); + + if (index < (PIT_FR1_8b - PIT_MIN) * 2) + { + T0 = PIT_MIN + (index >> 1); + T0_frac = sub_int16(index, shl_int16(sub_int16(T0, PIT_MIN), 1)); + T0_frac = shl_int16(T0_frac, 1); + } + else + { + T0 = add_int16(index, PIT_FR1_8b - ((PIT_FR1_8b - PIT_MIN) * 2)); + T0_frac = 0; + } + } + else + { + index = Serial_parm(9, &prms); + + if (index < (PIT_FR2 - PIT_MIN) * 4) + { + T0 = PIT_MIN + (index >> 2); + T0_frac = sub_int16(index, shl_int16(sub_int16(T0, PIT_MIN), 2)); + } + else if (index < (((PIT_FR2 - PIT_MIN) << 2) + ((PIT_FR1_9b - PIT_FR2) << 1))) + { + index -= (PIT_FR2 - PIT_MIN) << 2; + T0 = PIT_FR2 + (index >> 1); + T0_frac = sub_int16(index, shl_int16(sub_int16(T0, PIT_FR2), 1)); + T0_frac = shl_int16(T0_frac, 1); + } + else + { + T0 = add_int16(index, (PIT_FR1_9b - ((PIT_FR2 - PIT_MIN) * 4) - ((PIT_FR1_9b - PIT_FR2) * 2))); + T0_frac = 0; + } + } + + /* find T0_min and T0_max for subframe 2 and 4 */ + + T0_min = T0 - 8; + + if (T0_min < PIT_MIN) + { + T0_min = PIT_MIN; + } + T0_max = T0_min + 15; + + if (T0_max > PIT_MAX) + { + T0_max = PIT_MAX; + T0_min = PIT_MAX - 15; + } + } + else + { /* if subframe 2 or 4 */ + + if (nb_bits <= NBBITS_9k) + { + index = Serial_parm(5, &prms); + + T0 = T0_min + (index >> 1); + T0_frac = sub_int16(index, shl_int16(T0 - T0_min, 1)); + T0_frac = shl_int16(T0_frac, 1); + } + else + { + index = Serial_parm(6, &prms); + + T0 = T0_min + (index >> 2); + T0_frac = sub_int16(index, shl_int16(T0 - T0_min, 2)); + } + } + + /* check BFI after pitch lag decoding */ + + if (bfi != 0) /* if frame erasure */ + { + lagconceal(&(st->dec_gain[17]), st->lag_hist, &T0, &(st->old_T0), &(st->seed3), unusable_frame); + T0_frac = 0; + } + /* + * Find the pitch gain, the interpolation filter + * and the adaptive codebook vector. + */ + + Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1); + + + if (unusable_frame) + { + select = 1; + } + else + { + + if (nb_bits <= NBBITS_9k) + { + select = 0; + } + else + { + select = Serial_parm_1bit(&prms); + } + } + + + if (select == 0) + { + /* find pitch excitation with lp filter */ + for (i = 0; i < L_SUBFR; i++) + { + L_tmp = ((int32) exc[i-1+i_subfr] + exc[i+1+i_subfr]); + L_tmp *= 5898; + L_tmp += ((int32) exc[i+i_subfr] * 20972); + + code[i] = amr_wb_round(L_tmp << 1); + } + pv_memcpy((void *)&exc[i_subfr], (void *)code, L_SUBFR*sizeof(*code)); + + } + /* + * Decode innovative codebook. + * Add the fixed-gain pitch contribution to code[]. + */ + + 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] = noise_gen_amrwb(&(st->seed)) >> 3; + } + } + else if (nb_bits <= NBBITS_7k) + { + ind[0] = Serial_parm(12, &prms); + dec_acelp_2p_in_64(ind[0], code); + } + else if (nb_bits <= NBBITS_9k) + { + for (i = 0; i < 4; i++) + { + ind[i] = Serial_parm(5, &prms); + } + dec_acelp_4p_in_64(ind, 20, code); + } + else if (nb_bits <= NBBITS_12k) + { + for (i = 0; i < 4; i++) + { + ind[i] = Serial_parm(9, &prms); + } + dec_acelp_4p_in_64(ind, 36, code); + } + else if (nb_bits <= NBBITS_14k) + { + ind[0] = Serial_parm(13, &prms); + ind[1] = Serial_parm(13, &prms); + ind[2] = Serial_parm(9, &prms); + ind[3] = Serial_parm(9, &prms); + dec_acelp_4p_in_64(ind, 44, code); + } + else if (nb_bits <= NBBITS_16k) + { + for (i = 0; i < 4; i++) + { + ind[i] = Serial_parm(13, &prms); + } + dec_acelp_4p_in_64(ind, 52, code); + } + else if (nb_bits <= NBBITS_18k) + { + for (i = 0; i < 4; i++) + { + ind[i] = Serial_parm(2, &prms); + } + for (i = 4; i < 8; i++) + { + ind[i] = Serial_parm(14, &prms); + } + dec_acelp_4p_in_64(ind, 64, code); + } + else if (nb_bits <= NBBITS_20k) + { + ind[0] = Serial_parm(10, &prms); + ind[1] = Serial_parm(10, &prms); + ind[2] = Serial_parm(2, &prms); + ind[3] = Serial_parm(2, &prms); + ind[4] = Serial_parm(10, &prms); + ind[5] = Serial_parm(10, &prms); + ind[6] = Serial_parm(14, &prms); + ind[7] = Serial_parm(14, &prms); + dec_acelp_4p_in_64(ind, 72, code); + } + else + { + for (i = 0; i < 8; i++) + { + ind[i] = Serial_parm(11, &prms); + } + + dec_acelp_4p_in_64(ind, 88, code); + } + + preemph_amrwb_dec(code, st->tilt_code, L_SUBFR); + + tmp = T0; + + if (T0_frac > 2) + { + tmp++; + } + Pit_shrp(code, tmp, PIT_SHARP, L_SUBFR); + + /* + * Decode codebooks gains. + */ + + if (nb_bits <= NBBITS_9k) + { + index = Serial_parm(6, &prms); /* codebook gain index */ + + dec_gain2_amr_wb(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 */ + + dec_gain2_amr_wb(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++) + { + if (st->Qsubfr[i] < tmp) + { + tmp = st->Qsubfr[i]; + } + } + + /* limit scaling (Q_new) to Q_MAX: see pv_amr_wb_cnst.h and syn_filt_32() */ + + if (tmp > Q_MAX) + { + tmp = Q_MAX; + } + Q_new = 0; + L_tmp = L_gain_code; /* L_gain_code in Q16 */ + + + while ((L_tmp < 0x08000000L) && (Q_new < tmp)) + { + L_tmp <<= 1; + Q_new += 1; + + } + gain_code = amr_wb_round(L_tmp); /* scaled gain_code with Qnew */ + + scale_signal(exc + i_subfr - (PIT_MAX + L_INTERPOL), + PIT_MAX + L_INTERPOL + L_SUBFR, + (int16)(Q_new - st->Q_old)); + + st->Q_old = Q_new; + + + /* + * Update parameters for the next subframe. + * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) + */ + + + if (bfi == 0) + { + /* LTP-Lag history update */ + for (i = 4; i > 0; i--) + { + st->lag_hist[i] = st->lag_hist[i - 1]; + } + st->lag_hist[0] = T0; + + st->old_T0 = T0; + st->old_T0_frac = 0; /* Remove fraction in case of BFI */ + } + /* find voice factor in Q15 (1=voiced, -1=unvoiced) */ + + /* + * Scale down by 1/8 + */ + for (i = L_SUBFR - 1; i >= 0; i--) + { + exc2[i] = (exc[i_subfr + i] + (0x0004 * (exc[i_subfr + i] != MAX_16))) >> 3; + } + + + /* post processing of excitation elements */ + + if (nb_bits <= NBBITS_9k) + { + pit_sharp = shl_int16(gain_pit, 1); + + if (pit_sharp > 16384) + { + for (i = 0; i < L_SUBFR; i++) + { + tmp = mult_int16(exc2[i], pit_sharp); + L_tmp = mul_16by16_to_int32(tmp, gain_pit); + L_tmp >>= 1; + excp[i] = amr_wb_round(L_tmp); + } + } + } + else + { + pit_sharp = 0; + } + + 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 = (voice_fac >> 2) + 8192; + + /* + * - Find the total excitation. + * - Find synthesis speech corresponding to exc[]. + * - Find maximum value of excitation for next scaling + */ + + pv_memcpy((void *)exc2, (void *)&exc[i_subfr], L_SUBFR*sizeof(*exc2)); + max = 1; + + for (i = 0; i < L_SUBFR; i++) + { + L_tmp = mul_16by16_to_int32(code[i], gain_code); + L_tmp = shl_int32(L_tmp, 5); + L_tmp = mac_16by16_to_int32(L_tmp, exc[i + i_subfr], gain_pit); + L_tmp = shl_int32(L_tmp, 1); + tmp = amr_wb_round(L_tmp); + exc[i + i_subfr] = tmp; + tmp = tmp - (tmp < 0); + max |= tmp ^(tmp >> 15); /* |= tmp ^sign(tmp) */ + } + + + /* tmp = scaling possible according to max value of excitation */ + tmp = add_int16(norm_s(max), Q_new) - 1; + + st->Qsubfr[3] = st->Qsubfr[2]; + st->Qsubfr[2] = st->Qsubfr[1]; + st->Qsubfr[1] = st->Qsubfr[0]; + st->Qsubfr[0] = tmp; + + /* + * phase dispersion to enhance noise in low bit rate + */ + + + if (nb_bits <= NBBITS_7k) + { + j = 0; /* high dispersion for rate <= 7.5 kbit/s */ + } + else if (nb_bits <= NBBITS_9k) + { + j = 1; /* low dispersion for rate <= 9.6 kbit/s */ + } + else + { + j = 2; /* no dispersion for rate > 9.6 kbit/s */ + } + + /* L_gain_code in Q16 */ + + phase_dispersion((int16)(L_gain_code >> 16), + gain_pit, + code, + j, + st->disp_mem, + ScratchMem); + + /* + * 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 = 16384 - (voice_fac >> 1); /* 1=unvoiced, 0=voiced */ + fac = mult_int16(stab_fac, tmp); + + L_tmp = L_gain_code; + + if (L_tmp < st->L_gc_thres) + { + L_tmp += fxp_mul32_by_16b(L_gain_code, 6226) << 1; + + if (L_tmp > st->L_gc_thres) + { + L_tmp = st->L_gc_thres; + } + } + else + { + L_tmp = fxp_mul32_by_16b(L_gain_code, 27536) << 1; + + if (L_tmp < st->L_gc_thres) + { + L_tmp = st->L_gc_thres; + } + } + st->L_gc_thres = L_tmp; + + L_gain_code = fxp_mul32_by_16b(L_gain_code, (32767 - fac)) << 1; + + + L_gain_code = add_int32(L_gain_code, fxp_mul32_by_16b(L_tmp, fac) << 1); + + /* + * 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 = (voice_fac >> 3) + 4096;/* 0.25=voiced, 0=unvoiced */ + + /* build excitation */ + + gain_code = amr_wb_round(shl_int32(L_gain_code, Q_new)); + + L_tmp = (int32)(code[0] << 16); + L_tmp = msu_16by16_from_int32(L_tmp, code[1], tmp); + L_tmp = mul_16by16_to_int32(amr_wb_round(L_tmp), gain_code); + L_tmp = shl_int32(L_tmp, 5); + L_tmp = mac_16by16_to_int32(L_tmp, exc2[0], gain_pit); + L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */ + exc2[0] = amr_wb_round(L_tmp); + + + for (i = 1; i < L_SUBFR - 1; i++) + { + L_tmp = (int32)(code[i] << 16); + L_tmp = msu_16by16_from_int32(L_tmp, (code[i + 1] + code[i - 1]), tmp); + L_tmp = mul_16by16_to_int32(amr_wb_round(L_tmp), gain_code); + L_tmp = shl_int32(L_tmp, 5); + L_tmp = mac_16by16_to_int32(L_tmp, exc2[i], gain_pit); + L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */ + exc2[i] = amr_wb_round(L_tmp); + } + + L_tmp = (int32)(code[L_SUBFR - 1] << 16); + L_tmp = msu_16by16_from_int32(L_tmp, code[L_SUBFR - 2], tmp); + L_tmp = mul_16by16_to_int32(amr_wb_round(L_tmp), gain_code); + L_tmp = shl_int32(L_tmp, 5); + L_tmp = mac_16by16_to_int32(L_tmp, exc2[L_SUBFR - 1], gain_pit); + L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */ + exc2[L_SUBFR - 1] = amr_wb_round(L_tmp); + + + + if (nb_bits <= NBBITS_9k) + { + if (pit_sharp > 16384) + { + for (i = 0; i < L_SUBFR; i++) + { + excp[i] = add_int16(excp[i], exc2[i]); + } + agc2_amr_wb(exc2, excp, L_SUBFR); + pv_memcpy((void *)exc2, (void *)excp, L_SUBFR*sizeof(*exc2)); + + } + } + if (nb_bits <= NBBITS_7k) + { + j = i_subfr >> 6; + for (i = 0; i < M; i++) + { + L_tmp = mul_16by16_to_int32(isf_tmp[i], sub_int16(32767, interpol_frac[j])); + L_tmp = mac_16by16_to_int32(L_tmp, isf[i], interpol_frac[j]); + HfIsf[i] = amr_wb_round(L_tmp); + } + } + else + { + pv_memset((void *)st->mem_syn_hf, + 0, + (M16k - M)*sizeof(*st->mem_syn_hf)); + } + + if (nb_bits >= NBBITS_24k) + { + corr_gain = Serial_parm(4, &prms); + } + else + { + corr_gain = 0; + } + + synthesis_amr_wb(p_Aq, + exc2, + Q_new, + &synth16k[i_subfr + (i_subfr>>2)], + corr_gain, + HfIsf, + nb_bits, + newDTXState, + st, + bfi, + ScratchMem); + + p_Aq += (M + 1); /* interpolated LPC parameters for next subframe */ + } + + /* + * Update signal for next frame. + * -> save past of exc[] + * -> save pitch parameters + */ + + pv_memcpy((void *)st->old_exc, + (void *)&old_exc[L_FRAME], + (PIT_MAX + L_INTERPOL)*sizeof(*old_exc)); + + scale_signal(exc, L_FRAME, (int16)(-Q_new)); + + dtx_dec_amr_wb_activity_update(&(st->dtx_decSt), isf, exc); + + st->dtx_decSt.dtxGlobalState = newDTXState; + + st->prev_bfi = bfi; + + return 0; +} + |