view libtwamr/dec_main.c @ 553:ebcf414b7d99

doc/TFO-transform: describe details for FRv1, both modes
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 07 Oct 2024 08:24:24 +0000
parents 357d1faad55d
children
line wrap: on
line source

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