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