FreeCalypso > hg > gsm-codec-lib
diff libgsmfr2/pp_bad.c @ 256:a33edf624061
libgsmfr2: start with API definition and port of libgsmfrp code
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 12 Apr 2024 20:49:53 +0000 |
parents | libgsmfrp/bad_frame.c@6ac547f0b903 |
children | 573afa985df6 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgsmfr2/pp_bad.c Fri Apr 12 20:49:53 2024 +0000 @@ -0,0 +1,137 @@ +/* + * 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_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; + } +}