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