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/c2_9pf.c
     35  Funtions: code_2i40_9bits
     36            search_2i40
     37            Test_search_2i40
     38            build_code
     39            Test_build_code
     40 
     41      Date: 05/26/2000
     42 
     43 ------------------------------------------------------------------------------
     44  REVISION HISTORY
     45 
     46  Description: Changed template used to PV coding template. First attempt at
     47           optimizing C code.
     48 
     49  Description: Updated file per comments gathered from Phase 2/3 review.
     50 
     51  Description: Added setting of Overflow flag in inlined code.
     52 
     53  Description: Synchronized file with UMTS version 3.2.0. Updated coding
     54               template.
     55 
     56  Description: Replaced basic_op.h with the header files of the math functions
     57               used by the file.
     58 
     59  Description: Made the following changes per comments from Phase 2/3 review:
     60               1. Defined one local variable per line.
     61 
     62  Description: Passed in pOverflow flag for EPOC compatibility.
     63 
     64  Description: Optimized search_2i40() to reduce clock cycle usage.
     65 
     66  Description: Removed unnecessary include files and #defines.
     67 
     68  Description: Changed function name to pv_round to avoid conflict with
     69               round function in C standard library.
     70 
     71  Description:  Replaced "int" and/or "char" with OSCL defined types.
     72 
     73  Description: Added #ifdef __cplusplus around extern'ed table.
     74 
     75  Description:
     76 
     77 ------------------------------------------------------------------------------
     78  MODULE DESCRIPTION
     79 
     80  This file contains the functions that search a 9 bit algebraic codebook
     81  containing 2 pulses in a frame of 40 samples.
     82 
     83 ------------------------------------------------------------------------------
     84 */
     85 
     86 /*----------------------------------------------------------------------------
     87 ; INCLUDES
     88 ----------------------------------------------------------------------------*/
     89 #include "c2_9pf.h"
     90 #include "typedef.h"
     91 #include "basic_op.h"
     92 #include "inv_sqrt.h"
     93 #include "cnst.h"
     94 #include "cor_h.h"
     95 #include "cor_h_x.h"
     96 #include "set_sign.h"
     97 
     98 /*--------------------------------------------------------------------------*/
     99 #ifdef __cplusplus
    100 extern "C"
    101 {
    102 #endif
    103 
    104     /*----------------------------------------------------------------------------
    105     ; MACROS
    106     ; Define module specific macros here
    107     ----------------------------------------------------------------------------*/
    108 
    109     /*----------------------------------------------------------------------------
    110     ; DEFINES
    111     ; Include all pre-processor statements here. Include conditional
    112     ; compile variables also.
    113     ----------------------------------------------------------------------------*/
    114 #define NB_PULSE  2
    115 
    116     /*----------------------------------------------------------------------------
    117     ; LOCAL FUNCTION DEFINITIONS
    118     ; Function Prototype declaration
    119     ----------------------------------------------------------------------------*/
    120     static void search_2i40(
    121         Word16 subNr,       /* i : subframe number                               */
    122         Word16 dn[],        /* i : correlation between target and h[]            */
    123         Word16 rr[][L_CODE],/* i : matrix of autocorrelation                     */
    124         Word16 codvec[],    /* o : algebraic codebook vector                     */
    125         Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
    126     );
    127 
    128     static Word16 build_code(
    129         Word16 subNr,       /* i : subframe number                               */
    130         Word16 codvec[],    /* i : algebraic codebook vector                     */
    131         Word16 dn_sign[],   /* i : sign of dn[]                                  */
    132         Word16 cod[],       /* o : algebraic (fixed) codebook excitation         */
    133         Word16 h[],         /* i : impulse response of weighted synthesis filter */
    134         Word16 y[],         /* o : filtered fixed codebook excitation            */
    135         Word16 sign[],      /* o : sign of 2 pulses                              */
    136         Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
    137     );
    138 
    139     /*----------------------------------------------------------------------------
    140     ; LOCAL VARIABLE DEFINITIONS
    141     ; Variable declaration - defined here and used outside this module
    142     ----------------------------------------------------------------------------*/
    143 
    144     const Word16 trackTable[4*5] =
    145     {
    146         0, 1, 0, 1, -1, /* subframe 1; track to code;
    147                          * -1 do not code this position
    148                          */
    149         0, -1, 1, 0, 1, /* subframe 2 */
    150         0, 1, 0, -1, 1, /* subframe 3 */
    151         0, 1, -1, 0, 1
    152     };/* subframe 4 */
    153 
    154 
    155     /*----------------------------------------------------------------------------
    156     ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
    157     ; Declare variables used in this module but defined elsewhere
    158     ----------------------------------------------------------------------------*/
    159     extern const Word16 startPos[];
    160 
    161     /*
    162     ------------------------------------------------------------------------------
    163      FUNCTION NAME: code_2i40_9bits
    164     ------------------------------------------------------------------------------
    165      INPUT AND OUTPUT DEFINITIONS
    166 
    167      Inputs:
    168         subNr = subframe number (Word16)
    169         x  = target buffer (Word16)
    170         h  = buffer containing the impulse response of the
    171              weighted synthesis filter; h[-L_subfr .. -1] must be
    172              set to zero (Word16)
    173         T0 = pitch lag (Word16)
    174         pitch_sharp = last quantized pitch gain (Word16)
    175         code = buffer containing the innovative codebook (Word16)
    176         y = buffer containing the filtered fixed codebook excitation (Word16)
    177         sign = pointer to the signs of 2 pulses (Word16)
    178 
    179      Outputs:
    180         code buffer contains the new innovation vector gains
    181 
    182      Returns:
    183         index = code index (Word16)
    184 
    185      Global Variables Used:
    186         Overflow = overflow flag (Flag)
    187 
    188      Local Variables Needed:
    189         None
    190 
    191     ------------------------------------------------------------------------------
    192      FUNCTION DESCRIPTION
    193 
    194      This function searches a 9 bit algebraic codebook containing 2 pulses in a
    195      frame of 40 samples.
    196 
    197      The code length is 40, containing 2 nonzero pulses: i0...i1. All pulses can
    198      have two possible amplitudes: +1 or -1. Pulse i0 can have 8 possible positions,
    199      pulse i1 can have 8 positions. Also coded is which track pair should be used,
    200      i.e. first or second pair. Where each pair contains 2 tracks.
    201 
    202         First subframe:
    203         first   i0 :  0, 5, 10, 15, 20, 25, 30, 35.
    204             i1 :  2, 7, 12, 17, 22, 27, 32, 37.
    205         second  i0 :  1, 6, 11, 16, 21, 26, 31, 36.
    206                     i1 :  3, 8, 13, 18, 23, 28, 33, 38.
    207 
    208         Second subframe:
    209         first   i0 :  0, 5, 10, 15, 20, 25, 30, 35.
    210                     i1 :  3, 8, 13, 18, 23, 28, 33, 38.
    211         second  i0 :  2, 7, 12, 17, 22, 27, 32, 37.
    212                     i1 :  4, 9, 14, 19, 24, 29, 34, 39.
    213 
    214         Third subframe:
    215         first   i0 :  0, 5, 10, 15, 20, 25, 30, 35.
    216                     i1 :  2, 7, 12, 17, 22, 27, 32, 37.
    217         second  i0 :  1, 6, 11, 16, 21, 26, 31, 36.
    218                     i1 :  4, 9, 14, 19, 24, 29, 34, 39.
    219 
    220         Fourth subframe:
    221         first   i0 :  0, 5, 10, 15, 20, 25, 30, 35.
    222                     i1 :  3, 8, 13, 18, 23, 28, 33, 38.
    223         second  i0 :  1, 6, 11, 16, 21, 26, 31, 36.
    224                     i1 :  4, 9, 14, 19, 24, 29, 34, 39.
    225 
    226     ------------------------------------------------------------------------------
    227      REQUIREMENTS
    228 
    229      None
    230 
    231     ------------------------------------------------------------------------------
    232      REFERENCES
    233 
    234      [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    235 
    236     ------------------------------------------------------------------------------
    237      PSEUDO-CODE
    238 
    239     Word16 code_2i40_9bits(
    240         Word16 subNr,       // i : subframe number
    241         Word16 x[],         // i : target vector
    242         Word16 h[],         // i : impulse response of weighted synthesis filter
    243                             //     h[-L_subfr..-1] must be set to zero.
    244         Word16 T0,          // i : Pitch lag
    245         Word16 pitch_sharp, // i : Last quantized pitch gain
    246         Word16 code[],      // o : Innovative codebook
    247         Word16 y[],         // o : filtered fixed codebook excitation
    248         Word16 * sign       // o : Signs of 2 pulses
    249     )
    250     {
    251         Word16 codvec[NB_PULSE];
    252         Word16 dn[L_CODE], dn2[L_CODE], dn_sign[L_CODE];
    253         Word16 rr[L_CODE][L_CODE];
    254         Word16 i, index, sharp;
    255 
    256         sharp = shl(pitch_sharp, 1);
    257         if (sub(T0, L_CODE) < 0)
    258            for (i = T0; i < L_CODE; i++) {
    259               h[i] = add(h[i], mult(h[i - T0], sharp));
    260            }
    261         cor_h_x(h, x, dn, 1);
    262         set_sign(dn, dn_sign, dn2, 8); // dn2[] not used in this codebook search
    263         cor_h(h, dn_sign, rr);
    264         search_2i40(subNr, dn, rr, codvec);
    265         index = build_code(subNr, codvec, dn_sign, code, h, y, sign);
    266 
    267        *-----------------------------------------------------------------*
    268        * Compute innovation vector gain.                                 *
    269        * Include fixed-gain pitch contribution into code[].              *
    270        *-----------------------------------------------------------------*
    271 
    272         if (sub(T0, L_CODE) < 0)
    273            for (i = T0; i < L_CODE; i++) {
    274               code[i] = add(code[i], mult(code[i - T0], sharp));
    275            }
    276         return index;
    277     }
    278 
    279     ------------------------------------------------------------------------------
    280      RESOURCES USED [optional]
    281 
    282      When the code is written for a specific target processor the
    283      the resources used should be documented below.
    284 
    285      HEAP MEMORY USED: x bytes
    286 
    287      STACK MEMORY USED: x bytes
    288 
    289      CLOCK CYCLES: (cycle count equation for this function) + (variable
    290                     used to represent cycle count for each subroutine
    291                     called)
    292          where: (cycle count variable) = cycle count for [subroutine
    293                                          name]
    294 
    295     ------------------------------------------------------------------------------
    296      CAUTION [optional]
    297      [State any special notes, constraints or cautions for users of this function]
    298 
    299     ------------------------------------------------------------------------------
    300     */
    301 
    302     Word16 code_2i40_9bits(
    303         Word16 subNr,       /* i : subframe number                          */
    304         Word16 x[],         /* i : target vector                            */
    305         Word16 h[],         /* i : impulse response of weighted synthesis   */
    306         /*     filter h[-L_subfr..-1] must be set to 0. */
    307         Word16 T0,          /* i : Pitch lag                                */
    308         Word16 pitch_sharp, /* i : Last quantized pitch gain                */
    309         Word16 code[],      /* o : Innovative codebook                      */
    310         Word16 y[],         /* o : filtered fixed codebook excitation       */
    311         Word16 * sign,      /* o : Signs of 2 pulses                        */
    312         Flag   * pOverflow  /* o : Flag set when overflow occurs            */
    313     )
    314     {
    315         Word16 codvec[NB_PULSE];
    316         Word16 dn[L_CODE];
    317         Word16 dn2[L_CODE];
    318         Word16 dn_sign[L_CODE];
    319         Word16 rr[L_CODE][L_CODE];
    320 
    321         register Word16 i;
    322 
    323         Word16 index;
    324         Word16 sharp;
    325         Word16 temp;
    326         Word32 L_temp;
    327 
    328         L_temp = ((Word32) pitch_sharp) << 1;
    329 
    330         /* Check for overflow condition */
    331         if (L_temp != (Word32)((Word16) L_temp))
    332         {
    333             *(pOverflow) = 1;
    334             sharp = (pitch_sharp > 0) ? MAX_16 : MIN_16;
    335         }
    336         else
    337         {
    338             sharp = (Word16) L_temp;
    339         }
    340 
    341         if (T0 < L_CODE)
    342         {
    343             for (i = T0; i < L_CODE; i++)
    344             {
    345                 temp =
    346                     mult(
    347                         *(h + i - T0),
    348                         sharp,
    349                         pOverflow);
    350 
    351                 *(h + i) =
    352                     add(
    353                         *(h + i),
    354                         temp,
    355                         pOverflow);
    356             }
    357         }
    358 
    359         cor_h_x(
    360             h,
    361             x,
    362             dn,
    363             1,
    364             pOverflow);
    365 
    366         /* dn2[] not used in this codebook search */
    367 
    368         set_sign(
    369             dn,
    370             dn_sign,
    371             dn2,
    372             8);
    373 
    374         cor_h(
    375             h,
    376             dn_sign,
    377             rr,
    378             pOverflow);
    379 
    380         search_2i40(
    381             subNr,
    382             dn,
    383             rr,
    384             codvec,
    385             pOverflow);
    386 
    387         index =
    388             build_code(
    389                 subNr,
    390                 codvec,
    391                 dn_sign,
    392                 code,
    393                 h,
    394                 y,
    395                 sign,
    396                 pOverflow);
    397 
    398         /*-----------------------------------------------------------------*
    399          * Compute innovation vector gain.                                 *
    400          * Include fixed-gain pitch contribution into code[].              *
    401          *-----------------------------------------------------------------*/
    402 
    403         if (T0 < L_CODE)
    404         {
    405             for (i = T0; i < L_CODE; i++)
    406             {
    407                 temp =
    408                     mult(
    409                         *(code + i - T0),
    410                         sharp,
    411                         pOverflow);
    412 
    413                 *(code + i) =
    414                     add(
    415                         *(code + i),
    416                         temp,
    417                         pOverflow);
    418             }
    419         }
    420 
    421         return(index);
    422     }
    423 
    424     /****************************************************************************/
    425 
    426 
    427     /*
    428     ------------------------------------------------------------------------------
    429      FUNCTION NAME: search_2i40
    430     ------------------------------------------------------------------------------
    431      INPUT AND OUTPUT DEFINITIONS
    432 
    433      Inputs:
    434         subNr = subframe number (Word16)
    435         dn = vector containing the correlation between target and the impulse
    436              response of the weighted synthesis filter (Word16)
    437         rr = autocorrelation matrix (Word16)
    438         codvec = algebraic codebook vector (Word16)
    439 
    440      Outputs:
    441         codvec contains the newly calculated codevectors
    442 
    443      Returns:
    444         None
    445 
    446      Global Variables Used:
    447         None
    448 
    449      Local Variables Needed:
    450         startPos = table containing the start positions used by fixed codebook
    451                    routines (const Word16)
    452 
    453     ------------------------------------------------------------------------------
    454      FUNCTION DESCRIPTION
    455 
    456      This function searches the best codevector and determines the positions of
    457      the 2 pulses in the 40-sample frame.
    458 
    459     ------------------------------------------------------------------------------
    460      REQUIREMENTS
    461 
    462      None
    463 
    464     ------------------------------------------------------------------------------
    465      REFERENCES
    466 
    467      [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    468 
    469     ------------------------------------------------------------------------------
    470      PSEUDO-CODE
    471 
    472     static void search_2i40(
    473         Word16 subNr,        // i : subframe number
    474         Word16 dn[],         // i : correlation between target and h[]
    475         Word16 rr[][L_CODE], // i : matrix of autocorrelation
    476         Word16 codvec[]      // o : algebraic codebook vector
    477     )
    478     {
    479         Word16 i0, i1;
    480         Word16 ix = 0; // initialization only needed to keep gcc silent
    481         Word16  track1, ipos[NB_PULSE];
    482         Word16 psk, ps0, ps1, sq, sq1;
    483         Word16 alpk, alp, alp_16;
    484         Word32 s, alp0, alp1;
    485         Word16 i;
    486 
    487         psk = -1;
    488         alpk = 1;
    489         for (i = 0; i < NB_PULSE; i++)
    490         {
    491            codvec[i] = i;
    492         }
    493 
    494         for (track1 = 0; track1 < 2; track1++) {
    495            // fix starting position
    496 
    497            ipos[0] = startPos[subNr*2+8*track1];
    498            ipos[1] = startPos[subNr*2+1+8*track1];
    499 
    500 
    501                *----------------------------------------------------------------*
    502                * i0 loop: try 8 positions.                                      *
    503                *----------------------------------------------------------------*
    504 
    505               for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP) {
    506 
    507                  ps0 = dn[i0];
    508                  alp0 = L_mult(rr[i0][i0], _1_4);
    509 
    510                *----------------------------------------------------------------*
    511                * i1 loop: 8 positions.                                          *
    512                *----------------------------------------------------------------*
    513 
    514                  sq = -1;
    515                  alp = 1;
    516                  ix = ipos[1];
    517 
    518             *-------------------------------------------------------------------*
    519             *  These index have low complexity address computation because      *
    520             *  they are, in fact, pointers with fixed increment.  For example,  *
    521             *  "rr[i0][i2]" is a pointer initialized to "&rr[i0][ipos[2]]"      *
    522             *  and incremented by "STEP".                                       *
    523             *-------------------------------------------------------------------*
    524 
    525                  for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP) {
    526                     ps1 = add(ps0, dn[i1]);   // idx increment = STEP
    527 
    528                     // alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1];
    529 
    530                     alp1 = L_mac(alp0, rr[i1][i1], _1_4); // idx incr = STEP
    531                     alp1 = L_mac(alp1, rr[i0][i1], _1_2); // idx incr = STEP
    532 
    533                     sq1 = mult(ps1, ps1);
    534 
    535                     alp_16 = pv_round(alp1);
    536 
    537                     s = L_msu(L_mult(alp, sq1), sq, alp_16);
    538 
    539                     if (s > 0) {
    540                        sq = sq1;
    541                        alp = alp_16;
    542                        ix = i1;
    543                     }
    544                  }
    545 
    546                *----------------------------------------------------------------*
    547                * memorise codevector if this one is better than the last one.   *
    548                *----------------------------------------------------------------*
    549 
    550                  s = L_msu(L_mult(alpk, sq), psk, alp);
    551 
    552                  if (s > 0) {
    553                     psk = sq;
    554                     alpk = alp;
    555                     codvec[0] = i0;
    556                     codvec[1] = ix;
    557                  }
    558               }
    559         }
    560 
    561         return;
    562     }
    563 
    564     ------------------------------------------------------------------------------
    565      RESOURCES USED [optional]
    566 
    567      When the code is written for a specific target processor the
    568      the resources used should be documented below.
    569 
    570      HEAP MEMORY USED: x bytes
    571 
    572      STACK MEMORY USED: x bytes
    573 
    574      CLOCK CYCLES: (cycle count equation for this function) + (variable
    575                     used to represent cycle count for each subroutine
    576                     called)
    577          where: (cycle count variable) = cycle count for [subroutine
    578                                          name]
    579 
    580     ------------------------------------------------------------------------------
    581      CAUTION [optional]
    582      [State any special notes, constraints or cautions for users of this function]
    583 
    584     ------------------------------------------------------------------------------
    585     */
    586 
    587     static void search_2i40(
    588         Word16 subNr,        /* i : subframe number                    */
    589         Word16 dn[],         /* i : correlation between target and h[] */
    590         Word16 rr[][L_CODE], /* i : matrix of autocorrelation          */
    591         Word16 codvec[],     /* o : algebraic codebook vector          */
    592         Flag   * pOverflow   /* o : Flag set when overflow occurs      */
    593     )
    594     {
    595         register Word16 i0;
    596         register Word16 i1;
    597         Word16 ix = 0; /* initialization only needed to keep gcc silent */
    598         register Word16  track1;
    599         Word16 ipos[NB_PULSE];
    600         Word16 psk;
    601         Word16 ps0;
    602         Word16 ps1;
    603         Word16 sq;
    604         Word16 sq1;
    605         Word16 alpk;
    606         Word16 alp;
    607         Word16 alp_16;
    608         Word32 s;
    609         Word32 alp0;
    610         Word32 alp1;
    611         register Word16 i;
    612         Word32 L_temp;
    613         Word16 *p_codvec = &codvec[0];
    614 
    615         OSCL_UNUSED_ARG(pOverflow);
    616 
    617         psk = -1;
    618         alpk = 1;
    619 
    620         /* Unrolled the following FOR loop to save MIPS */
    621         /* for (i = 0; i < NB_PULSE; i++)           */
    622         /* {                            */
    623         /*  *(codvec + i) = i;          */
    624         /* }                        */
    625 
    626         *(p_codvec++) = 0;
    627         *(p_codvec) = 1;
    628 
    629         for (track1 = 0; track1 < 2; track1++)
    630         {
    631             /* fix starting position */
    632 
    633             i = (subNr << 1) + (track1 << 3);
    634             *ipos = *(startPos + i);
    635             *(ipos + 1) = *(startPos + i + 1);
    636 
    637 
    638             /*----------------------------------------------------------*
    639              * i0 loop: try 8 positions.                                *
    640              *----------------------------------------------------------*/
    641 
    642             for (i0 = *ipos; i0 < L_CODE; i0 += STEP)
    643             {
    644                 ps0 = *(dn + i0);
    645 
    646                 /* Left shift by 1 converts integer product to */
    647                 /* fractional product.                 */
    648                 alp0 = (Word32) rr[i0][i0] << 14;
    649 
    650                 /*--------------------------------------------------*
    651                  * i1 loop: 8 positions.                            *
    652                  *--------------------------------------------------*/
    653 
    654                 sq = -1;
    655                 alp = 1;
    656                 ix = *(ipos + 1);
    657 
    658                 /*--------------------------------------------------*
    659                  * These index have low complexity address          *
    660                  * computation because they are, in fact, pointers  *
    661                  * with fixed increment. For example, "rr[i0][i2]"  *
    662                  * is a pointer initialized to "&rr[i0][ipos[2]]"   *
    663                 *  and incremented by "STEP".                       *
    664                 *---------------------------------------------------*/
    665 
    666                 for (i1 = *(ipos + 1); i1 < L_CODE; i1 += STEP)
    667                 {
    668                     /* idx increment = STEP */
    669                     /* ps1 = add(ps0, *(dn + i1), pOverflow); */
    670                     ps1 = ps0 + dn[i1];
    671 
    672                     /* alp1 = alp0+rr[i0][i1]+1/2*rr[i1][i1]; */
    673 
    674                     /* idx incr = STEP */
    675                     /* Extra left shift by 1 converts integer  */
    676                     /* product to fractional product     */
    677                     /* alp1 = L_add(alp0, s, pOverflow); */
    678                     alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
    679 
    680                     /* idx incr = STEP */
    681                     /* Extra left shift by 1 converts integer  */
    682                     /* product to fractional product     */
    683                     /* alp1 = L_add(alp1, s, pOverflow); */
    684                     alp1 += (Word32) rr[i0][i1] << 15;
    685 
    686                     /* sq1 = mult(ps1, ps1, pOverflow); */
    687                     sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
    688 
    689                     /* alp_16 = pv_round(alp1, pOverflow); */
    690                     alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
    691 
    692                     /* L_temp = L_mult(alp, sq1, pOverflow); */
    693                     L_temp = ((Word32) alp * sq1) << 1;
    694 
    695                     /* s = L_msu(L_temp, sq, alp_16, pOverflow); */
    696                     s = L_temp - (((Word32) sq * alp_16) << 1);
    697 
    698                     if (s > 0)
    699                     {
    700                         sq = sq1;
    701                         alp = alp_16;
    702                         ix = i1;
    703                     }
    704                 }
    705 
    706                 /* memorize codevector if this one is better than the last one. */
    707 
    708                 /* L_temp = L_mult(alpk, sq, pOverflow); */
    709                 L_temp = ((Word32) alpk * sq) << 1;
    710 
    711                 /* s = L_msu(L_temp, psk, alp, pOverflow); */
    712                 s = L_temp - (((Word32) psk * alp) << 1);
    713 
    714                 if (s > 0)
    715                 {
    716                     psk = sq;
    717                     alpk = alp;
    718                     p_codvec = &codvec[0];
    719                     *(p_codvec++) = i0;
    720                     *(p_codvec) = ix;
    721                 }
    722             }
    723         }
    724 
    725         return;
    726     }
    727 
    728     /****************************************************************************/
    729 
    730     /*
    731     ------------------------------------------------------------------------------
    732      FUNCTION NAME: Test_search_2i40
    733     ------------------------------------------------------------------------------
    734      INPUT AND OUTPUT DEFINITIONS
    735 
    736      Inputs:
    737         subNr = subframe number (Word16)
    738         dn = vector containing the correlation between target and the impulse
    739              response of the weighted synthesis filter (Word16)
    740         rr = autocorrelation matrix (Word16)
    741         codvec = algebraic codebook vector (Word16)
    742 
    743      Outputs:
    744         codvec contains the newly calculated codevectors
    745 
    746      Returns:
    747         None
    748 
    749      Global Variables Used:
    750         None
    751 
    752      Local Variables Needed:
    753         startPos = table containing the start positions used by fixed codebook
    754                    routines (const Word16)
    755 
    756     ------------------------------------------------------------------------------
    757      FUNCTION DESCRIPTION
    758 
    759      This function provides external access to the local function search_2i40.
    760 
    761     ------------------------------------------------------------------------------
    762      REQUIREMENTS
    763 
    764      None
    765 
    766     ------------------------------------------------------------------------------
    767      REFERENCES
    768 
    769      [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    770 
    771     ------------------------------------------------------------------------------
    772      PSEUDO-CODE
    773 
    774      CALL search_2i40 ( subNr = subNr
    775                 dn = dn
    776                 rr = rr
    777                 codvec = codvec )
    778        MODIFYING(nothing)
    779        RETURNING(nothing)
    780 
    781     ------------------------------------------------------------------------------
    782      RESOURCES USED [optional]
    783 
    784      When the code is written for a specific target processor the
    785      the resources used should be documented below.
    786 
    787      HEAP MEMORY USED: x bytes
    788 
    789      STACK MEMORY USED: x bytes
    790 
    791      CLOCK CYCLES: (cycle count equation for this function) + (variable
    792                     used to represent cycle count for each subroutine
    793                     called)
    794          where: (cycle count variable) = cycle count for [subroutine
    795                                          name]
    796 
    797     ------------------------------------------------------------------------------
    798      CAUTION [optional]
    799      [State any special notes, constraints or cautions for users of this function]
    800 
    801     ------------------------------------------------------------------------------
    802     */
    803 
    804     void Test_search_2i40(
    805         Word16 subNr,        /* i : subframe number                    */
    806         Word16 dn[],         /* i : correlation between target and h[] */
    807         Word16 rr[][L_CODE], /* i : matrix of autocorrelation          */
    808         Word16 codvec[],     /* o : algebraic codebook vector          */
    809         Flag   * pOverflow   /* o : Flag set when overflow occurs      */
    810     )
    811     {
    812         /*----------------------------------------------------------------------------
    813          CALL search_2i40 ( subNr = subNr
    814                     dn = dn
    815                     rr = rr
    816                     codvec = codvec )
    817            MODIFYING(nothing)
    818            RETURNING(nothing)
    819         ----------------------------------------------------------------------------*/
    820         search_2i40(
    821             subNr,
    822             dn,
    823             rr,
    824             codvec,
    825             pOverflow);
    826 
    827         return;
    828     }
    829 
    830     /****************************************************************************/
    831 
    832     /*
    833     ------------------------------------------------------------------------------
    834      FUNCTION NAME: build_code
    835     ------------------------------------------------------------------------------
    836      INPUT AND OUTPUT DEFINITIONS
    837 
    838      Inputs:
    839         subNr = subframe number (Word16)
    840         codvec = vector containing the position of pulses (Word16)
    841         dn_sign = vector containing the sign of pulses (Word16)
    842         cod = innovative code vector (Word16)
    843         h = vector containing the impulse response of the weighted
    844             synthesis filter (Word16)
    845         y = vector containing the filtered innovative code (Word16)
    846         sign = vector containing the sign of 2 pulses (Word16)
    847 
    848      Outputs:
    849         cod vector contains the new innovative code
    850         y vector contains the new filtered innovative code
    851         sign vector contains the sign of 2 pulses
    852 
    853      Returns:
    854         indx = codebook index (Word16)
    855 
    856      Global Variables Used:
    857         None
    858 
    859      Local Variables Needed:
    860         trackTable = table used for tracking codewords (Word16)
    861 
    862     ------------------------------------------------------------------------------
    863      FUNCTION DESCRIPTION
    864 
    865      This function builds the codeword, the filtered codeword and index of the
    866      codevector, based on the signs and positions of 2 pulses.
    867 
    868     ------------------------------------------------------------------------------
    869      REQUIREMENTS
    870 
    871      None
    872 
    873     ------------------------------------------------------------------------------
    874      REFERENCES
    875 
    876      [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    877 
    878     ------------------------------------------------------------------------------
    879      PSEUDO-CODE
    880 
    881     static Word16 build_code(
    882         Word16 subNr,     // i : subframe number
    883         Word16 codvec[],  // i : position of pulses
    884         Word16 dn_sign[], // i : sign of pulses
    885         Word16 cod[],     // o : innovative code vector
    886         Word16 h[],       // i : impulse response of weighted synthesis filter
    887         Word16 y[],       // o : filtered innovative code
    888         Word16 sign[]     // o : sign of 2 pulses
    889     )
    890     {
    891         Word16 i, j, k, track, first, index, _sign[NB_PULSE], indx, rsign;
    892         Word16 *p0, *p1, *pt;
    893         Word32 s;
    894         static Word16 trackTable[4*5] = {
    895            0, 1, 0, 1, -1, // subframe 1; track to code; -1 do not code this position
    896            0, -1, 1, 0, 1, // subframe 2
    897            0, 1, 0, -1, 1, // subframe 3
    898            0, 1, -1, 0, 1};// subframe 4
    899 
    900         pt = &trackTable[add(subNr, shl(subNr, 2))];
    901 
    902         for (i = 0; i < L_CODE; i++) {
    903             cod[i] = 0;
    904         }
    905 
    906         indx = 0;
    907         rsign = 0;
    908         for (k = 0; k < NB_PULSE; k++) {
    909            i = codvec[k];    // read pulse position
    910            j = dn_sign[i];   // read sign
    911 
    912            index = mult(i, 6554);    // index = pos/5
    913                                      // track = pos%5
    914            track = sub(i, extract_l(L_shr(L_mult(index, 5), 1)));
    915 
    916            first = pt[track];
    917 
    918            if (first == 0) {
    919               if (k == 0) {
    920                  track = 0;
    921               } else {
    922                  track = 1;
    923                  index = shl(index, 3);
    924               }
    925            } else {
    926               if (k == 0) {
    927                  track = 0;
    928                  index = add(index, 64);  // table bit is MSB
    929               } else {
    930                  track = 1;
    931                  index = shl(index, 3);
    932               }
    933            }
    934 
    935            if (j > 0) {
    936               cod[i] = 8191;
    937               _sign[k] = 32767;
    938               rsign = add(rsign, shl(1, track));
    939            } else {
    940               cod[i] = -8192;
    941               _sign[k] = (Word16) - 32768L;
    942             }
    943 
    944            indx = add(indx, index);
    945         }
    946         *sign = rsign;
    947 
    948         p0 = h - codvec[0];
    949         p1 = h - codvec[1];
    950 
    951         for (i = 0; i < L_CODE; i++) {
    952            s = 0;
    953            s = L_mac(s, *p0++, _sign[0]);
    954            s = L_mac(s, *p1++, _sign[1]);
    955            y[i] = pv_round(s);
    956         }
    957 
    958         return indx;
    959     }
    960 
    961     ------------------------------------------------------------------------------
    962      RESOURCES USED [optional]
    963 
    964      When the code is written for a specific target processor the
    965      the resources used should be documented below.
    966 
    967      HEAP MEMORY USED: x bytes
    968 
    969      STACK MEMORY USED: x bytes
    970 
    971      CLOCK CYCLES: (cycle count equation for this function) + (variable
    972                     used to represent cycle count for each subroutine
    973                     called)
    974          where: (cycle count variable) = cycle count for [subroutine
    975                                          name]
    976 
    977     ------------------------------------------------------------------------------
    978      CAUTION [optional]
    979      [State any special notes, constraints or cautions for users of this function]
    980 
    981     ------------------------------------------------------------------------------
    982     */
    983 
    984     static Word16 build_code(
    985         Word16 subNr,     /* i : subframe number                            */
    986         Word16 codvec[],  /* i : position of pulses                         */
    987         Word16 dn_sign[], /* i : sign of pulses                             */
    988         Word16 cod[],     /* o : innovative code vector                     */
    989         Word16 h[],       /* i : impulse response of weighted synthesis     */
    990         /*     filter                                     */
    991         Word16 y[],       /* o : filtered innovative code                   */
    992         Word16 sign[],    /* o : sign of 2 pulses                           */
    993         Flag  *pOverflow  /* o : Flag set when overflow occurs              */
    994     )
    995     {
    996         register Word16 i;
    997         register Word16 j;
    998         register Word16 k;
    999         register Word16 track;
   1000         register Word16 first;
   1001         register Word16 index;
   1002         register Word16 rsign;
   1003         Word16 indx;
   1004         Word16 _sign[NB_PULSE];
   1005         Word16 *p0;
   1006         Word16 *p1;
   1007 
   1008         const Word16 *pt;
   1009 
   1010         Word32 s;
   1011 
   1012         pt = trackTable + subNr + (subNr << 2);
   1013 
   1014         for (i = 0; i < L_CODE; i++)
   1015         {
   1016             *(cod + i) = 0;
   1017         }
   1018 
   1019         indx = 0;
   1020         rsign = 0;
   1021 
   1022         for (k = 0; k < NB_PULSE; k++)
   1023         {
   1024             i = *(codvec + k);  /* read pulse position */
   1025             j = *(dn_sign + i); /* read sign           */
   1026 
   1027             s = ((Word32)(i * 6554)) >> 15;
   1028             index = (Word16) s; /* index = pos/5 */
   1029 
   1030             track = i - (5 * index);    /* track = pos%5 */
   1031 
   1032             first = *(pt + track);
   1033 
   1034 
   1035             if (k == 0)
   1036             {
   1037                 track = 0;
   1038 
   1039                 if (first != 0)
   1040                 {
   1041                     index += 64;  /* table bit is MSB */
   1042                 }
   1043             }
   1044             else
   1045             {
   1046                 track = 1;
   1047                 index <<= 3;
   1048             }
   1049 
   1050             if (j > 0)
   1051             {
   1052                 *(cod + i) = 8191;
   1053                 *(_sign + k) = 32767;
   1054                 rsign += (1 << track);
   1055             }
   1056             else
   1057             {
   1058                 *(cod + i) = ~(8192) + 1;
   1059                 *(_sign + k) = (Word16)(~(32768) + 1);
   1060             }
   1061 
   1062             indx += index;
   1063         }
   1064 
   1065         *sign = rsign;
   1066 
   1067         p0 = h - *codvec;
   1068         p1 = h - *(codvec + 1);
   1069 
   1070         for (i = 0; i < L_CODE; i++)
   1071         {
   1072             s = 0;
   1073             s =
   1074                 L_mult(
   1075                     *p0++,
   1076                     *_sign,
   1077                     pOverflow);
   1078 
   1079             s =
   1080                 L_mac(
   1081                     s,
   1082                     *p1++,
   1083                     *(_sign + 1),
   1084                     pOverflow);
   1085 
   1086             *(y + i) =
   1087                 pv_round(
   1088                     s,
   1089                     pOverflow);
   1090         }
   1091 
   1092         return(indx);
   1093     }
   1094 
   1095     /****************************************************************************/
   1096 
   1097     /*
   1098     ------------------------------------------------------------------------------
   1099      FUNCTION NAME: Test_build_code
   1100     ------------------------------------------------------------------------------
   1101      INPUT AND OUTPUT DEFINITIONS
   1102 
   1103      Inputs:
   1104         subNr = subframe number (Word16)
   1105         codvec = vector containing the position of pulses (Word16)
   1106         dn_sign = vector containing the sign of pulses (Word16)
   1107         cod = innovative code vector (Word16)
   1108         h = vector containing the impulse response of the weighted
   1109             synthesis filter (Word16)
   1110         y = vector containing the filtered innovative code (Word16)
   1111         sign = vector containing the sign of 2 pulses (Word16)
   1112 
   1113      Outputs:
   1114         cod vector contains the new innovative code
   1115         y vector contains the new filtered innovative code
   1116         sign vector contains the sign of 2 pulses
   1117 
   1118      Returns:
   1119         indx = codebook index (Word16)
   1120 
   1121      Global Variables Used:
   1122         None
   1123 
   1124      Local Variables Needed:
   1125         trackTable = table used for tracking codewords (Word16)
   1126 
   1127     ------------------------------------------------------------------------------
   1128      FUNCTION DESCRIPTION
   1129 
   1130      This function provides external access to the local function build_code.
   1131 
   1132     ------------------------------------------------------------------------------
   1133      REQUIREMENTS
   1134 
   1135      None
   1136 
   1137     ------------------------------------------------------------------------------
   1138      REFERENCES
   1139 
   1140      [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
   1141 
   1142     ------------------------------------------------------------------------------
   1143      PSEUDO-CODE
   1144 
   1145      CALL build_code ( subNr = subNr
   1146                codvec = codvec
   1147                dn_sign = dn_sign
   1148                cod = cod
   1149                h = h
   1150                y = y
   1151                sign = sign )
   1152        MODIFYING(nothing)
   1153        RETURNING(indx)
   1154 
   1155     ------------------------------------------------------------------------------
   1156      RESOURCES USED [optional]
   1157 
   1158      When the code is written for a specific target processor the
   1159      the resources used should be documented below.
   1160 
   1161      HEAP MEMORY USED: x bytes
   1162 
   1163      STACK MEMORY USED: x bytes
   1164 
   1165      CLOCK CYCLES: (cycle count equation for this function) + (variable
   1166                     used to represent cycle count for each subroutine
   1167                     called)
   1168          where: (cycle count variable) = cycle count for [subroutine
   1169                                          name]
   1170 
   1171     ------------------------------------------------------------------------------
   1172      CAUTION [optional]
   1173      [State any special notes, constraints or cautions for users of this function]
   1174 
   1175     ------------------------------------------------------------------------------
   1176     */
   1177 
   1178     Word16 Test_build_code(
   1179         Word16 subNr,      /* i : subframe number                            */
   1180         Word16 codvec[],   /* i : position of pulses                         */
   1181         Word16 dn_sign[],  /* i : sign of pulses                             */
   1182         Word16 cod[],      /* o : innovative code vector                     */
   1183         Word16 h[],        /* i : impulse response of weighted synthesis     */
   1184         /*     filter                                     */
   1185         Word16 y[],        /* o : filtered innovative code                   */
   1186         Word16 sign[],     /* o : sign of 2 pulses                           */
   1187         Flag   * pOverflow /* o : Flag set when overflow occurs              */
   1188     )
   1189     {
   1190         Word16  test_index;
   1191 
   1192         /*----------------------------------------------------------------------------
   1193          CALL build_code ( subNr = subNr
   1194                    codvec = codvec
   1195                    dn_sign = dn_sign
   1196                    cod = cod
   1197                    h = h
   1198                    y = y
   1199                    sign = sign )
   1200            MODIFYING(nothing)
   1201            RETURNING(indx)
   1202         ----------------------------------------------------------------------------*/
   1203         test_index =
   1204             build_code(
   1205                 subNr,
   1206                 codvec,
   1207                 dn_sign,
   1208                 cod,
   1209                 h,
   1210                 y,
   1211                 sign,
   1212                 pOverflow);
   1213 
   1214         return(test_index);
   1215     }
   1216 
   1217 #ifdef __cplusplus
   1218 }
   1219 #endif
   1220