xref: /aosp_15_r20/frameworks/av/media/module/codecs/amrnb/enc/src/c4_17pf.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 mul;
420         Word32 alp0;
421         Word32 alp1;
422 
423         OSCL_UNUSED_ARG(pOverflow);
424 
425         /* Default value */
426         psk = -1;
427         alpk = 1;
428         for (i = 0; i < NB_PULSE; i++)
429         {
430             *(p_codvec++) = i;
431         }
432 
433         for (track = 3; track < 5; track++)
434         {
435             /* fix starting position */
436 
437             ipos[0] = 0;
438             ipos[1] = 1;
439             ipos[2] = 2;
440             ipos[3] = track;
441 
442             /*------------------------------------------------------------------*
443              * main loop: try 4 tracks.                                         *
444              *------------------------------------------------------------------*/
445 
446             for (i = 0; i < NB_PULSE; i++)
447             {
448                 /*----------------------------------------------------------------*
449                  * i0 loop: try 4 positions (use position with max of corr.).     *
450                  *----------------------------------------------------------------*/
451 
452                 for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP)
453                 {
454                     if (dn2[i0] >= 0)
455                     {
456                         ps0 = dn[i0];
457 
458                         alp0 = (Word32) rr[i0][i0] << 14;
459 
460                         /*----------------------------------------------------------------*
461                          * i1 loop: 8 positions.                                          *
462                          *----------------------------------------------------------------*/
463 
464                         sq = -1;
465                         alp = 1;
466                         ps = 0;
467                         ix = ipos[1];
468 
469                         /* initialize 4 index for next loop. */
470                         /*-------------------------------------------------------------------*
471                          *  These index have low complexity address computation because      *
472                          *  they are, in fact, pointers with fixed increment.  For example,  *
473                          *  "rr[i0][i3]" is a pointer initialized to "&rr[i0][ipos[3]]"      *
474                          *  and incremented by "STEP".                                       *
475                          *-------------------------------------------------------------------*/
476 
477                         for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP)
478                         {
479                             /* idx increment = STEP */
480                             /* ps1 = add(ps0, dn[i1], pOverflow); */
481                             ps1 = ps0 + dn[i1];
482 
483                             /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */
484 
485                             /* alp1 = L_mac(alp0, rr[i1][i1], _1_4, pOverflow); */
486                             alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
487 
488                             /* alp1 = L_mac(alp1, rr[i0][i1], _1_2, pOverflow); */
489                             alp1 += (Word32) rr[i0][i1] << 15;
490 
491                             /* sq1 = mult(ps1, ps1, pOverflow); */
492                             sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
493 
494                             /* alp_16 = pv_round(alp1, pOverflow); */
495                             alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
496 
497                             /* s = L_mult(alp, sq1, pOverflow); */
498                             s = ((Word32) alp * sq1) << 1;
499 
500                             /* s = L_msu(s, sq, alp_16, pOverflow); */
501                             __builtin_mul_overflow(sq, alp_16, &mul);
502                             __builtin_sub_overflow(s, (mul << 1), &s);
503 
504                             if (s > 0)
505                             {
506                                 sq = sq1;
507                                 ps = ps1;
508                                 alp = alp_16;
509                                 ix = i1;
510                             }
511                         }
512                         i1 = ix;
513 
514                         /*----------------------------------------------------------------*
515                          * i2 loop: 8 positions.                                          *
516                          *----------------------------------------------------------------*/
517 
518                         ps0 = ps;
519 
520                         /* alp0 = L_mult(alp, _1_4, pOverflow); */
521                         alp0 = (Word32) alp << 14;
522 
523                         sq = -1;
524                         alp = 1;
525                         ps = 0;
526                         ix = ipos[2];
527 
528                         /* initialize 4 index for next loop (see i1 loop) */
529 
530                         for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP)
531                         {
532                             /* index increment = STEP */
533                             /* ps1 = add(ps0, dn[i2], pOverflow); */
534                             ps1 = ps0 + dn[i2];
535 
536                             /* alp1 = alp0 + rr[i0][i2] + rr[i1][i2] + 1/2*rr[i2][i2]; */
537 
538                             /* idx incr = STEP */
539                             /* alp1 = L_mac(alp0, rr[i2][i2], _1_16, pOverflow); */
540                             alp1 = alp0 + ((Word32) rr[i2][i2] << 12);
541 
542                             /* idx incr = STEP */
543                             /* alp1 = L_mac(alp1, rr[i1][i2], _1_8, pOverflow); */
544                             alp1 += (Word32) rr[i1][i2] << 13;
545 
546                             /* idx incr = STEP */
547                             /* alp1 = L_mac(alp1,rr[i0][i2], _1_8, pOverflow); */
548                             alp1 += (Word32) rr[i0][i2] << 13;
549 
550                             /* sq1 = mult(ps1, ps1, pOverflow); */
551                             sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
552 
553                             /* alp_16 = pv_round(alp1, pOverflow); */
554                             alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
555 
556                             /* s = L_mult(alp, sq1, pOverflow); */
557                             s = ((Word32) alp * sq1) << 1;
558 
559                             /* s = L_msu(s, sq, alp_16, pOverflow); */
560                             s -= (((Word32) sq * alp_16) << 1);
561 
562                             if (s > 0)
563                             {
564                                 sq = sq1;
565                                 ps = ps1;
566                                 alp = alp_16;
567                                 ix = i2;
568                             }
569                         }
570                         i2 = ix;
571 
572                         /*----------------------------------------------------------------*
573                          * i3 loop: 8 positions.                                          *
574                          *----------------------------------------------------------------*/
575 
576                         ps0 = ps;
577                         alp0 = L_deposit_h(alp);
578 
579                         sq = -1;
580                         alp = 1;
581                         ps = 0;
582                         ix = ipos[3];
583 
584                         /* initialize 5 index for next loop (see i1 loop) */
585 
586                         for (i3 = ipos[3]; i3 < L_CODE; i3 += STEP)
587                         {
588                             /* ps1 = add(ps0, dn[i3], pOverflow); */
589                             ps1 = ps0 + dn[i3]; /* index increment = STEP */
590 
591                             /* alp1 = alp0 + rr[i0][i3] + rr[i1][i3] + rr[i2][i3] + 1/2*rr[i3][i3]; */
592 
593                             /* alp1 = L_mac(alp0, rr[i3][i3], _1_16, pOverflow); */
594                             alp1 = alp0 + ((Word32) rr[i3][i3] << 12); /* idx incr = STEP */
595 
596                             /* alp1 = L_mac(alp1, rr[i2][i3], _1_8, pOverflow); */
597                             alp1 += (Word32) rr[i2][i3] << 13;  /* idx incr = STEP */
598 
599                             /* alp1 = L_mac(alp1, rr[i1][i3], _1_8, pOverflow); */
600                             alp1 += (Word32) rr[i1][i3] << 13;  /* idx incr = STEP */
601 
602                             /* alp1 = L_mac(alp1, rr[i0][i3], _1_8, pOverflow); */
603                             alp1 += (Word32) rr[i0][i3] << 13;  /* idx incr = STEP */
604 
605                             /* sq1 = mult(ps1, ps1, pOverflow); */
606                             sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
607 
608                             /* alp_16 = pv_round(alp1, pOverflow); */
609                             alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
610 
611                             /* s = L_mult(alp, sq1, pOverflow); */
612                             s = ((Word32) alp * sq1) << 1;
613 
614                             /* s = L_msu(s, sq, alp_16, pOverflow); */
615                             __builtin_mul_overflow(sq, alp_16, &mul);
616                             __builtin_sub_overflow(s, (mul << 1), &s);
617 
618                             if (s > 0)
619                             {
620                                 sq = sq1;
621                                 ps = ps1;
622                                 alp = alp_16;
623                                 ix = i3;
624                             }
625                         }
626 
627 
628                         /*----------------------------------------------------------------*
629                          * memorise codevector if this one is better than the last one.   *
630                          *----------------------------------------------------------------*/
631 
632                         /* s = L_mult(alpk, sq, pOverflow); */
633                         s = ((Word32) alpk * sq) << 1;
634 
635                         /* s = L_msu(s, psk, alp, pOverflow); */
636                         __builtin_mul_overflow(psk, alp, &mul);
637                         __builtin_sub_overflow(s, (mul << 1), &s);
638 
639                         if (s > 0)
640                         {
641                             psk = sq;
642                             alpk = alp;
643                             p_codvec = &codvec[0];
644 
645                             *(p_codvec++) = i0;
646                             *(p_codvec++) = i1;
647                             *(p_codvec++) = i2;
648                             *(p_codvec) = ix;
649                         }
650                     }
651                 }
652 
653                 /*----------------------------------------------------------------*
654                  * Cyclic permutation of i0,i1,i2 and i3.                         *
655                  *----------------------------------------------------------------*/
656 
657                 pos = ipos[3];
658                 ipos[3] = ipos[2];
659                 ipos[2] = ipos[1];
660                 ipos[1] = ipos[0];
661                 ipos[0] = pos;
662             }
663         }
664 
665         return;
666     }
667 
668 
669 
670 
671     /****************************************************************************/
672 
673     /*
674     ------------------------------------------------------------------------------
675      FUNCTION NAME:  build_code()
676     ------------------------------------------------------------------------------
677      INPUT AND OUTPUT DEFINITIONS
678 
679      Inputs:
680         codvec[]   Array of type Word16 -- position of pulses
681         dn_sign[]  Array of type Word16 -- sign of pulses
682         h[]        Array of type Word16 -- impulse response of
683                                            weighted synthesis filter
684 
685      Outputs:
686         cod[]  Array of type Word16 -- innovative code vector
687         y[]    Array of type Word16 -- filtered innovative code
688         sign[] Array of type Word16 -- index of 4 pulses (sign + position)
689         pOverflow  Pointer to Flag  -- set when overflow occurs
690 
691      Returns:
692         indx
693 
694      Global Variables Used:
695         None
696 
697      Local Variables Needed:
698 
699     ------------------------------------------------------------------------------
700      FUNCTION DESCRIPTION
701 
702      PURPOSE: Builds the codeword, the filtered codeword and index of the
703               codevector, based on the signs and positions of 4 pulses.
704 
705     ------------------------------------------------------------------------------
706      REQUIREMENTS
707 
708      None
709 
710     ------------------------------------------------------------------------------
711      REFERENCES
712 
713      [1] c4_17pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
714 
715     ------------------------------------------------------------------------------
716      PSEUDO-CODE
717 
718     ------------------------------------------------------------------------------
719      RESOURCES USED [optional]
720 
721      When the code is written for a specific target processor the
722      the resources used should be documented below.
723 
724      HEAP MEMORY USED: x bytes
725 
726      STACK MEMORY USED: x bytes
727 
728      CLOCK CYCLES: (cycle count equation for this function) + (variable
729                     used to represent cycle count for each subroutine
730                     called)
731          where: (cycle count variable) = cycle count for [subroutine
732                                          name]
733 
734     ------------------------------------------------------------------------------
735      CAUTION [optional]
736      [State any special notes, constraints or cautions for users of this function]
737 
738     ------------------------------------------------------------------------------
739     */
740 
741     static Word16
build_code(Word16 codvec[],Word16 dn_sign[],Word16 cod[],Word16 h[],Word16 y[],Word16 sign[],Flag * pOverflow)742     build_code(
743         Word16 codvec[],  /* i : position of pulses                            */
744         Word16 dn_sign[], /* i : sign of pulses                                */
745         Word16 cod[],     /* o : innovative code vector                        */
746         Word16 h[],       /* i : impulse response of weighted synthesis filter */
747         Word16 y[],       /* o : filtered innovative code                      */
748         Word16 sign[],    /* o : index of 4 pulses (sign+position)             */
749         Flag   * pOverflow  /* o : Flag set when overflow occurs               */
750     )
751     {
752         Word16 i;
753         Word16 j;
754         Word16 k;
755         Word16 track;
756         Word16 index;
757         Word16 _sign[NB_PULSE];
758         Word16 indx;
759         Word16 rsign;
760 
761         Word16 *p0;
762         Word16 *p1;
763         Word16 *p2;
764         Word16 *p3;
765         Word16 *p_cod = &cod[0];
766 
767         Word32 s;
768 
769         for (i = 0; i < L_CODE; i++)
770         {
771             *(p_cod++) = 0;
772         }
773 
774         indx = 0;
775         rsign = 0;
776 
777         for (k = 0; k < NB_PULSE; k++)
778         {
779             i = codvec[k]; /* read pulse position */
780             j = dn_sign[i]; /* read sign          */
781 
782             /* index = pos/5 */
783             /* index = mult(i, 6554, pOverflow); */
784             index = (Word16)(((Word32) i * 6554) >> 15);
785 
786             /* track = pos%5 */
787             /* s = L_mult(index, 5, pOverflow); */
788             s = ((Word32) index * 5) << 1;
789 
790             /* s = L_shr(s, 1, pOverflow); */
791             s >>= 1;
792 
793             /* track = sub(i, (Word16) s, pOverflow); */
794             track = i - (Word16) s;
795 
796             index = gray[index];
797 
798             if (track == 1)
799             {
800                 /* index = shl(index, 3, pOverflow); */
801                 index <<= 3;
802             }
803             else if (track == 2)
804             {
805                 /* index = shl(index, 6, pOverflow); */
806                 index <<= 6;
807             }
808             else if (track == 3)
809             {
810                 /* index = shl(index, 10, pOverflow); */
811                 index <<= 10;
812             }
813             else if (track == 4)
814             {
815                 track = 3;
816 
817                 /* index = shl(index, 10, pOverflow); */
818                 index <<= 10;
819 
820                 /* index = add(index, 512, pOverflow); */
821                 index += 512;
822             }
823 
824             if (j > 0)
825             {
826                 cod[i] = 8191;
827                 _sign[k] = 32767;
828 
829                 /* track = shl(1, track, pOverflow); */
830                 track = 1 << track;
831 
832                 /* rsign = add(rsign, track, pOverflow); */
833                 rsign += track;
834             }
835             else
836             {
837                 cod[i] = -8192;
838                 _sign[k] = (Word16) - 32768L;
839             }
840 
841             /* indx = add(indx, index, pOverflow); */
842             indx += index;
843         }
844         *sign = rsign;
845 
846         p0 = h - codvec[0];
847         p1 = h - codvec[1];
848         p2 = h - codvec[2];
849         p3 = h - codvec[3];
850 
851         for (i = 0; i < L_CODE; i++)
852         {
853             s = 0;
854             s =
855                 L_mac(
856                     s,
857                     *p0++,
858                     _sign[0],
859                     pOverflow);
860 
861             s =
862                 L_mac(
863                     s,
864                     *p1++,
865                     _sign[1],
866                     pOverflow);
867 
868             s =
869                 L_mac(
870                     s,
871                     *p2++,
872                     _sign[2],
873                     pOverflow);
874 
875             s =
876                 L_mac(
877                     s,
878                     *p3++,
879                     _sign[3],
880                     pOverflow);
881 
882             y[i] =
883                 pv_round(
884                     s,
885                     pOverflow);
886 
887         } /* for (i = 0; i < L_CODE; i++) */
888 
889         return indx;
890 
891     } /* build_code */
892 
893 #ifdef __cplusplus
894 }
895 #endif
896