• 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/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         Word32 mul;
614         Word16 *p_codvec = &codvec[0];
615 
616         OSCL_UNUSED_ARG(pOverflow);
617 
618         psk = -1;
619         alpk = 1;
620 
621         /* Unrolled the following FOR loop to save MIPS */
622         /* for (i = 0; i < NB_PULSE; i++)           */
623         /* {                            */
624         /*  *(codvec + i) = i;          */
625         /* }                        */
626 
627         *(p_codvec++) = 0;
628         *(p_codvec) = 1;
629 
630         for (track1 = 0; track1 < 2; track1++)
631         {
632             /* fix starting position */
633 
634             i = (subNr << 1) + (track1 << 3);
635             *ipos = *(startPos + i);
636             *(ipos + 1) = *(startPos + i + 1);
637 
638 
639             /*----------------------------------------------------------*
640              * i0 loop: try 8 positions.                                *
641              *----------------------------------------------------------*/
642 
643             for (i0 = *ipos; i0 < L_CODE; i0 += STEP)
644             {
645                 ps0 = *(dn + i0);
646 
647                 /* Left shift by 1 converts integer product to */
648                 /* fractional product.                 */
649                 alp0 = (Word32) rr[i0][i0] << 14;
650 
651                 /*--------------------------------------------------*
652                  * i1 loop: 8 positions.                            *
653                  *--------------------------------------------------*/
654 
655                 sq = -1;
656                 alp = 1;
657                 ix = *(ipos + 1);
658 
659                 /*--------------------------------------------------*
660                  * These index have low complexity address          *
661                  * computation because they are, in fact, pointers  *
662                  * with fixed increment. For example, "rr[i0][i2]"  *
663                  * is a pointer initialized to "&rr[i0][ipos[2]]"   *
664                 *  and incremented by "STEP".                       *
665                 *---------------------------------------------------*/
666 
667                 for (i1 = *(ipos + 1); i1 < L_CODE; i1 += STEP)
668                 {
669                     /* idx increment = STEP */
670                     /* ps1 = add(ps0, *(dn + i1), pOverflow); */
671                     ps1 = ps0 + dn[i1];
672 
673                     /* alp1 = alp0+rr[i0][i1]+1/2*rr[i1][i1]; */
674 
675                     /* idx incr = STEP */
676                     /* Extra left shift by 1 converts integer  */
677                     /* product to fractional product     */
678                     /* alp1 = L_add(alp0, s, pOverflow); */
679                     alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
680 
681                     /* idx incr = STEP */
682                     /* Extra left shift by 1 converts integer  */
683                     /* product to fractional product     */
684                     /* alp1 = L_add(alp1, s, pOverflow); */
685                     alp1 += (Word32) rr[i0][i1] << 15;
686 
687                     /* sq1 = mult(ps1, ps1, pOverflow); */
688                     sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
689 
690                     /* alp_16 = pv_round(alp1, pOverflow); */
691                     alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
692 
693                     /* L_temp = L_mult(alp, sq1, pOverflow); */
694                     L_temp = ((Word32) alp * sq1) << 1;
695 
696                     /* s = L_msu(L_temp, sq, alp_16, pOverflow); */
697                     __builtin_mul_overflow(sq, alp_16, &mul);
698                     __builtin_sub_overflow(L_temp, (mul << 1), &s);
699 
700                     if (s > 0)
701                     {
702                         sq = sq1;
703                         alp = alp_16;
704                         ix = i1;
705                     }
706                 }
707 
708                 /* memorize codevector if this one is better than the last one. */
709 
710                 /* L_temp = L_mult(alpk, sq, pOverflow); */
711                 L_temp = ((Word32) alpk * sq) << 1;
712 
713                 /* s = L_msu(L_temp, psk, alp, pOverflow); */
714                 s = L_temp - (((Word32) psk * alp) << 1);
715 
716                 if (s > 0)
717                 {
718                     psk = sq;
719                     alpk = alp;
720                     p_codvec = &codvec[0];
721                     *(p_codvec++) = i0;
722                     *(p_codvec) = ix;
723                 }
724             }
725         }
726 
727         return;
728     }
729 
730     /****************************************************************************/
731 
732     /*
733     ------------------------------------------------------------------------------
734      FUNCTION NAME: Test_search_2i40
735     ------------------------------------------------------------------------------
736      INPUT AND OUTPUT DEFINITIONS
737 
738      Inputs:
739         subNr = subframe number (Word16)
740         dn = vector containing the correlation between target and the impulse
741              response of the weighted synthesis filter (Word16)
742         rr = autocorrelation matrix (Word16)
743         codvec = algebraic codebook vector (Word16)
744 
745      Outputs:
746         codvec contains the newly calculated codevectors
747 
748      Returns:
749         None
750 
751      Global Variables Used:
752         None
753 
754      Local Variables Needed:
755         startPos = table containing the start positions used by fixed codebook
756                    routines (const Word16)
757 
758     ------------------------------------------------------------------------------
759      FUNCTION DESCRIPTION
760 
761      This function provides external access to the local function search_2i40.
762 
763     ------------------------------------------------------------------------------
764      REQUIREMENTS
765 
766      None
767 
768     ------------------------------------------------------------------------------
769      REFERENCES
770 
771      [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
772 
773     ------------------------------------------------------------------------------
774      PSEUDO-CODE
775 
776      CALL search_2i40 ( subNr = subNr
777                 dn = dn
778                 rr = rr
779                 codvec = codvec )
780        MODIFYING(nothing)
781        RETURNING(nothing)
782 
783     ------------------------------------------------------------------------------
784      RESOURCES USED [optional]
785 
786      When the code is written for a specific target processor the
787      the resources used should be documented below.
788 
789      HEAP MEMORY USED: x bytes
790 
791      STACK MEMORY USED: x bytes
792 
793      CLOCK CYCLES: (cycle count equation for this function) + (variable
794                     used to represent cycle count for each subroutine
795                     called)
796          where: (cycle count variable) = cycle count for [subroutine
797                                          name]
798 
799     ------------------------------------------------------------------------------
800      CAUTION [optional]
801      [State any special notes, constraints or cautions for users of this function]
802 
803     ------------------------------------------------------------------------------
804     */
805 
Test_search_2i40(Word16 subNr,Word16 dn[],Word16 rr[][L_CODE],Word16 codvec[],Flag * pOverflow)806     void Test_search_2i40(
807         Word16 subNr,        /* i : subframe number                    */
808         Word16 dn[],         /* i : correlation between target and h[] */
809         Word16 rr[][L_CODE], /* i : matrix of autocorrelation          */
810         Word16 codvec[],     /* o : algebraic codebook vector          */
811         Flag   * pOverflow   /* o : Flag set when overflow occurs      */
812     )
813     {
814         /*----------------------------------------------------------------------------
815          CALL search_2i40 ( subNr = subNr
816                     dn = dn
817                     rr = rr
818                     codvec = codvec )
819            MODIFYING(nothing)
820            RETURNING(nothing)
821         ----------------------------------------------------------------------------*/
822         search_2i40(
823             subNr,
824             dn,
825             rr,
826             codvec,
827             pOverflow);
828 
829         return;
830     }
831 
832     /****************************************************************************/
833 
834     /*
835     ------------------------------------------------------------------------------
836      FUNCTION NAME: build_code
837     ------------------------------------------------------------------------------
838      INPUT AND OUTPUT DEFINITIONS
839 
840      Inputs:
841         subNr = subframe number (Word16)
842         codvec = vector containing the position of pulses (Word16)
843         dn_sign = vector containing the sign of pulses (Word16)
844         cod = innovative code vector (Word16)
845         h = vector containing the impulse response of the weighted
846             synthesis filter (Word16)
847         y = vector containing the filtered innovative code (Word16)
848         sign = vector containing the sign of 2 pulses (Word16)
849 
850      Outputs:
851         cod vector contains the new innovative code
852         y vector contains the new filtered innovative code
853         sign vector contains the sign of 2 pulses
854 
855      Returns:
856         indx = codebook index (Word16)
857 
858      Global Variables Used:
859         None
860 
861      Local Variables Needed:
862         trackTable = table used for tracking codewords (Word16)
863 
864     ------------------------------------------------------------------------------
865      FUNCTION DESCRIPTION
866 
867      This function builds the codeword, the filtered codeword and index of the
868      codevector, based on the signs and positions of 2 pulses.
869 
870     ------------------------------------------------------------------------------
871      REQUIREMENTS
872 
873      None
874 
875     ------------------------------------------------------------------------------
876      REFERENCES
877 
878      [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
879 
880     ------------------------------------------------------------------------------
881      PSEUDO-CODE
882 
883     static Word16 build_code(
884         Word16 subNr,     // i : subframe number
885         Word16 codvec[],  // i : position of pulses
886         Word16 dn_sign[], // i : sign of pulses
887         Word16 cod[],     // o : innovative code vector
888         Word16 h[],       // i : impulse response of weighted synthesis filter
889         Word16 y[],       // o : filtered innovative code
890         Word16 sign[]     // o : sign of 2 pulses
891     )
892     {
893         Word16 i, j, k, track, first, index, _sign[NB_PULSE], indx, rsign;
894         Word16 *p0, *p1, *pt;
895         Word32 s;
896         static Word16 trackTable[4*5] = {
897            0, 1, 0, 1, -1, // subframe 1; track to code; -1 do not code this position
898            0, -1, 1, 0, 1, // subframe 2
899            0, 1, 0, -1, 1, // subframe 3
900            0, 1, -1, 0, 1};// subframe 4
901 
902         pt = &trackTable[add(subNr, shl(subNr, 2))];
903 
904         for (i = 0; i < L_CODE; i++) {
905             cod[i] = 0;
906         }
907 
908         indx = 0;
909         rsign = 0;
910         for (k = 0; k < NB_PULSE; k++) {
911            i = codvec[k];    // read pulse position
912            j = dn_sign[i];   // read sign
913 
914            index = mult(i, 6554);    // index = pos/5
915                                      // track = pos%5
916            track = sub(i, extract_l(L_shr(L_mult(index, 5), 1)));
917 
918            first = pt[track];
919 
920            if (first == 0) {
921               if (k == 0) {
922                  track = 0;
923               } else {
924                  track = 1;
925                  index = shl(index, 3);
926               }
927            } else {
928               if (k == 0) {
929                  track = 0;
930                  index = add(index, 64);  // table bit is MSB
931               } else {
932                  track = 1;
933                  index = shl(index, 3);
934               }
935            }
936 
937            if (j > 0) {
938               cod[i] = 8191;
939               _sign[k] = 32767;
940               rsign = add(rsign, shl(1, track));
941            } else {
942               cod[i] = -8192;
943               _sign[k] = (Word16) - 32768L;
944             }
945 
946            indx = add(indx, index);
947         }
948         *sign = rsign;
949 
950         p0 = h - codvec[0];
951         p1 = h - codvec[1];
952 
953         for (i = 0; i < L_CODE; i++) {
954            s = 0;
955            s = L_mac(s, *p0++, _sign[0]);
956            s = L_mac(s, *p1++, _sign[1]);
957            y[i] = pv_round(s);
958         }
959 
960         return indx;
961     }
962 
963     ------------------------------------------------------------------------------
964      RESOURCES USED [optional]
965 
966      When the code is written for a specific target processor the
967      the resources used should be documented below.
968 
969      HEAP MEMORY USED: x bytes
970 
971      STACK MEMORY USED: x bytes
972 
973      CLOCK CYCLES: (cycle count equation for this function) + (variable
974                     used to represent cycle count for each subroutine
975                     called)
976          where: (cycle count variable) = cycle count for [subroutine
977                                          name]
978 
979     ------------------------------------------------------------------------------
980      CAUTION [optional]
981      [State any special notes, constraints or cautions for users of this function]
982 
983     ------------------------------------------------------------------------------
984     */
985 
build_code(Word16 subNr,Word16 codvec[],Word16 dn_sign[],Word16 cod[],Word16 h[],Word16 y[],Word16 sign[],Flag * pOverflow)986     static Word16 build_code(
987         Word16 subNr,     /* i : subframe number                            */
988         Word16 codvec[],  /* i : position of pulses                         */
989         Word16 dn_sign[], /* i : sign of pulses                             */
990         Word16 cod[],     /* o : innovative code vector                     */
991         Word16 h[],       /* i : impulse response of weighted synthesis     */
992         /*     filter                                     */
993         Word16 y[],       /* o : filtered innovative code                   */
994         Word16 sign[],    /* o : sign of 2 pulses                           */
995         Flag  *pOverflow  /* o : Flag set when overflow occurs              */
996     )
997     {
998         Word16 i;
999         Word16 j;
1000         Word16 k;
1001         Word16 track;
1002         Word16 first;
1003         Word16 index;
1004         Word16 rsign;
1005         Word16 indx;
1006         Word16 _sign[NB_PULSE];
1007         Word16 *p0;
1008         Word16 *p1;
1009 
1010         const Word16 *pt;
1011 
1012         Word32 s;
1013 
1014         pt = trackTable + subNr + (subNr << 2);
1015 
1016         for (i = 0; i < L_CODE; i++)
1017         {
1018             *(cod + i) = 0;
1019         }
1020 
1021         indx = 0;
1022         rsign = 0;
1023 
1024         for (k = 0; k < NB_PULSE; k++)
1025         {
1026             i = *(codvec + k);  /* read pulse position */
1027             j = *(dn_sign + i); /* read sign           */
1028 
1029             s = ((Word32)(i * 6554)) >> 15;
1030             index = (Word16) s; /* index = pos/5 */
1031 
1032             track = i - (5 * index);    /* track = pos%5 */
1033 
1034             first = *(pt + track);
1035 
1036 
1037             if (k == 0)
1038             {
1039                 track = 0;
1040 
1041                 if (first != 0)
1042                 {
1043                     index += 64;  /* table bit is MSB */
1044                 }
1045             }
1046             else
1047             {
1048                 track = 1;
1049                 index <<= 3;
1050             }
1051 
1052             if (j > 0)
1053             {
1054                 *(cod + i) = 8191;
1055                 *(_sign + k) = 32767;
1056                 rsign += (1 << track);
1057             }
1058             else
1059             {
1060                 *(cod + i) = ~(8192) + 1;
1061                 *(_sign + k) = (Word16)(~(32768) + 1);
1062             }
1063 
1064             indx += index;
1065         }
1066 
1067         *sign = rsign;
1068 
1069         p0 = h - *codvec;
1070         p1 = h - *(codvec + 1);
1071 
1072         for (i = 0; i < L_CODE; i++)
1073         {
1074             s = 0;
1075             s =
1076                 L_mult(
1077                     *p0++,
1078                     *_sign,
1079                     pOverflow);
1080 
1081             s =
1082                 L_mac(
1083                     s,
1084                     *p1++,
1085                     *(_sign + 1),
1086                     pOverflow);
1087 
1088             *(y + i) =
1089                 pv_round(
1090                     s,
1091                     pOverflow);
1092         }
1093 
1094         return(indx);
1095     }
1096 
1097     /****************************************************************************/
1098 
1099     /*
1100     ------------------------------------------------------------------------------
1101      FUNCTION NAME: Test_build_code
1102     ------------------------------------------------------------------------------
1103      INPUT AND OUTPUT DEFINITIONS
1104 
1105      Inputs:
1106         subNr = subframe number (Word16)
1107         codvec = vector containing the position of pulses (Word16)
1108         dn_sign = vector containing the sign of pulses (Word16)
1109         cod = innovative code vector (Word16)
1110         h = vector containing the impulse response of the weighted
1111             synthesis filter (Word16)
1112         y = vector containing the filtered innovative code (Word16)
1113         sign = vector containing the sign of 2 pulses (Word16)
1114 
1115      Outputs:
1116         cod vector contains the new innovative code
1117         y vector contains the new filtered innovative code
1118         sign vector contains the sign of 2 pulses
1119 
1120      Returns:
1121         indx = codebook index (Word16)
1122 
1123      Global Variables Used:
1124         None
1125 
1126      Local Variables Needed:
1127         trackTable = table used for tracking codewords (Word16)
1128 
1129     ------------------------------------------------------------------------------
1130      FUNCTION DESCRIPTION
1131 
1132      This function provides external access to the local function build_code.
1133 
1134     ------------------------------------------------------------------------------
1135      REQUIREMENTS
1136 
1137      None
1138 
1139     ------------------------------------------------------------------------------
1140      REFERENCES
1141 
1142      [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
1143 
1144     ------------------------------------------------------------------------------
1145      PSEUDO-CODE
1146 
1147      CALL build_code ( subNr = subNr
1148                codvec = codvec
1149                dn_sign = dn_sign
1150                cod = cod
1151                h = h
1152                y = y
1153                sign = sign )
1154        MODIFYING(nothing)
1155        RETURNING(indx)
1156 
1157     ------------------------------------------------------------------------------
1158      RESOURCES USED [optional]
1159 
1160      When the code is written for a specific target processor the
1161      the resources used should be documented below.
1162 
1163      HEAP MEMORY USED: x bytes
1164 
1165      STACK MEMORY USED: x bytes
1166 
1167      CLOCK CYCLES: (cycle count equation for this function) + (variable
1168                     used to represent cycle count for each subroutine
1169                     called)
1170          where: (cycle count variable) = cycle count for [subroutine
1171                                          name]
1172 
1173     ------------------------------------------------------------------------------
1174      CAUTION [optional]
1175      [State any special notes, constraints or cautions for users of this function]
1176 
1177     ------------------------------------------------------------------------------
1178     */
1179 
Test_build_code(Word16 subNr,Word16 codvec[],Word16 dn_sign[],Word16 cod[],Word16 h[],Word16 y[],Word16 sign[],Flag * pOverflow)1180     Word16 Test_build_code(
1181         Word16 subNr,      /* i : subframe number                            */
1182         Word16 codvec[],   /* i : position of pulses                         */
1183         Word16 dn_sign[],  /* i : sign of pulses                             */
1184         Word16 cod[],      /* o : innovative code vector                     */
1185         Word16 h[],        /* i : impulse response of weighted synthesis     */
1186         /*     filter                                     */
1187         Word16 y[],        /* o : filtered innovative code                   */
1188         Word16 sign[],     /* o : sign of 2 pulses                           */
1189         Flag   * pOverflow /* o : Flag set when overflow occurs              */
1190     )
1191     {
1192         Word16  test_index;
1193 
1194         /*----------------------------------------------------------------------------
1195          CALL build_code ( subNr = subNr
1196                    codvec = codvec
1197                    dn_sign = dn_sign
1198                    cod = cod
1199                    h = h
1200                    y = y
1201                    sign = sign )
1202            MODIFYING(nothing)
1203            RETURNING(indx)
1204         ----------------------------------------------------------------------------*/
1205         test_index =
1206             build_code(
1207                 subNr,
1208                 codvec,
1209                 dn_sign,
1210                 cod,
1211                 h,
1212                 y,
1213                 sign,
1214                 pOverflow);
1215 
1216         return(test_index);
1217     }
1218 
1219 #ifdef __cplusplus
1220 }
1221 #endif
1222