1/* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18/****************************************************************************************
19Portions of this file are derived from the following 3GPP standard:
20
21    3GPP TS 26.073
22    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23    Available from http://www.3gpp.org
24
25(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26Permission to distribute, modify and use this file under the standard license
27terms listed above has been obtained from the copyright holder.
28****************************************************************************************/
29/*
30------------------------------------------------------------------------------
31
32
33
34 Pathname: ./audio/gsm-amr/c/src/c4_17pf.c
35 Functions:
36
37     Date: 05/26/2000
38
39------------------------------------------------------------------------------
40 REVISION HISTORY
41
42 Description: Modified to pass overflow flag through to basic math function.
43 The flag is passed back to the calling function by pointer reference.
44
45 Description: Optimized functions to further reduce clock cycle usage.
46              Updated copyright year, removed unnecessary include files,
47              and removed unused #defines.
48
49 Description: Changed round function name to pv_round to avoid conflict with
50              round function in C standard library.
51
52 Description:  Replaced "int" and/or "char" with OSCL defined types.
53
54 Description: Added #ifdef __cplusplus around extern'ed table.
55
56 Description:
57
58------------------------------------------------------------------------------
59 MODULE DESCRIPTION
60
61 Purpose          : Searches a 17 bit algebraic codebook containing 4 pulses
62                    in a frame of 40 samples
63------------------------------------------------------------------------------
64*/
65
66/*----------------------------------------------------------------------------
67; INCLUDES
68----------------------------------------------------------------------------*/
69#include "c4_17pf.h"
70#include "typedef.h"
71#include "inv_sqrt.h"
72#include "cnst.h"
73#include "cor_h.h"
74#include "set_sign.h"
75#include "basic_op.h"
76
77/*--------------------------------------------------------------------------*/
78#ifdef __cplusplus
79extern "C"
80{
81#endif
82
83    /*----------------------------------------------------------------------------
84    ; MACROS
85    ; Define module specific macros here
86    ----------------------------------------------------------------------------*/
87
88    /*----------------------------------------------------------------------------
89    ; DEFINES
90    ; Include all pre-processor statements here. Include conditional
91    ; compile variables also.
92    ----------------------------------------------------------------------------*/
93#define NB_PULSE  4
94
95    /*----------------------------------------------------------------------------
96    ; LOCAL FUNCTION DEFINITIONS
97    ; Function Prototype declaration
98    ----------------------------------------------------------------------------*/
99
100    static void search_4i40(
101        Word16 dn[],        /* i : correlation between target and h[]            */
102        Word16 dn2[],       /* i : maximum of corr. in each track.               */
103        Word16 rr[][L_CODE],/* i : matrix of autocorrelation                     */
104        Word16 codvec[],    /* o : algebraic codebook vector                     */
105        Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
106    );
107
108    static Word16 build_code(
109        Word16 codvec[],    /* i : algebraic codebook vector                     */
110        Word16 dn_sign[],   /* i : sign of dn[]                                  */
111        Word16 cod[],       /* o : algebraic (fixed) codebook excitation         */
112        Word16 h[],         /* i : impulse response of weighted synthesis filter */
113        Word16 y[],         /* o : filtered fixed codebook excitation            */
114        Word16 sign[],      /* o : index of 4 pulses (position+sign+ampl)*4      */
115        Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
116    );
117
118    /*----------------------------------------------------------------------------
119    ; LOCAL VARIABLE DEFINITIONS
120    ; Variable declaration - defined here and used outside this module
121    ----------------------------------------------------------------------------*/
122
123    /*----------------------------------------------------------------------------
124    ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
125    ; Declare variables used in this module but defined elsewhere
126    ----------------------------------------------------------------------------*/
127    extern const Word16 gray[];
128    extern const Word16 dgray[];
129
130    /*
131    ------------------------------------------------------------------------------
132     FUNCTION NAME:  code_4i40_17bits()
133    ------------------------------------------------------------------------------
134     INPUT AND OUTPUT DEFINITIONS
135
136     Inputs:
137        x[]   Array of type Word16 -- target vector
138        h[]   Array of type Word16 -- impulse response of weighted synthesis filter
139                                      h[-L_subfr..-1] must be set to zero.
140
141        T0           Array of type Word16 -- Pitch lag
142        pitch_sharp, Array of type Word16 --  Last quantized pitch gain
143
144     Outputs:
145        code[]  Array of type Word16 -- Innovative codebook
146        y[]     Array of type Word16 -- filtered fixed codebook excitation
147        * sign  Pointer of type Word16 -- Pointer to the signs of 4 pulses
148        pOverflow    Pointer to Flag      -- set when overflow occurs
149
150     Returns:
151        index
152
153     Global Variables Used:
154        None
155
156     Local Variables Needed:
157
158    ------------------------------------------------------------------------------
159     FUNCTION DESCRIPTION
160
161     PURPOSE:  Searches a 17 bit algebraic codebook containing 4 pulses
162               in a frame of 40 samples.
163
164     DESCRIPTION:
165       The code length is 40, containing 4 nonzero pulses: i0...i3.
166       All pulses can have two possible amplitudes: +1 or -1.
167       Pulse i0 to i2 can have 8 possible positions, pulse i3 can have
168       2x8=16 positions.
169
170          i0 :  0, 5, 10, 15, 20, 25, 30, 35.
171          i1 :  1, 6, 11, 16, 21, 26, 31, 36.
172          i2 :  2, 7, 12, 17, 22, 27, 32, 37.
173          i3 :  3, 8, 13, 18, 23, 28, 33, 38.
174                4, 9, 14, 19, 24, 29, 34, 39.
175
176    ------------------------------------------------------------------------------
177     REQUIREMENTS
178
179     None
180
181    ------------------------------------------------------------------------------
182     REFERENCES
183
184     [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
185
186    ------------------------------------------------------------------------------
187     PSEUDO-CODE
188
189    ------------------------------------------------------------------------------
190     RESOURCES USED [optional]
191
192     When the code is written for a specific target processor the
193     the resources used should be documented below.
194
195     HEAP MEMORY USED: x bytes
196
197     STACK MEMORY USED: x bytes
198
199     CLOCK CYCLES: (cycle count equation for this function) + (variable
200                    used to represent cycle count for each subroutine
201                    called)
202         where: (cycle count variable) = cycle count for [subroutine
203                                         name]
204
205    ------------------------------------------------------------------------------
206     CAUTION [optional]
207     [State any special notes, constraints or cautions for users of this function]
208
209    ------------------------------------------------------------------------------
210    */
211
212    Word16 code_4i40_17bits(
213        Word16 x[],         /* i : target vector                                 */
214        Word16 h[],         /* i : impulse response of weighted synthesis filter */
215        /*     h[-L_subfr..-1] must be set to zero.          */
216        Word16 T0,          /* i : Pitch lag                                     */
217        Word16 pitch_sharp, /* i : Last quantized pitch gain                     */
218        Word16 code[],      /* o : Innovative codebook                           */
219        Word16 y[],         /* o : filtered fixed codebook excitation            */
220        Word16 * sign,      /* o : Signs of 4 pulses                             */
221        Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
222    )
223    {
224        Word16 codvec[NB_PULSE];
225        Word16 dn[L_CODE];
226        Word16 dn2[L_CODE];
227        Word16 dn_sign[L_CODE];
228
229        Word16 rr[L_CODE][L_CODE];
230        Word16 i;
231        Word16 index;
232        Word16 sharp;
233        Word16 tempWord;
234
235        sharp = pitch_sharp << 1;
236
237        if (T0 < L_CODE)
238        {
239            for (i = T0; i < L_CODE; i++)
240            {
241                tempWord =
242                    mult(
243                        h[i - T0],
244                        sharp,
245                        pOverflow);
246
247                h[i] =
248                    add(
249                        h[i],
250                        tempWord,
251                        pOverflow);
252            }
253        }
254
255        cor_h_x(
256            h,
257            x,
258            dn,
259            1,
260            pOverflow);
261
262        set_sign(
263            dn,
264            dn_sign,
265            dn2,
266            4);
267
268        cor_h(
269            h,
270            dn_sign,
271            rr,
272            pOverflow);
273
274        search_4i40(
275            dn,
276            dn2,
277            rr,
278            codvec,
279            pOverflow);
280
281        /* function result */
282        index =
283            build_code(
284                codvec,
285                dn_sign,
286                code,
287                h,
288                y,
289                sign,
290                pOverflow);
291
292        /*-----------------------------------------------------------------*
293        * Compute innovation vector gain.                                 *
294        * Include fixed-gain pitch contribution into code[].              *
295        *-----------------------------------------------------------------*/
296
297        tempWord = T0 - L_CODE;
298
299        if (tempWord < 0)
300        {
301            for (i = T0; i < L_CODE; i++)
302            {
303                tempWord =
304                    mult(
305                        code[i - T0],
306                        sharp,
307                        pOverflow);
308
309                code[i] =
310                    add(
311                        code[i],
312                        tempWord,
313                        pOverflow);
314            }
315        }
316
317        return index;
318    }
319    /****************************************************************************/
320
321    /*
322    ------------------------------------------------------------------------------
323     FUNCTION NAME: search_4i40()
324    ------------------------------------------------------------------------------
325     INPUT AND OUTPUT DEFINITIONS
326
327     Inputs:
328        dn[]         Array of type Word16 -- correlation between target and h[]
329        dn2[]        Array of type Word16 -- maximum of corr. in each track.
330        rr[][L_CODE] Double Array of type Word16 -- autocorrelation matrix
331
332     Outputs:
333        codvec[]     Array of type Word16 -- algebraic codebook vector
334        pOverflow    Pointer to Flag      -- set when overflow occurs
335
336     Returns:
337
338
339     Global Variables Used:
340        None
341
342     Local Variables Needed:
343
344
345    ------------------------------------------------------------------------------
346     FUNCTION DESCRIPTION
347
348     PURPOSE: Search the best codevector; determine positions of the 4 pulses
349              in the 40-sample frame.
350
351    ------------------------------------------------------------------------------
352     REQUIREMENTS
353
354     None
355
356    ------------------------------------------------------------------------------
357     REFERENCES
358
359     [1] c4_17pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
360
361    ------------------------------------------------------------------------------
362     PSEUDO-CODE
363
364    ------------------------------------------------------------------------------
365     RESOURCES USED [optional]
366
367     When the code is written for a specific target processor the
368     the resources used should be documented below.
369
370     HEAP MEMORY USED: x bytes
371
372     STACK MEMORY USED: x bytes
373
374     CLOCK CYCLES: (cycle count equation for this function) + (variable
375                    used to represent cycle count for each subroutine
376                    called)
377         where: (cycle count variable) = cycle count for [subroutine
378                                         name]
379
380    ------------------------------------------------------------------------------
381     CAUTION [optional]
382     [State any special notes, constraints or cautions for users of this function]
383
384    ------------------------------------------------------------------------------
385    */
386    static void search_4i40(
387        Word16 dn[],         /* i : correlation between target and h[]  */
388        Word16 dn2[],        /* i : maximum of corr. in each track.     */
389        Word16 rr[][L_CODE], /* i : matrix of autocorrelation           */
390        Word16 codvec[],     /* o : algebraic codebook vector           */
391        Flag   * pOverflow   /* o : Flag set when overflow occurs       */
392    )
393    {
394        Word16 i0;
395        Word16 i1;
396        Word16 i2;
397        Word16 i3;
398
399        Word16 ix = 0; /* initialization only needed to keep gcc silent */
400        Word16 ps = 0; /* initialization only needed to keep gcc silent */
401
402        Word16 i;
403        Word16 pos;
404        Word16 track;
405        Word16 ipos[NB_PULSE];
406
407        Word16 psk;
408        Word16 ps0;
409        Word16 ps1;
410        Word16 sq;
411        Word16 sq1;
412
413        Word16 alpk;
414        Word16 alp;
415        Word16 alp_16;
416        Word16 *p_codvec = &codvec[0];
417
418        Word32 s;
419        Word32 alp0;
420        Word32 alp1;
421
422        OSCL_UNUSED_ARG(pOverflow);
423
424        /* Default value */
425        psk = -1;
426        alpk = 1;
427        for (i = 0; i < NB_PULSE; i++)
428        {
429            *(p_codvec++) = i;
430        }
431
432        for (track = 3; track < 5; track++)
433        {
434            /* fix starting position */
435
436            ipos[0] = 0;
437            ipos[1] = 1;
438            ipos[2] = 2;
439            ipos[3] = track;
440
441            /*------------------------------------------------------------------*
442             * main loop: try 4 tracks.                                         *
443             *------------------------------------------------------------------*/
444
445            for (i = 0; i < NB_PULSE; i++)
446            {
447                /*----------------------------------------------------------------*
448                 * i0 loop: try 4 positions (use position with max of corr.).     *
449                 *----------------------------------------------------------------*/
450
451                for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP)
452                {
453                    if (dn2[i0] >= 0)
454                    {
455                        ps0 = dn[i0];
456
457                        alp0 = (Word32) rr[i0][i0] << 14;
458
459                        /*----------------------------------------------------------------*
460                         * i1 loop: 8 positions.                                          *
461                         *----------------------------------------------------------------*/
462
463                        sq = -1;
464                        alp = 1;
465                        ps = 0;
466                        ix = ipos[1];
467
468                        /* initialize 4 index for next loop. */
469                        /*-------------------------------------------------------------------*
470                         *  These index have low complexity address computation because      *
471                         *  they are, in fact, pointers with fixed increment.  For example,  *
472                         *  "rr[i0][i3]" is a pointer initialized to "&rr[i0][ipos[3]]"      *
473                         *  and incremented by "STEP".                                       *
474                         *-------------------------------------------------------------------*/
475
476                        for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP)
477                        {
478                            /* idx increment = STEP */
479                            /* ps1 = add(ps0, dn[i1], pOverflow); */
480                            ps1 = ps0 + dn[i1];
481
482                            /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */
483
484                            /* alp1 = L_mac(alp0, rr[i1][i1], _1_4, pOverflow); */
485                            alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
486
487                            /* alp1 = L_mac(alp1, rr[i0][i1], _1_2, pOverflow); */
488                            alp1 += (Word32) rr[i0][i1] << 15;
489
490                            /* sq1 = mult(ps1, ps1, pOverflow); */
491                            sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
492
493                            /* alp_16 = pv_round(alp1, pOverflow); */
494                            alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
495
496                            /* s = L_mult(alp, sq1, pOverflow); */
497                            s = ((Word32) alp * sq1) << 1;
498
499                            /* s = L_msu(s, sq, alp_16, pOverflow); */
500                            s -= (((Word32) sq * alp_16) << 1);
501
502                            if (s > 0)
503                            {
504                                sq = sq1;
505                                ps = ps1;
506                                alp = alp_16;
507                                ix = i1;
508                            }
509                        }
510                        i1 = ix;
511
512                        /*----------------------------------------------------------------*
513                         * i2 loop: 8 positions.                                          *
514                         *----------------------------------------------------------------*/
515
516                        ps0 = ps;
517
518                        /* alp0 = L_mult(alp, _1_4, pOverflow); */
519                        alp0 = (Word32) alp << 14;
520
521                        sq = -1;
522                        alp = 1;
523                        ps = 0;
524                        ix = ipos[2];
525
526                        /* initialize 4 index for next loop (see i1 loop) */
527
528                        for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP)
529                        {
530                            /* index increment = STEP */
531                            /* ps1 = add(ps0, dn[i2], pOverflow); */
532                            ps1 = ps0 + dn[i2];
533
534                            /* alp1 = alp0 + rr[i0][i2] + rr[i1][i2] + 1/2*rr[i2][i2]; */
535
536                            /* idx incr = STEP */
537                            /* alp1 = L_mac(alp0, rr[i2][i2], _1_16, pOverflow); */
538                            alp1 = alp0 + ((Word32) rr[i2][i2] << 12);
539
540                            /* idx incr = STEP */
541                            /* alp1 = L_mac(alp1, rr[i1][i2], _1_8, pOverflow); */
542                            alp1 += (Word32) rr[i1][i2] << 13;
543
544                            /* idx incr = STEP */
545                            /* alp1 = L_mac(alp1,rr[i0][i2], _1_8, pOverflow); */
546                            alp1 += (Word32) rr[i0][i2] << 13;
547
548                            /* sq1 = mult(ps1, ps1, pOverflow); */
549                            sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
550
551                            /* alp_16 = pv_round(alp1, pOverflow); */
552                            alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
553
554                            /* s = L_mult(alp, sq1, pOverflow); */
555                            s = ((Word32) alp * sq1) << 1;
556
557                            /* s = L_msu(s, sq, alp_16, pOverflow); */
558                            s -= (((Word32) sq * alp_16) << 1);
559
560                            if (s > 0)
561                            {
562                                sq = sq1;
563                                ps = ps1;
564                                alp = alp_16;
565                                ix = i2;
566                            }
567                        }
568                        i2 = ix;
569
570                        /*----------------------------------------------------------------*
571                         * i3 loop: 8 positions.                                          *
572                         *----------------------------------------------------------------*/
573
574                        ps0 = ps;
575                        alp0 = L_deposit_h(alp);
576
577                        sq = -1;
578                        alp = 1;
579                        ps = 0;
580                        ix = ipos[3];
581
582                        /* initialize 5 index for next loop (see i1 loop) */
583
584                        for (i3 = ipos[3]; i3 < L_CODE; i3 += STEP)
585                        {
586                            /* ps1 = add(ps0, dn[i3], pOverflow); */
587                            ps1 = ps0 + dn[i3]; /* index increment = STEP */
588
589                            /* alp1 = alp0 + rr[i0][i3] + rr[i1][i3] + rr[i2][i3] + 1/2*rr[i3][i3]; */
590
591                            /* alp1 = L_mac(alp0, rr[i3][i3], _1_16, pOverflow); */
592                            alp1 = alp0 + ((Word32) rr[i3][i3] << 12); /* idx incr = STEP */
593
594                            /* alp1 = L_mac(alp1, rr[i2][i3], _1_8, pOverflow); */
595                            alp1 += (Word32) rr[i2][i3] << 13;  /* idx incr = STEP */
596
597                            /* alp1 = L_mac(alp1, rr[i1][i3], _1_8, pOverflow); */
598                            alp1 += (Word32) rr[i1][i3] << 13;  /* idx incr = STEP */
599
600                            /* alp1 = L_mac(alp1, rr[i0][i3], _1_8, pOverflow); */
601                            alp1 += (Word32) rr[i0][i3] << 13;  /* idx incr = STEP */
602
603                            /* sq1 = mult(ps1, ps1, pOverflow); */
604                            sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
605
606                            /* alp_16 = pv_round(alp1, pOverflow); */
607                            alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
608
609                            /* s = L_mult(alp, sq1, pOverflow); */
610                            s = ((Word32) alp * sq1) << 1;
611
612                            /* s = L_msu(s, sq, alp_16, pOverflow); */
613                            s -= (((Word32) sq * alp_16) << 1);
614
615                            if (s > 0)
616                            {
617                                sq = sq1;
618                                ps = ps1;
619                                alp = alp_16;
620                                ix = i3;
621                            }
622                        }
623
624
625                        /*----------------------------------------------------------------*
626                         * memorise codevector if this one is better than the last one.   *
627                         *----------------------------------------------------------------*/
628
629                        /* s = L_mult(alpk, sq, pOverflow); */
630                        s = ((Word32) alpk * sq) << 1;
631
632                        /* s = L_msu(s, psk, alp, pOverflow); */
633                        s -= (((Word32) psk * alp) << 1);
634
635                        if (s > 0)
636                        {
637                            psk = sq;
638                            alpk = alp;
639                            p_codvec = &codvec[0];
640
641                            *(p_codvec++) = i0;
642                            *(p_codvec++) = i1;
643                            *(p_codvec++) = i2;
644                            *(p_codvec) = ix;
645                        }
646                    }
647                }
648
649                /*----------------------------------------------------------------*
650                 * Cyclic permutation of i0,i1,i2 and i3.                         *
651                 *----------------------------------------------------------------*/
652
653                pos = ipos[3];
654                ipos[3] = ipos[2];
655                ipos[2] = ipos[1];
656                ipos[1] = ipos[0];
657                ipos[0] = pos;
658            }
659        }
660
661        return;
662    }
663
664
665
666
667    /****************************************************************************/
668
669    /*
670    ------------------------------------------------------------------------------
671     FUNCTION NAME:  build_code()
672    ------------------------------------------------------------------------------
673     INPUT AND OUTPUT DEFINITIONS
674
675     Inputs:
676        codvec[]   Array of type Word16 -- position of pulses
677        dn_sign[]  Array of type Word16 -- sign of pulses
678        h[]        Array of type Word16 -- impulse response of
679                                           weighted synthesis filter
680
681     Outputs:
682        cod[]  Array of type Word16 -- innovative code vector
683        y[]    Array of type Word16 -- filtered innovative code
684        sign[] Array of type Word16 -- index of 4 pulses (sign + position)
685        pOverflow  Pointer to Flag  -- set when overflow occurs
686
687     Returns:
688        indx
689
690     Global Variables Used:
691        None
692
693     Local Variables Needed:
694
695    ------------------------------------------------------------------------------
696     FUNCTION DESCRIPTION
697
698     PURPOSE: Builds the codeword, the filtered codeword and index of the
699              codevector, based on the signs and positions of 4 pulses.
700
701    ------------------------------------------------------------------------------
702     REQUIREMENTS
703
704     None
705
706    ------------------------------------------------------------------------------
707     REFERENCES
708
709     [1] c4_17pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
710
711    ------------------------------------------------------------------------------
712     PSEUDO-CODE
713
714    ------------------------------------------------------------------------------
715     RESOURCES USED [optional]
716
717     When the code is written for a specific target processor the
718     the resources used should be documented below.
719
720     HEAP MEMORY USED: x bytes
721
722     STACK MEMORY USED: x bytes
723
724     CLOCK CYCLES: (cycle count equation for this function) + (variable
725                    used to represent cycle count for each subroutine
726                    called)
727         where: (cycle count variable) = cycle count for [subroutine
728                                         name]
729
730    ------------------------------------------------------------------------------
731     CAUTION [optional]
732     [State any special notes, constraints or cautions for users of this function]
733
734    ------------------------------------------------------------------------------
735    */
736
737    static Word16
738    build_code(
739        Word16 codvec[],  /* i : position of pulses                            */
740        Word16 dn_sign[], /* i : sign of pulses                                */
741        Word16 cod[],     /* o : innovative code vector                        */
742        Word16 h[],       /* i : impulse response of weighted synthesis filter */
743        Word16 y[],       /* o : filtered innovative code                      */
744        Word16 sign[],    /* o : index of 4 pulses (sign+position)             */
745        Flag   * pOverflow  /* o : Flag set when overflow occurs               */
746    )
747    {
748        Word16 i;
749        Word16 j;
750        Word16 k;
751        Word16 track;
752        Word16 index;
753        Word16 _sign[NB_PULSE];
754        Word16 indx;
755        Word16 rsign;
756
757        Word16 *p0;
758        Word16 *p1;
759        Word16 *p2;
760        Word16 *p3;
761        Word16 *p_cod = &cod[0];
762
763        Word32 s;
764
765        for (i = 0; i < L_CODE; i++)
766        {
767            *(p_cod++) = 0;
768        }
769
770        indx = 0;
771        rsign = 0;
772
773        for (k = 0; k < NB_PULSE; k++)
774        {
775            i = codvec[k]; /* read pulse position */
776            j = dn_sign[i]; /* read sign          */
777
778            /* index = pos/5 */
779            /* index = mult(i, 6554, pOverflow); */
780            index = (Word16)(((Word32) i * 6554) >> 15);
781
782            /* track = pos%5 */
783            /* s = L_mult(index, 5, pOverflow); */
784            s = ((Word32) index * 5) << 1;
785
786            /* s = L_shr(s, 1, pOverflow); */
787            s >>= 1;
788
789            /* track = sub(i, (Word16) s, pOverflow); */
790            track = i - (Word16) s;
791
792            index = gray[index];
793
794            if (track == 1)
795            {
796                /* index = shl(index, 3, pOverflow); */
797                index <<= 3;
798            }
799            else if (track == 2)
800            {
801                /* index = shl(index, 6, pOverflow); */
802                index <<= 6;
803            }
804            else if (track == 3)
805            {
806                /* index = shl(index, 10, pOverflow); */
807                index <<= 10;
808            }
809            else if (track == 4)
810            {
811                track = 3;
812
813                /* index = shl(index, 10, pOverflow); */
814                index <<= 10;
815
816                /* index = add(index, 512, pOverflow); */
817                index += 512;
818            }
819
820            if (j > 0)
821            {
822                cod[i] = 8191;
823                _sign[k] = 32767;
824
825                /* track = shl(1, track, pOverflow); */
826                track = 1 << track;
827
828                /* rsign = add(rsign, track, pOverflow); */
829                rsign += track;
830            }
831            else
832            {
833                cod[i] = -8192;
834                _sign[k] = (Word16) - 32768L;
835            }
836
837            /* indx = add(indx, index, pOverflow); */
838            indx += index;
839        }
840        *sign = rsign;
841
842        p0 = h - codvec[0];
843        p1 = h - codvec[1];
844        p2 = h - codvec[2];
845        p3 = h - codvec[3];
846
847        for (i = 0; i < L_CODE; i++)
848        {
849            s = 0;
850            s =
851                L_mac(
852                    s,
853                    *p0++,
854                    _sign[0],
855                    pOverflow);
856
857            s =
858                L_mac(
859                    s,
860                    *p1++,
861                    _sign[1],
862                    pOverflow);
863
864            s =
865                L_mac(
866                    s,
867                    *p2++,
868                    _sign[2],
869                    pOverflow);
870
871            s =
872                L_mac(
873                    s,
874                    *p3++,
875                    _sign[3],
876                    pOverflow);
877
878            y[i] =
879                pv_round(
880                    s,
881                    pOverflow);
882
883        } /* for (i = 0; i < L_CODE; i++) */
884
885        return indx;
886
887    } /* build_code */
888
889#ifdef __cplusplus
890}
891#endif
892