changeset 279:4db5fc10fd1a

libgsmfr2: implement full decoder
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 14 Apr 2024 04:48:48 +0000
parents c94d9a336e8f
children 356d9675701d
files libgsmfr2/Makefile libgsmfr2/full_dec.c
diffstat 2 files changed, 80 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/libgsmfr2/Makefile	Sun Apr 14 04:10:02 2024 +0000
+++ b/libgsmfr2/Makefile	Sun Apr 14 04:48:48 2024 +0000
@@ -1,10 +1,10 @@
 CC=	gcc
 CFLAGS=	-O2
 OBJS=	add.o comfort_noise.o dec_main.o dec_wrap.o dhf.o ed_state.o \
-	enc_homing.o enc_main.o enc_wrap.o long_term.o lpc.o pack_frame.o \
-	pack_frame2.o pp_bad.o pp_good.o pp_state.o preprocess.o prng.o rpe.o \
-	short_term.o sidclass.o silence_frame.o table.o unpack_frame.o \
-	unpack_frame2.o xmaxc_mean.o
+	enc_homing.o enc_main.o enc_wrap.o full_dec.o long_term.o lpc.o \
+	pack_frame.o pack_frame2.o pp_bad.o pp_good.o pp_state.o preprocess.o \
+	prng.o rpe.o short_term.o sidclass.o silence_frame.o table.o \
+	unpack_frame.o unpack_frame2.o xmaxc_mean.o
 HDRS=	ed_internal.h ed_state.h pp_internal.h pp_state.h tw_gsmfr.h typedef.h
 LIB=	libgsmfr2.a
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmfr2/full_dec.c	Sun Apr 14 04:48:48 2024 +0000
@@ -0,0 +1,76 @@
+/*
+ * This module implements the "full decoder" functionality of libgsmfr2:
+ * first the Rx DTX handler, then the regular GSM 06.10 decoder.  This full
+ * decoder also implements the optional homing feature, resetting both
+ * components upon receiving DHF.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tw_gsmfr.h"
+#include "typedef.h"
+#include "ed_state.h"
+#include "pp_state.h"
+
+struct gsmfr_fulldec_state {
+	struct gsmfr_0610_state		dec_0610;
+	struct gsmfr_preproc_state	rx_dtx;
+	int	is_homed;
+};
+
+struct gsmfr_fulldec_state *gsmfr_fulldec_create(void)
+{
+	struct gsmfr_fulldec_state *st;
+
+	st = malloc(sizeof(struct gsmfr_fulldec_state));
+	if (st)
+		gsmfr_fulldec_reset(st);
+	return st;
+}
+
+void gsmfr_fulldec_reset(struct gsmfr_fulldec_state *st)
+{
+	gsmfr_0610_reset(&st->dec_0610);
+	gsmfr_preproc_reset(&st->rx_dtx);
+	st->is_homed = 1;
+}
+
+static void emit_ehf_output(int16_t *pcm_out)
+{
+	unsigned n;
+
+	for (n = 0; n < 160; n++)
+		pcm_out[n] = 0x0008;
+}
+
+void gsmfr_fulldec_good_frame(struct gsmfr_fulldec_state *st,
+			      const uint8_t *frame_in, int16_t *pcm_out)
+{
+	uint8_t frame_mod[GSMFR_RTP_FRAME_LEN];
+
+	if (st->is_homed && !memcmp(frame_in, gsmfr_decoder_homing_frame, 12)) {
+		emit_ehf_output(pcm_out);
+		return;
+	}
+	memcpy(frame_mod, frame_in, GSMFR_RTP_FRAME_LEN);
+	gsmfr_preproc_good_frame(&st->rx_dtx, frame_mod);
+	gsmfr_0610_decode_frame(&st->dec_0610, frame_mod, pcm_out);
+	if (!memcmp(frame_in, gsmfr_decoder_homing_frame, GSMFR_RTP_FRAME_LEN))
+		gsmfr_fulldec_reset(st);
+	else
+		st->is_homed = 0;
+}
+
+void gsmfr_fulldec_bfi(struct gsmfr_fulldec_state *st, int taf,
+			int16_t *pcm_out)
+{
+	uint8_t frame_mod[GSMFR_RTP_FRAME_LEN];
+
+	if (st->is_homed) {
+		memset(pcm_out, 0, sizeof(int16_t) * 160);
+		return;
+	}
+	gsmfr_preproc_bfi(&st->rx_dtx, taf, frame_mod);
+	gsmfr_0610_decode_frame(&st->dec_0610, frame_mod, pcm_out);
+}