# HG changeset patch # User Mychaela Falconia # Date 1716579854 0 # Node ID 0565aaa84b17cdad1f1e40b8a99591e12eef2fcb # Parent 85662304252e2917c7f6261e175ea3ee9d1ac2b8 trau-decode: implement trau-extr program diff -r 85662304252e -r 0565aaa84b17 .hgignore --- a/.hgignore Fri May 24 18:59:04 2024 +0000 +++ b/.hgignore Fri May 24 19:44:14 2024 +0000 @@ -2,6 +2,7 @@ \.[oa]$ +^trau-decode/trau-extr$ ^trau-decode/trau-parse$ ^trau-files/.*\.dump$ diff -r 85662304252e -r 0565aaa84b17 trau-decode/Makefile --- a/trau-decode/Makefile Fri May 24 18:59:04 2024 +0000 +++ b/trau-decode/Makefile Fri May 24 19:44:14 2024 +0000 @@ -1,9 +1,12 @@ CC= gcc CFLAGS= -O2 -PROGS= trau-parse +PROGS= trau-extr trau-parse all: ${PROGS} +trau-extr: extr-fr.o extr-efr.o extr-main.o + ${CC} ${CFLAGS} -o $@ $^ -lgsmfr2 + trau-parse: crc8gen.o parse-fr.o parse-efr.o parse-main.o ${CC} ${CFLAGS} -o $@ $^ -lgsmfr2 -lgsmefr diff -r 85662304252e -r 0565aaa84b17 trau-decode/extr-efr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/extr-efr.c Fri May 24 19:44:14 2024 +0000 @@ -0,0 +1,53 @@ +/* + * This module implements the EFR decoding part of trau-extr. + */ + +#include +#include +#include +#include +#include +#include +#include "osmo_bits.h" + +static void +dbits_to_frame(d_bits, frame) + ubit_t *d_bits; + uint8_t *frame; +{ + ubit_t intermed[248], *ip; + uint8_t *op, mask; + unsigned nb; + + intermed[0] = 1; + intermed[1] = 1; + intermed[2] = 0; + intermed[3] = 0; + bcopy(d_bits + 1, intermed + 4, 38); + bcopy(d_bits + 42, intermed + 42, 53); + bcopy(d_bits + 98, intermed + 95, 50); + bcopy(d_bits + 151, intermed + 145, 53); + bcopy(d_bits + 207, intermed + 198, 50); + ip = intermed; + op = frame; + for (nb = 0; nb < EFR_RTP_FRAME_LEN; nb++) { + *op = 0; + for (mask = 0x80; mask; mask >>= 1) { + if (*ip) + *op |= mask; + ip++; + } + op++; + } +} + +void +convert_efr_frame(d_bits, outf) + ubit_t *d_bits; + FILE *outf; +{ + uint8_t frame[EFR_RTP_FRAME_LEN]; + + dbits_to_frame(d_bits, frame); + fwrite(frame, 1, EFR_RTP_FRAME_LEN, outf); +} diff -r 85662304252e -r 0565aaa84b17 trau-decode/extr-fr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/extr-fr.c Fri May 24 19:44:14 2024 +0000 @@ -0,0 +1,75 @@ +/* + * This module implements the FR decoding part of trau-extr. + */ + +#include +#include +#include +#include +#include +#include + +/* this corresponds to the bit-lengths of the individual codec + * parameters as indicated in Table 1.1 of TS 46.010 */ +static const uint8_t gsm_fr_map[GSMFR_NUM_PARAMS] = { + 6, 6, 5, 5, 4, 4, 3, 3, + 7, 2, 2, 6, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 7, 2, 2, 6, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 7, 2, 2, 6, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 7, 2, 2, 6, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3 +}; + +static unsigned +get_le(bits, nbits) + uint8_t *bits; + unsigned nbits; +{ + unsigned accum, mask; + unsigned n; + + accum = 0; + mask = 1; + for (n = 0; n < nbits; n++) { + if (*bits) + accum |= mask; + bits++; + mask <<= 1; + } + return accum; +} + +static void +dbits_to_params(d_bits, params) + uint8_t *d_bits; + int16_t *params; +{ + unsigned np, len; + uint8_t *ip; + int16_t *op; + + ip = d_bits; + op = params; + for (np = 0; np < GSMFR_NUM_PARAMS; np++) { + len = gsm_fr_map[np]; + *op++ = get_le(ip, len); + ip += len; + } +} + +void +convert_fr_frame(d_bits, outf) + uint8_t *d_bits; + FILE *outf; +{ + int16_t params[GSMFR_NUM_PARAMS]; + uint8_t rtp_pack[GSMFR_RTP_FRAME_LEN]; + + dbits_to_params(d_bits, params); + gsmfr_pack_from_array(params, rtp_pack); + fwrite(rtp_pack, 1, GSMFR_RTP_FRAME_LEN, outf); +} diff -r 85662304252e -r 0565aaa84b17 trau-decode/extr-main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/extr-main.c Fri May 24 19:44:14 2024 +0000 @@ -0,0 +1,166 @@ +/* + * This program reads a 64 kbit/s timeslot recording file with a focus + * on a single sub-timeslot just like trau-parse, but it needs to be + * invoked with a starting and ending offset for the frame-aligned + * portion of interest (found with trau-parse), and it saves (converts) + * the selected stream of TRAU-UL frames to a Themyscira gsmx file. + */ + +#include +#include +#include +#include +#include +#include + +static void +reduce_to_subslot(buf, right_shift) + uint8_t *buf; +{ + unsigned n; + + for (n = 0; n < 160; n++) { + buf[n] >>= right_shift; + buf[n] &= 3; + } +} + +static void +unpack_dibits(dibits, frame_bits) + uint8_t *dibits, *frame_bits; +{ + int i, inb; + uint8_t *op; + + op = frame_bits; + for (i = 0; i < 160; i++) { + inb = dibits[i]; + if (inb & 2) + *op++ = 1; + else + *op++ = 0; + if (inb & 1) + *op++ = 1; + else + *op++ = 0; + } +} + +static unsigned +bits_to_num(bits, nbits) + uint8_t *bits; + unsigned nbits; +{ + unsigned accum; + unsigned n; + + accum = 0; + for (n = 0; n < nbits; n++) { + accum <<= 1; + if (*bits) + accum |= 1; + bits++; + } + return accum; +} + +static void +collect_d_bits(frame_bits, d_bits) + uint8_t *frame_bits, *d_bits; +{ + bcopy(frame_bits + 33, d_bits, 15); + bcopy(frame_bits + 49, d_bits + 15, 15); + bcopy(frame_bits + 65, d_bits + 30, 15); + bcopy(frame_bits + 81, d_bits + 45, 15); + bcopy(frame_bits + 97, d_bits + 60, 15); + bcopy(frame_bits + 113, d_bits + 75, 15); + bcopy(frame_bits + 129, d_bits + 90, 15); + bcopy(frame_bits + 145, d_bits + 105, 15); + bcopy(frame_bits + 161, d_bits + 120, 15); + bcopy(frame_bits + 177, d_bits + 135, 15); + bcopy(frame_bits + 193, d_bits + 150, 15); + bcopy(frame_bits + 209, d_bits + 165, 15); + bcopy(frame_bits + 225, d_bits + 180, 15); + bcopy(frame_bits + 241, d_bits + 195, 15); + bcopy(frame_bits + 257, d_bits + 210, 15); + bcopy(frame_bits + 273, d_bits + 225, 15); + bcopy(frame_bits + 289, d_bits + 240, 15); + bcopy(frame_bits + 305, d_bits + 255, 5); +} + +static void +process_frame(cur_offset, dibits, outf) + u_long cur_offset; + uint8_t *dibits; + FILE *outf; +{ + uint8_t frame_bits[320], d_bits[260]; + unsigned c1_5; + + unpack_dibits(dibits, frame_bits); + if (frame_bits[28]) { /* C12 aka BFI */ + putc(0xBF, outf); + putc(frame_bits[31], outf); /* C15 aka TAF */ + return; + } + collect_d_bits(frame_bits, d_bits); + c1_5 = bits_to_num(frame_bits + 17, 5); + switch (c1_5) { + case 0x02: + convert_fr_frame(d_bits, outf); + break; + case 0x1A: + convert_efr_frame(d_bits, outf); + break; + default: + fprintf(stderr, + "error: unknown frame type 0x%x at file offset 0x%lx\n", + c1_5, cur_offset); + exit(1); + } +} + +main(argc, argv) + char **argv; +{ + FILE *inf, *outf; + int subslot, right_shift; + u_long start_offset, end_offset, cur_offset; + uint8_t readbuf[160]; + int cc; + + if (argc != 6) { + fprintf(stderr, "usage: %s binfile subslot start end outfile\n", + argv[0]); + exit(1); + } + inf = fopen(argv[1], "r"); + if (!inf) { + perror(argv[1]); + exit(1); + } + subslot = atoi(argv[2]); + if (subslot < 0 || subslot > 3) { + fprintf(stderr, "error: invalid subslot argument\n"); + exit(1); + } + right_shift = (3 - subslot) * 2; + start_offset = strtoul(argv[3], 0, 0); + fseek(inf, start_offset, SEEK_SET); + end_offset = strtoul(argv[4], 0, 0); + outf = fopen(argv[5], "w"); + if (!outf) { + perror(argv[5]); + exit(1); + } + for (cur_offset = start_offset; ; cur_offset += 160) { + if (end_offset && cur_offset >= end_offset) + break; + cc = fread(readbuf, 1, 160, inf); + if (cc < 160) + break; + reduce_to_subslot(readbuf, right_shift); + process_frame(cur_offset, readbuf, outf); + } + exit(0); +}