changeset 427:357d1faad55d

libtwamr: implement decoder top level
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 07 May 2024 21:45:47 +0000
parents 7bef001cd8b8
children ffd87f972f86
files libtwamr/Makefile libtwamr/dec_main.c
diffstat 2 files changed, 95 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/libtwamr/Makefile	Tue May 07 20:33:01 2024 +0000
+++ b/libtwamr/Makefile	Tue May 07 21:45:47 2024 +0000
@@ -5,19 +5,19 @@
 	c8_31pf.o c_g_aver.o calc_cor.o calc_en.o cbsearch.o cl_ltp.o cod_amr.o\
 	convolve.o cor_h.o d1035pf.o d2_11pf.o d2_9pf.o d3_14pf.o d4_17pf.o \
 	d8_31pf.o d_gain_c.o d_gain_p.o d_plsf.o d_plsf_3.o d_plsf_5.o \
-	dec_amr.o dec_gain.o dec_lag3.o dec_lag6.o dhf_check.o dhf_tables.o \
-	dtx_dec.o dtx_enc.o e_homing.o ec_gains.o enc_lag3.o enc_lag6.o \
-	enc_main.o ex_ctrl.o g_adapt.o g_code.o g_pitch.o gain_q.o gains_tab.o \
-	gc_pred.o gmed_n.o graytab.o hp_max.o int_lpc.o int_lsf.o inter_36.o \
-	inv_sqrt.o lag_wind.o levinson.o lflg_upd.o log2.o lpc.o lsfwt.o lsp.o \
-	lsp_avg.o lsp_az.o lsp_lsf.o lsp_tab.o mac_32.o ol_ltp.o oper_32b.o \
-	p_ol_wgh.o ph_disp.o pitch_fr.o pitch_ol.o post_pro.o pow2.o pre_big.o \
-	pre_proc.o pred_lt.o preemph.o prm2bits.o prmno.o pstfilt.o q_gain_c.o \
-	q_gain_p.o q_plsf.o q_plsf3_tab.o q_plsf5_tab.o q_plsf_3.o q_plsf_5.o \
-	qgain475.o qgain795.o qua_gain.o qua_gain_tab.o r_fft.o reorder.o \
-	residu.o s10_8pf.o set_sign.o sid_sync.o spreproc.o spstproc.o sqrt_l.o\
-	syn_filt.o tls_flags.o ton_stab.o tseq_out.o vad1.o vad2.o vad_reset.o \
-	weight_a.o window.o
+	dec_amr.o dec_gain.o dec_lag3.o dec_lag6.o dec_main.o dhf_check.o \
+	dhf_tables.o dtx_dec.o dtx_enc.o e_homing.o ec_gains.o enc_lag3.o \
+	enc_lag6.o enc_main.o ex_ctrl.o g_adapt.o g_code.o g_pitch.o gain_q.o \
+	gains_tab.o gc_pred.o gmed_n.o graytab.o hp_max.o int_lpc.o int_lsf.o \
+	inter_36.o inv_sqrt.o lag_wind.o levinson.o lflg_upd.o log2.o lpc.o \
+	lsfwt.o lsp.o lsp_avg.o lsp_az.o lsp_lsf.o lsp_tab.o mac_32.o ol_ltp.o \
+	oper_32b.o p_ol_wgh.o ph_disp.o pitch_fr.o pitch_ol.o post_pro.o pow2.o\
+	pre_big.o pre_proc.o pred_lt.o preemph.o prm2bits.o prmno.o pstfilt.o \
+	q_gain_c.o q_gain_p.o q_plsf.o q_plsf3_tab.o q_plsf5_tab.o q_plsf_3.o \
+	q_plsf_5.o qgain475.o qgain795.o qua_gain.o qua_gain_tab.o r_fft.o \
+	reorder.o residu.o s10_8pf.o set_sign.o sid_sync.o spreproc.o \
+	spstproc.o sqrt_l.o syn_filt.o tls_flags.o ton_stab.o tseq_out.o vad1.o\
+	vad2.o vad_reset.o weight_a.o window.o
 HDRS=	a_refl.h agc.h autocorr.h az_lsp.h b_cn_cod.h basic_op.h bgnscd.h \
 	bitno.h bits2prm.h c1035pf.h c2_11pf.h c2_9pf.h c3_14pf.h c4_17pf.h \
 	c8_31pf.h c_g_aver.h calc_cor.h calc_en.h cbsearch.h cl_ltp.h cnst.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libtwamr/dec_main.c	Tue May 07 21:45:47 2024 +0000
@@ -0,0 +1,82 @@
+/*
+ * This C module is the top level entity for our stateful decoder engine.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tw_amr.h"
+#include "namespace.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "dec_amr.h"
+#include "pstfilt.h"
+#include "post_pro.h"
+#include "bitno.h"
+
+struct amr_decoder_state {
+	Decoder_amrState	dec;
+	Post_FilterState	pstfilt;
+	Post_ProcessState	posthp;
+	enum Mode		prev_mode;
+	Flag			is_homed;
+};
+
+struct amr_decoder_state *amr_decoder_create(void)
+{
+	struct amr_decoder_state *st;
+
+	st = malloc(sizeof(struct amr_decoder_state));
+	if (st)
+		amr_decoder_reset(st);
+	return st;
+}
+
+void amr_decoder_reset(struct amr_decoder_state *st)
+{
+	Decoder_amr_reset(&st->dec, 0);
+	Post_Filter_reset(&st->pstfilt);
+	Post_Process_reset(&st->posthp);
+	st->prev_mode = (enum Mode) 0;
+	st->is_homed = 1;
+}
+
+void amr_decode_frame(struct amr_decoder_state *st,
+			const struct amr_param_frame *frame, int16_t *pcm)
+{
+	enum Mode mode;
+	Word16 parm[MAX_PRM_SIZE];
+	Word16 Az_dec[AZ_SIZE];
+	Word16 i;
+
+	/* fast home state handling needs to be first */
+	if (st->is_homed && amr_check_dhf(frame, 1)) {
+		for (i = 0; i < L_FRAME; i++)
+			pcm[i] = EHF_MASK;
+		return;
+	}
+	/* "unpack" into internal form */
+	if (frame->type == RX_NO_DATA)
+		mode = st->prev_mode;
+	else {
+		mode = frame->mode & 7;
+		st->prev_mode = mode;
+	}
+	memcpy(parm, frame->param, prmno[mode] * sizeof(int16_t));
+	/* now we can call the guts of the decoder */
+	Decoder_amr(&st->dec, mode, parm, frame->type, pcm, Az_dec);
+	Post_Filter(&st->pstfilt, mode, pcm, Az_dec);
+	Post_Process(&st->posthp, pcm, L_FRAME);
+	/*
+	 * The 3 lsbs of each speech sample typically won't be all 0
+	 * out of Post_Process(), hence we have to clear them explicitly
+	 * to maintain overall bit-exact operation.
+	 */
+	for (i = 0; i < L_FRAME; i++)
+		pcm[i] &= 0xFFF8;
+	/* final check for full DHF */
+	if (amr_check_dhf(frame, 0))
+		amr_decoder_reset(st);
+	else
+		st->is_homed = 0;
+}