Home | History | Annotate | Download | only in src
      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 /****************************************************************************************
     19 Portions 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)
     26 Permission to distribute, modify and use this file under the standard license
     27 terms 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
     79 extern "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