FreeCalypso > hg > gsm-codec-lib
changeset 4:286d5f097eb4
libgsmfrp: implement comfort noise generation
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 19 Nov 2022 20:16:09 +0000 |
parents | 3cd5ad24b1d4 |
children | 4812e00bc100 |
files | libgsmfrp/Makefile libgsmfrp/comfort_noise.c libgsmfrp/internal.h libgsmfrp/state.c |
diffstat | 4 files changed, 126 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/libgsmfrp/Makefile Sat Nov 19 09:03:57 2022 +0000 +++ b/libgsmfrp/Makefile Sat Nov 19 20:16:09 2022 +0000 @@ -1,6 +1,6 @@ CC= gcc CFLAGS= -O2 -OBJS= sidclass.o silence_frame.o state.o +OBJS= comfort_noise.o sidclass.o silence_frame.o state.o LIB= libgsmfrp.a all: ${LIB}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgsmfrp/comfort_noise.c Sat Nov 19 20:16:09 2022 +0000 @@ -0,0 +1,112 @@ +/* + * In this module we implement comfort noise generation per GSM 06.12 + * or 3GPP TS 46.012. + */ + +#include <stdint.h> +#include <string.h> +#include "gsm_fr_preproc.h" +#include "internal.h" + +static const uint8_t fold_table_8to6[24] = { + 1, 2, 3, 4, 5, 6, 1, 2, + 1, 2, 3, 4, 5, 6, 3, 4, + 1, 2, 3, 4, 5, 6, 5, 6, +}; + +static const uint8_t bc[4] = {0, 0, 0, 0}; +static const uint8_t Nc[4] = {40, 120, 40, 120}; + +/* pseudonoise() function is based on ETSI EFR code */ + +static uint16_t pseudonoise(struct gsmfr_preproc_state *st, uint16_t no_bits) +{ + uint16_t noise_bits, Sn, i; + + noise_bits = 0; + for (i = 0; i < no_bits; i++) + { + /* State n == 31 */ + if ((st->cn_random_lfsr & 0x00000001L) != 0) + { + Sn = 1; + } + else + { + Sn = 0; + } + + /* State n == 3 */ + if ((st->cn_random_lfsr & 0x10000000L) != 0) + { + Sn = Sn ^ 1; + } + else + { + Sn = Sn ^ 0; + } + + noise_bits = noise_bits << 1; + noise_bits = noise_bits | st->cn_random_lfsr & 1; + + st->cn_random_lfsr >>= 1; + if (Sn & 1) + { + st->cn_random_lfsr |= 0x40000000L; + } + } + + return noise_bits; +} + +static uint8_t random_1to6(struct gsmfr_preproc_state *st) +{ + uint8_t range8, range6; + + range8 = pseudonoise(st, 3); + range6 = fold_table_8to6[(st->cn_random_6fold << 3) | range8]; + st->cn_random_6fold++; + if (st->cn_random_6fold >= 3) + st->cn_random_6fold = 0; + return range6; +} + +void gsmfr_preproc_gen_cn(struct gsmfr_preproc_state *st, gsm_byte *frame) +{ + unsigned sub, pulse; + uint8_t Mc, xmc[13]; + gsm_byte *c; + + /* global bytes (magic and LARc) are fixed */ + memcpy(frame, st->sid_prefix, 5); + c = frame + 5; + /* now do the 4 subframes, mostly PRNG output */ + for (sub = 0; sub < 4; sub++) { + Mc = pseudonoise(st, 2); + for (pulse = 0; pulse < 13; pulse++) + xmc[pulse] = random_1to6(st); + /* packing code from libgsm */ + *c++ = ((Nc[sub] & 0x7F) << 1) + | ((bc[sub] >> 1) & 0x1); + *c++ = ((bc[sub] & 0x1) << 7) + | ((Mc & 0x3) << 5) + | ((st->sid_xmaxc[sub] >> 1) & 0x1F); + *c++ = ((st->sid_xmaxc[sub] & 0x1) << 7) + | ((xmc[0] & 0x7) << 4) + | ((xmc[1] & 0x7) << 1) + | ((xmc[2] >> 2) & 0x1); + *c++ = ((xmc[2] & 0x3) << 6) + | ((xmc[3] & 0x7) << 3) + | (xmc[4] & 0x7); + *c++ = ((xmc[5] & 0x7) << 5) + | ((xmc[6] & 0x7) << 2) + | ((xmc[7] >> 1) & 0x3); + *c++ = ((xmc[7] & 0x1) << 7) + | ((xmc[8] & 0x7) << 4) + | ((xmc[9] & 0x7) << 1) + | ((xmc[10] >> 2) & 0x1); + *c++ = ((xmc[10] & 0x3) << 6) + | ((xmc[11] & 0x7) << 3) + | (xmc[12] & 0x7); + } +}
--- a/libgsmfrp/internal.h Sat Nov 19 09:03:57 2022 +0000 +++ b/libgsmfrp/internal.h Sat Nov 19 20:16:09 2022 +0000 @@ -11,12 +11,19 @@ LOST_SID, }; -typedef unsigned char cparam; - struct gsmfr_preproc_state { enum rx_state rx_state; int got_valid_sid; gsm_frame speech_frame; - cparam cnoise_larc[8]; - cparam cnoise_xmaxc[4]; + gsm_byte sid_prefix[5]; + uint8_t sid_xmaxc[4]; + uint32_t cn_random_lfsr; + unsigned cn_random_6fold; }; + +/* we use the same LFSR PRNG for CN as ETSI EFR implementation */ +#define PN_INITIAL_SEED 0x70816958L /* Pseudo noise generator seed value */ + +/* internal function */ +extern void gsmfr_preproc_gen_cn(struct gsmfr_preproc_state *state, + gsm_byte *frame);
--- a/libgsmfrp/state.c Sat Nov 19 09:03:57 2022 +0000 +++ b/libgsmfrp/state.c Sat Nov 19 20:16:09 2022 +0000 @@ -3,6 +3,7 @@ * of state structures for our GSM FR preprocessor. */ +#include <stdint.h> #include <stdlib.h> #include <string.h> #include "gsm_fr_preproc.h" @@ -21,4 +22,5 @@ void gsmfr_preproc_reset(struct gsmfr_preproc_state *st) { memset(st, 0, sizeof(struct gsmfr_preproc_state)); + st->cn_random_lfsr = PN_INITIAL_SEED; }