view libgsmfr2/full_dec.c @ 477:4c9222d95647

libtwamr encoder: always emit frame->mode = mode; In the original implementation of amr_encode_frame(), the 'mode' member of the output struct was set to 0xFF if the output frame type is TX_NO_DATA. This design was made to mimic the mode field (16-bit word) being set to 0xFFFF (or -1) in 3GPP test sequence format - but nothing actually depends on this struct member being set in any way, and amr_frame_to_tseq() generates the needed 0xFFFF on its own, based on frame->type being equal to TX_NO_DATA. It is simpler and more efficient to always set frame->mode to the actual encoding mode in amr_encode_frame(), and this new behavior has already been documented in doc/AMR-library-API description in anticipation of the present change.
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 18 May 2024 22:30:42 +0000
parents 4db5fc10fd1a
children f3246d109e2d
line wrap: on
line source

/*
 * 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);
}