diff libtwamr/c4_17pf.c @ 322:fc82b113977f

libtwamr: integrate c4_17pf.c
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 18 Apr 2024 19:41:41 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libtwamr/c4_17pf.c	Thu Apr 18 19:41:41 2024 +0000
@@ -0,0 +1,476 @@
+/*
+********************************************************************************
+*
+*      GSM AMR-NB speech codec   R98   Version 7.6.0   December 12, 2001
+*                                R99   Version 3.3.0                
+*                                REL-4 Version 4.1.0                
+*
+********************************************************************************
+*
+*      File             : c4_17pf.c
+*      Purpose          : Searches a 17 bit algebraic codebook containing 4 pulses
+*                         in a frame of 40 samples.
+*
+********************************************************************************
+*/
+
+/*
+********************************************************************************
+*                         MODULE INCLUDE FILE AND VERSION ID
+********************************************************************************
+*/
+#include "namespace.h"
+#include "c4_17pf.h"
+ 
+/*
+********************************************************************************
+*                         INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+#include "basic_op.h"
+#include "no_count.h"
+#include "inv_sqrt.h"
+#include "cnst.h"
+#include "cor_h.h"
+#include "set_sign.h"
+#include "graytab.h"
+
+/*
+********************************************************************************
+*                         LOCAL VARIABLES AND TABLES
+********************************************************************************
+*/
+#define NB_PULSE  4
+
+/*
+********************************************************************************
+*                         DECLARATION OF PROTOTYPES
+********************************************************************************
+*/
+static void search_4i40(
+    Word16 dn[],        /* i : correlation between target and h[]            */
+    Word16 dn2[],       /* i : maximum of corr. in each track.               */
+    Word16 rr[][L_CODE],/* i : matrix of autocorrelation                     */
+    Word16 codvec[]     /* o : algebraic codebook vector                     */
+);
+
+static Word16 build_code(   
+    Word16 codvec[],    /* i : algebraic codebook vector                     */
+    Word16 dn_sign[],   /* i : sign of dn[]                                  */
+    Word16 cod[],       /* o : algebraic (fixed) codebook excitation         */
+    Word16 h[],         /* i : impulse response of weighted synthesis filter */
+    Word16 y[],         /* o : filtered fixed codebook excitation            */
+    Word16 sign[]       /* o : index of 4 pulses (position+sign+ampl)*4      */
+);
+
+
+/*
+********************************************************************************
+*                         PUBLIC PROGRAM CODE
+********************************************************************************
+*/
+/*************************************************************************
+ *
+ *  FUNCTION:  code_4i40_17bits()
+ *
+ *  PURPOSE:  Searches a 17 bit algebraic codebook containing 4 pulses
+ *            in a frame of 40 samples.
+ *
+ *  DESCRIPTION:
+ *    The code length is 40, containing 4 nonzero pulses: i0...i3.
+ *    All pulses can have two possible amplitudes: +1 or -1.
+ *    Pulse i0 to i2 can have 8 possible positions, pulse i3 can have
+ *    2x8=16 positions.
+ *
+ *       i0 :  0, 5, 10, 15, 20, 25, 30, 35.
+ *       i1 :  1, 6, 11, 16, 21, 26, 31, 36.
+ *       i2 :  2, 7, 12, 17, 22, 27, 32, 37.
+ *       i3 :  3, 8, 13, 18, 23, 28, 33, 38.
+ *             4, 9, 14, 19, 24, 29, 34, 39.
+ *
+ *************************************************************************/
+
+Word16 code_4i40_17bits(
+    Word16 x[],         /* i : target vector                                 */
+    Word16 h[],         /* i : impulse response of weighted synthesis filter */
+                        /*     h[-L_subfr..-1] must be set to zero.          */
+    Word16 T0,          /* i : Pitch lag                                     */
+    Word16 pitch_sharp, /* i : Last quantized pitch gain                     */
+    Word16 code[],      /* o : Innovative codebook                           */
+    Word16 y[],         /* o : filtered fixed codebook excitation            */
+    Word16 * sign       /* o : Signs of 4 pulses                             */
+)
+{
+    Word16 codvec[NB_PULSE];
+    Word16 dn[L_CODE], dn2[L_CODE], dn_sign[L_CODE];
+    Word16 rr[L_CODE][L_CODE];
+    Word16 i, index, sharp;
+
+    sharp = shl(pitch_sharp, 1);
+    test ();
+    if (sub(T0, L_CODE) < 0)
+    {
+       for (i = T0; i < L_CODE; i++) {
+          h[i] = add(h[i], mult(h[i - T0], sharp));   move16 ();
+       }
+    }
+    
+    cor_h_x(h, x, dn, 1);
+    set_sign(dn, dn_sign, dn2, 4);
+    cor_h(h, dn_sign, rr);
+    search_4i40(dn, dn2, rr, codvec);
+                                    move16 (); /* function result */
+    index = build_code(codvec, dn_sign, code, h, y, sign);
+
+  /*-----------------------------------------------------------------*
+  * Compute innovation vector gain.                                 *
+  * Include fixed-gain pitch contribution into code[].              *
+  *-----------------------------------------------------------------*/
+
+    test ();
+    if (sub(T0, L_CODE) < 0)
+    {
+       for (i = T0; i < L_CODE; i++) {
+          code[i] = add(code[i], mult(code[i - T0], sharp));  move16 ();
+       }
+    }
+    return index;
+}
+
+/*
+********************************************************************************
+*                         PRIVATE PROGRAM CODE
+********************************************************************************
+*/
+
+/*************************************************************************
+ *
+ *  FUNCTION  search_4i40()
+ *
+ *  PURPOSE: Search the best codevector; determine positions of the 4 pulses
+ *           in the 40-sample frame.
+ *
+ *************************************************************************/
+
+#define _1_2    (Word16)(32768L/2)
+#define _1_4    (Word16)(32768L/4)
+#define _1_8    (Word16)(32768L/8)
+#define _1_16   (Word16)(32768L/16)
+
+static void search_4i40(
+    Word16 dn[],         /* i : correlation between target and h[]  */
+    Word16 dn2[],        /* i : maximum of corr. in each track.     */
+    Word16 rr[][L_CODE], /* i : matrix of autocorrelation           */
+    Word16 codvec[]      /* o : algebraic codebook vector           */
+)
+{
+    Word16 i0, i1, i2, i3;
+    Word16 ix = 0; /* initialization only needed to keep gcc silent */
+    Word16 ps = 0; /* initialization only needed to keep gcc silent */
+    Word16 i, pos, track, ipos[NB_PULSE];
+    Word16 psk, ps0, ps1, sq, sq1;
+    Word16 alpk, alp, alp_16;
+    Word32 s, alp0, alp1;
+    
+    /* Default value */
+    psk = -1;            move16 ();
+    alpk = 1;            move16 ();
+    for (i = 0; i < NB_PULSE; i++)
+    {
+       codvec[i] = i;    move16 ();
+    }
+
+    for (track = 3; track < 5; track++) {
+    /* fix starting position */
+
+       ipos[0] = 0;     move16 ();
+       ipos[1] = 1;     move16 ();
+       ipos[2] = 2;     move16 ();
+       ipos[3] = track; move16 ();
+       
+       /*------------------------------------------------------------------*
+        * main loop: try 4 tracks.                                         *
+        *------------------------------------------------------------------*/
+       
+       for (i = 0; i < NB_PULSE; i++)
+       {
+          /*----------------------------------------------------------------*
+           * i0 loop: try 4 positions (use position with max of corr.).     *
+           *----------------------------------------------------------------*/
+          
+          move16 (); /* account for ptr. init. (rr[io]) */
+          for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP)
+          {
+             test (); move16 ();
+             if (dn2[i0] >= 0)
+             {
+                ps0 = dn[i0];     move16 ();
+                alp0 = L_mult(rr[i0][i0], _1_4);
+                
+                /*----------------------------------------------------------------*
+                 * i1 loop: 8 positions.                                          *
+                 *----------------------------------------------------------------*/
+                
+                sq = -1;          move16 ();
+                alp = 1;          move16 ();
+                ps = 0;           move16 ();
+                ix = ipos[1];     move16 ();
+                    
+                /* initialize 4 index for next loop. */
+                /*-------------------------------------------------------------------*
+                 *  These index have low complexity address computation because      *
+                 *  they are, in fact, pointers with fixed increment.  For example,  *
+                 *  "rr[i0][i3]" is a pointer initialized to "&rr[i0][ipos[3]]"      *
+                 *  and incremented by "STEP".                                       *
+                 *-------------------------------------------------------------------*/
+                
+                move16 (); /* account for ptr. init. (rr[i1]) */
+                move16 (); /* account for ptr. init. (dn[i1]) */
+                move16 (); /* account for ptr. init. (rr[io]) */
+                for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP)
+                {
+                   ps1 = add(ps0, dn[i1]);   /* idx increment = STEP */
+                   
+                   /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */
+                   
+                   alp1 = L_mac(alp0, rr[i1][i1], _1_4); /* idx incr = STEP */
+                   alp1 = L_mac(alp1, rr[i0][i1], _1_2); /* idx incr = STEP */
+                   
+                   sq1 = mult(ps1, ps1);
+                   
+                   alp_16 = round(alp1);
+                   
+                   s = L_msu(L_mult(alp, sq1), sq, alp_16);
+                   
+                   test ();
+                   if (s > 0)
+                   {
+                      sq = sq1;         move16 ();
+                      ps = ps1;         move16 ();
+                      alp = alp_16;     move16 ();
+                      ix = i1;          move16 ();
+                   }
+                }
+                i1 = ix;                  move16 ();
+                
+                /*----------------------------------------------------------------*
+                 * i2 loop: 8 positions.                                          *
+                 *----------------------------------------------------------------*/
+                
+                ps0 = ps;                 move16 ();
+                alp0 = L_mult(alp, _1_4);
+                
+                sq = -1;                  move16 ();
+                alp = 1;                  move16 ();
+                ps = 0;                   move16 ();
+                ix = ipos[2];             move16 ();
+                                    
+                /* initialize 4 index for next loop (see i1 loop) */
+                
+                move16 (); /* account for ptr. init. (rr[i2]) */
+                move16 (); /* account for ptr. init. (rr[i1]) */
+                move16 (); /* account for ptr. init. (dn[i2]) */
+                move16 (); /* account for ptr. init. (rr[io]) */
+                for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP)
+                {
+                   ps1 = add(ps0, dn[i2]); /* index increment = STEP */
+                   
+                   /* alp1 = alp0 + rr[i0][i2] + rr[i1][i2] + 1/2*rr[i2][i2]; */
+                   
+                   alp1 = L_mac(alp0, rr[i2][i2], _1_16); /* idx incr = STEP */
+                   alp1 = L_mac(alp1, rr[i1][i2], _1_8);  /* idx incr = STEP */
+                   alp1 = L_mac(alp1, rr[i0][i2], _1_8);  /* idx incr = STEP */
+                   
+                   sq1 = mult(ps1, ps1);
+                   
+                   alp_16 = round(alp1);
+                   
+                   s = L_msu(L_mult(alp, sq1), sq, alp_16);
+                   
+                   test ();
+                   if (s > 0)
+                   {
+                      sq = sq1;         move16 ();
+                      ps = ps1;         move16 ();
+                      alp = alp_16;     move16 ();
+                      ix = i2;          move16 ();
+                   }
+                }
+                i2 = ix;                  move16 ();
+                
+                /*----------------------------------------------------------------*
+                 * i3 loop: 8 positions.                                          *
+                 *----------------------------------------------------------------*/
+                
+                ps0 = ps;                 move16 ();
+                alp0 = L_deposit_h(alp);
+                
+                sq = -1;                  move16 ();
+                alp = 1;                  move16 ();
+                ps = 0;                   move16 ();
+                ix = ipos[3];             move16 ();
+                                    
+                /* initialize 5 index for next loop (see i1 loop) */
+                
+                move16 (); /* account for ptr. init. (rr[i3]) */
+                move16 (); /* account for ptr. init. (rr[i2]) */
+                move16 (); /* account for ptr. init. (rr[i1]) */
+                move16 (); /* account for ptr. init. (dn[i3]) */
+                move16 (); /* account for ptr. init. (rr[io]) */
+                for (i3 = ipos[3]; i3 < L_CODE; i3 += STEP)
+                {
+                   ps1 = add(ps0, dn[i3]); /* index increment = STEP */
+                   
+                   /* alp1 = alp0 + rr[i0][i3] + rr[i1][i3] + rr[i2][i3] + 1/2*rr[i3][i3]; */
+                   
+                   alp1 = L_mac(alp0, rr[i3][i3], _1_16); /* idx incr = STEP */
+                   alp1 = L_mac(alp1, rr[i2][i3], _1_8);  /* idx incr = STEP */
+                   alp1 = L_mac(alp1, rr[i1][i3], _1_8);  /* idx incr = STEP */
+                   alp1 = L_mac(alp1, rr[i0][i3], _1_8);  /* idx incr = STEP */
+                   
+                   sq1 = mult(ps1, ps1);
+                   
+                   alp_16 = round(alp1);
+                   
+                   s = L_msu(L_mult(alp, sq1), sq, alp_16);
+                   
+                   test ();
+                   if (s > 0)
+                   {
+                      sq = sq1;         move16 ();
+                      ps = ps1;         move16 ();
+                      alp = alp_16;     move16 ();
+                      ix = i3;          move16 ();
+                   }
+                }
+                
+                
+                /*----------------------------------------------------------------*
+                 * memorise codevector if this one is better than the last one.   *
+                 *----------------------------------------------------------------*/
+                
+                s = L_msu(L_mult(alpk, sq), psk, alp);
+                
+                test ();
+                if (s > 0)
+                {
+                   psk = sq;            move16 ();
+                   alpk = alp;          move16 ();
+                   codvec[0] = i0;      move16 ();
+                   codvec[1] = i1;      move16 ();
+                   codvec[2] = i2;      move16 ();
+                   codvec[3] = ix;      move16 ();
+                }
+             }
+          }
+          
+          /*----------------------------------------------------------------*
+           * Cyclic permutation of i0,i1,i2 and i3.                         *
+           *----------------------------------------------------------------*/
+          
+          pos = ipos[3];                   move16 ();
+          ipos[3] = ipos[2];               move16 ();
+          ipos[2] = ipos[1];               move16 ();
+          ipos[1] = ipos[0];               move16 ();
+          ipos[0] = pos;                   move16 ();
+       }
+    }
+    
+    return;
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:  build_code()
+ *
+ *  PURPOSE: Builds the codeword, the filtered codeword and index of the
+ *           codevector, based on the signs and positions of 4 pulses.
+ *
+ *************************************************************************/
+
+static Word16
+build_code(
+    Word16 codvec[],  /* i : position of pulses                            */
+    Word16 dn_sign[], /* i : sign of pulses                                */
+    Word16 cod[],     /* o : innovative code vector                        */
+    Word16 h[],       /* i : impulse response of weighted synthesis filter */
+    Word16 y[],       /* o : filtered innovative code                      */
+    Word16 sign[]     /* o : index of 4 pulses (sign+position)             */
+)
+{
+    Word16 i, j, k, track, index, _sign[NB_PULSE], indx, rsign;
+    Word16 *p0, *p1, *p2, *p3;
+    Word32 s;
+
+    for (i = 0; i < L_CODE; i++)
+    {
+        cod[i] = 0;                         move16 ();
+    }          
+
+    indx = 0;                               move16 ();
+    rsign = 0;                              move16 ();
+    for (k = 0; k < NB_PULSE; k++)
+    {
+       i = codvec[k];            move16 (); /* read pulse position */
+       j = dn_sign[i];           move16 (); /* read sign          */
+       
+       index = mult(i, 6554);    /* index = pos/5 */
+       /* track = pos%5 */
+       track = sub(i, extract_l(L_shr(L_mult(index, 5), 1)));
+       
+       
+       index = gray[index];                 move16 ();
+       
+       test ();
+       if (sub(track, 1) == 0)
+          index = shl(index, 3);
+       else if (sub(track, 2) == 0)
+       {
+          test ();
+          index = shl(index, 6);
+       }
+       else if (sub(track, 3) == 0)
+       {
+          test ();test ();			
+          index = shl(index, 10);
+       }
+       else if (sub(track, 4) == 0)
+       {
+          test ();test ();test ();			
+          track = 3;                        move16 ();
+          index = add(shl(index, 10), 512);
+       }
+       
+       test ();
+       if (j > 0)
+       {
+          cod[i] = 8191;                    move16 ();
+          _sign[k] = 32767;                 move16 ();
+          rsign = add(rsign, shl(1, track));
+       } else {
+          cod[i] = -8192;                   move16 ();
+          _sign[k] = (Word16) - 32768L;     move16 ();
+       }
+       
+       indx = add(indx, index);
+    }
+    *sign = rsign;                          move16 ();
+    
+    p0 = h - codvec[0];                     move16 ();
+    p1 = h - codvec[1];                     move16 ();
+    p2 = h - codvec[2];                     move16 ();
+    p3 = h - codvec[3];                     move16 ();
+    
+    for (i = 0; i < L_CODE; i++)
+    {
+       s = 0;                               move32 ();
+       s = L_mac(s, *p0++, _sign[0]);
+       s = L_mac(s, *p1++, _sign[1]);
+       s = L_mac(s, *p2++, _sign[2]);
+       s = L_mac(s, *p3++, _sign[3]);
+       y[i] = round(s);                     move16 ();
+    }
+    
+    return indx;
+}