diff options
Diffstat (limited to 'media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c')
-rw-r--r-- | media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c | 3882 |
1 files changed, 1941 insertions, 1941 deletions
diff --git a/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c index d0d99a7..bac00dd 100644 --- a/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c +++ b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c @@ -1,1941 +1,1941 @@ -/*
- ** Copyright 2003-2010, VisualOn, Inc.
- **
- ** 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.
- */
-
-/***********************************************************************
-* File: voAMRWBEnc.c *
-* *
-* Description: Performs the main encoder routine *
-* Fixed-point C simulation of AMR WB ACELP coding *
-* algorithm with 20 msspeech frames for *
-* wideband speech signals. *
-* *
-************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "typedef.h"
-#include "basic_op.h"
-#include "oper_32b.h"
-#include "math_op.h"
-#include "cnst.h"
-#include "acelp.h"
-#include "cod_main.h"
-#include "bits.h"
-#include "main.h"
-#include "voAMRWB.h"
-#include "mem_align.h"
-#include "cmnMemory.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */
-static Word16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767};
-
-/* 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
-};
-
-/* 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
-};
-
-/* Private function declaration */
-static Word16 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 */
- Coder_State * st /* (i/o) : State structure */
- );
-
-/* Codec some parameters initialization */
-void Reset_encoder(void *st, Word16 reset_all)
-{
- Word16 i;
- Coder_State *cod_state;
- cod_state = (Coder_State *) st;
- Set_zero(cod_state->old_exc, PIT_MAX + L_INTERPOL);
- Set_zero(cod_state->mem_syn, M);
- Set_zero(cod_state->past_isfq, M);
- cod_state->mem_w0 = 0;
- cod_state->tilt_code = 0;
- cod_state->first_frame = 1;
- Init_gp_clip(cod_state->gp_clip);
- cod_state->L_gc_thres = 0;
- if (reset_all != 0)
- {
- /* Static vectors to zero */
- Set_zero(cod_state->old_speech, L_TOTAL - L_FRAME);
- Set_zero(cod_state->old_wsp, (PIT_MAX / OPL_DECIM));
- Set_zero(cod_state->mem_decim2, 3);
- /* routines initialization */
- Init_Decim_12k8(cod_state->mem_decim);
- Init_HP50_12k8(cod_state->mem_sig_in);
- Init_Levinson(cod_state->mem_levinson);
- Init_Q_gain2(cod_state->qua_gain);
- Init_Hp_wsp(cod_state->hp_wsp_mem);
- /* isp initialization */
- Copy(isp_init, cod_state->ispold, M);
- Copy(isp_init, cod_state->ispold_q, M);
- /* variable initialization */
- cod_state->mem_preemph = 0;
- cod_state->mem_wsp = 0;
- cod_state->Q_old = 15;
- cod_state->Q_max[0] = 15;
- cod_state->Q_max[1] = 15;
- cod_state->old_wsp_max = 0;
- cod_state->old_wsp_shift = 0;
- /* pitch ol initialization */
- cod_state->old_T0_med = 40;
- cod_state->ol_gain = 0;
- cod_state->ada_w = 0;
- cod_state->ol_wght_flg = 0;
- for (i = 0; i < 5; i++)
- {
- cod_state->old_ol_lag[i] = 40;
- }
- Set_zero(cod_state->old_hp_wsp, (L_FRAME / 2) / OPL_DECIM + (PIT_MAX / OPL_DECIM));
- Set_zero(cod_state->mem_syn_hf, M);
- Set_zero(cod_state->mem_syn_hi, M);
- Set_zero(cod_state->mem_syn_lo, M);
- Init_HP50_12k8(cod_state->mem_sig_out);
- Init_Filt_6k_7k(cod_state->mem_hf);
- Init_HP400_12k8(cod_state->mem_hp400);
- Copy(isf_init, cod_state->isfold, M);
- cod_state->mem_deemph = 0;
- cod_state->seed2 = 21845;
- Init_Filt_6k_7k(cod_state->mem_hf2);
- cod_state->gain_alpha = 32767;
- cod_state->vad_hist = 0;
- wb_vad_reset(cod_state->vadSt);
- dtx_enc_reset(cod_state->dtx_encSt, isf_init);
- }
- return;
-}
-
-/*-----------------------------------------------------------------*
-* Funtion coder *
-* ~~~~~ *
-* ->Main coder routine. *
-* *
-*-----------------------------------------------------------------*/
-void coder(
- Word16 * mode, /* input : used mode */
- Word16 speech16k[], /* input : 320 new speech samples (at 16 kHz) */
- Word16 prms[], /* output: output parameters */
- Word16 * ser_size, /* output: bit rate of the used mode */
- void *spe_state, /* i/o : State structure */
- Word16 allow_dtx /* input : DTX ON/OFF */
- )
-{
- /* Coder states */
- Coder_State *st;
- /* Speech vector */
- Word16 old_speech[L_TOTAL];
- Word16 *new_speech, *speech, *p_window;
-
- /* Weighted speech vector */
- Word16 old_wsp[L_FRAME + (PIT_MAX / OPL_DECIM)];
- Word16 *wsp;
-
- /* Excitation vector */
- Word16 old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL];
- Word16 *exc;
-
- /* LPC coefficients */
- Word16 r_h[M + 1], r_l[M + 1]; /* Autocorrelations of windowed speech */
- Word16 rc[M]; /* Reflection coefficients. */
- Word16 Ap[M + 1]; /* A(z) with spectral expansion */
- Word16 ispnew[M]; /* immittance spectral pairs at 4nd sfr */
- Word16 ispnew_q[M]; /* quantized ISPs at 4nd subframe */
- Word16 isf[M]; /* ISF (frequency domain) at 4nd sfr */
- Word16 *p_A, *p_Aq; /* ptr to A(z) for the 4 subframes */
- Word16 A[NB_SUBFR * (M + 1)]; /* A(z) unquantized for the 4 subframes */
- Word16 Aq[NB_SUBFR * (M + 1)]; /* A(z) quantized for the 4 subframes */
-
- /* Other vectors */
- Word16 xn[L_SUBFR]; /* Target vector for pitch search */
- Word16 xn2[L_SUBFR]; /* Target vector for codebook search */
- Word16 dn[L_SUBFR]; /* Correlation between xn2 and h1 */
- Word16 cn[L_SUBFR]; /* Target vector in residual domain */
- Word16 h1[L_SUBFR]; /* Impulse response vector */
- Word16 h2[L_SUBFR]; /* Impulse response vector */
- Word16 code[L_SUBFR]; /* Fixed codebook excitation */
- Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
- Word16 y2[L_SUBFR]; /* Filtered adaptive excitation */
- Word16 error[M + L_SUBFR]; /* error of quantization */
- Word16 synth[L_SUBFR]; /* 12.8kHz synthesis vector */
- Word16 exc2[L_FRAME]; /* excitation vector */
- Word16 buf[L_FRAME]; /* VAD buffer */
-
- /* Scalars */
- Word32 i, j, i_subfr, select, pit_flag, clip_gain, vad_flag;
- Word16 codec_mode;
- Word16 T_op, T_op2, T0, T0_min, T0_max, T0_frac, index;
- Word16 gain_pit, gain_code, g_coeff[4], g_coeff2[4];
- Word16 tmp, gain1, gain2, exp, Q_new, mu, shift, max;
- Word16 voice_fac;
- Word16 indice[8];
- Word32 L_tmp, L_gain_code, L_max, L_tmp1;
- Word16 code2[L_SUBFR]; /* Fixed codebook excitation */
- Word16 stab_fac, fac, gain_code_lo;
-
- Word16 corr_gain;
- Word16 *vo_p0, *vo_p1, *vo_p2, *vo_p3;
-
- st = (Coder_State *) spe_state;
-
- *ser_size = nb_of_bits[*mode];
- codec_mode = *mode;
-
- /*--------------------------------------------------------------------------*
- * Initialize pointers to speech vector. *
- * *
- * *
- * |-------|-------|-------|-------|-------|-------| *
- * past sp sf1 sf2 sf3 sf4 L_NEXT *
- * <------- Total speech buffer (L_TOTAL) ------> *
- * old_speech *
- * <------- LPC analysis window (L_WINDOW) ------> *
- * | <-- present frame (L_FRAME) ----> *
- * p_window | <----- new speech (L_FRAME) ----> *
- * | | *
- * speech | *
- * new_speech *
- *--------------------------------------------------------------------------*/
-
- new_speech = old_speech + L_TOTAL - L_FRAME - L_FILT; /* New speech */
- speech = old_speech + L_TOTAL - L_FRAME - L_NEXT; /* Present frame */
- p_window = old_speech + L_TOTAL - L_WINDOW;
-
- exc = old_exc + PIT_MAX + L_INTERPOL;
- wsp = old_wsp + (PIT_MAX / OPL_DECIM);
-
- /* copy coder memory state into working space */
- Copy(st->old_speech, old_speech, L_TOTAL - L_FRAME);
- Copy(st->old_wsp, old_wsp, PIT_MAX / OPL_DECIM);
- Copy(st->old_exc, old_exc, PIT_MAX + L_INTERPOL);
-
- /*---------------------------------------------------------------*
- * Down sampling signal from 16kHz to 12.8kHz *
- * -> The signal is extended by L_FILT samples (padded to zero) *
- * to avoid additional delay (L_FILT samples) in the coder. *
- * The last L_FILT samples are approximated after decimation and *
- * are used (and windowed) only in autocorrelations. *
- *---------------------------------------------------------------*/
-
- Decim_12k8(speech16k, L_FRAME16k, new_speech, st->mem_decim);
-
- /* last L_FILT samples for autocorrelation window */
- Copy(st->mem_decim, code, 2 * L_FILT16k);
- Set_zero(error, L_FILT16k); /* set next sample to zero */
- Decim_12k8(error, L_FILT16k, new_speech + L_FRAME, code);
-
- /*---------------------------------------------------------------*
- * Perform 50Hz HP filtering of input signal. *
- *---------------------------------------------------------------*/
-
- HP50_12k8(new_speech, L_FRAME, st->mem_sig_in);
-
- /* last L_FILT samples for autocorrelation window */
- Copy(st->mem_sig_in, code, 6);
- HP50_12k8(new_speech + L_FRAME, L_FILT, code);
-
- /*---------------------------------------------------------------*
- * Perform fixed preemphasis through 1 - g z^-1 *
- * Scale signal to get maximum of precision in filtering *
- *---------------------------------------------------------------*/
-
- mu = PREEMPH_FAC >> 1; /* Q15 --> Q14 */
-
- /* get max of new preemphased samples (L_FRAME+L_FILT) */
- L_tmp = new_speech[0] << 15;
- L_tmp -= (st->mem_preemph * mu)<<1;
- L_max = L_abs(L_tmp);
-
- for (i = 1; i < L_FRAME + L_FILT; i++)
- {
- L_tmp = new_speech[i] << 15;
- L_tmp -= (new_speech[i - 1] * mu)<<1;
- L_tmp = L_abs(L_tmp);
- if(L_tmp > L_max)
- {
- L_max = L_tmp;
- }
- }
-
- /* get scaling factor for new and previous samples */
- /* limit scaling to Q_MAX to keep dynamic for ringing in low signal */
- /* limit scaling to Q_MAX also to avoid a[0]<1 in syn_filt_32 */
- tmp = extract_h(L_max);
- if (tmp == 0)
- {
- shift = Q_MAX;
- } else
- {
- shift = norm_s(tmp) - 1;
- if (shift < 0)
- {
- shift = 0;
- }
- if (shift > Q_MAX)
- {
- shift = Q_MAX;
- }
- }
- Q_new = shift;
- if (Q_new > st->Q_max[0])
- {
- Q_new = st->Q_max[0];
- }
- if (Q_new > st->Q_max[1])
- {
- Q_new = st->Q_max[1];
- }
- exp = (Q_new - st->Q_old);
- st->Q_old = Q_new;
- st->Q_max[1] = st->Q_max[0];
- st->Q_max[0] = shift;
-
- /* preemphasis with scaling (L_FRAME+L_FILT) */
- tmp = new_speech[L_FRAME - 1];
-
- for (i = L_FRAME + L_FILT - 1; i > 0; i--)
- {
- L_tmp = new_speech[i] << 15;
- L_tmp -= (new_speech[i - 1] * mu)<<1;
- L_tmp = (L_tmp << Q_new);
- new_speech[i] = vo_round(L_tmp);
- }
-
- L_tmp = new_speech[0] << 15;
- L_tmp -= (st->mem_preemph * mu)<<1;
- L_tmp = (L_tmp << Q_new);
- new_speech[0] = vo_round(L_tmp);
-
- st->mem_preemph = tmp;
-
- /* scale previous samples and memory */
-
- Scale_sig(old_speech, L_TOTAL - L_FRAME - L_FILT, exp);
- Scale_sig(old_exc, PIT_MAX + L_INTERPOL, exp);
- Scale_sig(st->mem_syn, M, exp);
- Scale_sig(st->mem_decim2, 3, exp);
- Scale_sig(&(st->mem_wsp), 1, exp);
- Scale_sig(&(st->mem_w0), 1, exp);
-
- /*------------------------------------------------------------------------*
- * Call VAD *
- * Preemphesis scale down signal in low frequency and keep dynamic in HF.*
- * Vad work slightly in futur (new_speech = speech + L_NEXT - L_FILT). *
- *------------------------------------------------------------------------*/
- Copy(new_speech, buf, L_FRAME);
-
-#ifdef ASM_OPT /* asm optimization branch */
- Scale_sig_opt(buf, L_FRAME, 1 - Q_new);
-#else
- Scale_sig(buf, L_FRAME, 1 - Q_new);
-#endif
-
- vad_flag = wb_vad(st->vadSt, buf); /* Voice Activity Detection */
- if (vad_flag == 0)
- {
- st->vad_hist = (st->vad_hist + 1);
- } else
- {
- st->vad_hist = 0;
- }
-
- /* DTX processing */
- if (allow_dtx != 0)
- {
- /* Note that mode may change here */
- tx_dtx_handler(st->dtx_encSt, vad_flag, mode);
- *ser_size = nb_of_bits[*mode];
- }
-
- if(*mode != MRDTX)
- {
- Parm_serial(vad_flag, 1, &prms);
- }
- /*------------------------------------------------------------------------*
- * Perform LPC analysis *
- * ~~~~~~~~~~~~~~~~~~~~ *
- * - autocorrelation + lag windowing *
- * - Levinson-durbin algorithm to find a[] *
- * - convert a[] to isp[] *
- * - convert isp[] to isf[] for quantization *
- * - quantize and code the isf[] *
- * - convert isf[] to isp[] for interpolation *
- * - find the interpolated ISPs and convert to a[] for the 4 subframes *
- *------------------------------------------------------------------------*/
-
- /* LP analysis centered at 4nd subframe */
- Autocorr(p_window, M, r_h, r_l); /* Autocorrelations */
- Lag_window(r_h, r_l); /* Lag windowing */
- Levinson(r_h, r_l, A, rc, st->mem_levinson); /* Levinson Durbin */
- Az_isp(A, ispnew, st->ispold); /* From A(z) to ISP */
-
- /* Find the interpolated ISPs and convert to a[] for all subframes */
- Int_isp(st->ispold, ispnew, interpol_frac, A);
-
- /* update ispold[] for the next frame */
- Copy(ispnew, st->ispold, M);
-
- /* Convert ISPs to frequency domain 0..6400 */
- Isp_isf(ispnew, isf, M);
-
- /* check resonance for pitch clipping algorithm */
- Gp_clip_test_isf(isf, st->gp_clip);
-
- /*----------------------------------------------------------------------*
- * Perform PITCH_OL analysis *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~ *
- * - Find the residual res[] for the whole speech frame *
- * - Find the weighted input speech wsp[] for the whole speech frame *
- * - scale wsp[] to avoid overflow in pitch estimation *
- * - Find open loop pitch lag for whole speech frame *
- *----------------------------------------------------------------------*/
- p_A = A;
- for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
- {
- /* Weighting of LPC coefficients */
- Weight_a(p_A, Ap, GAMMA1, M);
-
-#ifdef ASM_OPT /* asm optimization branch */
- Residu_opt(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR);
-#else
- Residu(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR);
-#endif
-
- p_A += (M + 1);
- }
-
- Deemph2(wsp, TILT_FAC, L_FRAME, &(st->mem_wsp));
-
- /* find maximum value on wsp[] for 12 bits scaling */
- max = 0;
- for (i = 0; i < L_FRAME; i++)
- {
- tmp = abs_s(wsp[i]);
- if(tmp > max)
- {
- max = tmp;
- }
- }
- tmp = st->old_wsp_max;
- if(max > tmp)
- {
- tmp = max; /* tmp = max(wsp_max, old_wsp_max) */
- }
- st->old_wsp_max = max;
-
- shift = norm_s(tmp) - 3;
- if (shift > 0)
- {
- shift = 0; /* shift = 0..-3 */
- }
- /* decimation of wsp[] to search pitch in LF and to reduce complexity */
- LP_Decim2(wsp, L_FRAME, st->mem_decim2);
-
- /* scale wsp[] in 12 bits to avoid overflow */
-#ifdef ASM_OPT /* asm optimization branch */
- Scale_sig_opt(wsp, L_FRAME / OPL_DECIM, shift);
-#else
- Scale_sig(wsp, L_FRAME / OPL_DECIM, shift);
-#endif
- /* scale old_wsp (warning: exp must be Q_new-Q_old) */
- exp = exp + (shift - st->old_wsp_shift);
- st->old_wsp_shift = shift;
-
- Scale_sig(old_wsp, PIT_MAX / OPL_DECIM, exp);
- Scale_sig(st->old_hp_wsp, PIT_MAX / OPL_DECIM, exp);
-
- scale_mem_Hp_wsp(st->hp_wsp_mem, exp);
-
- /* Find open loop pitch lag for whole speech frame */
-
- if(*ser_size == NBBITS_7k)
- {
- /* Find open loop pitch lag for whole speech frame */
- T_op = Pitch_med_ol(wsp, st, L_FRAME / OPL_DECIM);
- } else
- {
- /* Find open loop pitch lag for first 1/2 frame */
- T_op = Pitch_med_ol(wsp, st, (L_FRAME/2) / OPL_DECIM);
- }
-
- if(st->ol_gain > 19661) /* 0.6 in Q15 */
- {
- st->old_T0_med = Med_olag(T_op, st->old_ol_lag);
- st->ada_w = 32767;
- } else
- {
- st->ada_w = vo_mult(st->ada_w, 29491);
- }
-
- if(st->ada_w < 26214)
- st->ol_wght_flg = 0;
- else
- st->ol_wght_flg = 1;
-
- wb_vad_tone_detection(st->vadSt, st->ol_gain);
- T_op *= OPL_DECIM;
-
- if(*ser_size != NBBITS_7k)
- {
- /* Find open loop pitch lag for second 1/2 frame */
- T_op2 = Pitch_med_ol(wsp + ((L_FRAME / 2) / OPL_DECIM), st, (L_FRAME/2) / OPL_DECIM);
-
- if(st->ol_gain > 19661) /* 0.6 in Q15 */
- {
- st->old_T0_med = Med_olag(T_op2, st->old_ol_lag);
- st->ada_w = 32767;
- } else
- {
- st->ada_w = mult(st->ada_w, 29491);
- }
-
- if(st->ada_w < 26214)
- st->ol_wght_flg = 0;
- else
- st->ol_wght_flg = 1;
-
- wb_vad_tone_detection(st->vadSt, st->ol_gain);
-
- T_op2 *= OPL_DECIM;
-
- } else
- {
- T_op2 = T_op;
- }
- /*----------------------------------------------------------------------*
- * DTX-CNG *
- *----------------------------------------------------------------------*/
- if(*mode == MRDTX) /* CNG mode */
- {
- /* Buffer isf's and energy */
-#ifdef ASM_OPT /* asm optimization branch */
- Residu_opt(&A[3 * (M + 1)], speech, exc, L_FRAME);
-#else
- Residu(&A[3 * (M + 1)], speech, exc, L_FRAME);
-#endif
-
- for (i = 0; i < L_FRAME; i++)
- {
- exc2[i] = shr(exc[i], Q_new);
- }
-
- L_tmp = 0;
- for (i = 0; i < L_FRAME; i++)
- L_tmp += (exc2[i] * exc2[i])<<1;
-
- L_tmp >>= 1;
-
- dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode);
-
- /* Quantize and code the ISFs */
- dtx_enc(st->dtx_encSt, isf, exc2, &prms);
-
- /* Convert ISFs to the cosine domain */
- Isf_isp(isf, ispnew_q, M);
- Isp_Az(ispnew_q, Aq, M, 0);
-
- for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
- {
- corr_gain = synthesis(Aq, &exc2[i_subfr], 0, &speech16k[i_subfr * 5 / 4], st);
- }
- Copy(isf, st->isfold, M);
-
- /* reset speech coder memories */
- Reset_encoder(st, 0);
-
- /*--------------------------------------------------*
- * Update signal for next frame. *
- * -> save past of speech[] and wsp[]. *
- *--------------------------------------------------*/
-
- Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME);
- Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM);
-
- return;
- }
- /*----------------------------------------------------------------------*
- * ACELP *
- *----------------------------------------------------------------------*/
-
- /* Quantize and code the ISFs */
-
- if (*ser_size <= NBBITS_7k)
- {
- Qpisf_2s_36b(isf, isf, st->past_isfq, indice, 4);
-
- Parm_serial(indice[0], 8, &prms);
- Parm_serial(indice[1], 8, &prms);
- Parm_serial(indice[2], 7, &prms);
- Parm_serial(indice[3], 7, &prms);
- Parm_serial(indice[4], 6, &prms);
- } else
- {
- Qpisf_2s_46b(isf, isf, st->past_isfq, indice, 4);
-
- Parm_serial(indice[0], 8, &prms);
- Parm_serial(indice[1], 8, &prms);
- Parm_serial(indice[2], 6, &prms);
- Parm_serial(indice[3], 7, &prms);
- Parm_serial(indice[4], 7, &prms);
- Parm_serial(indice[5], 5, &prms);
- Parm_serial(indice[6], 5, &prms);
- }
-
- /* Check stability on isf : distance between old isf and current isf */
-
- L_tmp = 0;
- for (i = 0; i < M - 1; i++)
- {
- tmp = vo_sub(isf[i], st->isfold[i]);
- L_tmp += (tmp * tmp)<<1;
- }
-
- tmp = extract_h(L_shl2(L_tmp, 8));
-
- tmp = vo_mult(tmp, 26214); /* tmp = L_tmp*0.8/256 */
- tmp = vo_sub(20480, tmp); /* 1.25 - tmp (in Q14) */
-
- stab_fac = shl(tmp, 1);
-
- if (stab_fac < 0)
- {
- stab_fac = 0;
- }
- Copy(isf, st->isfold, M);
-
- /* Convert ISFs to the cosine domain */
- Isf_isp(isf, ispnew_q, M);
-
- if (st->first_frame != 0)
- {
- st->first_frame = 0;
- Copy(ispnew_q, st->ispold_q, M);
- }
- /* Find the interpolated ISPs and convert to a[] for all subframes */
-
- Int_isp(st->ispold_q, ispnew_q, interpol_frac, Aq);
-
- /* update ispold[] for the next frame */
- Copy(ispnew_q, st->ispold_q, M);
-
- p_Aq = Aq;
- for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
- {
-#ifdef ASM_OPT /* asm optimization branch */
- Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
-#else
- Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
-#endif
- p_Aq += (M + 1);
- }
-
- /* Buffer isf's and energy for dtx on non-speech frame */
- if (vad_flag == 0)
- {
- for (i = 0; i < L_FRAME; i++)
- {
- exc2[i] = exc[i] >> Q_new;
- }
- L_tmp = 0;
- for (i = 0; i < L_FRAME; i++)
- L_tmp += (exc2[i] * exc2[i])<<1;
- L_tmp >>= 1;
-
- dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode);
- }
- /* range for closed loop pitch search in 1st subframe */
-
- T0_min = T_op - 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 = T0_max - 15;
- }
- /*------------------------------------------------------------------------*
- * Loop for every subframe in the analysis frame *
- *------------------------------------------------------------------------*
- * To find the pitch and innovation parameters. The subframe size is *
- * L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. *
- * - compute the target signal for pitch search *
- * - compute impulse response of weighted synthesis filter (h1[]) *
- * - find the closed-loop pitch parameters *
- * - encode the pitch dealy *
- * - find 2 lt prediction (with / without LP filter for lt pred) *
- * - find 2 pitch gains and choose the best lt prediction. *
- * - find target vector for codebook search *
- * - update the impulse response h1[] for codebook search *
- * - correlation between target vector and impulse response *
- * - codebook search and encoding *
- * - VQ of pitch and codebook gains *
- * - find voicing factor and tilt of code for next subframe. *
- * - update states of weighting filter *
- * - find excitation and synthesis speech *
- *------------------------------------------------------------------------*/
- p_A = A;
- p_Aq = Aq;
- for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
- {
- pit_flag = i_subfr;
- if ((i_subfr == 2 * L_SUBFR) && (*ser_size > NBBITS_7k))
- {
- pit_flag = 0;
- /* range for closed loop pitch search in 3rd subframe */
- T0_min = (T_op2 - 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 = (T0_max - 15);
- }
- }
- /*-----------------------------------------------------------------------*
- * *
- * Find the target vector for pitch search: *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
- * *
- * |------| res[n] *
- * speech[n]---| A(z) |-------- *
- * |------| | |--------| error[n] |------| *
- * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target *
- * exc |--------| |------| *
- * *
- * Instead of subtracting the zero-input response of filters from *
- * the weighted input speech, the above configuration is used to *
- * compute the target vector. *
- * *
- *-----------------------------------------------------------------------*/
-
- for (i = 0; i < M; i++)
- {
- error[i] = vo_sub(speech[i + i_subfr - M], st->mem_syn[i]);
- }
-
-#ifdef ASM_OPT /* asm optimization branch */
- Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
-#else
- Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
-#endif
- Syn_filt(p_Aq, &exc[i_subfr], error + M, L_SUBFR, error, 0);
- Weight_a(p_A, Ap, GAMMA1, M);
-
-#ifdef ASM_OPT /* asm optimization branch */
- Residu_opt(Ap, error + M, xn, L_SUBFR);
-#else
- Residu(Ap, error + M, xn, L_SUBFR);
-#endif
- Deemph2(xn, TILT_FAC, L_SUBFR, &(st->mem_w0));
-
- /*----------------------------------------------------------------------*
- * Find approx. target in residual domain "cn[]" for inovation search. *
- *----------------------------------------------------------------------*/
- /* first half: xn[] --> cn[] */
- Set_zero(code, M);
- Copy(xn, code + M, L_SUBFR / 2);
- tmp = 0;
- Preemph2(code + M, TILT_FAC, L_SUBFR / 2, &tmp);
- Weight_a(p_A, Ap, GAMMA1, M);
- Syn_filt(Ap,code + M, code + M, L_SUBFR / 2, code, 0);
-
-#ifdef ASM_OPT /* asm optimization branch */
- Residu_opt(p_Aq,code + M, cn, L_SUBFR / 2);
-#else
- Residu(p_Aq,code + M, cn, L_SUBFR / 2);
-#endif
-
- /* second half: res[] --> cn[] (approximated and faster) */
- Copy(&exc[i_subfr + (L_SUBFR / 2)], cn + (L_SUBFR / 2), L_SUBFR / 2);
-
- /*---------------------------------------------------------------*
- * Compute impulse response, h1[], of weighted synthesis filter *
- *---------------------------------------------------------------*/
-
- Set_zero(error, M + L_SUBFR);
- Weight_a(p_A, error + M, GAMMA1, M);
-
- vo_p0 = error+M;
- vo_p3 = h1;
- for (i = 0; i < L_SUBFR; i++)
- {
- L_tmp = *vo_p0 << 14; /* x4 (Q12 to Q14) */
- vo_p1 = p_Aq + 1;
- vo_p2 = vo_p0-1;
- for (j = 1; j <= M/4; j++)
- {
- L_tmp -= *vo_p1++ * *vo_p2--;
- L_tmp -= *vo_p1++ * *vo_p2--;
- L_tmp -= *vo_p1++ * *vo_p2--;
- L_tmp -= *vo_p1++ * *vo_p2--;
- }
- *vo_p3++ = *vo_p0++ = vo_round((L_tmp <<4));
- }
- /* deemph without division by 2 -> Q14 to Q15 */
- tmp = 0;
- Deemph2(h1, TILT_FAC, L_SUBFR, &tmp); /* h1 in Q14 */
-
- /* h2 in Q12 for codebook search */
- Copy(h1, h2, L_SUBFR);
-
- /*---------------------------------------------------------------*
- * scale xn[] and h1[] to avoid overflow in dot_product12() *
- *---------------------------------------------------------------*/
-#ifdef ASM_OPT /* asm optimization branch */
- Scale_sig_opt(h2, L_SUBFR, -2);
- Scale_sig_opt(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */
- Scale_sig_opt(h1, L_SUBFR, 1 + shift); /* set h1[] in Q15 with scaling for convolution */
-#else
- Scale_sig(h2, L_SUBFR, -2);
- Scale_sig(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */
- Scale_sig(h1, L_SUBFR, 1 + shift); /* set h1[] in Q15 with scaling for convolution */
-#endif
- /*----------------------------------------------------------------------*
- * Closed-loop fractional pitch search *
- *----------------------------------------------------------------------*/
- /* find closed loop fractional pitch lag */
- if(*ser_size <= NBBITS_9k)
- {
- T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,
- pit_flag, PIT_MIN, PIT_FR1_8b, L_SUBFR);
-
- /* encode pitch lag */
- if (pit_flag == 0) /* if 1st/3rd subframe */
- {
- /*--------------------------------------------------------------*
- * The pitch range for the 1st/3rd subframe is encoded with *
- * 8 bits and is divided as follows: *
- * PIT_MIN to PIT_FR1-1 resolution 1/2 (frac = 0 or 2) *
- * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) *
- *--------------------------------------------------------------*/
- if (T0 < PIT_FR1_8b)
- {
- index = ((T0 << 1) + (T0_frac >> 1) - (PIT_MIN<<1));
- } else
- {
- index = ((T0 - PIT_FR1_8b) + ((PIT_FR1_8b - PIT_MIN)*2));
- }
-
- Parm_serial(index, 8, &prms);
-
- /* 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 = (T0_max - 15);
- }
- } else
- { /* if subframe 2 or 4 */
- /*--------------------------------------------------------------*
- * The pitch range for subframe 2 or 4 is encoded with 5 bits: *
- * T0_min to T0_max resolution 1/2 (frac = 0 or 2) *
- *--------------------------------------------------------------*/
- i = (T0 - T0_min);
- index = (i << 1) + (T0_frac >> 1);
-
- Parm_serial(index, 5, &prms);
- }
- } else
- {
- T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,
- pit_flag, PIT_FR2, PIT_FR1_9b, L_SUBFR);
-
- /* encode pitch lag */
- if (pit_flag == 0) /* if 1st/3rd subframe */
- {
- /*--------------------------------------------------------------*
- * The pitch range for the 1st/3rd subframe is encoded with *
- * 9 bits and is divided as follows: *
- * PIT_MIN to PIT_FR2-1 resolution 1/4 (frac = 0,1,2 or 3) *
- * PIT_FR2 to PIT_FR1-1 resolution 1/2 (frac = 0 or 1) *
- * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) *
- *--------------------------------------------------------------*/
-
- if (T0 < PIT_FR2)
- {
- index = ((T0 << 2) + T0_frac) - (PIT_MIN << 2);
- } else if(T0 < PIT_FR1_9b)
- {
- index = ((((T0 << 1) + (T0_frac >> 1)) - (PIT_FR2<<1)) + ((PIT_FR2 - PIT_MIN)<<2));
- } else
- {
- index = (((T0 - PIT_FR1_9b) + ((PIT_FR2 - PIT_MIN)<<2)) + ((PIT_FR1_9b - PIT_FR2)<<1));
- }
-
- Parm_serial(index, 9, &prms);
-
- /* 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 = (T0_max - 15);
- }
- } else
- { /* if subframe 2 or 4 */
- /*--------------------------------------------------------------*
- * The pitch range for subframe 2 or 4 is encoded with 6 bits: *
- * T0_min to T0_max resolution 1/4 (frac = 0,1,2 or 3) *
- *--------------------------------------------------------------*/
- i = (T0 - T0_min);
- index = (i << 2) + T0_frac;
- Parm_serial(index, 6, &prms);
- }
- }
-
- /*-----------------------------------------------------------------*
- * Gain clipping test to avoid unstable synthesis on frame erasure *
- *-----------------------------------------------------------------*/
-
- clip_gain = 0;
- if((st->gp_clip[0] < 154) && (st->gp_clip[1] > 14746))
- clip_gain = 1;
-
- /*-----------------------------------------------------------------*
- * - find unity gain pitch excitation (adaptive codebook entry) *
- * with fractional interpolation. *
- * - find filtered pitch exc. y1[]=exc[] convolved with h1[]) *
- * - compute pitch gain1 *
- *-----------------------------------------------------------------*/
- /* find pitch exitation */
-#ifdef ASM_OPT /* asm optimization branch */
- pred_lt4_asm(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);
-#else
- Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);
-#endif
- if (*ser_size > NBBITS_9k)
- {
-#ifdef ASM_OPT /* asm optimization branch */
- Convolve_asm(&exc[i_subfr], h1, y1, L_SUBFR);
-#else
- Convolve(&exc[i_subfr], h1, y1, L_SUBFR);
-#endif
- gain1 = G_pitch(xn, y1, g_coeff, L_SUBFR);
- /* clip gain if necessary to avoid problem at decoder */
- if ((clip_gain != 0) && (gain1 > GP_CLIP))
- {
- gain1 = GP_CLIP;
- }
- /* find energy of new target xn2[] */
- Updt_tar(xn, dn, y1, gain1, L_SUBFR); /* dn used temporary */
- } else
- {
- gain1 = 0;
- }
- /*-----------------------------------------------------------------*
- * - find pitch excitation filtered by 1st order LP filter. *
- * - find filtered pitch exc. y2[]=exc[] convolved with h1[]) *
- * - compute pitch gain2 *
- *-----------------------------------------------------------------*/
- /* find pitch excitation with lp filter */
- vo_p0 = exc + i_subfr-1;
- vo_p1 = code;
- /* find pitch excitation with lp filter */
- for (i = 0; i < L_SUBFR/2; i++)
- {
- L_tmp = 5898 * *vo_p0++;
- L_tmp1 = 5898 * *vo_p0;
- L_tmp += 20972 * *vo_p0++;
- L_tmp1 += 20972 * *vo_p0++;
- L_tmp1 += 5898 * *vo_p0--;
- L_tmp += 5898 * *vo_p0;
- *vo_p1++ = (L_tmp + 0x4000)>>15;
- *vo_p1++ = (L_tmp1 + 0x4000)>>15;
- }
-
-#ifdef ASM_OPT /* asm optimization branch */
- Convolve_asm(code, h1, y2, L_SUBFR);
-#else
- Convolve(code, h1, y2, L_SUBFR);
-#endif
-
- gain2 = G_pitch(xn, y2, g_coeff2, L_SUBFR);
-
- /* clip gain if necessary to avoid problem at decoder */
- if ((clip_gain != 0) && (gain2 > GP_CLIP))
- {
- gain2 = GP_CLIP;
- }
- /* find energy of new target xn2[] */
- Updt_tar(xn, xn2, y2, gain2, L_SUBFR);
- /*-----------------------------------------------------------------*
- * use the best prediction (minimise quadratic error). *
- *-----------------------------------------------------------------*/
- select = 0;
- if(*ser_size > NBBITS_9k)
- {
- L_tmp = 0L;
- vo_p0 = dn;
- vo_p1 = xn2;
- for (i = 0; i < L_SUBFR/2; i++)
- {
- L_tmp += *vo_p0 * *vo_p0;
- vo_p0++;
- L_tmp -= *vo_p1 * *vo_p1;
- vo_p1++;
- L_tmp += *vo_p0 * *vo_p0;
- vo_p0++;
- L_tmp -= *vo_p1 * *vo_p1;
- vo_p1++;
- }
-
- if (L_tmp <= 0)
- {
- select = 1;
- }
- Parm_serial(select, 1, &prms);
- }
- if (select == 0)
- {
- /* use the lp filter for pitch excitation prediction */
- gain_pit = gain2;
- Copy(code, &exc[i_subfr], L_SUBFR);
- Copy(y2, y1, L_SUBFR);
- Copy(g_coeff2, g_coeff, 4);
- } else
- {
- /* no filter used for pitch excitation prediction */
- gain_pit = gain1;
- Copy(dn, xn2, L_SUBFR); /* target vector for codebook search */
- }
- /*-----------------------------------------------------------------*
- * - update cn[] for codebook search *
- *-----------------------------------------------------------------*/
- Updt_tar(cn, cn, &exc[i_subfr], gain_pit, L_SUBFR);
-
-#ifdef ASM_OPT /* asm optimization branch */
- Scale_sig_opt(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */
-#else
- Scale_sig(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */
-#endif
- /*-----------------------------------------------------------------*
- * - include fixed-gain pitch contribution into impulse resp. h1[] *
- *-----------------------------------------------------------------*/
- tmp = 0;
- Preemph(h2, st->tilt_code, L_SUBFR, &tmp);
-
- if (T0_frac > 2)
- T0 = (T0 + 1);
- Pit_shrp(h2, T0, PIT_SHARP, L_SUBFR);
- /*-----------------------------------------------------------------*
- * - Correlation between target xn2[] and impulse response h1[] *
- * - Innovative codebook search *
- *-----------------------------------------------------------------*/
- cor_h_x(h2, xn2, dn);
- if (*ser_size <= NBBITS_7k)
- {
- ACELP_2t64_fx(dn, cn, h2, code, y2, indice);
-
- Parm_serial(indice[0], 12, &prms);
- } else if(*ser_size <= NBBITS_9k)
- {
- ACELP_4t64_fx(dn, cn, h2, code, y2, 20, *ser_size, indice);
-
- Parm_serial(indice[0], 5, &prms);
- Parm_serial(indice[1], 5, &prms);
- Parm_serial(indice[2], 5, &prms);
- Parm_serial(indice[3], 5, &prms);
- } else if(*ser_size <= NBBITS_12k)
- {
- ACELP_4t64_fx(dn, cn, h2, code, y2, 36, *ser_size, indice);
-
- Parm_serial(indice[0], 9, &prms);
- Parm_serial(indice[1], 9, &prms);
- Parm_serial(indice[2], 9, &prms);
- Parm_serial(indice[3], 9, &prms);
- } else if(*ser_size <= NBBITS_14k)
- {
- ACELP_4t64_fx(dn, cn, h2, code, y2, 44, *ser_size, indice);
-
- Parm_serial(indice[0], 13, &prms);
- Parm_serial(indice[1], 13, &prms);
- Parm_serial(indice[2], 9, &prms);
- Parm_serial(indice[3], 9, &prms);
- } else if(*ser_size <= NBBITS_16k)
- {
- ACELP_4t64_fx(dn, cn, h2, code, y2, 52, *ser_size, indice);
-
- Parm_serial(indice[0], 13, &prms);
- Parm_serial(indice[1], 13, &prms);
- Parm_serial(indice[2], 13, &prms);
- Parm_serial(indice[3], 13, &prms);
- } else if(*ser_size <= NBBITS_18k)
- {
- ACELP_4t64_fx(dn, cn, h2, code, y2, 64, *ser_size, indice);
-
- Parm_serial(indice[0], 2, &prms);
- Parm_serial(indice[1], 2, &prms);
- Parm_serial(indice[2], 2, &prms);
- Parm_serial(indice[3], 2, &prms);
- Parm_serial(indice[4], 14, &prms);
- Parm_serial(indice[5], 14, &prms);
- Parm_serial(indice[6], 14, &prms);
- Parm_serial(indice[7], 14, &prms);
- } else if(*ser_size <= NBBITS_20k)
- {
- ACELP_4t64_fx(dn, cn, h2, code, y2, 72, *ser_size, indice);
-
- Parm_serial(indice[0], 10, &prms);
- Parm_serial(indice[1], 10, &prms);
- Parm_serial(indice[2], 2, &prms);
- Parm_serial(indice[3], 2, &prms);
- Parm_serial(indice[4], 10, &prms);
- Parm_serial(indice[5], 10, &prms);
- Parm_serial(indice[6], 14, &prms);
- Parm_serial(indice[7], 14, &prms);
- } else
- {
- ACELP_4t64_fx(dn, cn, h2, code, y2, 88, *ser_size, indice);
-
- Parm_serial(indice[0], 11, &prms);
- Parm_serial(indice[1], 11, &prms);
- Parm_serial(indice[2], 11, &prms);
- Parm_serial(indice[3], 11, &prms);
- Parm_serial(indice[4], 11, &prms);
- Parm_serial(indice[5], 11, &prms);
- Parm_serial(indice[6], 11, &prms);
- Parm_serial(indice[7], 11, &prms);
- }
- /*-------------------------------------------------------*
- * - Add the fixed-gain pitch contribution to code[]. *
- *-------------------------------------------------------*/
- tmp = 0;
- Preemph(code, st->tilt_code, L_SUBFR, &tmp);
- Pit_shrp(code, T0, PIT_SHARP, L_SUBFR);
- /*----------------------------------------------------------*
- * - Compute the fixed codebook gain *
- * - quantize fixed codebook gain *
- *----------------------------------------------------------*/
- if(*ser_size <= NBBITS_9k)
- {
- index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 6,
- &gain_pit, &L_gain_code, clip_gain, st->qua_gain);
- Parm_serial(index, 6, &prms);
- } else
- {
- index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 7,
- &gain_pit, &L_gain_code, clip_gain, st->qua_gain);
- Parm_serial(index, 7, &prms);
- }
- /* test quantized gain of pitch for pitch clipping algorithm */
- Gp_clip_test_gain_pit(gain_pit, st->gp_clip);
-
- L_tmp = L_shl(L_gain_code, Q_new);
- gain_code = extract_h(L_add(L_tmp, 0x8000));
-
- /*----------------------------------------------------------*
- * Update parameters for the next subframe. *
- * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) *
- *----------------------------------------------------------*/
- /* find voice factor in Q15 (1=voiced, -1=unvoiced) */
- Copy(&exc[i_subfr], exc2, L_SUBFR);
-
-#ifdef ASM_OPT /* asm optimization branch */
- Scale_sig_opt(exc2, L_SUBFR, shift);
-#else
- Scale_sig(exc2, L_SUBFR, shift);
-#endif
- voice_fac = voice_factor(exc2, shift, 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);
- /*------------------------------------------------------*
- * - Update filter's memory "mem_w0" for finding the *
- * target vector in the next subframe. *
- * - Find the total excitation *
- * - Find synthesis speech to update mem_syn[]. *
- *------------------------------------------------------*/
-
- /* y2 in Q9, gain_pit in Q14 */
- L_tmp = (gain_code * y2[L_SUBFR - 1])<<1;
- L_tmp = L_shl(L_tmp, (5 + shift));
- L_tmp = L_negate(L_tmp);
- L_tmp += (xn[L_SUBFR - 1] * 16384)<<1;
- L_tmp -= (y1[L_SUBFR - 1] * gain_pit)<<1;
- L_tmp = L_shl(L_tmp, (1 - shift));
- st->mem_w0 = extract_h(L_add(L_tmp, 0x8000));
-
- if (*ser_size >= NBBITS_24k)
- Copy(&exc[i_subfr], exc2, L_SUBFR);
-
- for (i = 0; i < L_SUBFR; i++)
- {
- /* code in Q9, gain_pit in Q14 */
- L_tmp = (gain_code * code[i])<<1;
- L_tmp = (L_tmp << 5);
- L_tmp += (exc[i + i_subfr] * gain_pit)<<1;
- L_tmp = L_shl2(L_tmp, 1);
- exc[i + i_subfr] = extract_h(L_add(L_tmp, 0x8000));
- }
-
- Syn_filt(p_Aq,&exc[i_subfr], synth, L_SUBFR, st->mem_syn, 1);
-
- if(*ser_size >= NBBITS_24k)
- {
- /*------------------------------------------------------------*
- * phase dispersion to enhance noise in low bit rate *
- *------------------------------------------------------------*/
- /* L_gain_code in Q16 */
- VO_L_Extract(L_gain_code, &gain_code, &gain_code_lo);
-
- /*------------------------------------------------------------*
- * 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 = vo_mult(stab_fac, tmp);
- L_tmp = L_gain_code;
- if(L_tmp < st->L_gc_thres)
- {
- L_tmp = vo_L_add(L_tmp, Mpy_32_16(gain_code, gain_code_lo, 6226));
- if(L_tmp > st->L_gc_thres)
- {
- L_tmp = st->L_gc_thres;
- }
- } else
- {
- L_tmp = Mpy_32_16(gain_code, gain_code_lo, 27536);
- if(L_tmp < st->L_gc_thres)
- {
- L_tmp = st->L_gc_thres;
- }
- }
- st->L_gc_thres = L_tmp;
-
- L_gain_code = Mpy_32_16(gain_code, gain_code_lo, (32767 - fac));
- VO_L_Extract(L_tmp, &gain_code, &gain_code_lo);
- L_gain_code = vo_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 = ((voice_fac >> 3) + 4096); /* 0.25=voiced, 0=unvoiced */
-
- L_tmp = L_deposit_h(code[0]);
- L_tmp -= (code[1] * tmp)<<1;
- code2[0] = vo_round(L_tmp);
-
- for (i = 1; i < L_SUBFR - 1; i++)
- {
- L_tmp = L_deposit_h(code[i]);
- L_tmp -= (code[i + 1] * tmp)<<1;
- L_tmp -= (code[i - 1] * tmp)<<1;
- code2[i] = vo_round(L_tmp);
- }
-
- L_tmp = L_deposit_h(code[L_SUBFR - 1]);
- L_tmp -= (code[L_SUBFR - 2] * tmp)<<1;
- code2[L_SUBFR - 1] = vo_round(L_tmp);
-
- /* build excitation */
- gain_code = vo_round(L_shl(L_gain_code, Q_new));
-
- for (i = 0; i < L_SUBFR; i++)
- {
- L_tmp = (code2[i] * gain_code)<<1;
- L_tmp = (L_tmp << 5);
- L_tmp += (exc2[i] * gain_pit)<<1;
- L_tmp = (L_tmp << 1);
- exc2[i] = vo_round(L_tmp);
- }
-
- corr_gain = synthesis(p_Aq, exc2, Q_new, &speech16k[i_subfr * 5 / 4], st);
- Parm_serial(corr_gain, 4, &prms);
- }
- p_A += (M + 1);
- p_Aq += (M + 1);
- } /* end of subframe loop */
-
- /*--------------------------------------------------*
- * Update signal for next frame. *
- * -> save past of speech[], wsp[] and exc[]. *
- *--------------------------------------------------*/
- Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME);
- Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM);
- Copy(&old_exc[L_FRAME], st->old_exc, PIT_MAX + L_INTERPOL);
- return;
-}
-
-/*-----------------------------------------------------*
-* Function synthesis() *
-* *
-* Synthesis of signal at 16kHz with HF extension. *
-* *
-*-----------------------------------------------------*/
-
-static Word16 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 */
- Coder_State * st /* (i/o) : State structure */
- )
-{
- Word16 fac, tmp, exp;
- Word16 ener, exp_ener;
- Word32 L_tmp, i;
-
- Word16 synth_hi[M + L_SUBFR], synth_lo[M + L_SUBFR];
- Word16 synth[L_SUBFR];
- Word16 HF[L_SUBFR16k]; /* High Frequency vector */
- Word16 Ap[M + 1];
-
- Word16 HF_SP[L_SUBFR16k]; /* High Frequency vector (from original signal) */
-
- Word16 HP_est_gain, HP_calc_gain, HP_corr_gain;
- Word16 dist_min, dist;
- Word16 HP_gain_ind = 0;
- 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);
-
-#ifdef ASM_OPT /* asm optimization branch */
- Syn_filt_32_asm(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);
-#else
- Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);
-#endif
-
- Copy(synth_hi + L_SUBFR, st->mem_syn_hi, M);
- Copy(synth_lo + L_SUBFR, st->mem_syn_lo, M);
-
-#ifdef ASM_OPT /* asm optimization branch */
- Deemph_32_asm(synth_hi + M, synth_lo + M, synth, &(st->mem_deemph));
-#else
- Deemph_32(synth_hi + M, synth_lo + M, synth, PREEMPH_FAC, L_SUBFR, &(st->mem_deemph));
-#endif
-
- HP50_12k8(synth, L_SUBFR, st->mem_sig_out);
-
- /* Original speech signal as reference for high band gain quantisation */
- for (i = 0; i < L_SUBFR16k; i++)
- {
- HF_SP[i] = synth16k[i];
- }
-
- /*------------------------------------------------------*
- * 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] = Random(&(st->seed2))>>3;
- }
- /* energy of excitation */
-#ifdef ASM_OPT /* asm optimization branch */
- Scale_sig_opt(exc, L_SUBFR, -3);
- Q_new = Q_new - 3;
- ener = extract_h(Dot_product12_asm(exc, exc, L_SUBFR, &exp_ener));
-#else
- Scale_sig(exc, L_SUBFR, -3);
- Q_new = Q_new - 3;
- ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener));
-#endif
-
- exp_ener = exp_ener - (Q_new + Q_new);
- /* set energy of white noise to energy of excitation */
-#ifdef ASM_OPT /* asm optimization branch */
- tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp));
-#else
- tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
-#endif
-
- if(tmp > ener)
- {
- tmp = (tmp >> 1); /* Be sure tmp < ener */
- exp = (exp + 1);
- }
- L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */
- exp = (exp - exp_ener);
- Isqrt_n(&L_tmp, &exp);
- L_tmp = L_shl(L_tmp, (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] = vo_mult(HF[i], tmp);
- }
-
- /* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */
- HP400_12k8(synth, L_SUBFR, st->mem_hp400);
-
- L_tmp = 1L;
- for (i = 0; i < L_SUBFR; i++)
- L_tmp += (synth[i] * synth[i])<<1;
-
- exp = norm_l(L_tmp);
- ener = extract_h(L_tmp << exp); /* ener = r[0] */
-
- L_tmp = 1L;
- for (i = 1; i < L_SUBFR; i++)
- L_tmp +=(synth[i] * synth[i - 1])<<1;
-
- tmp = extract_h(L_tmp << exp); /* tmp = r[1] */
-
- if (tmp > 0)
- {
- fac = div_s(tmp, ener);
- } else
- {
- fac = 0;
- }
-
- /* modify energy of white noise according to synthesis tilt */
- gain1 = 32767 - fac;
- gain2 = vo_mult(gain1, 20480);
- gain2 = shl(gain2, 1);
-
- if (st->vad_hist > 0)
- {
- weight1 = 0;
- weight2 = 32767;
- } else
- {
- weight1 = 32767;
- weight2 = 0;
- }
- tmp = vo_mult(weight1, gain1);
- tmp = add1(tmp, vo_mult(weight2, gain2));
-
- if (tmp != 0)
- {
- tmp = (tmp + 1);
- }
- HP_est_gain = tmp;
-
- if(HP_est_gain < 3277)
- {
- HP_est_gain = 3277; /* 0.1 in Q15 */
- }
- /* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */
- Weight_a(Aq, Ap, 19661, M); /* fac=0.6 */
-
-#ifdef ASM_OPT /* asm optimization branch */
- Syn_filt_asm(Ap, HF, HF, st->mem_syn_hf);
- /* noise High Pass filtering (1ms of delay) */
- Filt_6k_7k_asm(HF, L_SUBFR16k, st->mem_hf);
- /* filtering of the original signal */
- Filt_6k_7k_asm(HF_SP, L_SUBFR16k, st->mem_hf2);
-
- /* check the gain difference */
- Scale_sig_opt(HF_SP, L_SUBFR16k, -1);
- ener = extract_h(Dot_product12_asm(HF_SP, HF_SP, L_SUBFR16k, &exp_ener));
- /* set energy of white noise to energy of excitation */
- tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp));
-#else
- Syn_filt(Ap, HF, HF, L_SUBFR16k, st->mem_syn_hf, 1);
- /* noise High Pass filtering (1ms of delay) */
- Filt_6k_7k(HF, L_SUBFR16k, st->mem_hf);
- /* filtering of the original signal */
- Filt_6k_7k(HF_SP, L_SUBFR16k, st->mem_hf2);
- /* check the gain difference */
- Scale_sig(HF_SP, L_SUBFR16k, -1);
- ener = extract_h(Dot_product12(HF_SP, HF_SP, L_SUBFR16k, &exp_ener));
- /* set energy of white noise to energy of excitation */
- tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
-#endif
-
- if (tmp > ener)
- {
- tmp = (tmp >> 1); /* Be sure tmp < ener */
- exp = (exp + 1);
- }
- L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */
- exp = vo_sub(exp, exp_ener);
- Isqrt_n(&L_tmp, &exp);
- L_tmp = L_shl(L_tmp, exp); /* L_tmp, L_tmp in Q31 */
- HP_calc_gain = extract_h(L_tmp); /* tmp = sqrt(ener_input/ener_hf) */
-
- /* st->gain_alpha *= st->dtx_encSt->dtxHangoverCount/7 */
- L_tmp = (vo_L_mult(st->dtx_encSt->dtxHangoverCount, 4681) << 15);
- st->gain_alpha = vo_mult(st->gain_alpha, extract_h(L_tmp));
-
- if(st->dtx_encSt->dtxHangoverCount > 6)
- st->gain_alpha = 32767;
- HP_est_gain = HP_est_gain >> 1; /* From Q15 to Q14 */
- HP_corr_gain = add1(vo_mult(HP_calc_gain, st->gain_alpha), vo_mult((32767 - st->gain_alpha), HP_est_gain));
-
- /* Quantise the correction gain */
- dist_min = 32767;
- for (i = 0; i < 16; i++)
- {
- dist = vo_mult((HP_corr_gain - HP_gain[i]), (HP_corr_gain - HP_gain[i]));
- if (dist_min > dist)
- {
- dist_min = dist;
- HP_gain_ind = i;
- }
- }
- HP_corr_gain = HP_gain[HP_gain_ind];
- /* return the quantised gain index when using the highest mode, otherwise zero */
- return (HP_gain_ind);
-}
-
-/*************************************************
-*
-* Breif: Codec main function
-*
-**************************************************/
-
-int AMR_Enc_Encode(HAMRENC hCodec)
-{
- Word32 i;
- Coder_State *gData = (Coder_State*)hCodec;
- Word16 *signal;
- Word16 packed_size = 0;
- Word16 prms[NB_BITS_MAX];
- Word16 coding_mode = 0, nb_bits, allow_dtx, mode, reset_flag;
- mode = gData->mode;
- coding_mode = gData->mode;
- nb_bits = nb_of_bits[mode];
- signal = (Word16 *)gData->inputStream;
- allow_dtx = gData->allow_dtx;
-
- /* check for homing frame */
- reset_flag = encoder_homing_frame_test(signal);
-
- for (i = 0; i < L_FRAME16k; i++) /* Delete the 2 LSBs (14-bit input) */
- {
- *(signal + i) = (Word16) (*(signal + i) & 0xfffC);
- }
-
- coder(&coding_mode, signal, prms, &nb_bits, gData, allow_dtx);
- packed_size = PackBits(prms, coding_mode, mode, gData);
- if (reset_flag != 0)
- {
- Reset_encoder(gData, 1);
- }
- return packed_size;
-}
-
-/***************************************************************************
-*
-*Brief: Codec API function --- Initialize the codec and return a codec handle
-*
-***************************************************************************/
-
-VO_U32 VO_API voAMRWB_Init(VO_HANDLE * phCodec, /* o: the audio codec handle */
- VO_AUDIO_CODINGTYPE vType, /* i: Codec Type ID */
- VO_CODEC_INIT_USERDATA * pUserData /* i: init Parameters */
- )
-{
- Coder_State *st;
- FrameStream *stream;
-#ifdef USE_DEAULT_MEM
- VO_MEM_OPERATOR voMemoprator;
-#endif
- VO_MEM_OPERATOR *pMemOP;
- int interMem = 0;
-
- if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )
- {
-#ifdef USE_DEAULT_MEM
- voMemoprator.Alloc = cmnMemAlloc;
- voMemoprator.Copy = cmnMemCopy;
- voMemoprator.Free = cmnMemFree;
- voMemoprator.Set = cmnMemSet;
- voMemoprator.Check = cmnMemCheck;
- interMem = 1;
- pMemOP = &voMemoprator;
-#else
- *phCodec = NULL;
- return VO_ERR_INVALID_ARG;
-#endif
- }
- else
- {
- pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;
- }
- /*-------------------------------------------------------------------------*
- * Memory allocation for coder state. *
- *-------------------------------------------------------------------------*/
- if ((st = (Coder_State *)mem_malloc(pMemOP, sizeof(Coder_State), 32, VO_INDEX_ENC_AMRWB)) == NULL)
- {
- return VO_ERR_OUTOF_MEMORY;
- }
-
- st->vadSt = NULL;
- st->dtx_encSt = NULL;
- st->sid_update_counter = 3;
- st->sid_handover_debt = 0;
- st->prev_ft = TX_SPEECH;
- st->inputStream = NULL;
- st->inputSize = 0;
-
- /* Default setting */
- st->mode = VOAMRWB_MD2385; /* bit rate 23.85kbps */
- st->frameType = VOAMRWB_RFC3267; /* frame type: RFC3267 */
- st->allow_dtx = 0; /* disable DTX mode */
-
- st->outputStream = NULL;
- st->outputSize = 0;
-
- st->stream = (FrameStream *)mem_malloc(pMemOP, sizeof(FrameStream), 32, VO_INDEX_ENC_AMRWB);
- if(st->stream == NULL)
- return VO_ERR_OUTOF_MEMORY;
-
- st->stream->frame_ptr = (unsigned char *)mem_malloc(pMemOP, Frame_Maxsize, 32, VO_INDEX_ENC_AMRWB);
- if(st->stream->frame_ptr == NULL)
- return VO_ERR_OUTOF_MEMORY;
-
- stream = st->stream;
- voAWB_InitFrameBuffer(stream);
-
- wb_vad_init(&(st->vadSt), pMemOP);
- dtx_enc_init(&(st->dtx_encSt), isf_init, pMemOP);
-
- Reset_encoder((void *) st, 1);
-
- if(interMem)
- {
- st->voMemoprator.Alloc = cmnMemAlloc;
- st->voMemoprator.Copy = cmnMemCopy;
- st->voMemoprator.Free = cmnMemFree;
- st->voMemoprator.Set = cmnMemSet;
- st->voMemoprator.Check = cmnMemCheck;
- pMemOP = &st->voMemoprator;
- }
-
- st->pvoMemop = pMemOP;
-
- *phCodec = (void *) st;
-
- return VO_ERR_NONE;
-}
-
-/**********************************************************************************
-*
-* Brief: Codec API function: Input PCM data
-*
-***********************************************************************************/
-
-VO_U32 VO_API voAMRWB_SetInputData(
- VO_HANDLE hCodec, /* i/o: The codec handle which was created by Init function */
- VO_CODECBUFFER * pInput /* i: The input buffer parameter */
- )
-{
- Coder_State *gData;
- FrameStream *stream;
-
- if(NULL == hCodec)
- {
- return VO_ERR_INVALID_ARG;
- }
-
- gData = (Coder_State *)hCodec;
- stream = gData->stream;
-
- if(NULL == pInput || NULL == pInput->Buffer || 0 > pInput->Length)
- {
- return VO_ERR_INVALID_ARG;
- }
-
- stream->set_ptr = pInput->Buffer;
- stream->set_len = pInput->Length;
- stream->frame_ptr = stream->frame_ptr_bk;
- stream->used_len = 0;
-
- return VO_ERR_NONE;
-}
-
-/**************************************************************************************
-*
-* Brief: Codec API function: Get the compression audio data frame by frame
-*
-***************************************************************************************/
-
-VO_U32 VO_API voAMRWB_GetOutputData(
- VO_HANDLE hCodec, /* i: The Codec Handle which was created by Init function*/
- VO_CODECBUFFER * pOutput, /* o: The output audio data */
- VO_AUDIO_OUTPUTINFO * pAudioFormat /* o: The encoder module filled audio format and used the input size*/
- )
-{
- Coder_State* gData = (Coder_State*)hCodec;
- VO_MEM_OPERATOR *pMemOP;
- FrameStream *stream = (FrameStream *)gData->stream;
- pMemOP = (VO_MEM_OPERATOR *)gData->pvoMemop;
-
- if(stream->framebuffer_len < Frame_MaxByte) /* check the work buffer len */
- {
- stream->frame_storelen = stream->framebuffer_len;
- if(stream->frame_storelen)
- {
- pMemOP->Copy(VO_INDEX_ENC_AMRWB, stream->frame_ptr_bk , stream->frame_ptr , stream->frame_storelen);
- }
- if(stream->set_len > 0)
- {
- voAWB_UpdateFrameBuffer(stream, pMemOP);
- }
- if(stream->framebuffer_len < Frame_MaxByte)
- {
- if(pAudioFormat)
- pAudioFormat->InputUsed = stream->used_len;
- return VO_ERR_INPUT_BUFFER_SMALL;
- }
- }
-
- gData->inputStream = stream->frame_ptr;
- gData->outputStream = (unsigned short*)pOutput->Buffer;
-
- gData->outputSize = AMR_Enc_Encode(gData); /* encoder main function */
-
- pOutput->Length = gData->outputSize; /* get the output buffer length */
- stream->frame_ptr += 640; /* update the work buffer ptr */
- stream->framebuffer_len -= 640;
-
- if(pAudioFormat) /* return output audio information */
- {
- pAudioFormat->Format.Channels = 1;
- pAudioFormat->Format.SampleRate = 8000;
- pAudioFormat->Format.SampleBits = 16;
- pAudioFormat->InputUsed = stream->used_len;
- }
- return VO_ERR_NONE;
-}
-
-/*************************************************************************
-*
-* Brief: Codec API function---set the data by specified parameter ID
-*
-*************************************************************************/
-
-
-VO_U32 VO_API voAMRWB_SetParam(
- VO_HANDLE hCodec, /* i/o: The Codec Handle which was created by Init function */
- VO_S32 uParamID, /* i: The param ID */
- VO_PTR pData /* i: The param value depend on the ID */
- )
-{
- Coder_State* gData = (Coder_State*)hCodec;
- FrameStream *stream = (FrameStream *)(gData->stream);
- int *lValue = (int*)pData;
-
- switch(uParamID)
- {
- /* setting AMR-WB frame type*/
- case VO_PID_AMRWB_FRAMETYPE:
- if(*lValue < VOAMRWB_DEFAULT || *lValue > VOAMRWB_RFC3267)
- return VO_ERR_WRONG_PARAM_ID;
- gData->frameType = *lValue;
- break;
- /* setting AMR-WB bit rate */
- case VO_PID_AMRWB_MODE:
- {
- if(*lValue < VOAMRWB_MD66 || *lValue > VOAMRWB_MD2385)
- return VO_ERR_WRONG_PARAM_ID;
- gData->mode = *lValue;
- }
- break;
- /* enable or disable DTX mode */
- case VO_PID_AMRWB_DTX:
- gData->allow_dtx = (Word16)(*lValue);
- break;
-
- case VO_PID_COMMON_HEADDATA:
- break;
- /* flush the work buffer */
- case VO_PID_COMMON_FLUSH:
- stream->set_ptr = NULL;
- stream->frame_storelen = 0;
- stream->framebuffer_len = 0;
- stream->set_len = 0;
- break;
-
- default:
- return VO_ERR_WRONG_PARAM_ID;
- }
- return VO_ERR_NONE;
-}
-
-/**************************************************************************
-*
-*Brief: Codec API function---Get the data by specified parameter ID
-*
-***************************************************************************/
-
-VO_U32 VO_API voAMRWB_GetParam(
- VO_HANDLE hCodec, /* i: The Codec Handle which was created by Init function */
- VO_S32 uParamID, /* i: The param ID */
- VO_PTR pData /* o: The param value depend on the ID */
- )
-{
- int temp;
- Coder_State* gData = (Coder_State*)hCodec;
-
- if (gData==NULL)
- return VO_ERR_INVALID_ARG;
- switch(uParamID)
- {
- /* output audio format */
- case VO_PID_AMRWB_FORMAT:
- {
- VO_AUDIO_FORMAT* fmt = (VO_AUDIO_FORMAT*)pData;
- fmt->Channels = 1;
- fmt->SampleRate = 16000;
- fmt->SampleBits = 16;
- break;
- }
- /* output audio channel number */
- case VO_PID_AMRWB_CHANNELS:
- temp = 1;
- pData = (void *)(&temp);
- break;
- /* output audio sample rate */
- case VO_PID_AMRWB_SAMPLERATE:
- temp = 16000;
- pData = (void *)(&temp);
- break;
- /* output audio frame type */
- case VO_PID_AMRWB_FRAMETYPE:
- temp = gData->frameType;
- pData = (void *)(&temp);
- break;
- /* output audio bit rate */
- case VO_PID_AMRWB_MODE:
- temp = gData->mode;
- pData = (void *)(&temp);
- break;
- default:
- return VO_ERR_WRONG_PARAM_ID;
- }
-
- return VO_ERR_NONE;
-}
-
-/***********************************************************************************
-*
-* Brief: Codec API function---Release the codec after all encoder operations are done
-*
-*************************************************************************************/
-
-VO_U32 VO_API voAMRWB_Uninit(VO_HANDLE hCodec /* i/o: Codec handle pointer */
- )
-{
- Coder_State* gData = (Coder_State*)hCodec;
- VO_MEM_OPERATOR *pMemOP;
- pMemOP = gData->pvoMemop;
-
- if(hCodec)
- {
- if(gData->stream)
- {
- if(gData->stream->frame_ptr_bk)
- {
- mem_free(pMemOP, gData->stream->frame_ptr_bk, VO_INDEX_ENC_AMRWB);
- gData->stream->frame_ptr_bk = NULL;
- }
- mem_free(pMemOP, gData->stream, VO_INDEX_ENC_AMRWB);
- gData->stream = NULL;
- }
- wb_vad_exit(&(((Coder_State *) gData)->vadSt), pMemOP);
- dtx_enc_exit(&(((Coder_State *) gData)->dtx_encSt), pMemOP);
-
- mem_free(pMemOP, hCodec, VO_INDEX_ENC_AMRWB);
- hCodec = NULL;
- }
-
- return VO_ERR_NONE;
-}
-
-/********************************************************************************
-*
-* Brief: voGetAMRWBEncAPI gets the API handle of the codec
-*
-********************************************************************************/
-
-VO_S32 VO_API voGetAMRWBEncAPI(
- VO_AUDIO_CODECAPI * pEncHandle /* i/o: Codec handle pointer */
- )
-{
- if(NULL == pEncHandle)
- return VO_ERR_INVALID_ARG;
- pEncHandle->Init = voAMRWB_Init;
- pEncHandle->SetInputData = voAMRWB_SetInputData;
- pEncHandle->GetOutputData = voAMRWB_GetOutputData;
- pEncHandle->SetParam = voAMRWB_SetParam;
- pEncHandle->GetParam = voAMRWB_GetParam;
- pEncHandle->Uninit = voAMRWB_Uninit;
-
- return VO_ERR_NONE;
-}
-
-#ifdef __cplusplus
-}
-#endif
+/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: voAMRWBEnc.c * +* * +* Description: Performs the main encoder routine * +* Fixed-point C simulation of AMR WB ACELP coding * +* algorithm with 20 msspeech frames for * +* wideband speech signals. * +* * +************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "math_op.h" +#include "cnst.h" +#include "acelp.h" +#include "cod_main.h" +#include "bits.h" +#include "main.h" +#include "voAMRWB.h" +#include "mem_align.h" +#include "cmnMemory.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */ +static Word16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767}; + +/* 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 +}; + +/* 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 +}; + +/* Private function declaration */ +static Word16 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 */ + Coder_State * st /* (i/o) : State structure */ + ); + +/* Codec some parameters initialization */ +void Reset_encoder(void *st, Word16 reset_all) +{ + Word16 i; + Coder_State *cod_state; + cod_state = (Coder_State *) st; + Set_zero(cod_state->old_exc, PIT_MAX + L_INTERPOL); + Set_zero(cod_state->mem_syn, M); + Set_zero(cod_state->past_isfq, M); + cod_state->mem_w0 = 0; + cod_state->tilt_code = 0; + cod_state->first_frame = 1; + Init_gp_clip(cod_state->gp_clip); + cod_state->L_gc_thres = 0; + if (reset_all != 0) + { + /* Static vectors to zero */ + Set_zero(cod_state->old_speech, L_TOTAL - L_FRAME); + Set_zero(cod_state->old_wsp, (PIT_MAX / OPL_DECIM)); + Set_zero(cod_state->mem_decim2, 3); + /* routines initialization */ + Init_Decim_12k8(cod_state->mem_decim); + Init_HP50_12k8(cod_state->mem_sig_in); + Init_Levinson(cod_state->mem_levinson); + Init_Q_gain2(cod_state->qua_gain); + Init_Hp_wsp(cod_state->hp_wsp_mem); + /* isp initialization */ + Copy(isp_init, cod_state->ispold, M); + Copy(isp_init, cod_state->ispold_q, M); + /* variable initialization */ + cod_state->mem_preemph = 0; + cod_state->mem_wsp = 0; + cod_state->Q_old = 15; + cod_state->Q_max[0] = 15; + cod_state->Q_max[1] = 15; + cod_state->old_wsp_max = 0; + cod_state->old_wsp_shift = 0; + /* pitch ol initialization */ + cod_state->old_T0_med = 40; + cod_state->ol_gain = 0; + cod_state->ada_w = 0; + cod_state->ol_wght_flg = 0; + for (i = 0; i < 5; i++) + { + cod_state->old_ol_lag[i] = 40; + } + Set_zero(cod_state->old_hp_wsp, (L_FRAME / 2) / OPL_DECIM + (PIT_MAX / OPL_DECIM)); + Set_zero(cod_state->mem_syn_hf, M); + Set_zero(cod_state->mem_syn_hi, M); + Set_zero(cod_state->mem_syn_lo, M); + Init_HP50_12k8(cod_state->mem_sig_out); + Init_Filt_6k_7k(cod_state->mem_hf); + Init_HP400_12k8(cod_state->mem_hp400); + Copy(isf_init, cod_state->isfold, M); + cod_state->mem_deemph = 0; + cod_state->seed2 = 21845; + Init_Filt_6k_7k(cod_state->mem_hf2); + cod_state->gain_alpha = 32767; + cod_state->vad_hist = 0; + wb_vad_reset(cod_state->vadSt); + dtx_enc_reset(cod_state->dtx_encSt, isf_init); + } + return; +} + +/*-----------------------------------------------------------------* +* Funtion coder * +* ~~~~~ * +* ->Main coder routine. * +* * +*-----------------------------------------------------------------*/ +void coder( + Word16 * mode, /* input : used mode */ + Word16 speech16k[], /* input : 320 new speech samples (at 16 kHz) */ + Word16 prms[], /* output: output parameters */ + Word16 * ser_size, /* output: bit rate of the used mode */ + void *spe_state, /* i/o : State structure */ + Word16 allow_dtx /* input : DTX ON/OFF */ + ) +{ + /* Coder states */ + Coder_State *st; + /* Speech vector */ + Word16 old_speech[L_TOTAL]; + Word16 *new_speech, *speech, *p_window; + + /* Weighted speech vector */ + Word16 old_wsp[L_FRAME + (PIT_MAX / OPL_DECIM)]; + Word16 *wsp; + + /* Excitation vector */ + Word16 old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL]; + Word16 *exc; + + /* LPC coefficients */ + Word16 r_h[M + 1], r_l[M + 1]; /* Autocorrelations of windowed speech */ + Word16 rc[M]; /* Reflection coefficients. */ + Word16 Ap[M + 1]; /* A(z) with spectral expansion */ + Word16 ispnew[M]; /* immittance spectral pairs at 4nd sfr */ + Word16 ispnew_q[M]; /* quantized ISPs at 4nd subframe */ + Word16 isf[M]; /* ISF (frequency domain) at 4nd sfr */ + Word16 *p_A, *p_Aq; /* ptr to A(z) for the 4 subframes */ + Word16 A[NB_SUBFR * (M + 1)]; /* A(z) unquantized for the 4 subframes */ + Word16 Aq[NB_SUBFR * (M + 1)]; /* A(z) quantized for the 4 subframes */ + + /* Other vectors */ + Word16 xn[L_SUBFR]; /* Target vector for pitch search */ + Word16 xn2[L_SUBFR]; /* Target vector for codebook search */ + Word16 dn[L_SUBFR]; /* Correlation between xn2 and h1 */ + Word16 cn[L_SUBFR]; /* Target vector in residual domain */ + Word16 h1[L_SUBFR]; /* Impulse response vector */ + Word16 h2[L_SUBFR]; /* Impulse response vector */ + Word16 code[L_SUBFR]; /* Fixed codebook excitation */ + Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 y2[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 error[M + L_SUBFR]; /* error of quantization */ + Word16 synth[L_SUBFR]; /* 12.8kHz synthesis vector */ + Word16 exc2[L_FRAME]; /* excitation vector */ + Word16 buf[L_FRAME]; /* VAD buffer */ + + /* Scalars */ + Word32 i, j, i_subfr, select, pit_flag, clip_gain, vad_flag; + Word16 codec_mode; + Word16 T_op, T_op2, T0, T0_min, T0_max, T0_frac, index; + Word16 gain_pit, gain_code, g_coeff[4], g_coeff2[4]; + Word16 tmp, gain1, gain2, exp, Q_new, mu, shift, max; + Word16 voice_fac; + Word16 indice[8]; + Word32 L_tmp, L_gain_code, L_max, L_tmp1; + Word16 code2[L_SUBFR]; /* Fixed codebook excitation */ + Word16 stab_fac, fac, gain_code_lo; + + Word16 corr_gain; + Word16 *vo_p0, *vo_p1, *vo_p2, *vo_p3; + + st = (Coder_State *) spe_state; + + *ser_size = nb_of_bits[*mode]; + codec_mode = *mode; + + /*--------------------------------------------------------------------------* + * Initialize pointers to speech vector. * + * * + * * + * |-------|-------|-------|-------|-------|-------| * + * past sp sf1 sf2 sf3 sf4 L_NEXT * + * <------- Total speech buffer (L_TOTAL) ------> * + * old_speech * + * <------- LPC analysis window (L_WINDOW) ------> * + * | <-- present frame (L_FRAME) ----> * + * p_window | <----- new speech (L_FRAME) ----> * + * | | * + * speech | * + * new_speech * + *--------------------------------------------------------------------------*/ + + new_speech = old_speech + L_TOTAL - L_FRAME - L_FILT; /* New speech */ + speech = old_speech + L_TOTAL - L_FRAME - L_NEXT; /* Present frame */ + p_window = old_speech + L_TOTAL - L_WINDOW; + + exc = old_exc + PIT_MAX + L_INTERPOL; + wsp = old_wsp + (PIT_MAX / OPL_DECIM); + + /* copy coder memory state into working space */ + Copy(st->old_speech, old_speech, L_TOTAL - L_FRAME); + Copy(st->old_wsp, old_wsp, PIT_MAX / OPL_DECIM); + Copy(st->old_exc, old_exc, PIT_MAX + L_INTERPOL); + + /*---------------------------------------------------------------* + * Down sampling signal from 16kHz to 12.8kHz * + * -> The signal is extended by L_FILT samples (padded to zero) * + * to avoid additional delay (L_FILT samples) in the coder. * + * The last L_FILT samples are approximated after decimation and * + * are used (and windowed) only in autocorrelations. * + *---------------------------------------------------------------*/ + + Decim_12k8(speech16k, L_FRAME16k, new_speech, st->mem_decim); + + /* last L_FILT samples for autocorrelation window */ + Copy(st->mem_decim, code, 2 * L_FILT16k); + Set_zero(error, L_FILT16k); /* set next sample to zero */ + Decim_12k8(error, L_FILT16k, new_speech + L_FRAME, code); + + /*---------------------------------------------------------------* + * Perform 50Hz HP filtering of input signal. * + *---------------------------------------------------------------*/ + + HP50_12k8(new_speech, L_FRAME, st->mem_sig_in); + + /* last L_FILT samples for autocorrelation window */ + Copy(st->mem_sig_in, code, 6); + HP50_12k8(new_speech + L_FRAME, L_FILT, code); + + /*---------------------------------------------------------------* + * Perform fixed preemphasis through 1 - g z^-1 * + * Scale signal to get maximum of precision in filtering * + *---------------------------------------------------------------*/ + + mu = PREEMPH_FAC >> 1; /* Q15 --> Q14 */ + + /* get max of new preemphased samples (L_FRAME+L_FILT) */ + L_tmp = new_speech[0] << 15; + L_tmp -= (st->mem_preemph * mu)<<1; + L_max = L_abs(L_tmp); + + for (i = 1; i < L_FRAME + L_FILT; i++) + { + L_tmp = new_speech[i] << 15; + L_tmp -= (new_speech[i - 1] * mu)<<1; + L_tmp = L_abs(L_tmp); + if(L_tmp > L_max) + { + L_max = L_tmp; + } + } + + /* get scaling factor for new and previous samples */ + /* limit scaling to Q_MAX to keep dynamic for ringing in low signal */ + /* limit scaling to Q_MAX also to avoid a[0]<1 in syn_filt_32 */ + tmp = extract_h(L_max); + if (tmp == 0) + { + shift = Q_MAX; + } else + { + shift = norm_s(tmp) - 1; + if (shift < 0) + { + shift = 0; + } + if (shift > Q_MAX) + { + shift = Q_MAX; + } + } + Q_new = shift; + if (Q_new > st->Q_max[0]) + { + Q_new = st->Q_max[0]; + } + if (Q_new > st->Q_max[1]) + { + Q_new = st->Q_max[1]; + } + exp = (Q_new - st->Q_old); + st->Q_old = Q_new; + st->Q_max[1] = st->Q_max[0]; + st->Q_max[0] = shift; + + /* preemphasis with scaling (L_FRAME+L_FILT) */ + tmp = new_speech[L_FRAME - 1]; + + for (i = L_FRAME + L_FILT - 1; i > 0; i--) + { + L_tmp = new_speech[i] << 15; + L_tmp -= (new_speech[i - 1] * mu)<<1; + L_tmp = (L_tmp << Q_new); + new_speech[i] = vo_round(L_tmp); + } + + L_tmp = new_speech[0] << 15; + L_tmp -= (st->mem_preemph * mu)<<1; + L_tmp = (L_tmp << Q_new); + new_speech[0] = vo_round(L_tmp); + + st->mem_preemph = tmp; + + /* scale previous samples and memory */ + + Scale_sig(old_speech, L_TOTAL - L_FRAME - L_FILT, exp); + Scale_sig(old_exc, PIT_MAX + L_INTERPOL, exp); + Scale_sig(st->mem_syn, M, exp); + Scale_sig(st->mem_decim2, 3, exp); + Scale_sig(&(st->mem_wsp), 1, exp); + Scale_sig(&(st->mem_w0), 1, exp); + + /*------------------------------------------------------------------------* + * Call VAD * + * Preemphesis scale down signal in low frequency and keep dynamic in HF.* + * Vad work slightly in futur (new_speech = speech + L_NEXT - L_FILT). * + *------------------------------------------------------------------------*/ + Copy(new_speech, buf, L_FRAME); + +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(buf, L_FRAME, 1 - Q_new); +#else + Scale_sig(buf, L_FRAME, 1 - Q_new); +#endif + + vad_flag = wb_vad(st->vadSt, buf); /* Voice Activity Detection */ + if (vad_flag == 0) + { + st->vad_hist = (st->vad_hist + 1); + } else + { + st->vad_hist = 0; + } + + /* DTX processing */ + if (allow_dtx != 0) + { + /* Note that mode may change here */ + tx_dtx_handler(st->dtx_encSt, vad_flag, mode); + *ser_size = nb_of_bits[*mode]; + } + + if(*mode != MRDTX) + { + Parm_serial(vad_flag, 1, &prms); + } + /*------------------------------------------------------------------------* + * Perform LPC analysis * + * ~~~~~~~~~~~~~~~~~~~~ * + * - autocorrelation + lag windowing * + * - Levinson-durbin algorithm to find a[] * + * - convert a[] to isp[] * + * - convert isp[] to isf[] for quantization * + * - quantize and code the isf[] * + * - convert isf[] to isp[] for interpolation * + * - find the interpolated ISPs and convert to a[] for the 4 subframes * + *------------------------------------------------------------------------*/ + + /* LP analysis centered at 4nd subframe */ + Autocorr(p_window, M, r_h, r_l); /* Autocorrelations */ + Lag_window(r_h, r_l); /* Lag windowing */ + Levinson(r_h, r_l, A, rc, st->mem_levinson); /* Levinson Durbin */ + Az_isp(A, ispnew, st->ispold); /* From A(z) to ISP */ + + /* Find the interpolated ISPs and convert to a[] for all subframes */ + Int_isp(st->ispold, ispnew, interpol_frac, A); + + /* update ispold[] for the next frame */ + Copy(ispnew, st->ispold, M); + + /* Convert ISPs to frequency domain 0..6400 */ + Isp_isf(ispnew, isf, M); + + /* check resonance for pitch clipping algorithm */ + Gp_clip_test_isf(isf, st->gp_clip); + + /*----------------------------------------------------------------------* + * Perform PITCH_OL analysis * + * ~~~~~~~~~~~~~~~~~~~~~~~~~ * + * - Find the residual res[] for the whole speech frame * + * - Find the weighted input speech wsp[] for the whole speech frame * + * - scale wsp[] to avoid overflow in pitch estimation * + * - Find open loop pitch lag for whole speech frame * + *----------------------------------------------------------------------*/ + p_A = A; + for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) + { + /* Weighting of LPC coefficients */ + Weight_a(p_A, Ap, GAMMA1, M); + +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR); +#else + Residu(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR); +#endif + + p_A += (M + 1); + } + + Deemph2(wsp, TILT_FAC, L_FRAME, &(st->mem_wsp)); + + /* find maximum value on wsp[] for 12 bits scaling */ + max = 0; + for (i = 0; i < L_FRAME; i++) + { + tmp = abs_s(wsp[i]); + if(tmp > max) + { + max = tmp; + } + } + tmp = st->old_wsp_max; + if(max > tmp) + { + tmp = max; /* tmp = max(wsp_max, old_wsp_max) */ + } + st->old_wsp_max = max; + + shift = norm_s(tmp) - 3; + if (shift > 0) + { + shift = 0; /* shift = 0..-3 */ + } + /* decimation of wsp[] to search pitch in LF and to reduce complexity */ + LP_Decim2(wsp, L_FRAME, st->mem_decim2); + + /* scale wsp[] in 12 bits to avoid overflow */ +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(wsp, L_FRAME / OPL_DECIM, shift); +#else + Scale_sig(wsp, L_FRAME / OPL_DECIM, shift); +#endif + /* scale old_wsp (warning: exp must be Q_new-Q_old) */ + exp = exp + (shift - st->old_wsp_shift); + st->old_wsp_shift = shift; + + Scale_sig(old_wsp, PIT_MAX / OPL_DECIM, exp); + Scale_sig(st->old_hp_wsp, PIT_MAX / OPL_DECIM, exp); + + scale_mem_Hp_wsp(st->hp_wsp_mem, exp); + + /* Find open loop pitch lag for whole speech frame */ + + if(*ser_size == NBBITS_7k) + { + /* Find open loop pitch lag for whole speech frame */ + T_op = Pitch_med_ol(wsp, st, L_FRAME / OPL_DECIM); + } else + { + /* Find open loop pitch lag for first 1/2 frame */ + T_op = Pitch_med_ol(wsp, st, (L_FRAME/2) / OPL_DECIM); + } + + if(st->ol_gain > 19661) /* 0.6 in Q15 */ + { + st->old_T0_med = Med_olag(T_op, st->old_ol_lag); + st->ada_w = 32767; + } else + { + st->ada_w = vo_mult(st->ada_w, 29491); + } + + if(st->ada_w < 26214) + st->ol_wght_flg = 0; + else + st->ol_wght_flg = 1; + + wb_vad_tone_detection(st->vadSt, st->ol_gain); + T_op *= OPL_DECIM; + + if(*ser_size != NBBITS_7k) + { + /* Find open loop pitch lag for second 1/2 frame */ + T_op2 = Pitch_med_ol(wsp + ((L_FRAME / 2) / OPL_DECIM), st, (L_FRAME/2) / OPL_DECIM); + + if(st->ol_gain > 19661) /* 0.6 in Q15 */ + { + st->old_T0_med = Med_olag(T_op2, st->old_ol_lag); + st->ada_w = 32767; + } else + { + st->ada_w = mult(st->ada_w, 29491); + } + + if(st->ada_w < 26214) + st->ol_wght_flg = 0; + else + st->ol_wght_flg = 1; + + wb_vad_tone_detection(st->vadSt, st->ol_gain); + + T_op2 *= OPL_DECIM; + + } else + { + T_op2 = T_op; + } + /*----------------------------------------------------------------------* + * DTX-CNG * + *----------------------------------------------------------------------*/ + if(*mode == MRDTX) /* CNG mode */ + { + /* Buffer isf's and energy */ +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(&A[3 * (M + 1)], speech, exc, L_FRAME); +#else + Residu(&A[3 * (M + 1)], speech, exc, L_FRAME); +#endif + + for (i = 0; i < L_FRAME; i++) + { + exc2[i] = shr(exc[i], Q_new); + } + + L_tmp = 0; + for (i = 0; i < L_FRAME; i++) + L_tmp += (exc2[i] * exc2[i])<<1; + + L_tmp >>= 1; + + dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode); + + /* Quantize and code the ISFs */ + dtx_enc(st->dtx_encSt, isf, exc2, &prms); + + /* Convert ISFs to the cosine domain */ + Isf_isp(isf, ispnew_q, M); + Isp_Az(ispnew_q, Aq, M, 0); + + for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) + { + corr_gain = synthesis(Aq, &exc2[i_subfr], 0, &speech16k[i_subfr * 5 / 4], st); + } + Copy(isf, st->isfold, M); + + /* reset speech coder memories */ + Reset_encoder(st, 0); + + /*--------------------------------------------------* + * Update signal for next frame. * + * -> save past of speech[] and wsp[]. * + *--------------------------------------------------*/ + + Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME); + Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM); + + return; + } + /*----------------------------------------------------------------------* + * ACELP * + *----------------------------------------------------------------------*/ + + /* Quantize and code the ISFs */ + + if (*ser_size <= NBBITS_7k) + { + Qpisf_2s_36b(isf, isf, st->past_isfq, indice, 4); + + Parm_serial(indice[0], 8, &prms); + Parm_serial(indice[1], 8, &prms); + Parm_serial(indice[2], 7, &prms); + Parm_serial(indice[3], 7, &prms); + Parm_serial(indice[4], 6, &prms); + } else + { + Qpisf_2s_46b(isf, isf, st->past_isfq, indice, 4); + + Parm_serial(indice[0], 8, &prms); + Parm_serial(indice[1], 8, &prms); + Parm_serial(indice[2], 6, &prms); + Parm_serial(indice[3], 7, &prms); + Parm_serial(indice[4], 7, &prms); + Parm_serial(indice[5], 5, &prms); + Parm_serial(indice[6], 5, &prms); + } + + /* Check stability on isf : distance between old isf and current isf */ + + L_tmp = 0; + for (i = 0; i < M - 1; i++) + { + tmp = vo_sub(isf[i], st->isfold[i]); + L_tmp += (tmp * tmp)<<1; + } + + tmp = extract_h(L_shl2(L_tmp, 8)); + + tmp = vo_mult(tmp, 26214); /* tmp = L_tmp*0.8/256 */ + tmp = vo_sub(20480, tmp); /* 1.25 - tmp (in Q14) */ + + stab_fac = shl(tmp, 1); + + if (stab_fac < 0) + { + stab_fac = 0; + } + Copy(isf, st->isfold, M); + + /* Convert ISFs to the cosine domain */ + Isf_isp(isf, ispnew_q, M); + + if (st->first_frame != 0) + { + st->first_frame = 0; + Copy(ispnew_q, st->ispold_q, M); + } + /* Find the interpolated ISPs and convert to a[] for all subframes */ + + Int_isp(st->ispold_q, ispnew_q, interpol_frac, Aq); + + /* update ispold[] for the next frame */ + Copy(ispnew_q, st->ispold_q, M); + + p_Aq = Aq; + for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) + { +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); +#else + Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); +#endif + p_Aq += (M + 1); + } + + /* Buffer isf's and energy for dtx on non-speech frame */ + if (vad_flag == 0) + { + for (i = 0; i < L_FRAME; i++) + { + exc2[i] = exc[i] >> Q_new; + } + L_tmp = 0; + for (i = 0; i < L_FRAME; i++) + L_tmp += (exc2[i] * exc2[i])<<1; + L_tmp >>= 1; + + dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode); + } + /* range for closed loop pitch search in 1st subframe */ + + T0_min = T_op - 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 = T0_max - 15; + } + /*------------------------------------------------------------------------* + * Loop for every subframe in the analysis frame * + *------------------------------------------------------------------------* + * To find the pitch and innovation parameters. The subframe size is * + * L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. * + * - compute the target signal for pitch search * + * - compute impulse response of weighted synthesis filter (h1[]) * + * - find the closed-loop pitch parameters * + * - encode the pitch dealy * + * - find 2 lt prediction (with / without LP filter for lt pred) * + * - find 2 pitch gains and choose the best lt prediction. * + * - find target vector for codebook search * + * - update the impulse response h1[] for codebook search * + * - correlation between target vector and impulse response * + * - codebook search and encoding * + * - VQ of pitch and codebook gains * + * - find voicing factor and tilt of code for next subframe. * + * - update states of weighting filter * + * - find excitation and synthesis speech * + *------------------------------------------------------------------------*/ + p_A = A; + p_Aq = Aq; + for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) + { + pit_flag = i_subfr; + if ((i_subfr == 2 * L_SUBFR) && (*ser_size > NBBITS_7k)) + { + pit_flag = 0; + /* range for closed loop pitch search in 3rd subframe */ + T0_min = (T_op2 - 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 = (T0_max - 15); + } + } + /*-----------------------------------------------------------------------* + * * + * Find the target vector for pitch search: * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + * * + * |------| res[n] * + * speech[n]---| A(z) |-------- * + * |------| | |--------| error[n] |------| * + * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target * + * exc |--------| |------| * + * * + * Instead of subtracting the zero-input response of filters from * + * the weighted input speech, the above configuration is used to * + * compute the target vector. * + * * + *-----------------------------------------------------------------------*/ + + for (i = 0; i < M; i++) + { + error[i] = vo_sub(speech[i + i_subfr - M], st->mem_syn[i]); + } + +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); +#else + Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); +#endif + Syn_filt(p_Aq, &exc[i_subfr], error + M, L_SUBFR, error, 0); + Weight_a(p_A, Ap, GAMMA1, M); + +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(Ap, error + M, xn, L_SUBFR); +#else + Residu(Ap, error + M, xn, L_SUBFR); +#endif + Deemph2(xn, TILT_FAC, L_SUBFR, &(st->mem_w0)); + + /*----------------------------------------------------------------------* + * Find approx. target in residual domain "cn[]" for inovation search. * + *----------------------------------------------------------------------*/ + /* first half: xn[] --> cn[] */ + Set_zero(code, M); + Copy(xn, code + M, L_SUBFR / 2); + tmp = 0; + Preemph2(code + M, TILT_FAC, L_SUBFR / 2, &tmp); + Weight_a(p_A, Ap, GAMMA1, M); + Syn_filt(Ap,code + M, code + M, L_SUBFR / 2, code, 0); + +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(p_Aq,code + M, cn, L_SUBFR / 2); +#else + Residu(p_Aq,code + M, cn, L_SUBFR / 2); +#endif + + /* second half: res[] --> cn[] (approximated and faster) */ + Copy(&exc[i_subfr + (L_SUBFR / 2)], cn + (L_SUBFR / 2), L_SUBFR / 2); + + /*---------------------------------------------------------------* + * Compute impulse response, h1[], of weighted synthesis filter * + *---------------------------------------------------------------*/ + + Set_zero(error, M + L_SUBFR); + Weight_a(p_A, error + M, GAMMA1, M); + + vo_p0 = error+M; + vo_p3 = h1; + for (i = 0; i < L_SUBFR; i++) + { + L_tmp = *vo_p0 << 14; /* x4 (Q12 to Q14) */ + vo_p1 = p_Aq + 1; + vo_p2 = vo_p0-1; + for (j = 1; j <= M/4; j++) + { + L_tmp -= *vo_p1++ * *vo_p2--; + L_tmp -= *vo_p1++ * *vo_p2--; + L_tmp -= *vo_p1++ * *vo_p2--; + L_tmp -= *vo_p1++ * *vo_p2--; + } + *vo_p3++ = *vo_p0++ = vo_round((L_tmp <<4)); + } + /* deemph without division by 2 -> Q14 to Q15 */ + tmp = 0; + Deemph2(h1, TILT_FAC, L_SUBFR, &tmp); /* h1 in Q14 */ + + /* h2 in Q12 for codebook search */ + Copy(h1, h2, L_SUBFR); + + /*---------------------------------------------------------------* + * scale xn[] and h1[] to avoid overflow in dot_product12() * + *---------------------------------------------------------------*/ +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(h2, L_SUBFR, -2); + Scale_sig_opt(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig_opt(h1, L_SUBFR, 1 + shift); /* set h1[] in Q15 with scaling for convolution */ +#else + Scale_sig(h2, L_SUBFR, -2); + Scale_sig(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig(h1, L_SUBFR, 1 + shift); /* set h1[] in Q15 with scaling for convolution */ +#endif + /*----------------------------------------------------------------------* + * Closed-loop fractional pitch search * + *----------------------------------------------------------------------*/ + /* find closed loop fractional pitch lag */ + if(*ser_size <= NBBITS_9k) + { + T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac, + pit_flag, PIT_MIN, PIT_FR1_8b, L_SUBFR); + + /* encode pitch lag */ + if (pit_flag == 0) /* if 1st/3rd subframe */ + { + /*--------------------------------------------------------------* + * The pitch range for the 1st/3rd subframe is encoded with * + * 8 bits and is divided as follows: * + * PIT_MIN to PIT_FR1-1 resolution 1/2 (frac = 0 or 2) * + * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) * + *--------------------------------------------------------------*/ + if (T0 < PIT_FR1_8b) + { + index = ((T0 << 1) + (T0_frac >> 1) - (PIT_MIN<<1)); + } else + { + index = ((T0 - PIT_FR1_8b) + ((PIT_FR1_8b - PIT_MIN)*2)); + } + + Parm_serial(index, 8, &prms); + + /* 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 = (T0_max - 15); + } + } else + { /* if subframe 2 or 4 */ + /*--------------------------------------------------------------* + * The pitch range for subframe 2 or 4 is encoded with 5 bits: * + * T0_min to T0_max resolution 1/2 (frac = 0 or 2) * + *--------------------------------------------------------------*/ + i = (T0 - T0_min); + index = (i << 1) + (T0_frac >> 1); + + Parm_serial(index, 5, &prms); + } + } else + { + T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac, + pit_flag, PIT_FR2, PIT_FR1_9b, L_SUBFR); + + /* encode pitch lag */ + if (pit_flag == 0) /* if 1st/3rd subframe */ + { + /*--------------------------------------------------------------* + * The pitch range for the 1st/3rd subframe is encoded with * + * 9 bits and is divided as follows: * + * PIT_MIN to PIT_FR2-1 resolution 1/4 (frac = 0,1,2 or 3) * + * PIT_FR2 to PIT_FR1-1 resolution 1/2 (frac = 0 or 1) * + * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) * + *--------------------------------------------------------------*/ + + if (T0 < PIT_FR2) + { + index = ((T0 << 2) + T0_frac) - (PIT_MIN << 2); + } else if(T0 < PIT_FR1_9b) + { + index = ((((T0 << 1) + (T0_frac >> 1)) - (PIT_FR2<<1)) + ((PIT_FR2 - PIT_MIN)<<2)); + } else + { + index = (((T0 - PIT_FR1_9b) + ((PIT_FR2 - PIT_MIN)<<2)) + ((PIT_FR1_9b - PIT_FR2)<<1)); + } + + Parm_serial(index, 9, &prms); + + /* 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 = (T0_max - 15); + } + } else + { /* if subframe 2 or 4 */ + /*--------------------------------------------------------------* + * The pitch range for subframe 2 or 4 is encoded with 6 bits: * + * T0_min to T0_max resolution 1/4 (frac = 0,1,2 or 3) * + *--------------------------------------------------------------*/ + i = (T0 - T0_min); + index = (i << 2) + T0_frac; + Parm_serial(index, 6, &prms); + } + } + + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure * + *-----------------------------------------------------------------*/ + + clip_gain = 0; + if((st->gp_clip[0] < 154) && (st->gp_clip[1] > 14746)) + clip_gain = 1; + + /*-----------------------------------------------------------------* + * - find unity gain pitch excitation (adaptive codebook entry) * + * with fractional interpolation. * + * - find filtered pitch exc. y1[]=exc[] convolved with h1[]) * + * - compute pitch gain1 * + *-----------------------------------------------------------------*/ + /* find pitch exitation */ +#ifdef ASM_OPT /* asm optimization branch */ + pred_lt4_asm(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1); +#else + Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1); +#endif + if (*ser_size > NBBITS_9k) + { +#ifdef ASM_OPT /* asm optimization branch */ + Convolve_asm(&exc[i_subfr], h1, y1, L_SUBFR); +#else + Convolve(&exc[i_subfr], h1, y1, L_SUBFR); +#endif + gain1 = G_pitch(xn, y1, g_coeff, L_SUBFR); + /* clip gain if necessary to avoid problem at decoder */ + if ((clip_gain != 0) && (gain1 > GP_CLIP)) + { + gain1 = GP_CLIP; + } + /* find energy of new target xn2[] */ + Updt_tar(xn, dn, y1, gain1, L_SUBFR); /* dn used temporary */ + } else + { + gain1 = 0; + } + /*-----------------------------------------------------------------* + * - find pitch excitation filtered by 1st order LP filter. * + * - find filtered pitch exc. y2[]=exc[] convolved with h1[]) * + * - compute pitch gain2 * + *-----------------------------------------------------------------*/ + /* find pitch excitation with lp filter */ + vo_p0 = exc + i_subfr-1; + vo_p1 = code; + /* find pitch excitation with lp filter */ + for (i = 0; i < L_SUBFR/2; i++) + { + L_tmp = 5898 * *vo_p0++; + L_tmp1 = 5898 * *vo_p0; + L_tmp += 20972 * *vo_p0++; + L_tmp1 += 20972 * *vo_p0++; + L_tmp1 += 5898 * *vo_p0--; + L_tmp += 5898 * *vo_p0; + *vo_p1++ = (L_tmp + 0x4000)>>15; + *vo_p1++ = (L_tmp1 + 0x4000)>>15; + } + +#ifdef ASM_OPT /* asm optimization branch */ + Convolve_asm(code, h1, y2, L_SUBFR); +#else + Convolve(code, h1, y2, L_SUBFR); +#endif + + gain2 = G_pitch(xn, y2, g_coeff2, L_SUBFR); + + /* clip gain if necessary to avoid problem at decoder */ + if ((clip_gain != 0) && (gain2 > GP_CLIP)) + { + gain2 = GP_CLIP; + } + /* find energy of new target xn2[] */ + Updt_tar(xn, xn2, y2, gain2, L_SUBFR); + /*-----------------------------------------------------------------* + * use the best prediction (minimise quadratic error). * + *-----------------------------------------------------------------*/ + select = 0; + if(*ser_size > NBBITS_9k) + { + L_tmp = 0L; + vo_p0 = dn; + vo_p1 = xn2; + for (i = 0; i < L_SUBFR/2; i++) + { + L_tmp += *vo_p0 * *vo_p0; + vo_p0++; + L_tmp -= *vo_p1 * *vo_p1; + vo_p1++; + L_tmp += *vo_p0 * *vo_p0; + vo_p0++; + L_tmp -= *vo_p1 * *vo_p1; + vo_p1++; + } + + if (L_tmp <= 0) + { + select = 1; + } + Parm_serial(select, 1, &prms); + } + if (select == 0) + { + /* use the lp filter for pitch excitation prediction */ + gain_pit = gain2; + Copy(code, &exc[i_subfr], L_SUBFR); + Copy(y2, y1, L_SUBFR); + Copy(g_coeff2, g_coeff, 4); + } else + { + /* no filter used for pitch excitation prediction */ + gain_pit = gain1; + Copy(dn, xn2, L_SUBFR); /* target vector for codebook search */ + } + /*-----------------------------------------------------------------* + * - update cn[] for codebook search * + *-----------------------------------------------------------------*/ + Updt_tar(cn, cn, &exc[i_subfr], gain_pit, L_SUBFR); + +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */ +#else + Scale_sig(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */ +#endif + /*-----------------------------------------------------------------* + * - include fixed-gain pitch contribution into impulse resp. h1[] * + *-----------------------------------------------------------------*/ + tmp = 0; + Preemph(h2, st->tilt_code, L_SUBFR, &tmp); + + if (T0_frac > 2) + T0 = (T0 + 1); + Pit_shrp(h2, T0, PIT_SHARP, L_SUBFR); + /*-----------------------------------------------------------------* + * - Correlation between target xn2[] and impulse response h1[] * + * - Innovative codebook search * + *-----------------------------------------------------------------*/ + cor_h_x(h2, xn2, dn); + if (*ser_size <= NBBITS_7k) + { + ACELP_2t64_fx(dn, cn, h2, code, y2, indice); + + Parm_serial(indice[0], 12, &prms); + } else if(*ser_size <= NBBITS_9k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 20, *ser_size, indice); + + Parm_serial(indice[0], 5, &prms); + Parm_serial(indice[1], 5, &prms); + Parm_serial(indice[2], 5, &prms); + Parm_serial(indice[3], 5, &prms); + } else if(*ser_size <= NBBITS_12k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 36, *ser_size, indice); + + Parm_serial(indice[0], 9, &prms); + Parm_serial(indice[1], 9, &prms); + Parm_serial(indice[2], 9, &prms); + Parm_serial(indice[3], 9, &prms); + } else if(*ser_size <= NBBITS_14k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 44, *ser_size, indice); + + Parm_serial(indice[0], 13, &prms); + Parm_serial(indice[1], 13, &prms); + Parm_serial(indice[2], 9, &prms); + Parm_serial(indice[3], 9, &prms); + } else if(*ser_size <= NBBITS_16k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 52, *ser_size, indice); + + Parm_serial(indice[0], 13, &prms); + Parm_serial(indice[1], 13, &prms); + Parm_serial(indice[2], 13, &prms); + Parm_serial(indice[3], 13, &prms); + } else if(*ser_size <= NBBITS_18k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 64, *ser_size, indice); + + Parm_serial(indice[0], 2, &prms); + Parm_serial(indice[1], 2, &prms); + Parm_serial(indice[2], 2, &prms); + Parm_serial(indice[3], 2, &prms); + Parm_serial(indice[4], 14, &prms); + Parm_serial(indice[5], 14, &prms); + Parm_serial(indice[6], 14, &prms); + Parm_serial(indice[7], 14, &prms); + } else if(*ser_size <= NBBITS_20k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 72, *ser_size, indice); + + Parm_serial(indice[0], 10, &prms); + Parm_serial(indice[1], 10, &prms); + Parm_serial(indice[2], 2, &prms); + Parm_serial(indice[3], 2, &prms); + Parm_serial(indice[4], 10, &prms); + Parm_serial(indice[5], 10, &prms); + Parm_serial(indice[6], 14, &prms); + Parm_serial(indice[7], 14, &prms); + } else + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 88, *ser_size, indice); + + Parm_serial(indice[0], 11, &prms); + Parm_serial(indice[1], 11, &prms); + Parm_serial(indice[2], 11, &prms); + Parm_serial(indice[3], 11, &prms); + Parm_serial(indice[4], 11, &prms); + Parm_serial(indice[5], 11, &prms); + Parm_serial(indice[6], 11, &prms); + Parm_serial(indice[7], 11, &prms); + } + /*-------------------------------------------------------* + * - Add the fixed-gain pitch contribution to code[]. * + *-------------------------------------------------------*/ + tmp = 0; + Preemph(code, st->tilt_code, L_SUBFR, &tmp); + Pit_shrp(code, T0, PIT_SHARP, L_SUBFR); + /*----------------------------------------------------------* + * - Compute the fixed codebook gain * + * - quantize fixed codebook gain * + *----------------------------------------------------------*/ + if(*ser_size <= NBBITS_9k) + { + index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 6, + &gain_pit, &L_gain_code, clip_gain, st->qua_gain); + Parm_serial(index, 6, &prms); + } else + { + index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 7, + &gain_pit, &L_gain_code, clip_gain, st->qua_gain); + Parm_serial(index, 7, &prms); + } + /* test quantized gain of pitch for pitch clipping algorithm */ + Gp_clip_test_gain_pit(gain_pit, st->gp_clip); + + L_tmp = L_shl(L_gain_code, Q_new); + gain_code = extract_h(L_add(L_tmp, 0x8000)); + + /*----------------------------------------------------------* + * Update parameters for the next subframe. * + * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) * + *----------------------------------------------------------*/ + /* find voice factor in Q15 (1=voiced, -1=unvoiced) */ + Copy(&exc[i_subfr], exc2, L_SUBFR); + +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(exc2, L_SUBFR, shift); +#else + Scale_sig(exc2, L_SUBFR, shift); +#endif + voice_fac = voice_factor(exc2, shift, 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); + /*------------------------------------------------------* + * - Update filter's memory "mem_w0" for finding the * + * target vector in the next subframe. * + * - Find the total excitation * + * - Find synthesis speech to update mem_syn[]. * + *------------------------------------------------------*/ + + /* y2 in Q9, gain_pit in Q14 */ + L_tmp = (gain_code * y2[L_SUBFR - 1])<<1; + L_tmp = L_shl(L_tmp, (5 + shift)); + L_tmp = L_negate(L_tmp); + L_tmp += (xn[L_SUBFR - 1] * 16384)<<1; + L_tmp -= (y1[L_SUBFR - 1] * gain_pit)<<1; + L_tmp = L_shl(L_tmp, (1 - shift)); + st->mem_w0 = extract_h(L_add(L_tmp, 0x8000)); + + if (*ser_size >= NBBITS_24k) + Copy(&exc[i_subfr], exc2, L_SUBFR); + + for (i = 0; i < L_SUBFR; i++) + { + /* code in Q9, gain_pit in Q14 */ + L_tmp = (gain_code * code[i])<<1; + L_tmp = (L_tmp << 5); + L_tmp += (exc[i + i_subfr] * gain_pit)<<1; + L_tmp = L_shl2(L_tmp, 1); + exc[i + i_subfr] = extract_h(L_add(L_tmp, 0x8000)); + } + + Syn_filt(p_Aq,&exc[i_subfr], synth, L_SUBFR, st->mem_syn, 1); + + if(*ser_size >= NBBITS_24k) + { + /*------------------------------------------------------------* + * phase dispersion to enhance noise in low bit rate * + *------------------------------------------------------------*/ + /* L_gain_code in Q16 */ + VO_L_Extract(L_gain_code, &gain_code, &gain_code_lo); + + /*------------------------------------------------------------* + * 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 = vo_mult(stab_fac, tmp); + L_tmp = L_gain_code; + if(L_tmp < st->L_gc_thres) + { + L_tmp = vo_L_add(L_tmp, Mpy_32_16(gain_code, gain_code_lo, 6226)); + if(L_tmp > st->L_gc_thres) + { + L_tmp = st->L_gc_thres; + } + } else + { + L_tmp = Mpy_32_16(gain_code, gain_code_lo, 27536); + if(L_tmp < st->L_gc_thres) + { + L_tmp = st->L_gc_thres; + } + } + st->L_gc_thres = L_tmp; + + L_gain_code = Mpy_32_16(gain_code, gain_code_lo, (32767 - fac)); + VO_L_Extract(L_tmp, &gain_code, &gain_code_lo); + L_gain_code = vo_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 = ((voice_fac >> 3) + 4096); /* 0.25=voiced, 0=unvoiced */ + + L_tmp = L_deposit_h(code[0]); + L_tmp -= (code[1] * tmp)<<1; + code2[0] = vo_round(L_tmp); + + for (i = 1; i < L_SUBFR - 1; i++) + { + L_tmp = L_deposit_h(code[i]); + L_tmp -= (code[i + 1] * tmp)<<1; + L_tmp -= (code[i - 1] * tmp)<<1; + code2[i] = vo_round(L_tmp); + } + + L_tmp = L_deposit_h(code[L_SUBFR - 1]); + L_tmp -= (code[L_SUBFR - 2] * tmp)<<1; + code2[L_SUBFR - 1] = vo_round(L_tmp); + + /* build excitation */ + gain_code = vo_round(L_shl(L_gain_code, Q_new)); + + for (i = 0; i < L_SUBFR; i++) + { + L_tmp = (code2[i] * gain_code)<<1; + L_tmp = (L_tmp << 5); + L_tmp += (exc2[i] * gain_pit)<<1; + L_tmp = (L_tmp << 1); + exc2[i] = vo_round(L_tmp); + } + + corr_gain = synthesis(p_Aq, exc2, Q_new, &speech16k[i_subfr * 5 / 4], st); + Parm_serial(corr_gain, 4, &prms); + } + p_A += (M + 1); + p_Aq += (M + 1); + } /* end of subframe loop */ + + /*--------------------------------------------------* + * Update signal for next frame. * + * -> save past of speech[], wsp[] and exc[]. * + *--------------------------------------------------*/ + Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME); + Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM); + Copy(&old_exc[L_FRAME], st->old_exc, PIT_MAX + L_INTERPOL); + return; +} + +/*-----------------------------------------------------* +* Function synthesis() * +* * +* Synthesis of signal at 16kHz with HF extension. * +* * +*-----------------------------------------------------*/ + +static Word16 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 */ + Coder_State * st /* (i/o) : State structure */ + ) +{ + Word16 fac, tmp, exp; + Word16 ener, exp_ener; + Word32 L_tmp, i; + + Word16 synth_hi[M + L_SUBFR], synth_lo[M + L_SUBFR]; + Word16 synth[L_SUBFR]; + Word16 HF[L_SUBFR16k]; /* High Frequency vector */ + Word16 Ap[M + 1]; + + Word16 HF_SP[L_SUBFR16k]; /* High Frequency vector (from original signal) */ + + Word16 HP_est_gain, HP_calc_gain, HP_corr_gain; + Word16 dist_min, dist; + Word16 HP_gain_ind = 0; + 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); + +#ifdef ASM_OPT /* asm optimization branch */ + Syn_filt_32_asm(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR); +#else + Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR); +#endif + + Copy(synth_hi + L_SUBFR, st->mem_syn_hi, M); + Copy(synth_lo + L_SUBFR, st->mem_syn_lo, M); + +#ifdef ASM_OPT /* asm optimization branch */ + Deemph_32_asm(synth_hi + M, synth_lo + M, synth, &(st->mem_deemph)); +#else + Deemph_32(synth_hi + M, synth_lo + M, synth, PREEMPH_FAC, L_SUBFR, &(st->mem_deemph)); +#endif + + HP50_12k8(synth, L_SUBFR, st->mem_sig_out); + + /* Original speech signal as reference for high band gain quantisation */ + for (i = 0; i < L_SUBFR16k; i++) + { + HF_SP[i] = synth16k[i]; + } + + /*------------------------------------------------------* + * 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] = Random(&(st->seed2))>>3; + } + /* energy of excitation */ +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(exc, L_SUBFR, -3); + Q_new = Q_new - 3; + ener = extract_h(Dot_product12_asm(exc, exc, L_SUBFR, &exp_ener)); +#else + Scale_sig(exc, L_SUBFR, -3); + Q_new = Q_new - 3; + ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener)); +#endif + + exp_ener = exp_ener - (Q_new + Q_new); + /* set energy of white noise to energy of excitation */ +#ifdef ASM_OPT /* asm optimization branch */ + tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp)); +#else + tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp)); +#endif + + if(tmp > ener) + { + tmp = (tmp >> 1); /* Be sure tmp < ener */ + exp = (exp + 1); + } + L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */ + exp = (exp - exp_ener); + Isqrt_n(&L_tmp, &exp); + L_tmp = L_shl(L_tmp, (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] = vo_mult(HF[i], tmp); + } + + /* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */ + HP400_12k8(synth, L_SUBFR, st->mem_hp400); + + L_tmp = 1L; + for (i = 0; i < L_SUBFR; i++) + L_tmp += (synth[i] * synth[i])<<1; + + exp = norm_l(L_tmp); + ener = extract_h(L_tmp << exp); /* ener = r[0] */ + + L_tmp = 1L; + for (i = 1; i < L_SUBFR; i++) + L_tmp +=(synth[i] * synth[i - 1])<<1; + + tmp = extract_h(L_tmp << exp); /* tmp = r[1] */ + + if (tmp > 0) + { + fac = div_s(tmp, ener); + } else + { + fac = 0; + } + + /* modify energy of white noise according to synthesis tilt */ + gain1 = 32767 - fac; + gain2 = vo_mult(gain1, 20480); + gain2 = shl(gain2, 1); + + if (st->vad_hist > 0) + { + weight1 = 0; + weight2 = 32767; + } else + { + weight1 = 32767; + weight2 = 0; + } + tmp = vo_mult(weight1, gain1); + tmp = add1(tmp, vo_mult(weight2, gain2)); + + if (tmp != 0) + { + tmp = (tmp + 1); + } + HP_est_gain = tmp; + + if(HP_est_gain < 3277) + { + HP_est_gain = 3277; /* 0.1 in Q15 */ + } + /* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */ + Weight_a(Aq, Ap, 19661, M); /* fac=0.6 */ + +#ifdef ASM_OPT /* asm optimization branch */ + Syn_filt_asm(Ap, HF, HF, st->mem_syn_hf); + /* noise High Pass filtering (1ms of delay) */ + Filt_6k_7k_asm(HF, L_SUBFR16k, st->mem_hf); + /* filtering of the original signal */ + Filt_6k_7k_asm(HF_SP, L_SUBFR16k, st->mem_hf2); + + /* check the gain difference */ + Scale_sig_opt(HF_SP, L_SUBFR16k, -1); + ener = extract_h(Dot_product12_asm(HF_SP, HF_SP, L_SUBFR16k, &exp_ener)); + /* set energy of white noise to energy of excitation */ + tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp)); +#else + Syn_filt(Ap, HF, HF, L_SUBFR16k, st->mem_syn_hf, 1); + /* noise High Pass filtering (1ms of delay) */ + Filt_6k_7k(HF, L_SUBFR16k, st->mem_hf); + /* filtering of the original signal */ + Filt_6k_7k(HF_SP, L_SUBFR16k, st->mem_hf2); + /* check the gain difference */ + Scale_sig(HF_SP, L_SUBFR16k, -1); + ener = extract_h(Dot_product12(HF_SP, HF_SP, L_SUBFR16k, &exp_ener)); + /* set energy of white noise to energy of excitation */ + tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp)); +#endif + + if (tmp > ener) + { + tmp = (tmp >> 1); /* Be sure tmp < ener */ + exp = (exp + 1); + } + L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */ + exp = vo_sub(exp, exp_ener); + Isqrt_n(&L_tmp, &exp); + L_tmp = L_shl(L_tmp, exp); /* L_tmp, L_tmp in Q31 */ + HP_calc_gain = extract_h(L_tmp); /* tmp = sqrt(ener_input/ener_hf) */ + + /* st->gain_alpha *= st->dtx_encSt->dtxHangoverCount/7 */ + L_tmp = (vo_L_mult(st->dtx_encSt->dtxHangoverCount, 4681) << 15); + st->gain_alpha = vo_mult(st->gain_alpha, extract_h(L_tmp)); + + if(st->dtx_encSt->dtxHangoverCount > 6) + st->gain_alpha = 32767; + HP_est_gain = HP_est_gain >> 1; /* From Q15 to Q14 */ + HP_corr_gain = add1(vo_mult(HP_calc_gain, st->gain_alpha), vo_mult((32767 - st->gain_alpha), HP_est_gain)); + + /* Quantise the correction gain */ + dist_min = 32767; + for (i = 0; i < 16; i++) + { + dist = vo_mult((HP_corr_gain - HP_gain[i]), (HP_corr_gain - HP_gain[i])); + if (dist_min > dist) + { + dist_min = dist; + HP_gain_ind = i; + } + } + HP_corr_gain = HP_gain[HP_gain_ind]; + /* return the quantised gain index when using the highest mode, otherwise zero */ + return (HP_gain_ind); +} + +/************************************************* +* +* Breif: Codec main function +* +**************************************************/ + +int AMR_Enc_Encode(HAMRENC hCodec) +{ + Word32 i; + Coder_State *gData = (Coder_State*)hCodec; + Word16 *signal; + Word16 packed_size = 0; + Word16 prms[NB_BITS_MAX]; + Word16 coding_mode = 0, nb_bits, allow_dtx, mode, reset_flag; + mode = gData->mode; + coding_mode = gData->mode; + nb_bits = nb_of_bits[mode]; + signal = (Word16 *)gData->inputStream; + allow_dtx = gData->allow_dtx; + + /* check for homing frame */ + reset_flag = encoder_homing_frame_test(signal); + + for (i = 0; i < L_FRAME16k; i++) /* Delete the 2 LSBs (14-bit input) */ + { + *(signal + i) = (Word16) (*(signal + i) & 0xfffC); + } + + coder(&coding_mode, signal, prms, &nb_bits, gData, allow_dtx); + packed_size = PackBits(prms, coding_mode, mode, gData); + if (reset_flag != 0) + { + Reset_encoder(gData, 1); + } + return packed_size; +} + +/*************************************************************************** +* +*Brief: Codec API function --- Initialize the codec and return a codec handle +* +***************************************************************************/ + +VO_U32 VO_API voAMRWB_Init(VO_HANDLE * phCodec, /* o: the audio codec handle */ + VO_AUDIO_CODINGTYPE vType, /* i: Codec Type ID */ + VO_CODEC_INIT_USERDATA * pUserData /* i: init Parameters */ + ) +{ + Coder_State *st; + FrameStream *stream; +#ifdef USE_DEAULT_MEM + VO_MEM_OPERATOR voMemoprator; +#endif + VO_MEM_OPERATOR *pMemOP; + int interMem = 0; + + if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL ) + { +#ifdef USE_DEAULT_MEM + voMemoprator.Alloc = cmnMemAlloc; + voMemoprator.Copy = cmnMemCopy; + voMemoprator.Free = cmnMemFree; + voMemoprator.Set = cmnMemSet; + voMemoprator.Check = cmnMemCheck; + interMem = 1; + pMemOP = &voMemoprator; +#else + *phCodec = NULL; + return VO_ERR_INVALID_ARG; +#endif + } + else + { + pMemOP = (VO_MEM_OPERATOR *)pUserData->memData; + } + /*-------------------------------------------------------------------------* + * Memory allocation for coder state. * + *-------------------------------------------------------------------------*/ + if ((st = (Coder_State *)mem_malloc(pMemOP, sizeof(Coder_State), 32, VO_INDEX_ENC_AMRWB)) == NULL) + { + return VO_ERR_OUTOF_MEMORY; + } + + st->vadSt = NULL; + st->dtx_encSt = NULL; + st->sid_update_counter = 3; + st->sid_handover_debt = 0; + st->prev_ft = TX_SPEECH; + st->inputStream = NULL; + st->inputSize = 0; + + /* Default setting */ + st->mode = VOAMRWB_MD2385; /* bit rate 23.85kbps */ + st->frameType = VOAMRWB_RFC3267; /* frame type: RFC3267 */ + st->allow_dtx = 0; /* disable DTX mode */ + + st->outputStream = NULL; + st->outputSize = 0; + + st->stream = (FrameStream *)mem_malloc(pMemOP, sizeof(FrameStream), 32, VO_INDEX_ENC_AMRWB); + if(st->stream == NULL) + return VO_ERR_OUTOF_MEMORY; + + st->stream->frame_ptr = (unsigned char *)mem_malloc(pMemOP, Frame_Maxsize, 32, VO_INDEX_ENC_AMRWB); + if(st->stream->frame_ptr == NULL) + return VO_ERR_OUTOF_MEMORY; + + stream = st->stream; + voAWB_InitFrameBuffer(stream); + + wb_vad_init(&(st->vadSt), pMemOP); + dtx_enc_init(&(st->dtx_encSt), isf_init, pMemOP); + + Reset_encoder((void *) st, 1); + + if(interMem) + { + st->voMemoprator.Alloc = cmnMemAlloc; + st->voMemoprator.Copy = cmnMemCopy; + st->voMemoprator.Free = cmnMemFree; + st->voMemoprator.Set = cmnMemSet; + st->voMemoprator.Check = cmnMemCheck; + pMemOP = &st->voMemoprator; + } + + st->pvoMemop = pMemOP; + + *phCodec = (void *) st; + + return VO_ERR_NONE; +} + +/********************************************************************************** +* +* Brief: Codec API function: Input PCM data +* +***********************************************************************************/ + +VO_U32 VO_API voAMRWB_SetInputData( + VO_HANDLE hCodec, /* i/o: The codec handle which was created by Init function */ + VO_CODECBUFFER * pInput /* i: The input buffer parameter */ + ) +{ + Coder_State *gData; + FrameStream *stream; + + if(NULL == hCodec) + { + return VO_ERR_INVALID_ARG; + } + + gData = (Coder_State *)hCodec; + stream = gData->stream; + + if(NULL == pInput || NULL == pInput->Buffer || 0 > pInput->Length) + { + return VO_ERR_INVALID_ARG; + } + + stream->set_ptr = pInput->Buffer; + stream->set_len = pInput->Length; + stream->frame_ptr = stream->frame_ptr_bk; + stream->used_len = 0; + + return VO_ERR_NONE; +} + +/************************************************************************************** +* +* Brief: Codec API function: Get the compression audio data frame by frame +* +***************************************************************************************/ + +VO_U32 VO_API voAMRWB_GetOutputData( + VO_HANDLE hCodec, /* i: The Codec Handle which was created by Init function*/ + VO_CODECBUFFER * pOutput, /* o: The output audio data */ + VO_AUDIO_OUTPUTINFO * pAudioFormat /* o: The encoder module filled audio format and used the input size*/ + ) +{ + Coder_State* gData = (Coder_State*)hCodec; + VO_MEM_OPERATOR *pMemOP; + FrameStream *stream = (FrameStream *)gData->stream; + pMemOP = (VO_MEM_OPERATOR *)gData->pvoMemop; + + if(stream->framebuffer_len < Frame_MaxByte) /* check the work buffer len */ + { + stream->frame_storelen = stream->framebuffer_len; + if(stream->frame_storelen) + { + pMemOP->Copy(VO_INDEX_ENC_AMRWB, stream->frame_ptr_bk , stream->frame_ptr , stream->frame_storelen); + } + if(stream->set_len > 0) + { + voAWB_UpdateFrameBuffer(stream, pMemOP); + } + if(stream->framebuffer_len < Frame_MaxByte) + { + if(pAudioFormat) + pAudioFormat->InputUsed = stream->used_len; + return VO_ERR_INPUT_BUFFER_SMALL; + } + } + + gData->inputStream = stream->frame_ptr; + gData->outputStream = (unsigned short*)pOutput->Buffer; + + gData->outputSize = AMR_Enc_Encode(gData); /* encoder main function */ + + pOutput->Length = gData->outputSize; /* get the output buffer length */ + stream->frame_ptr += 640; /* update the work buffer ptr */ + stream->framebuffer_len -= 640; + + if(pAudioFormat) /* return output audio information */ + { + pAudioFormat->Format.Channels = 1; + pAudioFormat->Format.SampleRate = 8000; + pAudioFormat->Format.SampleBits = 16; + pAudioFormat->InputUsed = stream->used_len; + } + return VO_ERR_NONE; +} + +/************************************************************************* +* +* Brief: Codec API function---set the data by specified parameter ID +* +*************************************************************************/ + + +VO_U32 VO_API voAMRWB_SetParam( + VO_HANDLE hCodec, /* i/o: The Codec Handle which was created by Init function */ + VO_S32 uParamID, /* i: The param ID */ + VO_PTR pData /* i: The param value depend on the ID */ + ) +{ + Coder_State* gData = (Coder_State*)hCodec; + FrameStream *stream = (FrameStream *)(gData->stream); + int *lValue = (int*)pData; + + switch(uParamID) + { + /* setting AMR-WB frame type*/ + case VO_PID_AMRWB_FRAMETYPE: + if(*lValue < VOAMRWB_DEFAULT || *lValue > VOAMRWB_RFC3267) + return VO_ERR_WRONG_PARAM_ID; + gData->frameType = *lValue; + break; + /* setting AMR-WB bit rate */ + case VO_PID_AMRWB_MODE: + { + if(*lValue < VOAMRWB_MD66 || *lValue > VOAMRWB_MD2385) + return VO_ERR_WRONG_PARAM_ID; + gData->mode = *lValue; + } + break; + /* enable or disable DTX mode */ + case VO_PID_AMRWB_DTX: + gData->allow_dtx = (Word16)(*lValue); + break; + + case VO_PID_COMMON_HEADDATA: + break; + /* flush the work buffer */ + case VO_PID_COMMON_FLUSH: + stream->set_ptr = NULL; + stream->frame_storelen = 0; + stream->framebuffer_len = 0; + stream->set_len = 0; + break; + + default: + return VO_ERR_WRONG_PARAM_ID; + } + return VO_ERR_NONE; +} + +/************************************************************************** +* +*Brief: Codec API function---Get the data by specified parameter ID +* +***************************************************************************/ + +VO_U32 VO_API voAMRWB_GetParam( + VO_HANDLE hCodec, /* i: The Codec Handle which was created by Init function */ + VO_S32 uParamID, /* i: The param ID */ + VO_PTR pData /* o: The param value depend on the ID */ + ) +{ + int temp; + Coder_State* gData = (Coder_State*)hCodec; + + if (gData==NULL) + return VO_ERR_INVALID_ARG; + switch(uParamID) + { + /* output audio format */ + case VO_PID_AMRWB_FORMAT: + { + VO_AUDIO_FORMAT* fmt = (VO_AUDIO_FORMAT*)pData; + fmt->Channels = 1; + fmt->SampleRate = 16000; + fmt->SampleBits = 16; + break; + } + /* output audio channel number */ + case VO_PID_AMRWB_CHANNELS: + temp = 1; + pData = (void *)(&temp); + break; + /* output audio sample rate */ + case VO_PID_AMRWB_SAMPLERATE: + temp = 16000; + pData = (void *)(&temp); + break; + /* output audio frame type */ + case VO_PID_AMRWB_FRAMETYPE: + temp = gData->frameType; + pData = (void *)(&temp); + break; + /* output audio bit rate */ + case VO_PID_AMRWB_MODE: + temp = gData->mode; + pData = (void *)(&temp); + break; + default: + return VO_ERR_WRONG_PARAM_ID; + } + + return VO_ERR_NONE; +} + +/*********************************************************************************** +* +* Brief: Codec API function---Release the codec after all encoder operations are done +* +*************************************************************************************/ + +VO_U32 VO_API voAMRWB_Uninit(VO_HANDLE hCodec /* i/o: Codec handle pointer */ + ) +{ + Coder_State* gData = (Coder_State*)hCodec; + VO_MEM_OPERATOR *pMemOP; + pMemOP = gData->pvoMemop; + + if(hCodec) + { + if(gData->stream) + { + if(gData->stream->frame_ptr_bk) + { + mem_free(pMemOP, gData->stream->frame_ptr_bk, VO_INDEX_ENC_AMRWB); + gData->stream->frame_ptr_bk = NULL; + } + mem_free(pMemOP, gData->stream, VO_INDEX_ENC_AMRWB); + gData->stream = NULL; + } + wb_vad_exit(&(((Coder_State *) gData)->vadSt), pMemOP); + dtx_enc_exit(&(((Coder_State *) gData)->dtx_encSt), pMemOP); + + mem_free(pMemOP, hCodec, VO_INDEX_ENC_AMRWB); + hCodec = NULL; + } + + return VO_ERR_NONE; +} + +/******************************************************************************** +* +* Brief: voGetAMRWBEncAPI gets the API handle of the codec +* +********************************************************************************/ + +VO_S32 VO_API voGetAMRWBEncAPI( + VO_AUDIO_CODECAPI * pEncHandle /* i/o: Codec handle pointer */ + ) +{ + if(NULL == pEncHandle) + return VO_ERR_INVALID_ARG; + pEncHandle->Init = voAMRWB_Init; + pEncHandle->SetInputData = voAMRWB_SetInputData; + pEncHandle->GetOutputData = voAMRWB_GetOutputData; + pEncHandle->SetParam = voAMRWB_SetParam; + pEncHandle->GetParam = voAMRWB_GetParam; + pEncHandle->Uninit = voAMRWB_Uninit; + + return VO_ERR_NONE; +} + +#ifdef __cplusplus +} +#endif |