# HG changeset patch # User Mychaela Falconia # Date 1713070128 0 # Node ID 4db5fc10fd1ae4fece4487d55cc711c7ef4edd15 # Parent c94d9a336e8f029547c15be65c713e11c015973b libgsmfr2: implement full decoder diff -r c94d9a336e8f -r 4db5fc10fd1a libgsmfr2/Makefile --- 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 diff -r c94d9a336e8f -r 4db5fc10fd1a libgsmfr2/full_dec.c --- /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 +#include +#include +#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); +}