diff libgsmefr/g_pitch.c @ 53:49dd1ac8e75b

libgsmefr: import most *.c files from ETSI source
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 25 Nov 2022 16:18:21 +0000
parents
children d9229fdac1c7
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/g_pitch.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,128 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  G_pitch
+ *
+ *  PURPOSE:  Compute the pitch (adaptive codebook) gain. Result in Q12
+ *
+ *  DESCRIPTION:
+ *      The adaptive codebook gain is given by
+ *
+ *              g = <x[], y[]> / <y[], y[]>
+ *
+ *      where x[] is the target vector, y[] is the filtered adaptive
+ *      codevector, and <> denotes dot product.
+ *      The gain is limited to the range [0,1.2]
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "sig_proc.h"
+
+Word16 G_pitch (        /* (o)   : Gain of pitch lag saturated to 1.2      */
+    Word16 xn[],        /* (i)   : Pitch target.                           */
+    Word16 y1[],        /* (i)   : Filtered adaptive codebook.             */
+    Word16 L_subfr      /*       : Length of subframe.                     */
+)
+{
+    Word16 i;
+    Word16 xy, yy, exp_xy, exp_yy, gain;
+    Word32 s;
+
+    Word16 scaled_y1[80];       /* Usually dynamic allocation of (L_subfr) */
+
+    /* divide by 2 "y1[]" to avoid overflow */
+
+    for (i = 0; i < L_subfr; i++)
+    {
+        scaled_y1[i] = shr (y1[i], 2); move16 (); 
+    }
+
+    /* Compute scalar product <y1[],y1[]> */
+
+    s = 0L;                            move32 (); /* Avoid case of all zeros */
+    for (i = 0; i < L_subfr; i++)
+    {
+        s = L_mac (s, y1[i], y1[i]);
+    }
+    test (); 
+    if (L_sub (s, MAX_32) != 0L)       /* Test for overflow */
+    {
+        s = L_add (s, 1L);             /* Avoid case of all zeros */
+        exp_yy = norm_l (s);
+        yy = round (L_shl (s, exp_yy));
+    }
+    else
+    {
+        s = 1L;                        move32 (); /* Avoid case of all zeros */
+        for (i = 0; i < L_subfr; i++)
+        {
+            s = L_mac (s, scaled_y1[i], scaled_y1[i]);
+        }
+        exp_yy = norm_l (s);
+        yy = round (L_shl (s, exp_yy));
+        exp_yy = sub (exp_yy, 4);
+    }
+
+    /* Compute scalar product <xn[],y1[]> */
+
+    Overflow = 0;                      move16 (); 
+    s = 1L;                            move32 (); /* Avoid case of all zeros */
+    for (i = 0; i < L_subfr; i++)
+    {
+        Carry = 0;                     move16 ();
+        s = L_macNs (s, xn[i], y1[i]);
+
+        test ();
+        if (Overflow != 0)
+        {
+	    break;
+        }
+    }
+    test (); 
+    if (Overflow == 0)
+    {
+        exp_xy = norm_l (s);
+        xy = round (L_shl (s, exp_xy));
+    }
+    else
+    {
+        s = 1L;                        move32 (); /* Avoid case of all zeros */
+        for (i = 0; i < L_subfr; i++)
+        {
+            s = L_mac (s, xn[i], scaled_y1[i]);
+        }
+        exp_xy = norm_l (s);
+        xy = round (L_shl (s, exp_xy));
+        exp_xy = sub (exp_xy, 2);
+    }
+
+    /* If (xy < 4) gain = 0 */
+
+    i = sub (xy, 4);
+
+    test (); 
+    if (i < 0)
+        return ((Word16) 0);
+
+    /* compute gain = xy/yy */
+
+    xy = shr (xy, 1);                  /* Be sure xy < yy */
+    gain = div_s (xy, yy);
+
+    i = add (exp_xy, 3 - 1);           /* Denormalization of division */
+    i = sub (i, exp_yy);
+
+    gain = shr (gain, i);
+
+    /* if(gain >1.2) gain = 1.2 */
+
+    test (); 
+    if (sub (gain, 4915) > 0)
+    {
+        gain = 4915;                   move16 (); 
+    }
+    return (gain);
+}