FreeCalypso > hg > efr-experiments
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; +}