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