1/*
2 ** Copyright 2003-2010, VisualOn, Inc.
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 **     http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17/***********************************************************************
18*      File: voAMRWBEnc.c                                              *
19*                                                                      *
20*      Description: Performs the main encoder routine                  *
21*                   Fixed-point C simulation of AMR WB ACELP coding    *
22*           algorithm with 20 msspeech frames for              *
23*           wideband speech signals.                           *
24*                                                                      *
25************************************************************************/
26
27#include <stdio.h>
28#include <stdlib.h>
29#include "typedef.h"
30#include "basic_op.h"
31#include "oper_32b.h"
32#include "math_op.h"
33#include "cnst.h"
34#include "acelp.h"
35#include "cod_main.h"
36#include "bits.h"
37#include "main.h"
38#include "voAMRWB.h"
39#include "mem_align.h"
40#include "cmnMemory.h"
41
42#define UNUSED(x) (void)(x)
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */
49static Word16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767};
50
51/* isp tables for initialization */
52static Word16 isp_init[M] =
53{
54    32138, 30274, 27246, 23170, 18205, 12540, 6393, 0,
55    -6393, -12540, -18205, -23170, -27246, -30274, -32138, 1475
56};
57
58static Word16 isf_init[M] =
59{
60    1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192,
61    9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840
62};
63
64/* High Band encoding */
65static const Word16 HP_gain[16] =
66{
67    3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264,
68    11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728
69};
70
71/* Private function declaration */
72static Word16 synthesis(
73            Word16 Aq[],                          /* A(z)  : quantized Az               */
74            Word16 exc[],                         /* (i)   : excitation at 12kHz        */
75            Word16 Q_new,                         /* (i)   : scaling performed on exc   */
76            Word16 synth16k[],                    /* (o)   : 16kHz synthesis signal     */
77            Coder_State * st                      /* (i/o) : State structure            */
78            );
79
80/* Codec some parameters initialization */
81void Reset_encoder(void *st, Word16 reset_all)
82{
83    Word16 i;
84    Coder_State *cod_state;
85    cod_state = (Coder_State *) st;
86    Set_zero(cod_state->old_exc, PIT_MAX + L_INTERPOL);
87    Set_zero(cod_state->mem_syn, M);
88    Set_zero(cod_state->past_isfq, M);
89    cod_state->mem_w0 = 0;
90    cod_state->tilt_code = 0;
91    cod_state->first_frame = 1;
92    Init_gp_clip(cod_state->gp_clip);
93    cod_state->L_gc_thres = 0;
94    if (reset_all != 0)
95    {
96        /* Static vectors to zero */
97        Set_zero(cod_state->old_speech, L_TOTAL - L_FRAME);
98        Set_zero(cod_state->old_wsp, (PIT_MAX / OPL_DECIM));
99        Set_zero(cod_state->mem_decim2, 3);
100        /* routines initialization */
101        Init_Decim_12k8(cod_state->mem_decim);
102        Init_HP50_12k8(cod_state->mem_sig_in);
103        Init_Levinson(cod_state->mem_levinson);
104        Init_Q_gain2(cod_state->qua_gain);
105        Init_Hp_wsp(cod_state->hp_wsp_mem);
106        /* isp initialization */
107        Copy(isp_init, cod_state->ispold, M);
108        Copy(isp_init, cod_state->ispold_q, M);
109        /* variable initialization */
110        cod_state->mem_preemph = 0;
111        cod_state->mem_wsp = 0;
112        cod_state->Q_old = 15;
113        cod_state->Q_max[0] = 15;
114        cod_state->Q_max[1] = 15;
115        cod_state->old_wsp_max = 0;
116        cod_state->old_wsp_shift = 0;
117        /* pitch ol initialization */
118        cod_state->old_T0_med = 40;
119        cod_state->ol_gain = 0;
120        cod_state->ada_w = 0;
121        cod_state->ol_wght_flg = 0;
122        for (i = 0; i < 5; i++)
123        {
124            cod_state->old_ol_lag[i] = 40;
125        }
126        Set_zero(cod_state->old_hp_wsp, (L_FRAME / 2) / OPL_DECIM + (PIT_MAX / OPL_DECIM));
127        Set_zero(cod_state->mem_syn_hf, M);
128        Set_zero(cod_state->mem_syn_hi, M);
129        Set_zero(cod_state->mem_syn_lo, M);
130        Init_HP50_12k8(cod_state->mem_sig_out);
131        Init_Filt_6k_7k(cod_state->mem_hf);
132        Init_HP400_12k8(cod_state->mem_hp400);
133        Copy(isf_init, cod_state->isfold, M);
134        cod_state->mem_deemph = 0;
135        cod_state->seed2 = 21845;
136        Init_Filt_6k_7k(cod_state->mem_hf2);
137        cod_state->gain_alpha = 32767;
138        cod_state->vad_hist = 0;
139        wb_vad_reset(cod_state->vadSt);
140        dtx_enc_reset(cod_state->dtx_encSt, isf_init);
141    }
142    return;
143}
144
145/*-----------------------------------------------------------------*
146*   Funtion  coder                                                *
147*            ~~~~~                                                *
148*   ->Main coder routine.                                         *
149*                                                                 *
150*-----------------------------------------------------------------*/
151void coder(
152        Word16 * mode,                        /* input :  used mode                             */
153        Word16 speech16k[],                   /* input :  320 new speech samples (at 16 kHz)    */
154        Word16 prms[],                        /* output:  output parameters                     */
155        Word16 * ser_size,                    /* output:  bit rate of the used mode             */
156        void *spe_state,                      /* i/o   :  State structure                       */
157        Word16 allow_dtx                      /* input :  DTX ON/OFF                            */
158      )
159{
160    /* Coder states */
161    Coder_State *st;
162    /* Speech vector */
163    Word16 old_speech[L_TOTAL];
164    Word16 *new_speech, *speech, *p_window;
165
166    /* Weighted speech vector */
167    Word16 old_wsp[L_FRAME + (PIT_MAX / OPL_DECIM)];
168    Word16 *wsp;
169
170    /* Excitation vector */
171    Word16 old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL];
172    Word16 *exc;
173
174    /* LPC coefficients */
175    Word16 r_h[M + 1], r_l[M + 1];         /* Autocorrelations of windowed speech  */
176    Word16 rc[M];                          /* Reflection coefficients.             */
177    Word16 Ap[M + 1];                      /* A(z) with spectral expansion         */
178    Word16 ispnew[M];                      /* immittance spectral pairs at 4nd sfr */
179    Word16 ispnew_q[M];                    /* quantized ISPs at 4nd subframe       */
180    Word16 isf[M];                         /* ISF (frequency domain) at 4nd sfr    */
181    Word16 *p_A, *p_Aq;                    /* ptr to A(z) for the 4 subframes      */
182    Word16 A[NB_SUBFR * (M + 1)];          /* A(z) unquantized for the 4 subframes */
183    Word16 Aq[NB_SUBFR * (M + 1)];         /* A(z)   quantized for the 4 subframes */
184
185    /* Other vectors */
186    Word16 xn[L_SUBFR];                    /* Target vector for pitch search     */
187    Word16 xn2[L_SUBFR];                   /* Target vector for codebook search  */
188    Word16 dn[L_SUBFR];                    /* Correlation between xn2 and h1     */
189    Word16 cn[L_SUBFR];                    /* Target vector in residual domain   */
190    Word16 h1[L_SUBFR];                    /* Impulse response vector            */
191    Word16 h2[L_SUBFR];                    /* Impulse response vector            */
192    Word16 code[L_SUBFR];                  /* Fixed codebook excitation          */
193    Word16 y1[L_SUBFR];                    /* Filtered adaptive excitation       */
194    Word16 y2[L_SUBFR];                    /* Filtered adaptive excitation       */
195    Word16 error[M + L_SUBFR];             /* error of quantization              */
196    Word16 synth[L_SUBFR];                 /* 12.8kHz synthesis vector           */
197    Word16 exc2[L_FRAME];                  /* excitation vector                  */
198    Word16 buf[L_FRAME];                   /* VAD buffer                         */
199
200    /* Scalars */
201    Word32 i, j, i_subfr, select, pit_flag, clip_gain, vad_flag;
202    Word16 codec_mode;
203    Word16 T_op, T_op2, T0, T0_min, T0_max, T0_frac, index;
204    Word16 gain_pit, gain_code, g_coeff[4], g_coeff2[4];
205    Word16 tmp, gain1, gain2, exp, Q_new, mu, shift, max;
206    Word16 voice_fac;
207    Word16 indice[8];
208    Word32 L_tmp, L_gain_code, L_max, L_tmp1;
209    Word16 code2[L_SUBFR];                         /* Fixed codebook excitation  */
210    Word16 stab_fac, fac, gain_code_lo;
211
212    Word16 corr_gain;
213    Word16 *vo_p0, *vo_p1, *vo_p2, *vo_p3;
214
215    st = (Coder_State *) spe_state;
216
217    *ser_size = nb_of_bits[*mode];
218    codec_mode = *mode;
219
220    /*--------------------------------------------------------------------------*
221     *          Initialize pointers to speech vector.                           *
222     *                                                                          *
223     *                                                                          *
224     *                    |-------|-------|-------|-------|-------|-------|     *
225     *                     past sp   sf1     sf2     sf3     sf4    L_NEXT      *
226     *                    <-------  Total speech buffer (L_TOTAL)   ------>     *
227     *              old_speech                                                  *
228     *                    <-------  LPC analysis window (L_WINDOW)  ------>     *
229     *                    |       <-- present frame (L_FRAME) ---->             *
230     *                   p_window |       <----- new speech (L_FRAME) ---->     *
231     *                            |       |                                     *
232     *                          speech    |                                     *
233     *                                 new_speech                               *
234     *--------------------------------------------------------------------------*/
235
236    new_speech = old_speech + L_TOTAL - L_FRAME - L_FILT;         /* New speech     */
237    speech = old_speech + L_TOTAL - L_FRAME - L_NEXT;             /* Present frame  */
238    p_window = old_speech + L_TOTAL - L_WINDOW;
239
240    exc = old_exc + PIT_MAX + L_INTERPOL;
241    wsp = old_wsp + (PIT_MAX / OPL_DECIM);
242
243    /* copy coder memory state into working space */
244    Copy(st->old_speech, old_speech, L_TOTAL - L_FRAME);
245    Copy(st->old_wsp, old_wsp, PIT_MAX / OPL_DECIM);
246    Copy(st->old_exc, old_exc, PIT_MAX + L_INTERPOL);
247
248    /*---------------------------------------------------------------*
249     * Down sampling signal from 16kHz to 12.8kHz                    *
250     * -> The signal is extended by L_FILT samples (padded to zero)  *
251     * to avoid additional delay (L_FILT samples) in the coder.      *
252     * The last L_FILT samples are approximated after decimation and *
253     * are used (and windowed) only in autocorrelations.             *
254     *---------------------------------------------------------------*/
255
256    Decim_12k8(speech16k, L_FRAME16k, new_speech, st->mem_decim);
257
258    /* last L_FILT samples for autocorrelation window */
259    Copy(st->mem_decim, code, 2 * L_FILT16k);
260    Set_zero(error, L_FILT16k);            /* set next sample to zero */
261    Decim_12k8(error, L_FILT16k, new_speech + L_FRAME, code);
262
263    /*---------------------------------------------------------------*
264     * Perform 50Hz HP filtering of input signal.                    *
265     *---------------------------------------------------------------*/
266
267    HP50_12k8(new_speech, L_FRAME, st->mem_sig_in);
268
269    /* last L_FILT samples for autocorrelation window */
270    Copy(st->mem_sig_in, code, 6);
271    HP50_12k8(new_speech + L_FRAME, L_FILT, code);
272
273    /*---------------------------------------------------------------*
274     * Perform fixed preemphasis through 1 - g z^-1                  *
275     * Scale signal to get maximum of precision in filtering         *
276     *---------------------------------------------------------------*/
277
278    mu = PREEMPH_FAC >> 1;              /* Q15 --> Q14 */
279
280    /* get max of new preemphased samples (L_FRAME+L_FILT) */
281    L_tmp = new_speech[0] << 15;
282    L_tmp -= (st->mem_preemph * mu)<<1;
283    L_max = L_abs(L_tmp);
284
285    for (i = 1; i < L_FRAME + L_FILT; i++)
286    {
287        L_tmp = new_speech[i] << 15;
288        L_tmp -= (new_speech[i - 1] * mu)<<1;
289        L_tmp = L_abs(L_tmp);
290        if(L_tmp > L_max)
291        {
292            L_max = L_tmp;
293        }
294    }
295
296    /* get scaling factor for new and previous samples */
297    /* limit scaling to Q_MAX to keep dynamic for ringing in low signal */
298    /* limit scaling to Q_MAX also to avoid a[0]<1 in syn_filt_32 */
299    tmp = extract_h(L_max);
300    if (tmp == 0)
301    {
302        shift = Q_MAX;
303    } else
304    {
305        shift = norm_s(tmp) - 1;
306        if (shift < 0)
307        {
308            shift = 0;
309        }
310        if (shift > Q_MAX)
311        {
312            shift = Q_MAX;
313        }
314    }
315    Q_new = shift;
316    if (Q_new > st->Q_max[0])
317    {
318        Q_new = st->Q_max[0];
319    }
320    if (Q_new > st->Q_max[1])
321    {
322        Q_new = st->Q_max[1];
323    }
324    exp = (Q_new - st->Q_old);
325    st->Q_old = Q_new;
326    st->Q_max[1] = st->Q_max[0];
327    st->Q_max[0] = shift;
328
329    /* preemphasis with scaling (L_FRAME+L_FILT) */
330    tmp = new_speech[L_FRAME - 1];
331
332    for (i = L_FRAME + L_FILT - 1; i > 0; i--)
333    {
334        L_tmp = new_speech[i] << 15;
335        L_tmp -= (new_speech[i - 1] * mu)<<1;
336        L_tmp = (L_tmp << Q_new);
337        new_speech[i] = vo_round(L_tmp);
338    }
339
340    L_tmp = new_speech[0] << 15;
341    L_tmp -= (st->mem_preemph * mu)<<1;
342    L_tmp = (L_tmp << Q_new);
343    new_speech[0] = vo_round(L_tmp);
344
345    st->mem_preemph = tmp;
346
347    /* scale previous samples and memory */
348
349    Scale_sig(old_speech, L_TOTAL - L_FRAME - L_FILT, exp);
350    Scale_sig(old_exc, PIT_MAX + L_INTERPOL, exp);
351    Scale_sig(st->mem_syn, M, exp);
352    Scale_sig(st->mem_decim2, 3, exp);
353    Scale_sig(&(st->mem_wsp), 1, exp);
354    Scale_sig(&(st->mem_w0), 1, exp);
355
356    /*------------------------------------------------------------------------*
357     *  Call VAD                                                              *
358     *  Preemphesis scale down signal in low frequency and keep dynamic in HF.*
359     *  Vad work slightly in futur (new_speech = speech + L_NEXT - L_FILT).   *
360     *------------------------------------------------------------------------*/
361    Copy(new_speech, buf, L_FRAME);
362
363#ifdef ASM_OPT        /* asm optimization branch */
364    Scale_sig_opt(buf, L_FRAME, 1 - Q_new);
365#else
366    Scale_sig(buf, L_FRAME, 1 - Q_new);
367#endif
368
369    vad_flag = wb_vad(st->vadSt, buf);          /* Voice Activity Detection */
370    if (vad_flag == 0)
371    {
372        st->vad_hist = (st->vad_hist + 1);
373    } else
374    {
375        st->vad_hist = 0;
376    }
377
378    /* DTX processing */
379    if (allow_dtx != 0)
380    {
381        /* Note that mode may change here */
382        tx_dtx_handler(st->dtx_encSt, vad_flag, mode);
383        *ser_size = nb_of_bits[*mode];
384    }
385
386    if(*mode != MRDTX)
387    {
388        Parm_serial(vad_flag, 1, &prms);
389    }
390    /*------------------------------------------------------------------------*
391     *  Perform LPC analysis                                                  *
392     *  ~~~~~~~~~~~~~~~~~~~~                                                  *
393     *   - autocorrelation + lag windowing                                    *
394     *   - Levinson-durbin algorithm to find a[]                              *
395     *   - convert a[] to isp[]                                               *
396     *   - convert isp[] to isf[] for quantization                            *
397     *   - quantize and code the isf[]                                        *
398     *   - convert isf[] to isp[] for interpolation                           *
399     *   - find the interpolated ISPs and convert to a[] for the 4 subframes  *
400     *------------------------------------------------------------------------*/
401
402    /* LP analysis centered at 4nd subframe */
403    Autocorr(p_window, M, r_h, r_l);                        /* Autocorrelations */
404    Lag_window(r_h, r_l);                                   /* Lag windowing    */
405    Levinson(r_h, r_l, A, rc, st->mem_levinson);            /* Levinson Durbin  */
406    Az_isp(A, ispnew, st->ispold);                          /* From A(z) to ISP */
407
408    /* Find the interpolated ISPs and convert to a[] for all subframes */
409    Int_isp(st->ispold, ispnew, interpol_frac, A);
410
411    /* update ispold[] for the next frame */
412    Copy(ispnew, st->ispold, M);
413
414    /* Convert ISPs to frequency domain 0..6400 */
415    Isp_isf(ispnew, isf, M);
416
417    /* check resonance for pitch clipping algorithm */
418    Gp_clip_test_isf(isf, st->gp_clip);
419
420    /*----------------------------------------------------------------------*
421     *  Perform PITCH_OL analysis                                           *
422     *  ~~~~~~~~~~~~~~~~~~~~~~~~~                                           *
423     * - Find the residual res[] for the whole speech frame                 *
424     * - Find the weighted input speech wsp[] for the whole speech frame    *
425     * - scale wsp[] to avoid overflow in pitch estimation                  *
426     * - Find open loop pitch lag for whole speech frame                    *
427     *----------------------------------------------------------------------*/
428    p_A = A;
429    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
430    {
431        /* Weighting of LPC coefficients */
432        Weight_a(p_A, Ap, GAMMA1, M);
433
434#ifdef ASM_OPT                    /* asm optimization branch */
435        Residu_opt(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR);
436#else
437        Residu(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR);
438#endif
439
440        p_A += (M + 1);
441    }
442
443    Deemph2(wsp, TILT_FAC, L_FRAME, &(st->mem_wsp));
444
445    /* find maximum value on wsp[] for 12 bits scaling */
446    max = 0;
447    for (i = 0; i < L_FRAME; i++)
448    {
449        tmp = abs_s(wsp[i]);
450        if(tmp > max)
451        {
452            max = tmp;
453        }
454    }
455    tmp = st->old_wsp_max;
456    if(max > tmp)
457    {
458        tmp = max;                         /* tmp = max(wsp_max, old_wsp_max) */
459    }
460    st->old_wsp_max = max;
461
462    shift = norm_s(tmp) - 3;
463    if (shift > 0)
464    {
465        shift = 0;                         /* shift = 0..-3 */
466    }
467    /* decimation of wsp[] to search pitch in LF and to reduce complexity */
468    LP_Decim2(wsp, L_FRAME, st->mem_decim2);
469
470    /* scale wsp[] in 12 bits to avoid overflow */
471#ifdef  ASM_OPT                  /* asm optimization branch */
472    Scale_sig_opt(wsp, L_FRAME / OPL_DECIM, shift);
473#else
474    Scale_sig(wsp, L_FRAME / OPL_DECIM, shift);
475#endif
476    /* scale old_wsp (warning: exp must be Q_new-Q_old) */
477    exp = exp + (shift - st->old_wsp_shift);
478    st->old_wsp_shift = shift;
479
480    Scale_sig(old_wsp, PIT_MAX / OPL_DECIM, exp);
481    Scale_sig(st->old_hp_wsp, PIT_MAX / OPL_DECIM, exp);
482
483    scale_mem_Hp_wsp(st->hp_wsp_mem, exp);
484
485    /* Find open loop pitch lag for whole speech frame */
486
487    if(*ser_size == NBBITS_7k)
488    {
489        /* Find open loop pitch lag for whole speech frame */
490        T_op = Pitch_med_ol(wsp, st, L_FRAME / OPL_DECIM);
491    } else
492    {
493        /* Find open loop pitch lag for first 1/2 frame */
494        T_op = Pitch_med_ol(wsp, st, (L_FRAME/2) / OPL_DECIM);
495    }
496
497    if(st->ol_gain > 19661)       /* 0.6 in Q15 */
498    {
499        st->old_T0_med = Med_olag(T_op, st->old_ol_lag);
500        st->ada_w = 32767;
501    } else
502    {
503        st->ada_w = vo_mult(st->ada_w, 29491);
504    }
505
506    if(st->ada_w < 26214)
507        st->ol_wght_flg = 0;
508    else
509        st->ol_wght_flg = 1;
510
511    wb_vad_tone_detection(st->vadSt, st->ol_gain);
512    T_op *= OPL_DECIM;
513
514    if(*ser_size != NBBITS_7k)
515    {
516        /* Find open loop pitch lag for second 1/2 frame */
517        T_op2 = Pitch_med_ol(wsp + ((L_FRAME / 2) / OPL_DECIM), st, (L_FRAME/2) / OPL_DECIM);
518
519        if(st->ol_gain > 19661)   /* 0.6 in Q15 */
520        {
521            st->old_T0_med = Med_olag(T_op2, st->old_ol_lag);
522            st->ada_w = 32767;
523        } else
524        {
525            st->ada_w = mult(st->ada_w, 29491);
526        }
527
528        if(st->ada_w < 26214)
529            st->ol_wght_flg = 0;
530        else
531            st->ol_wght_flg = 1;
532
533        wb_vad_tone_detection(st->vadSt, st->ol_gain);
534
535        T_op2 *= OPL_DECIM;
536
537    } else
538    {
539        T_op2 = T_op;
540    }
541    /*----------------------------------------------------------------------*
542     *                              DTX-CNG                                 *
543     *----------------------------------------------------------------------*/
544    if(*mode == MRDTX)            /* CNG mode */
545    {
546        /* Buffer isf's and energy */
547#ifdef ASM_OPT                   /* asm optimization branch */
548        Residu_opt(&A[3 * (M + 1)], speech, exc, L_FRAME);
549#else
550        Residu(&A[3 * (M + 1)], speech, exc, L_FRAME);
551#endif
552
553        for (i = 0; i < L_FRAME; i++)
554        {
555            exc2[i] = shr(exc[i], Q_new);
556        }
557
558        L_tmp = 0;
559        for (i = 0; i < L_FRAME; i++)
560            L_tmp += (exc2[i] * exc2[i])<<1;
561
562        L_tmp >>= 1;
563
564        dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode);
565
566        /* Quantize and code the ISFs */
567        dtx_enc(st->dtx_encSt, isf, exc2, &prms);
568
569        /* Convert ISFs to the cosine domain */
570        Isf_isp(isf, ispnew_q, M);
571        Isp_Az(ispnew_q, Aq, M, 0);
572
573        for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
574        {
575            corr_gain = synthesis(Aq, &exc2[i_subfr], 0, &speech16k[i_subfr * 5 / 4], st);
576        }
577        Copy(isf, st->isfold, M);
578
579        /* reset speech coder memories */
580        Reset_encoder(st, 0);
581
582        /*--------------------------------------------------*
583         * Update signal for next frame.                    *
584         * -> save past of speech[] and wsp[].              *
585         *--------------------------------------------------*/
586
587        Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME);
588        Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM);
589
590        return;
591    }
592    /*----------------------------------------------------------------------*
593     *                               ACELP                                  *
594     *----------------------------------------------------------------------*/
595
596    /* Quantize and code the ISFs */
597
598    if (*ser_size <= NBBITS_7k)
599    {
600        Qpisf_2s_36b(isf, isf, st->past_isfq, indice, 4);
601
602        Parm_serial(indice[0], 8, &prms);
603        Parm_serial(indice[1], 8, &prms);
604        Parm_serial(indice[2], 7, &prms);
605        Parm_serial(indice[3], 7, &prms);
606        Parm_serial(indice[4], 6, &prms);
607    } else
608    {
609        Qpisf_2s_46b(isf, isf, st->past_isfq, indice, 4);
610
611        Parm_serial(indice[0], 8, &prms);
612        Parm_serial(indice[1], 8, &prms);
613        Parm_serial(indice[2], 6, &prms);
614        Parm_serial(indice[3], 7, &prms);
615        Parm_serial(indice[4], 7, &prms);
616        Parm_serial(indice[5], 5, &prms);
617        Parm_serial(indice[6], 5, &prms);
618    }
619
620    /* Check stability on isf : distance between old isf and current isf */
621
622    L_tmp = 0;
623    for (i = 0; i < M - 1; i++)
624    {
625        tmp = vo_sub(isf[i], st->isfold[i]);
626        L_tmp += (tmp * tmp)<<1;
627    }
628
629    tmp = extract_h(L_shl2(L_tmp, 8));
630
631    tmp = vo_mult(tmp, 26214);                /* tmp = L_tmp*0.8/256 */
632    tmp = vo_sub(20480, tmp);                 /* 1.25 - tmp (in Q14) */
633
634    stab_fac = shl(tmp, 1);
635
636    if (stab_fac < 0)
637    {
638        stab_fac = 0;
639    }
640    Copy(isf, st->isfold, M);
641
642    /* Convert ISFs to the cosine domain */
643    Isf_isp(isf, ispnew_q, M);
644
645    if (st->first_frame != 0)
646    {
647        st->first_frame = 0;
648        Copy(ispnew_q, st->ispold_q, M);
649    }
650    /* Find the interpolated ISPs and convert to a[] for all subframes */
651
652    Int_isp(st->ispold_q, ispnew_q, interpol_frac, Aq);
653
654    /* update ispold[] for the next frame */
655    Copy(ispnew_q, st->ispold_q, M);
656
657    p_Aq = Aq;
658    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
659    {
660#ifdef ASM_OPT               /* asm optimization branch */
661        Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
662#else
663        Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
664#endif
665        p_Aq += (M + 1);
666    }
667
668    /* Buffer isf's and energy for dtx on non-speech frame */
669    if (vad_flag == 0)
670    {
671        for (i = 0; i < L_FRAME; i++)
672        {
673            exc2[i] = exc[i] >> Q_new;
674        }
675        L_tmp = 0;
676        for (i = 0; i < L_FRAME; i++) {
677            Word32 tmp = L_mult(exc2[i], exc2[i]); // (exc2[i] * exc2[i])<<1;
678            L_tmp = L_add(L_tmp, tmp);
679        }
680        L_tmp >>= 1;
681
682        dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode);
683    }
684    /* range for closed loop pitch search in 1st subframe */
685
686    T0_min = T_op - 8;
687    if (T0_min < PIT_MIN)
688    {
689        T0_min = PIT_MIN;
690    }
691    T0_max = (T0_min + 15);
692
693    if(T0_max > PIT_MAX)
694    {
695        T0_max = PIT_MAX;
696        T0_min = T0_max - 15;
697    }
698    /*------------------------------------------------------------------------*
699     *          Loop for every subframe in the analysis frame                 *
700     *------------------------------------------------------------------------*
701     *  To find the pitch and innovation parameters. The subframe size is     *
702     *  L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times.               *
703     *     - compute the target signal for pitch search                       *
704     *     - compute impulse response of weighted synthesis filter (h1[])     *
705     *     - find the closed-loop pitch parameters                            *
706     *     - encode the pitch dealy                                           *
707     *     - find 2 lt prediction (with / without LP filter for lt pred)      *
708     *     - find 2 pitch gains and choose the best lt prediction.            *
709     *     - find target vector for codebook search                           *
710     *     - update the impulse response h1[] for codebook search             *
711     *     - correlation between target vector and impulse response           *
712     *     - codebook search and encoding                                     *
713     *     - VQ of pitch and codebook gains                                   *
714     *     - find voicing factor and tilt of code for next subframe.          *
715     *     - update states of weighting filter                                *
716     *     - find excitation and synthesis speech                             *
717     *------------------------------------------------------------------------*/
718    p_A = A;
719    p_Aq = Aq;
720    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
721    {
722        pit_flag = i_subfr;
723        if ((i_subfr == 2 * L_SUBFR) && (*ser_size > NBBITS_7k))
724        {
725            pit_flag = 0;
726            /* range for closed loop pitch search in 3rd subframe */
727            T0_min = (T_op2 - 8);
728
729            if (T0_min < PIT_MIN)
730            {
731                T0_min = PIT_MIN;
732            }
733            T0_max = (T0_min + 15);
734            if (T0_max > PIT_MAX)
735            {
736                T0_max = PIT_MAX;
737                T0_min = (T0_max - 15);
738            }
739        }
740        /*-----------------------------------------------------------------------*
741         *                                                                       *
742         *        Find the target vector for pitch search:                       *
743         *        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                        *
744         *                                                                       *
745         *             |------|  res[n]                                          *
746         * speech[n]---| A(z) |--------                                          *
747         *             |------|       |   |--------| error[n]  |------|          *
748         *                   zero -- (-)--| 1/A(z) |-----------| W(z) |-- target *
749         *                   exc          |--------|           |------|          *
750         *                                                                       *
751         * Instead of subtracting the zero-input response of filters from        *
752         * the weighted input speech, the above configuration is used to         *
753         * compute the target vector.                                            *
754         *                                                                       *
755         *-----------------------------------------------------------------------*/
756
757        for (i = 0; i < M; i++)
758        {
759            error[i] = vo_sub(speech[i + i_subfr - M], st->mem_syn[i]);
760        }
761
762#ifdef ASM_OPT              /* asm optimization branch */
763        Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
764#else
765        Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
766#endif
767        Syn_filt(p_Aq, &exc[i_subfr], error + M, L_SUBFR, error, 0);
768        Weight_a(p_A, Ap, GAMMA1, M);
769
770#ifdef ASM_OPT             /* asm optimization branch */
771        Residu_opt(Ap, error + M, xn, L_SUBFR);
772#else
773        Residu(Ap, error + M, xn, L_SUBFR);
774#endif
775        Deemph2(xn, TILT_FAC, L_SUBFR, &(st->mem_w0));
776
777        /*----------------------------------------------------------------------*
778         * Find approx. target in residual domain "cn[]" for inovation search.  *
779         *----------------------------------------------------------------------*/
780        /* first half: xn[] --> cn[] */
781        Set_zero(code, M);
782        Copy(xn, code + M, L_SUBFR / 2);
783        tmp = 0;
784        Preemph2(code + M, TILT_FAC, L_SUBFR / 2, &tmp);
785        Weight_a(p_A, Ap, GAMMA1, M);
786        Syn_filt(Ap,code + M, code + M, L_SUBFR / 2, code, 0);
787
788#ifdef ASM_OPT                /* asm optimization branch */
789        Residu_opt(p_Aq,code + M, cn, L_SUBFR / 2);
790#else
791        Residu(p_Aq,code + M, cn, L_SUBFR / 2);
792#endif
793
794        /* second half: res[] --> cn[] (approximated and faster) */
795        Copy(&exc[i_subfr + (L_SUBFR / 2)], cn + (L_SUBFR / 2), L_SUBFR / 2);
796
797        /*---------------------------------------------------------------*
798         * Compute impulse response, h1[], of weighted synthesis filter  *
799         *---------------------------------------------------------------*/
800
801        Set_zero(error, M + L_SUBFR);
802        Weight_a(p_A, error + M, GAMMA1, M);
803
804        vo_p0 = error+M;
805        vo_p3 = h1;
806        for (i = 0; i < L_SUBFR; i++)
807        {
808            L_tmp = *vo_p0 << 14;        /* x4 (Q12 to Q14) */
809            vo_p1 = p_Aq + 1;
810            vo_p2 = vo_p0-1;
811            for (j = 1; j <= M/4; j++)
812            {
813                L_tmp = L_sub(L_tmp, *vo_p1++ * *vo_p2--);
814                L_tmp = L_sub(L_tmp, *vo_p1++ * *vo_p2--);
815                L_tmp = L_sub(L_tmp, *vo_p1++ * *vo_p2--);
816                L_tmp = L_sub(L_tmp, *vo_p1++ * *vo_p2--);
817            }
818            *vo_p3++ = *vo_p0++ = vo_round((L_tmp <<4));
819        }
820        /* deemph without division by 2 -> Q14 to Q15 */
821        tmp = 0;
822        Deemph2(h1, TILT_FAC, L_SUBFR, &tmp);   /* h1 in Q14 */
823
824        /* h2 in Q12 for codebook search */
825        Copy(h1, h2, L_SUBFR);
826
827        /*---------------------------------------------------------------*
828         * scale xn[] and h1[] to avoid overflow in dot_product12()      *
829         *---------------------------------------------------------------*/
830#ifdef  ASM_OPT                  /* asm optimization branch */
831        Scale_sig_opt(h2, L_SUBFR, -2);
832        Scale_sig_opt(xn, L_SUBFR, shift);     /* scaling of xn[] to limit dynamic at 12 bits */
833        Scale_sig_opt(h1, L_SUBFR, 1 + shift);  /* set h1[] in Q15 with scaling for convolution */
834#else
835        Scale_sig(h2, L_SUBFR, -2);
836        Scale_sig(xn, L_SUBFR, shift);     /* scaling of xn[] to limit dynamic at 12 bits */
837        Scale_sig(h1, L_SUBFR, 1 + shift);  /* set h1[] in Q15 with scaling for convolution */
838#endif
839        /*----------------------------------------------------------------------*
840         *                 Closed-loop fractional pitch search                  *
841         *----------------------------------------------------------------------*/
842        /* find closed loop fractional pitch  lag */
843        if(*ser_size <= NBBITS_9k)
844        {
845            T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,
846                    pit_flag, PIT_MIN, PIT_FR1_8b, L_SUBFR);
847
848            /* encode pitch lag */
849            if (pit_flag == 0)             /* if 1st/3rd subframe */
850            {
851                /*--------------------------------------------------------------*
852                 * The pitch range for the 1st/3rd subframe is encoded with     *
853                 * 8 bits and is divided as follows:                            *
854                 *   PIT_MIN to PIT_FR1-1  resolution 1/2 (frac = 0 or 2)       *
855                 *   PIT_FR1 to PIT_MAX    resolution 1   (frac = 0)            *
856                 *--------------------------------------------------------------*/
857                if (T0 < PIT_FR1_8b)
858                {
859                    index = ((T0 << 1) + (T0_frac >> 1) - (PIT_MIN<<1));
860                } else
861                {
862                    index = ((T0 - PIT_FR1_8b) + ((PIT_FR1_8b - PIT_MIN)*2));
863                }
864
865                Parm_serial(index, 8, &prms);
866
867                /* find T0_min and T0_max for subframe 2 and 4 */
868                T0_min = (T0 - 8);
869                if (T0_min < PIT_MIN)
870                {
871                    T0_min = PIT_MIN;
872                }
873                T0_max = T0_min + 15;
874                if (T0_max > PIT_MAX)
875                {
876                    T0_max = PIT_MAX;
877                    T0_min = (T0_max - 15);
878                }
879            } else
880            {                              /* if subframe 2 or 4 */
881                /*--------------------------------------------------------------*
882                 * The pitch range for subframe 2 or 4 is encoded with 5 bits:  *
883                 *   T0_min  to T0_max     resolution 1/2 (frac = 0 or 2)       *
884                 *--------------------------------------------------------------*/
885                i = (T0 - T0_min);
886                index = (i << 1) + (T0_frac >> 1);
887
888                Parm_serial(index, 5, &prms);
889            }
890        } else
891        {
892            T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,
893                    pit_flag, PIT_FR2, PIT_FR1_9b, L_SUBFR);
894
895            /* encode pitch lag */
896            if (pit_flag == 0)             /* if 1st/3rd subframe */
897            {
898                /*--------------------------------------------------------------*
899                 * The pitch range for the 1st/3rd subframe is encoded with     *
900                 * 9 bits and is divided as follows:                            *
901                 *   PIT_MIN to PIT_FR2-1  resolution 1/4 (frac = 0,1,2 or 3)   *
902                 *   PIT_FR2 to PIT_FR1-1  resolution 1/2 (frac = 0 or 1)       *
903                 *   PIT_FR1 to PIT_MAX    resolution 1   (frac = 0)            *
904                 *--------------------------------------------------------------*/
905
906                if (T0 < PIT_FR2)
907                {
908                    index = ((T0 << 2) + T0_frac) - (PIT_MIN << 2);
909                } else if(T0 < PIT_FR1_9b)
910                {
911                    index = ((((T0 << 1) + (T0_frac >> 1)) - (PIT_FR2<<1)) + ((PIT_FR2 - PIT_MIN)<<2));
912                } else
913                {
914                    index = (((T0 - PIT_FR1_9b) + ((PIT_FR2 - PIT_MIN)<<2)) + ((PIT_FR1_9b - PIT_FR2)<<1));
915                }
916
917                Parm_serial(index, 9, &prms);
918
919                /* find T0_min and T0_max for subframe 2 and 4 */
920
921                T0_min = (T0 - 8);
922                if (T0_min < PIT_MIN)
923                {
924                    T0_min = PIT_MIN;
925                }
926                T0_max = T0_min + 15;
927
928                if (T0_max > PIT_MAX)
929                {
930                    T0_max = PIT_MAX;
931                    T0_min = (T0_max - 15);
932                }
933            } else
934            {                              /* if subframe 2 or 4 */
935                /*--------------------------------------------------------------*
936                 * The pitch range for subframe 2 or 4 is encoded with 6 bits:  *
937                 *   T0_min  to T0_max     resolution 1/4 (frac = 0,1,2 or 3)   *
938                 *--------------------------------------------------------------*/
939                i = (T0 - T0_min);
940                index = (i << 2) + T0_frac;
941                Parm_serial(index, 6, &prms);
942            }
943        }
944
945        /*-----------------------------------------------------------------*
946         * Gain clipping test to avoid unstable synthesis on frame erasure *
947         *-----------------------------------------------------------------*/
948
949        clip_gain = 0;
950        if((st->gp_clip[0] < 154) && (st->gp_clip[1] > 14746))
951            clip_gain = 1;
952
953        /*-----------------------------------------------------------------*
954         * - find unity gain pitch excitation (adaptive codebook entry)    *
955         *   with fractional interpolation.                                *
956         * - find filtered pitch exc. y1[]=exc[] convolved with h1[])      *
957         * - compute pitch gain1                                           *
958         *-----------------------------------------------------------------*/
959        /* find pitch exitation */
960#ifdef ASM_OPT                  /* asm optimization branch */
961        pred_lt4_asm(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);
962#else
963        Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);
964#endif
965        if (*ser_size > NBBITS_9k)
966        {
967#ifdef ASM_OPT                   /* asm optimization branch */
968            Convolve_asm(&exc[i_subfr], h1, y1, L_SUBFR);
969#else
970            Convolve(&exc[i_subfr], h1, y1, L_SUBFR);
971#endif
972            gain1 = G_pitch(xn, y1, g_coeff, L_SUBFR);
973            /* clip gain if necessary to avoid problem at decoder */
974            if ((clip_gain != 0) && (gain1 > GP_CLIP))
975            {
976                gain1 = GP_CLIP;
977            }
978            /* find energy of new target xn2[] */
979            Updt_tar(xn, dn, y1, gain1, L_SUBFR);       /* dn used temporary */
980        } else
981        {
982            gain1 = 0;
983        }
984        /*-----------------------------------------------------------------*
985         * - find pitch excitation filtered by 1st order LP filter.        *
986         * - find filtered pitch exc. y2[]=exc[] convolved with h1[])      *
987         * - compute pitch gain2                                           *
988         *-----------------------------------------------------------------*/
989        /* find pitch excitation with lp filter */
990        vo_p0 = exc + i_subfr-1;
991        vo_p1 = code;
992        /* find pitch excitation with lp filter */
993        for (i = 0; i < L_SUBFR/2; i++)
994        {
995            L_tmp = 5898 * *vo_p0++;
996            L_tmp1 = 5898 * *vo_p0;
997            L_tmp += 20972 * *vo_p0++;
998            L_tmp1 += 20972 * *vo_p0++;
999            L_tmp1 += 5898 * *vo_p0--;
1000            L_tmp += 5898 * *vo_p0;
1001            *vo_p1++ = (L_tmp + 0x4000)>>15;
1002            *vo_p1++ = (L_tmp1 + 0x4000)>>15;
1003        }
1004
1005#ifdef ASM_OPT                 /* asm optimization branch */
1006        Convolve_asm(code, h1, y2, L_SUBFR);
1007#else
1008        Convolve(code, h1, y2, L_SUBFR);
1009#endif
1010
1011        gain2 = G_pitch(xn, y2, g_coeff2, L_SUBFR);
1012
1013        /* clip gain if necessary to avoid problem at decoder */
1014        if ((clip_gain != 0) && (gain2 > GP_CLIP))
1015        {
1016            gain2 = GP_CLIP;
1017        }
1018        /* find energy of new target xn2[] */
1019        Updt_tar(xn, xn2, y2, gain2, L_SUBFR);
1020        /*-----------------------------------------------------------------*
1021         * use the best prediction (minimise quadratic error).             *
1022         *-----------------------------------------------------------------*/
1023        select = 0;
1024        if(*ser_size > NBBITS_9k)
1025        {
1026            L_tmp = 0L;
1027            vo_p0 = dn;
1028            vo_p1 = xn2;
1029            for (i = 0; i < L_SUBFR/2; i++)
1030            {
1031                L_tmp = L_add(L_tmp, *vo_p0 * *vo_p0);
1032                vo_p0++;
1033                L_tmp = L_sub(L_tmp, *vo_p1 * *vo_p1);
1034                vo_p1++;
1035                L_tmp = L_add(L_tmp, *vo_p0 * *vo_p0);
1036                vo_p0++;
1037                L_tmp = L_sub(L_tmp, *vo_p1 * *vo_p1);
1038                vo_p1++;
1039            }
1040
1041            if (L_tmp <= 0)
1042            {
1043                select = 1;
1044            }
1045            Parm_serial(select, 1, &prms);
1046        }
1047        if (select == 0)
1048        {
1049            /* use the lp filter for pitch excitation prediction */
1050            gain_pit = gain2;
1051            Copy(code, &exc[i_subfr], L_SUBFR);
1052            Copy(y2, y1, L_SUBFR);
1053            Copy(g_coeff2, g_coeff, 4);
1054        } else
1055        {
1056            /* no filter used for pitch excitation prediction */
1057            gain_pit = gain1;
1058            Copy(dn, xn2, L_SUBFR);        /* target vector for codebook search */
1059        }
1060        /*-----------------------------------------------------------------*
1061         * - update cn[] for codebook search                               *
1062         *-----------------------------------------------------------------*/
1063        Updt_tar(cn, cn, &exc[i_subfr], gain_pit, L_SUBFR);
1064
1065#ifdef  ASM_OPT                           /* asm optimization branch */
1066        Scale_sig_opt(cn, L_SUBFR, shift);     /* scaling of cn[] to limit dynamic at 12 bits */
1067#else
1068        Scale_sig(cn, L_SUBFR, shift);     /* scaling of cn[] to limit dynamic at 12 bits */
1069#endif
1070        /*-----------------------------------------------------------------*
1071         * - include fixed-gain pitch contribution into impulse resp. h1[] *
1072         *-----------------------------------------------------------------*/
1073        tmp = 0;
1074        Preemph(h2, st->tilt_code, L_SUBFR, &tmp);
1075
1076        if (T0_frac > 2)
1077            T0 = (T0 + 1);
1078        Pit_shrp(h2, T0, PIT_SHARP, L_SUBFR);
1079        /*-----------------------------------------------------------------*
1080         * - Correlation between target xn2[] and impulse response h1[]    *
1081         * - Innovative codebook search                                    *
1082         *-----------------------------------------------------------------*/
1083        cor_h_x(h2, xn2, dn);
1084        if (*ser_size <= NBBITS_7k)
1085        {
1086            ACELP_2t64_fx(dn, cn, h2, code, y2, indice);
1087
1088            Parm_serial(indice[0], 12, &prms);
1089        } else if(*ser_size <= NBBITS_9k)
1090        {
1091            ACELP_4t64_fx(dn, cn, h2, code, y2, 20, *ser_size, indice);
1092
1093            Parm_serial(indice[0], 5, &prms);
1094            Parm_serial(indice[1], 5, &prms);
1095            Parm_serial(indice[2], 5, &prms);
1096            Parm_serial(indice[3], 5, &prms);
1097        } else if(*ser_size <= NBBITS_12k)
1098        {
1099            ACELP_4t64_fx(dn, cn, h2, code, y2, 36, *ser_size, indice);
1100
1101            Parm_serial(indice[0], 9, &prms);
1102            Parm_serial(indice[1], 9, &prms);
1103            Parm_serial(indice[2], 9, &prms);
1104            Parm_serial(indice[3], 9, &prms);
1105        } else if(*ser_size <= NBBITS_14k)
1106        {
1107            ACELP_4t64_fx(dn, cn, h2, code, y2, 44, *ser_size, indice);
1108
1109            Parm_serial(indice[0], 13, &prms);
1110            Parm_serial(indice[1], 13, &prms);
1111            Parm_serial(indice[2], 9, &prms);
1112            Parm_serial(indice[3], 9, &prms);
1113        } else if(*ser_size <= NBBITS_16k)
1114        {
1115            ACELP_4t64_fx(dn, cn, h2, code, y2, 52, *ser_size, indice);
1116
1117            Parm_serial(indice[0], 13, &prms);
1118            Parm_serial(indice[1], 13, &prms);
1119            Parm_serial(indice[2], 13, &prms);
1120            Parm_serial(indice[3], 13, &prms);
1121        } else if(*ser_size <= NBBITS_18k)
1122        {
1123            ACELP_4t64_fx(dn, cn, h2, code, y2, 64, *ser_size, indice);
1124
1125            Parm_serial(indice[0], 2, &prms);
1126            Parm_serial(indice[1], 2, &prms);
1127            Parm_serial(indice[2], 2, &prms);
1128            Parm_serial(indice[3], 2, &prms);
1129            Parm_serial(indice[4], 14, &prms);
1130            Parm_serial(indice[5], 14, &prms);
1131            Parm_serial(indice[6], 14, &prms);
1132            Parm_serial(indice[7], 14, &prms);
1133        } else if(*ser_size <= NBBITS_20k)
1134        {
1135            ACELP_4t64_fx(dn, cn, h2, code, y2, 72, *ser_size, indice);
1136
1137            Parm_serial(indice[0], 10, &prms);
1138            Parm_serial(indice[1], 10, &prms);
1139            Parm_serial(indice[2], 2, &prms);
1140            Parm_serial(indice[3], 2, &prms);
1141            Parm_serial(indice[4], 10, &prms);
1142            Parm_serial(indice[5], 10, &prms);
1143            Parm_serial(indice[6], 14, &prms);
1144            Parm_serial(indice[7], 14, &prms);
1145        } else
1146        {
1147            ACELP_4t64_fx(dn, cn, h2, code, y2, 88, *ser_size, indice);
1148
1149            Parm_serial(indice[0], 11, &prms);
1150            Parm_serial(indice[1], 11, &prms);
1151            Parm_serial(indice[2], 11, &prms);
1152            Parm_serial(indice[3], 11, &prms);
1153            Parm_serial(indice[4], 11, &prms);
1154            Parm_serial(indice[5], 11, &prms);
1155            Parm_serial(indice[6], 11, &prms);
1156            Parm_serial(indice[7], 11, &prms);
1157        }
1158        /*-------------------------------------------------------*
1159         * - Add the fixed-gain pitch contribution to code[].    *
1160         *-------------------------------------------------------*/
1161        tmp = 0;
1162        Preemph(code, st->tilt_code, L_SUBFR, &tmp);
1163        Pit_shrp(code, T0, PIT_SHARP, L_SUBFR);
1164        /*----------------------------------------------------------*
1165         *  - Compute the fixed codebook gain                       *
1166         *  - quantize fixed codebook gain                          *
1167         *----------------------------------------------------------*/
1168        if(*ser_size <= NBBITS_9k)
1169        {
1170            index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 6,
1171                    &gain_pit, &L_gain_code, clip_gain, st->qua_gain);
1172            Parm_serial(index, 6, &prms);
1173        } else
1174        {
1175            index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 7,
1176                    &gain_pit, &L_gain_code, clip_gain, st->qua_gain);
1177            Parm_serial(index, 7, &prms);
1178        }
1179        /* test quantized gain of pitch for pitch clipping algorithm */
1180        Gp_clip_test_gain_pit(gain_pit, st->gp_clip);
1181
1182        L_tmp = L_shl(L_gain_code, Q_new);
1183        gain_code = extract_h(L_add(L_tmp, 0x8000));
1184
1185        /*----------------------------------------------------------*
1186         * Update parameters for the next subframe.                 *
1187         * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced)           *
1188         *----------------------------------------------------------*/
1189        /* find voice factor in Q15 (1=voiced, -1=unvoiced) */
1190        Copy(&exc[i_subfr], exc2, L_SUBFR);
1191
1192#ifdef ASM_OPT                           /* asm optimization branch */
1193        Scale_sig_opt(exc2, L_SUBFR, shift);
1194#else
1195        Scale_sig(exc2, L_SUBFR, shift);
1196#endif
1197        voice_fac = voice_factor(exc2, shift, gain_pit, code, gain_code, L_SUBFR);
1198        /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
1199        st->tilt_code = ((voice_fac >> 2) + 8192);
1200        /*------------------------------------------------------*
1201         * - Update filter's memory "mem_w0" for finding the    *
1202         *   target vector in the next subframe.                *
1203         * - Find the total excitation                          *
1204         * - Find synthesis speech to update mem_syn[].         *
1205         *------------------------------------------------------*/
1206
1207        /* y2 in Q9, gain_pit in Q14 */
1208        L_tmp = L_mult(gain_code, y2[L_SUBFR - 1]);
1209        L_tmp = L_shl(L_tmp, (5 + shift));
1210        L_tmp = L_negate(L_tmp);
1211        L_tmp += (xn[L_SUBFR - 1] * 16384)<<1;
1212        L_tmp -= (y1[L_SUBFR - 1] * gain_pit)<<1;
1213        L_tmp = L_shl(L_tmp, (1 - shift));
1214        st->mem_w0 = extract_h(L_add(L_tmp, 0x8000));
1215
1216        if (*ser_size >= NBBITS_24k)
1217            Copy(&exc[i_subfr], exc2, L_SUBFR);
1218
1219        for (i = 0; i < L_SUBFR; i++)
1220        {
1221            Word32 tmp;
1222            /* code in Q9, gain_pit in Q14 */
1223            L_tmp = L_mult(gain_code, code[i]);
1224            L_tmp = L_shl(L_tmp, 5);
1225            tmp = L_mult(exc[i + i_subfr], gain_pit); // (exc[i + i_subfr] * gain_pit)<<1
1226            L_tmp = L_add(L_tmp, tmp);
1227            L_tmp = L_shl2(L_tmp, 1);
1228            exc[i + i_subfr] = extract_h(L_add(L_tmp, 0x8000));
1229        }
1230
1231        Syn_filt(p_Aq,&exc[i_subfr], synth, L_SUBFR, st->mem_syn, 1);
1232
1233        if(*ser_size >= NBBITS_24k)
1234        {
1235            /*------------------------------------------------------------*
1236             * phase dispersion to enhance noise in low bit rate          *
1237             *------------------------------------------------------------*/
1238            /* L_gain_code in Q16 */
1239            VO_L_Extract(L_gain_code, &gain_code, &gain_code_lo);
1240
1241            /*------------------------------------------------------------*
1242             * noise enhancer                                             *
1243             * ~~~~~~~~~~~~~~                                             *
1244             * - Enhance excitation on noise. (modify gain of code)       *
1245             *   If signal is noisy and LPC filter is stable, move gain   *
1246             *   of code 1.5 dB toward gain of code threshold.            *
1247             *   This decrease by 3 dB noise energy variation.            *
1248             *------------------------------------------------------------*/
1249            tmp = (16384 - (voice_fac >> 1));        /* 1=unvoiced, 0=voiced */
1250            fac = vo_mult(stab_fac, tmp);
1251            L_tmp = L_gain_code;
1252            if(L_tmp < st->L_gc_thres)
1253            {
1254                L_tmp = vo_L_add(L_tmp, Mpy_32_16(gain_code, gain_code_lo, 6226));
1255                if(L_tmp > st->L_gc_thres)
1256                {
1257                    L_tmp = st->L_gc_thres;
1258                }
1259            } else
1260            {
1261                L_tmp = Mpy_32_16(gain_code, gain_code_lo, 27536);
1262                if(L_tmp < st->L_gc_thres)
1263                {
1264                    L_tmp = st->L_gc_thres;
1265                }
1266            }
1267            st->L_gc_thres = L_tmp;
1268
1269            L_gain_code = Mpy_32_16(gain_code, gain_code_lo, (32767 - fac));
1270            VO_L_Extract(L_tmp, &gain_code, &gain_code_lo);
1271            L_gain_code = vo_L_add(L_gain_code, Mpy_32_16(gain_code, gain_code_lo, fac));
1272
1273            /*------------------------------------------------------------*
1274             * pitch enhancer                                             *
1275             * ~~~~~~~~~~~~~~                                             *
1276             * - Enhance excitation on voice. (HP filtering of code)      *
1277             *   On voiced signal, filtering of code by a smooth fir HP   *
1278             *   filter to decrease energy of code in low frequency.      *
1279             *------------------------------------------------------------*/
1280
1281            tmp = ((voice_fac >> 3) + 4096); /* 0.25=voiced, 0=unvoiced */
1282
1283            L_tmp = L_deposit_h(code[0]);
1284            L_tmp -= (code[1] * tmp)<<1;
1285            code2[0] = vo_round(L_tmp);
1286
1287            for (i = 1; i < L_SUBFR - 1; i++)
1288            {
1289                L_tmp = L_deposit_h(code[i]);
1290                L_tmp -= (code[i + 1] * tmp)<<1;
1291                L_tmp -= (code[i - 1] * tmp)<<1;
1292                code2[i] = vo_round(L_tmp);
1293            }
1294
1295            L_tmp = L_deposit_h(code[L_SUBFR - 1]);
1296            L_tmp -= (code[L_SUBFR - 2] * tmp)<<1;
1297            code2[L_SUBFR - 1] = vo_round(L_tmp);
1298
1299            /* build excitation */
1300            gain_code = vo_round(L_shl(L_gain_code, Q_new));
1301
1302            for (i = 0; i < L_SUBFR; i++)
1303            {
1304                L_tmp = L_mult(code2[i], gain_code);
1305                L_tmp = L_shl(L_tmp, 5);
1306                L_tmp = L_add(L_tmp, L_mult(exc2[i], gain_pit));
1307                L_tmp = L_shl(L_tmp, 1);
1308                exc2[i] = voround(L_tmp);
1309            }
1310
1311            corr_gain = synthesis(p_Aq, exc2, Q_new, &speech16k[i_subfr * 5 / 4], st);
1312            Parm_serial(corr_gain, 4, &prms);
1313        }
1314        p_A += (M + 1);
1315        p_Aq += (M + 1);
1316    }                                      /* end of subframe loop */
1317
1318    /*--------------------------------------------------*
1319     * Update signal for next frame.                    *
1320     * -> save past of speech[], wsp[] and exc[].       *
1321     *--------------------------------------------------*/
1322    Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME);
1323    Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM);
1324    Copy(&old_exc[L_FRAME], st->old_exc, PIT_MAX + L_INTERPOL);
1325    return;
1326}
1327
1328/*-----------------------------------------------------*
1329* Function synthesis()                                *
1330*                                                     *
1331* Synthesis of signal at 16kHz with HF extension.     *
1332*                                                     *
1333*-----------------------------------------------------*/
1334
1335static Word16 synthesis(
1336        Word16 Aq[],                          /* A(z)  : quantized Az               */
1337        Word16 exc[],                         /* (i)   : excitation at 12kHz        */
1338        Word16 Q_new,                         /* (i)   : scaling performed on exc   */
1339        Word16 synth16k[],                    /* (o)   : 16kHz synthesis signal     */
1340        Coder_State * st                      /* (i/o) : State structure            */
1341        )
1342{
1343    Word16 fac, tmp, exp;
1344    Word16 ener, exp_ener;
1345    Word32 L_tmp, i;
1346
1347    Word16 synth_hi[M + L_SUBFR], synth_lo[M + L_SUBFR];
1348    Word16 synth[L_SUBFR];
1349    Word16 HF[L_SUBFR16k];                 /* High Frequency vector      */
1350    Word16 Ap[M + 1];
1351
1352    Word16 HF_SP[L_SUBFR16k];              /* High Frequency vector (from original signal) */
1353
1354    Word16 HP_est_gain, HP_calc_gain, HP_corr_gain;
1355    Word16 dist_min, dist;
1356    Word16 HP_gain_ind = 0;
1357    Word16 gain1, gain2;
1358    Word16 weight1, weight2;
1359
1360    /*------------------------------------------------------------*
1361     * speech synthesis                                           *
1362     * ~~~~~~~~~~~~~~~~                                           *
1363     * - Find synthesis speech corresponding to exc2[].           *
1364     * - Perform fixed deemphasis and hp 50hz filtering.          *
1365     * - Oversampling from 12.8kHz to 16kHz.                      *
1366     *------------------------------------------------------------*/
1367    Copy(st->mem_syn_hi, synth_hi, M);
1368    Copy(st->mem_syn_lo, synth_lo, M);
1369
1370#ifdef ASM_OPT                 /* asm optimization branch */
1371    Syn_filt_32_asm(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);
1372#else
1373    Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);
1374#endif
1375
1376    Copy(synth_hi + L_SUBFR, st->mem_syn_hi, M);
1377    Copy(synth_lo + L_SUBFR, st->mem_syn_lo, M);
1378
1379#ifdef ASM_OPT                 /* asm optimization branch */
1380    Deemph_32_asm(synth_hi + M, synth_lo + M, synth, &(st->mem_deemph));
1381#else
1382    Deemph_32(synth_hi + M, synth_lo + M, synth, PREEMPH_FAC, L_SUBFR, &(st->mem_deemph));
1383#endif
1384
1385    HP50_12k8(synth, L_SUBFR, st->mem_sig_out);
1386
1387    /* Original speech signal as reference for high band gain quantisation */
1388    for (i = 0; i < L_SUBFR16k; i++)
1389    {
1390        HF_SP[i] = synth16k[i];
1391    }
1392
1393    /*------------------------------------------------------*
1394     * HF noise synthesis                                   *
1395     * ~~~~~~~~~~~~~~~~~~                                   *
1396     * - Generate HF noise between 5.5 and 7.5 kHz.         *
1397     * - Set energy of noise according to synthesis tilt.   *
1398     *     tilt > 0.8 ==> - 14 dB (voiced)                  *
1399     *     tilt   0.5 ==> - 6 dB  (voiced or noise)         *
1400     *     tilt < 0.0 ==>   0 dB  (noise)                   *
1401     *------------------------------------------------------*/
1402    /* generate white noise vector */
1403    for (i = 0; i < L_SUBFR16k; i++)
1404    {
1405        HF[i] = Random(&(st->seed2))>>3;
1406    }
1407    /* energy of excitation */
1408#ifdef ASM_OPT                    /* asm optimization branch */
1409    Scale_sig_opt(exc, L_SUBFR, -3);
1410    Q_new = Q_new - 3;
1411    ener = extract_h(Dot_product12_asm(exc, exc, L_SUBFR, &exp_ener));
1412#else
1413    Scale_sig(exc, L_SUBFR, -3);
1414    Q_new = Q_new - 3;
1415    ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener));
1416#endif
1417
1418    exp_ener = exp_ener - (Q_new + Q_new);
1419    /* set energy of white noise to energy of excitation */
1420#ifdef ASM_OPT              /* asm optimization branch */
1421    tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp));
1422#else
1423    tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
1424#endif
1425
1426    if(tmp > ener)
1427    {
1428        tmp = (tmp >> 1);                 /* Be sure tmp < ener */
1429        exp = (exp + 1);
1430    }
1431    L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */
1432    exp = (exp - exp_ener);
1433    Isqrt_n(&L_tmp, &exp);
1434    L_tmp = L_shl(L_tmp, (exp + 1));       /* L_tmp x 2, L_tmp in Q31 */
1435    tmp = extract_h(L_tmp);                /* tmp = 2 x sqrt(ener_exc/ener_hf) */
1436
1437    for (i = 0; i < L_SUBFR16k; i++)
1438    {
1439        HF[i] = vo_mult(HF[i], tmp);
1440    }
1441
1442    /* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */
1443    HP400_12k8(synth, L_SUBFR, st->mem_hp400);
1444
1445    L_tmp = 1L;
1446    for (i = 0; i < L_SUBFR; i++)
1447        L_tmp += (synth[i] * synth[i])<<1;
1448
1449    exp = norm_l(L_tmp);
1450    ener = extract_h(L_tmp << exp);   /* ener = r[0] */
1451
1452    L_tmp = 1L;
1453    for (i = 1; i < L_SUBFR; i++)
1454        L_tmp +=(synth[i] * synth[i - 1])<<1;
1455
1456    tmp = extract_h(L_tmp << exp);    /* tmp = r[1] */
1457
1458    if (tmp > 0)
1459    {
1460        fac = div_s(tmp, ener);
1461    } else
1462    {
1463        fac = 0;
1464    }
1465
1466    /* modify energy of white noise according to synthesis tilt */
1467    gain1 = 32767 - fac;
1468    gain2 = vo_mult(gain1, 20480);
1469    gain2 = shl(gain2, 1);
1470
1471    if (st->vad_hist > 0)
1472    {
1473        weight1 = 0;
1474        weight2 = 32767;
1475    } else
1476    {
1477        weight1 = 32767;
1478        weight2 = 0;
1479    }
1480    tmp = vo_mult(weight1, gain1);
1481    tmp = add1(tmp, vo_mult(weight2, gain2));
1482
1483    if (tmp != 0)
1484    {
1485        tmp = (tmp + 1);
1486    }
1487    HP_est_gain = tmp;
1488
1489    if(HP_est_gain < 3277)
1490    {
1491        HP_est_gain = 3277;                /* 0.1 in Q15 */
1492    }
1493    /* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */
1494    Weight_a(Aq, Ap, 19661, M);            /* fac=0.6 */
1495
1496#ifdef ASM_OPT                /* asm optimization branch */
1497    Syn_filt_asm(Ap, HF, HF, st->mem_syn_hf);
1498    /* noise High Pass filtering (1ms of delay) */
1499    Filt_6k_7k_asm(HF, L_SUBFR16k, st->mem_hf);
1500    /* filtering of the original signal */
1501    Filt_6k_7k_asm(HF_SP, L_SUBFR16k, st->mem_hf2);
1502
1503    /* check the gain difference */
1504    Scale_sig_opt(HF_SP, L_SUBFR16k, -1);
1505    ener = extract_h(Dot_product12_asm(HF_SP, HF_SP, L_SUBFR16k, &exp_ener));
1506    /* set energy of white noise to energy of excitation */
1507    tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp));
1508#else
1509    Syn_filt(Ap, HF, HF, L_SUBFR16k, st->mem_syn_hf, 1);
1510    /* noise High Pass filtering (1ms of delay) */
1511    Filt_6k_7k(HF, L_SUBFR16k, st->mem_hf);
1512    /* filtering of the original signal */
1513    Filt_6k_7k(HF_SP, L_SUBFR16k, st->mem_hf2);
1514    /* check the gain difference */
1515    Scale_sig(HF_SP, L_SUBFR16k, -1);
1516    ener = extract_h(Dot_product12(HF_SP, HF_SP, L_SUBFR16k, &exp_ener));
1517    /* set energy of white noise to energy of excitation */
1518    tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
1519#endif
1520
1521    if (tmp > ener)
1522    {
1523        tmp = (tmp >> 1);                 /* Be sure tmp < ener */
1524        exp = (exp + 1);
1525    }
1526    L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */
1527    exp = vo_sub(exp, exp_ener);
1528    Isqrt_n(&L_tmp, &exp);
1529    L_tmp = L_shl(L_tmp, exp);             /* L_tmp, L_tmp in Q31 */
1530    HP_calc_gain = extract_h(L_tmp);       /* tmp = sqrt(ener_input/ener_hf) */
1531
1532    /* st->gain_alpha *= st->dtx_encSt->dtxHangoverCount/7 */
1533    L_tmp = (vo_L_mult(st->dtx_encSt->dtxHangoverCount, 4681) << 15);
1534    st->gain_alpha = vo_mult(st->gain_alpha, extract_h(L_tmp));
1535
1536    if(st->dtx_encSt->dtxHangoverCount > 6)
1537        st->gain_alpha = 32767;
1538    HP_est_gain = HP_est_gain >> 1;     /* From Q15 to Q14 */
1539    HP_corr_gain = add1(vo_mult(HP_calc_gain, st->gain_alpha), vo_mult((32767 - st->gain_alpha), HP_est_gain));
1540
1541    /* Quantise the correction gain */
1542    dist_min = 32767;
1543    for (i = 0; i < 16; i++)
1544    {
1545        dist = vo_mult((HP_corr_gain - HP_gain[i]), (HP_corr_gain - HP_gain[i]));
1546        if (dist_min > dist)
1547        {
1548            dist_min = dist;
1549            HP_gain_ind = i;
1550        }
1551    }
1552    HP_corr_gain = HP_gain[HP_gain_ind];
1553    /* return the quantised gain index when using the highest mode, otherwise zero */
1554    return (HP_gain_ind);
1555}
1556
1557/*************************************************
1558*
1559* Breif: Codec main function
1560*
1561**************************************************/
1562
1563int AMR_Enc_Encode(HAMRENC hCodec)
1564{
1565    Word32 i;
1566    Coder_State *gData = (Coder_State*)hCodec;
1567    Word16 *signal;
1568    Word16 packed_size = 0;
1569    Word16 prms[NB_BITS_MAX];
1570    Word16 coding_mode = 0, nb_bits, allow_dtx, mode, reset_flag;
1571    mode = gData->mode;
1572    coding_mode = gData->mode;
1573    nb_bits = nb_of_bits[mode];
1574    signal = (Word16 *)gData->inputStream;
1575    allow_dtx = gData->allow_dtx;
1576
1577    /* check for homing frame */
1578    reset_flag = encoder_homing_frame_test(signal);
1579
1580    for (i = 0; i < L_FRAME16k; i++)   /* Delete the 2 LSBs (14-bit input) */
1581    {
1582        *(signal + i) = (Word16) (*(signal + i) & 0xfffC);
1583    }
1584
1585    coder(&coding_mode, signal, prms, &nb_bits, gData, allow_dtx);
1586    packed_size = PackBits(prms, coding_mode, mode, gData);
1587    if (reset_flag != 0)
1588    {
1589        Reset_encoder(gData, 1);
1590    }
1591    return packed_size;
1592}
1593
1594/***************************************************************************
1595*
1596*Brief: Codec API function --- Initialize the codec and return a codec handle
1597*
1598***************************************************************************/
1599
1600VO_U32 VO_API voAMRWB_Init(VO_HANDLE * phCodec,                   /* o: the audio codec handle */
1601                           VO_AUDIO_CODINGTYPE vType,             /* i: Codec Type ID */
1602                           VO_CODEC_INIT_USERDATA * pUserData     /* i: init Parameters */
1603                           )
1604{
1605    Coder_State *st;
1606    FrameStream *stream;
1607#ifdef USE_DEAULT_MEM
1608    VO_MEM_OPERATOR voMemoprator;
1609#endif
1610    VO_MEM_OPERATOR *pMemOP;
1611        UNUSED(vType);
1612
1613    int interMem = 0;
1614
1615    if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )
1616    {
1617#ifdef USE_DEAULT_MEM
1618        voMemoprator.Alloc = cmnMemAlloc;
1619        voMemoprator.Copy = cmnMemCopy;
1620        voMemoprator.Free = cmnMemFree;
1621        voMemoprator.Set = cmnMemSet;
1622        voMemoprator.Check = cmnMemCheck;
1623        interMem = 1;
1624        pMemOP = &voMemoprator;
1625#else
1626        *phCodec = NULL;
1627        return VO_ERR_INVALID_ARG;
1628#endif
1629    }
1630    else
1631    {
1632        pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;
1633    }
1634    /*-------------------------------------------------------------------------*
1635     * Memory allocation for coder state.                                      *
1636     *-------------------------------------------------------------------------*/
1637    if ((st = (Coder_State *)mem_malloc(pMemOP, sizeof(Coder_State), 32, VO_INDEX_ENC_AMRWB)) == NULL)
1638    {
1639        return VO_ERR_OUTOF_MEMORY;
1640    }
1641
1642    st->vadSt = NULL;
1643    st->dtx_encSt = NULL;
1644    st->sid_update_counter = 3;
1645    st->sid_handover_debt = 0;
1646    st->prev_ft = TX_SPEECH;
1647    st->inputStream = NULL;
1648    st->inputSize = 0;
1649
1650    /* Default setting */
1651    st->mode = VOAMRWB_MD2385;                        /* bit rate 23.85kbps */
1652    st->frameType = VOAMRWB_RFC3267;                  /* frame type: RFC3267 */
1653    st->allow_dtx = 0;                                /* disable DTX mode */
1654
1655    st->outputStream = NULL;
1656    st->outputSize = 0;
1657
1658    st->stream = (FrameStream *)mem_malloc(pMemOP, sizeof(FrameStream), 32, VO_INDEX_ENC_AMRWB);
1659    if(st->stream == NULL)
1660        return VO_ERR_OUTOF_MEMORY;
1661
1662    st->stream->frame_ptr = (unsigned char *)mem_malloc(pMemOP, Frame_Maxsize, 32, VO_INDEX_ENC_AMRWB);
1663    if(st->stream->frame_ptr == NULL)
1664        return  VO_ERR_OUTOF_MEMORY;
1665
1666    stream = st->stream;
1667    voAWB_InitFrameBuffer(stream);
1668
1669    wb_vad_init(&(st->vadSt), pMemOP);
1670    dtx_enc_init(&(st->dtx_encSt), isf_init, pMemOP);
1671
1672    Reset_encoder((void *) st, 1);
1673
1674    if(interMem)
1675    {
1676        st->voMemoprator.Alloc = cmnMemAlloc;
1677        st->voMemoprator.Copy = cmnMemCopy;
1678        st->voMemoprator.Free = cmnMemFree;
1679        st->voMemoprator.Set = cmnMemSet;
1680        st->voMemoprator.Check = cmnMemCheck;
1681        pMemOP = &st->voMemoprator;
1682    }
1683
1684    st->pvoMemop = pMemOP;
1685
1686    *phCodec = (void *) st;
1687
1688    return VO_ERR_NONE;
1689}
1690
1691/**********************************************************************************
1692*
1693* Brief: Codec API function: Input PCM data
1694*
1695***********************************************************************************/
1696
1697VO_U32 VO_API voAMRWB_SetInputData(
1698        VO_HANDLE hCodec,                   /* i/o: The codec handle which was created by Init function */
1699        VO_CODECBUFFER * pInput             /*   i: The input buffer parameter  */
1700        )
1701{
1702    Coder_State  *gData;
1703    FrameStream  *stream;
1704
1705    if(NULL == hCodec)
1706    {
1707        return VO_ERR_INVALID_ARG;
1708    }
1709
1710    gData = (Coder_State *)hCodec;
1711    stream = gData->stream;
1712
1713    if(NULL == pInput || NULL == pInput->Buffer)
1714    {
1715        return VO_ERR_INVALID_ARG;
1716    }
1717
1718    stream->set_ptr    = pInput->Buffer;
1719    stream->set_len    = pInput->Length;
1720    stream->frame_ptr  = stream->frame_ptr_bk;
1721    stream->used_len   = 0;
1722
1723    return VO_ERR_NONE;
1724}
1725
1726/**************************************************************************************
1727*
1728* Brief: Codec API function: Get the compression audio data frame by frame
1729*
1730***************************************************************************************/
1731
1732VO_U32 VO_API voAMRWB_GetOutputData(
1733        VO_HANDLE hCodec,                    /* i: The Codec Handle which was created by Init function*/
1734        VO_CODECBUFFER * pOutput,            /* o: The output audio data */
1735        VO_AUDIO_OUTPUTINFO * pAudioFormat   /* o: The encoder module filled audio format and used the input size*/
1736        )
1737{
1738    Coder_State* gData = (Coder_State*)hCodec;
1739    VO_MEM_OPERATOR  *pMemOP;
1740    FrameStream  *stream = (FrameStream *)gData->stream;
1741    pMemOP = (VO_MEM_OPERATOR  *)gData->pvoMemop;
1742
1743    if(stream->framebuffer_len  < Frame_MaxByte)         /* check the work buffer len */
1744    {
1745        stream->frame_storelen = stream->framebuffer_len;
1746        if(stream->frame_storelen)
1747        {
1748            pMemOP->Copy(VO_INDEX_ENC_AMRWB, stream->frame_ptr_bk , stream->frame_ptr , stream->frame_storelen);
1749        }
1750        if(stream->set_len > 0)
1751        {
1752            voAWB_UpdateFrameBuffer(stream, pMemOP);
1753        }
1754        if(stream->framebuffer_len < Frame_MaxByte)
1755        {
1756            if(pAudioFormat)
1757                pAudioFormat->InputUsed = stream->used_len;
1758            return VO_ERR_INPUT_BUFFER_SMALL;
1759        }
1760    }
1761
1762    gData->inputStream = stream->frame_ptr;
1763    gData->outputStream = (unsigned short*)pOutput->Buffer;
1764
1765    gData->outputSize = AMR_Enc_Encode(gData);         /* encoder main function */
1766
1767    pOutput->Length = gData->outputSize;               /* get the output buffer length */
1768    stream->frame_ptr += 640;                          /* update the work buffer ptr */
1769    stream->framebuffer_len  -= 640;
1770
1771    if(pAudioFormat)                                   /* return output audio information */
1772    {
1773        pAudioFormat->Format.Channels = 1;
1774        pAudioFormat->Format.SampleRate = 8000;
1775        pAudioFormat->Format.SampleBits = 16;
1776        pAudioFormat->InputUsed = stream->used_len;
1777    }
1778    return VO_ERR_NONE;
1779}
1780
1781/*************************************************************************
1782*
1783* Brief: Codec API function---set the data by specified parameter ID
1784*
1785*************************************************************************/
1786
1787
1788VO_U32 VO_API voAMRWB_SetParam(
1789        VO_HANDLE hCodec,   /* i/o: The Codec Handle which was created by Init function */
1790        VO_S32 uParamID,    /*   i: The param ID */
1791        VO_PTR pData        /*   i: The param value depend on the ID */
1792        )
1793{
1794    Coder_State* gData = (Coder_State*)hCodec;
1795    FrameStream *stream = (FrameStream *)(gData->stream);
1796    int *lValue = (int*)pData;
1797
1798    switch(uParamID)
1799    {
1800        /* setting AMR-WB frame type*/
1801        case VO_PID_AMRWB_FRAMETYPE:
1802            if(*lValue < VOAMRWB_DEFAULT || *lValue > VOAMRWB_RFC3267)
1803                return VO_ERR_WRONG_PARAM_ID;
1804            gData->frameType = *lValue;
1805            break;
1806        /* setting AMR-WB bit rate */
1807        case VO_PID_AMRWB_MODE:
1808            {
1809                if(*lValue < VOAMRWB_MD66 || *lValue > VOAMRWB_MD2385)
1810                    return VO_ERR_WRONG_PARAM_ID;
1811                gData->mode = *lValue;
1812            }
1813            break;
1814        /* enable or disable DTX mode */
1815        case VO_PID_AMRWB_DTX:
1816            gData->allow_dtx = (Word16)(*lValue);
1817            break;
1818
1819        case VO_PID_COMMON_HEADDATA:
1820            break;
1821        /* flush the work buffer */
1822        case VO_PID_COMMON_FLUSH:
1823            stream->set_ptr = NULL;
1824            stream->frame_storelen = 0;
1825            stream->framebuffer_len = 0;
1826            stream->set_len = 0;
1827            break;
1828
1829        default:
1830            return VO_ERR_WRONG_PARAM_ID;
1831    }
1832    return VO_ERR_NONE;
1833}
1834
1835/**************************************************************************
1836*
1837*Brief: Codec API function---Get the data by specified parameter ID
1838*
1839***************************************************************************/
1840
1841VO_U32 VO_API voAMRWB_GetParam(
1842        VO_HANDLE hCodec,      /* i: The Codec Handle which was created by Init function */
1843        VO_S32 uParamID,       /* i: The param ID */
1844        VO_PTR pData           /* o: The param value depend on the ID */
1845        )
1846{
1847    int    temp;
1848    Coder_State* gData = (Coder_State*)hCodec;
1849
1850    if (gData==NULL)
1851        return VO_ERR_INVALID_ARG;
1852    switch(uParamID)
1853    {
1854        /* output audio format */
1855        case VO_PID_AMRWB_FORMAT:
1856            {
1857                VO_AUDIO_FORMAT* fmt = (VO_AUDIO_FORMAT*)pData;
1858                fmt->Channels   = 1;
1859                fmt->SampleRate = 16000;
1860                fmt->SampleBits = 16;
1861                break;
1862            }
1863        /* output audio channel number */
1864        case VO_PID_AMRWB_CHANNELS:
1865            temp = 1;
1866            pData = (void *)(&temp);
1867            break;
1868        /* output audio sample rate */
1869        case VO_PID_AMRWB_SAMPLERATE:
1870            temp = 16000;
1871            pData = (void *)(&temp);
1872            break;
1873        /* output audio frame type */
1874        case VO_PID_AMRWB_FRAMETYPE:
1875            temp = gData->frameType;
1876            pData = (void *)(&temp);
1877            break;
1878        /* output audio bit rate */
1879        case VO_PID_AMRWB_MODE:
1880            temp = gData->mode;
1881            pData = (void *)(&temp);
1882            break;
1883        default:
1884            return VO_ERR_WRONG_PARAM_ID;
1885    }
1886
1887    return VO_ERR_NONE;
1888}
1889
1890/***********************************************************************************
1891*
1892* Brief: Codec API function---Release the codec after all encoder operations are done
1893*
1894*************************************************************************************/
1895
1896VO_U32 VO_API voAMRWB_Uninit(VO_HANDLE hCodec           /* i/o: Codec handle pointer */
1897                             )
1898{
1899    Coder_State* gData = (Coder_State*)hCodec;
1900    VO_MEM_OPERATOR *pMemOP;
1901    pMemOP = gData->pvoMemop;
1902
1903    if(hCodec)
1904    {
1905        if(gData->stream)
1906        {
1907            if(gData->stream->frame_ptr_bk)
1908            {
1909                mem_free(pMemOP, gData->stream->frame_ptr_bk, VO_INDEX_ENC_AMRWB);
1910                gData->stream->frame_ptr_bk = NULL;
1911            }
1912            mem_free(pMemOP, gData->stream, VO_INDEX_ENC_AMRWB);
1913            gData->stream = NULL;
1914        }
1915        wb_vad_exit(&(((Coder_State *) gData)->vadSt), pMemOP);
1916        dtx_enc_exit(&(((Coder_State *) gData)->dtx_encSt), pMemOP);
1917
1918        mem_free(pMemOP, hCodec, VO_INDEX_ENC_AMRWB);
1919        hCodec = NULL;
1920    }
1921
1922    return VO_ERR_NONE;
1923}
1924
1925/********************************************************************************
1926*
1927* Brief: voGetAMRWBEncAPI gets the API handle of the codec
1928*
1929********************************************************************************/
1930
1931VO_S32 VO_API voGetAMRWBEncAPI(
1932                               VO_AUDIO_CODECAPI * pEncHandle      /* i/o: Codec handle pointer */
1933                               )
1934{
1935    if(NULL == pEncHandle)
1936        return VO_ERR_INVALID_ARG;
1937    pEncHandle->Init = voAMRWB_Init;
1938    pEncHandle->SetInputData = voAMRWB_SetInputData;
1939    pEncHandle->GetOutputData = voAMRWB_GetOutputData;
1940    pEncHandle->SetParam = voAMRWB_SetParam;
1941    pEncHandle->GetParam = voAMRWB_GetParam;
1942    pEncHandle->Uninit = voAMRWB_Uninit;
1943
1944    return VO_ERR_NONE;
1945}
1946
1947#ifdef __cplusplus
1948}
1949#endif
1950