FreeCalypso > hg > gsm-codec-lib
diff libgsmfr2/full_dec.c @ 279:4db5fc10fd1a
libgsmfr2: implement full decoder
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 14 Apr 2024 04:48:48 +0000 |
parents | |
children | f3246d109e2d |
line wrap: on
line diff
--- /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); +}