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 
code_2i40_9bits(Word16 subNr,Word16 x[],Word16 h[],Word16 T0,Word16 pitch_sharp,Word16 code[],Word16 y[],Word16 * sign,Flag * pOverflow)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         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 
search_2i40(Word16 subNr,Word16 dn[],Word16 rr[][L_CODE],Word16 codvec[],Flag * pOverflow)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         Word16 i0;
596         Word16 i1;
597         Word16 ix = 0; /* initialization only needed to keep gcc silent */
598         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         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 
Test_search_2i40(Word16 subNr,Word16 dn[],Word16 rr[][L_CODE],Word16 codvec[],Flag * pOverflow)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 
build_code(Word16 subNr,Word16 codvec[],Word16 dn_sign[],Word16 cod[],Word16 h[],Word16 y[],Word16 sign[],Flag * pOverflow)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         Word16 i;
997         Word16 j;
998         Word16 k;
999         Word16 track;
1000         Word16 first;
1001         Word16 index;
1002         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 
Test_build_code(Word16 subNr,Word16 codvec[],Word16 dn_sign[],Word16 cod[],Word16 h[],Word16 y[],Word16 sign[],Flag * pOverflow)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