summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp')
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp1149
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;
+}
+