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