FreeCalypso > hg > gsm-codec-lib
view libgsmfr2/pp_bad.c @ 483:4f13db3a7086
doc/Utils-overview: document new utilities
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 20 May 2024 01:26:12 +0000 |
parents | 573afa985df6 |
children | 405a84110997 |
line wrap: on
line source
/* * In this module we implement our handling of BFI frame gaps * and invalid SID frames. */ #include <stdint.h> #include <string.h> #include "tw_gsmfr.h" #include "pp_state.h" #include "pp_internal.h" static int reduce_xmaxc(uint8_t *frame) { int mute_flag = 1; unsigned sub, xmaxc; for (sub = 0; sub < 4; sub++) { xmaxc = ((frame[sub*7+6] & 0x1F) << 1) | (frame[sub*7+7] >> 7); if (xmaxc > 4) { xmaxc -= 4; mute_flag = 0; } else xmaxc = 0; frame[sub*7+6] &= 0xE0; frame[sub*7+6] |= xmaxc >> 1; frame[sub*7+7] &= 0x7F; frame[sub*7+7] |= (xmaxc & 1) << 7; } return mute_flag; } static void random_grid_pos(struct gsmfr_preproc_state *st, uint8_t *frame) { unsigned sub, Mc; for (sub = 0; sub < 4; sub++) { Mc = gsmfr_preproc_prng(st, 2); frame[sub*7+6] &= 0x9F; frame[sub*7+6] |= Mc << 5; } } static int reduce_xmaxc_sid(struct gsmfr_preproc_state *st) { if (st->sid_xmaxc > 4) { st->sid_xmaxc -= 4; return 0; } else { st->sid_xmaxc = 0; return 1; } } void gsmfr_preproc_bfi(struct gsmfr_preproc_state *st, int taf, uint8_t *frame) { int mute; switch (st->rx_state) { case NO_DATA: memcpy(frame, &gsmfr_preproc_silence_frame, GSMFR_RTP_FRAME_LEN); return; case SPEECH: memcpy(frame, &st->speech_frame, GSMFR_RTP_FRAME_LEN); st->rx_state = SPEECH_MUTING; return; case SPEECH_MUTING: mute = reduce_xmaxc(st->speech_frame); memcpy(frame, &st->speech_frame, GSMFR_RTP_FRAME_LEN); random_grid_pos(st, frame); if (mute) st->rx_state = NO_DATA; return; case COMFORT_NOISE: if (taf) st->rx_state = LOST_SID; gsmfr_preproc_gen_cn(st, frame); return; case LOST_SID: if (taf) { st->rx_state = CN_MUTING; reduce_xmaxc_sid(st); } gsmfr_preproc_gen_cn(st, frame); return; case CN_MUTING: if (reduce_xmaxc_sid(st)) { st->rx_state = NO_DATA; memcpy(frame, &gsmfr_preproc_silence_frame, GSMFR_RTP_FRAME_LEN); } else gsmfr_preproc_gen_cn(st, frame); return; } } void gsmfr_preproc_invalid_sid(struct gsmfr_preproc_state *st, uint8_t *frame) { int mute; switch (st->rx_state) { case NO_DATA: memcpy(frame, &gsmfr_preproc_silence_frame, GSMFR_RTP_FRAME_LEN); return; case SPEECH: /* * Make CN out of the last good speech frame, following the * "NOTE" at the end of section 6.1.2 in TS 46.031. */ st->rx_state = COMFORT_NOISE; memcpy(st->sid_prefix, &st->speech_frame, 5); st->sid_xmaxc = gsmfr_preproc_xmaxc_mean(st->speech_frame); gsmfr_preproc_gen_cn(st, frame); return; case SPEECH_MUTING: /* ignore invalid SID in this state and act as if we got BFI */ mute = reduce_xmaxc(st->speech_frame); memcpy(frame, &st->speech_frame, GSMFR_RTP_FRAME_LEN); random_grid_pos(st, frame); if (mute) st->rx_state = NO_DATA; return; case COMFORT_NOISE: case LOST_SID: st->rx_state = COMFORT_NOISE; gsmfr_preproc_gen_cn(st, frame); return; case CN_MUTING: if (reduce_xmaxc_sid(st)) { st->rx_state = NO_DATA; memcpy(frame, &gsmfr_preproc_silence_frame, GSMFR_RTP_FRAME_LEN); } else gsmfr_preproc_gen_cn(st, frame); return; } }