changeset 2:c511bfb36c2a

beginning of EFR2 decoder, using AMR version of AGC module
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 03 Apr 2024 05:47:51 +0000
parents cd1a63963fa4
children e22550b5a224
files .hgignore efr2/Makefile src/agc_amr.c
diffstat 3 files changed, 339 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Apr 03 05:35:21 2024 +0000
+++ b/.hgignore	Wed Apr 03 05:47:51 2024 +0000
@@ -2,6 +2,9 @@
 
 \.[oa]$
 
+^efr2/coder$
+^efr2/decoder$
+
 ^std/coder$
 ^std/decoder$
 ^std/ed_iface$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/efr2/Makefile	Wed Apr 03 05:47:51 2024 +0000
@@ -0,0 +1,92 @@
+#
+#	makefile for GSM Enhanced Full Rate Speech Codec
+#	EFR2 variant, with bits from AMR mixed in
+#
+
+# For GCC compiler
+CC = gcc
+LFLAG = 
+CFLAGS = -Wall -O4 -DWMOPS=0 -DEFR2_VARIANT -fno-builtin
+VPATH = ../src
+
+# Objects
+OBJ =  coder.o cod_12k2.o az_lsp.o autocorr.o convolve.o c1035pf.o basicop2.o \
+       pitch_ol.o pitch_f6.o enc_lag6.o g_pitch.o residu.o count.o weight_a.o \
+       q_gains.o g_code.o pred_lt6.o copy.o levinson.o lag_wind.o prm2bits.o \
+       syn_filt.o int_lpc.o q_plsf_5.o set_zero.o log2.o pow2.o oper_32b.o \
+       lsp_lsf.o reorder.o lsp_az.o inv_sqrt.o inter_6.o pre_proc.o n_proc.o \
+       vad.o dtx.o e_homing.o
+
+DOBJ = decoder.o dec_12k2.o basicop2.o pstfilt2.o pred_lt6.o dec_lag6.o \
+       int_lpc.o count.o weight_a.o agc_amr.o set_zero.o preemph.o residu.o \
+       syn_filt.o copy.o bits2prm.o reorder.o lsp_az.o inv_sqrt.o d_plsf_5.o \
+       d_gains.o d1035pf.o log2.o pow2.o oper_32b.o lsp_lsf.o n_proc.o dtx.o \
+       d_homing.o
+
+# Implicit Rules
+.c.o:
+	$(CC) $(CFLAGS)  -c  $<
+
+all:    coder decoder
+
+# Explicit Rules
+coder:    $(OBJ)
+	$(CC) $(LFLAG) -o coder $(CFLAGS) $(OBJ)
+decoder:  $(DOBJ)
+	$(CC) $(LFLAG) -o decoder $(CFLAGS) $(DOBJ)
+
+# Individual File Dependencies
+agc_amr.o:  typedef.h basic_op.h count.h sig_proc.h cnst.h
+autocorr.o: typedef.h basic_op.h oper_32b.h count.h cnst.h
+az_lsp.o:   typedef.h basic_op.h oper_32b.h count.h cnst.h grid.tab
+basicop2.o: typedef.h basic_op.h count.h
+bits2prm.o: typedef.h basic_op.h count.h
+c1035pf.o:  typedef.h basic_op.h sig_proc.h count.h
+cod_12k2.o: typedef.h basic_op.h sig_proc.h count.h codec.h cnst.h \
+	    window2.tab vad.h dtx.h
+coder.o:    typedef.h basic_op.h sig_proc.h count.h codec.h cnst.h \
+            n_stack.h e_homing.h dtx.h
+convolve.o: typedef.h basic_op.h count.h
+copy.o:     typedef.h basic_op.h count.h
+count.o:    typedef.h count.h
+d1035pf.o:  typedef.h basic_op.h count.h
+d_gains.o:  typedef.h basic_op.h oper_32b.h count.h sig_proc.h gains_tb.h \
+	    cnst.h dtx.h
+d_homing.o: typedef.h cnst.h dtx.h codec.h d_homing.h q_plsf_5.tab
+d_plsf_5.o: typedef.h basic_op.h count.h sig_proc.h q_plsf_5.tab cnst.h dtx.h
+dec_12k2.o: typedef.h basic_op.h sig_proc.h count.h codec.h cnst.h dtx.h
+dec_lag6.o: typedef.h basic_op.h count.h
+decoder.o:  typedef.h n_stack.h basic_op.h sig_proc.h count.h codec.h \
+            cnst.h d_homing.h
+dtx.o:      typedef.h basic_op.h cnst.h sig_proc.h count.h dtx.h
+e_homing.o: typedef.h cnst.h vad.h dtx.h codec.h sig_proc.h e_homing.h
+enc_lag6.o: typedef.h basic_op.h count.h
+g_code.o:   typedef.h basic_op.h count.h cnst.h
+g_pitch.o:  typedef.h basic_op.h oper_32b.h count.h sig_proc.h
+int_lpc.o:  typedef.h basic_op.h count.h sig_proc.h
+inter_6.o:  typedef.h basic_op.h count.h
+inv_sqrt.o: typedef.h basic_op.h count.h inv_sqrt.tab
+lag_wind.o: typedef.h basic_op.h oper_32b.h count.h lag_wind.tab
+levinson.o: typedef.h basic_op.h oper_32b.h count.h
+log2.o:     typedef.h basic_op.h count.h log2.tab
+lsp_az.o:   typedef.h basic_op.h oper_32b.h count.h sig_proc.h
+lsp_lsf.o:  typedef.h basic_op.h count.h lsp_lsf.tab
+n_proc.o:   
+oper_32b.o: typedef.h basic_op.h oper_32b.h count.h
+pitch_f6.o: typedef.h basic_op.h oper_32b.h count.h sig_proc.h codec.h
+pitch_ol.o: typedef.h basic_op.h oper_32b.h count.h sig_proc.h
+pow2.o:     typedef.h basic_op.h count.h pow2.tab
+pre_proc.o: typedef.h basic_op.h oper_32b.h count.h
+pred_lt6.o: typedef.h basic_op.h count.h
+preemph.o:  typedef.h basic_op.h count.h
+prm2bits.o: typedef.h basic_op.h count.h
+pstfilt2.o: typedef.h basic_op.h sig_proc.h count.h codec.h cnst.h
+q_gains.o:  typedef.h basic_op.h oper_32b.h count.h sig_proc.h gains_tb.h \
+	    cnst.h dtx.h
+q_plsf_5.o: typedef.h basic_op.h count.h sig_proc.h cnst.h dtx.h q_plsf_5.tab
+reorder.o:  typedef.h basic_op.h count.h
+residu.o:   typedef.h basic_op.h count.h
+set_zero.o: typedef.h basic_op.h count.h
+syn_filt.o: typedef.h basic_op.h count.h
+vad.o:      typedef.h cnst.h basic_op.h oper_32b.h count.h vad.h
+weight_a.o: typedef.h basic_op.h count.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/agc_amr.c	Wed Apr 03 05:47:51 2024 +0000
@@ -0,0 +1,244 @@
+/*
+*****************************************************************************
+*
+*      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             : agc.c
+*
+*****************************************************************************
+*/
+
+/*
+*****************************************************************************
+*                         MODULE INCLUDE FILE AND VERSION ID
+*****************************************************************************
+*/
+#if 0
+#include "agc.h"
+const char agc_id[] = "@(#)$Id $" agc_h;
+#endif
+
+/*
+*****************************************************************************
+*                         INCLUDE FILES
+*****************************************************************************
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "sig_proc.h"
+#include "cnst.h"
+ 
+Word16 past_gain;               /* initial value of past_gain = 1.0  */
+
+/*
+*****************************************************************************
+*                         LOCAL PROGRAM CODE
+*****************************************************************************
+*/
+
+static Word32 energy_old( /* o : return energy of signal     */
+    Word16 in[],          /* i : input signal (length l_trm) */
+    Word16 l_trm          /* i : signal length               */
+)
+{
+    Word32 s;
+    Word16 i, temp;
+
+    temp = shr (in[0], 2);
+    s = L_mult (temp, temp);
+    
+    for (i = 1; i < l_trm; i++)
+    {
+        temp = shr (in[i], 2);
+        s = L_mac (s, temp, temp);
+    }
+
+    return s;
+}
+
+static Word32 energy_new( /* o : return energy of signal     */
+    Word16 in[],          /* i : input signal (length l_trm) */
+    Word16 l_trm          /* i : signal length               */
+)
+{
+    Word32 s;
+    Word16 i;
+    Flag ov_save;
+
+    ov_save = Overflow; move16 (); /* save overflow flag in case energy_old */
+                                   /* must be called                        */
+    s = L_mult(in[0], in[0]);
+    for (i = 1; i < l_trm; i++)
+    {
+        s = L_mac(s, in[i], in[i]);
+    }
+    
+    /* check for overflow */
+    test (); 
+    if (L_sub (s, MAX_32) == 0L)
+    {
+        Overflow = ov_save; move16 (); /* restore overflow flag */
+        s = energy_old (in, l_trm); move32 (); /* function result */
+    }
+    else
+    {
+       s = L_shr(s, 4);
+    }
+
+    return s;
+}
+/*
+*****************************************************************************
+*                         PUBLIC PROGRAM CODE
+*****************************************************************************
+*/
+ 
+/*
+**************************************************************************
+*
+*  Function    : agc
+*  Purpose     : Scales the postfilter output on a subframe basis
+*
+**************************************************************************
+*/
+void agc (
+    Word16 *sig_in,    /* i   : postfilter input signal  (l_trm) */
+    Word16 *sig_out,   /* i/o : postfilter output signal (l_trm) */
+    Word16 agc_fac,    /* i   : AGC factor                       */
+    Word16 l_trm       /* i   : subframe size                    */
+)
+{
+    Word16 i, exp;
+    Word16 gain_in, gain_out, g0, gain;
+    Word32 s;
+            
+    /* calculate gain_out with exponent */
+    s = energy_new(sig_out, l_trm); move32 (); /* function result */
+        
+    test (); 
+    if (s == 0)
+    {
+        past_gain = 0;          move16 (); 
+        return;
+    }
+    exp = sub (norm_l (s), 1);
+    gain_out = round (L_shl (s, exp));
+
+    /* calculate gain_in with exponent */
+    s = energy_new(sig_in, l_trm);   move32 (); /* function result */
+    
+    test (); 
+    if (s == 0)
+    {
+        g0 = 0;                 move16 (); 
+    }
+    else
+    {
+        i = norm_l (s);
+        gain_in = round (L_shl (s, i));
+        exp = sub (exp, i);
+
+        /*---------------------------------------------------*
+         *  g0 = (1-agc_fac) * sqrt(gain_in/gain_out);       *
+         *---------------------------------------------------*/
+
+        s = L_deposit_l (div_s (gain_out, gain_in));
+        s = L_shl (s, 7);       /* s = gain_out / gain_in */
+        s = L_shr (s, exp);     /* add exponent */
+
+        s = Inv_sqrt (s); move32 (); /* function result */
+        i = round (L_shl (s, 9));
+
+        /* g0 = i * (1-agc_fac) */
+        g0 = mult (i, sub (32767, agc_fac));
+    }
+
+    /* compute gain[n] = agc_fac * gain[n-1]
+                        + (1-agc_fac) * sqrt(gain_in/gain_out) */
+    /* sig_out[n] = gain[n] * sig_out[n]                        */
+
+    gain = past_gain;           move16 (); 
+
+    for (i = 0; i < l_trm; i++)
+    {
+        gain = mult (gain, agc_fac);
+        gain = add (gain, g0);
+        sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], gain), 3));
+                                move16 (); 
+    }
+
+    past_gain = gain;           move16 (); 
+}
+
+/*
+**************************************************************************
+*
+*  Function    : agc2
+*  Purpose     : Scales the excitation on a subframe basis
+*
+**************************************************************************
+*/
+void agc2 (
+ Word16 *sig_in,        /* i   : postfilter input signal  */
+ Word16 *sig_out,       /* i/o : postfilter output signal */
+ Word16 l_trm           /* i   : subframe size            */
+)
+{
+    Word16 i, exp;
+    Word16 gain_in, gain_out, g0;
+    Word32 s;
+    
+    /* calculate gain_out with exponent */
+    s = energy_new(sig_out, l_trm);   move32 (); /* function result */
+        
+    test (); 
+    if (s == 0)
+    {
+        return;
+    }
+    exp = sub (norm_l (s), 1);
+    gain_out = round (L_shl (s, exp));
+
+    /* calculate gain_in with exponent */
+    s = energy_new(sig_in, l_trm);   move32 (); /* function result */
+    
+    test (); 
+    if (s == 0)
+    {
+        g0 = 0;                 move16 (); 
+    }
+    else
+    {
+        i = norm_l (s);
+        gain_in = round (L_shl (s, i));
+        exp = sub (exp, i);
+
+        /*---------------------------------------------------*
+         *  g0 = sqrt(gain_in/gain_out);                     *
+         *---------------------------------------------------*/
+
+        s = L_deposit_l (div_s (gain_out, gain_in));
+        s = L_shl (s, 7);       /* s = gain_out / gain_in */
+        s = L_shr (s, exp);     /* add exponent */
+
+        s = Inv_sqrt (s); move32 (); /* function result */
+        g0 = round (L_shl (s, 9));
+    }
+
+    /* sig_out(n) = gain(n) sig_out(n) */
+
+    for (i = 0; i < l_trm; i++)
+    {
+        sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], g0), 3));
+                                move16 (); 
+    }
+
+    return;
+}