# HG changeset patch # User Mychaela Falconia # Date 1716538285 0 # Node ID b2ef2c80fef1e1fdccffe7fc058de373c919a5bd # Parent b0dcd48a1c8a57ea18aea182cb8a2a5bb560ebd0 trau-parse: add FR decoding diff -r b0dcd48a1c8a -r b2ef2c80fef1 .hgignore --- a/.hgignore Fri May 24 07:25:11 2024 +0000 +++ b/.hgignore Fri May 24 08:11:25 2024 +0000 @@ -2,4 +2,4 @@ \.[oa]$ -^trau-parse$ +^trau-decode/trau-parse$ diff -r b0dcd48a1c8a -r b2ef2c80fef1 Makefile --- a/Makefile Fri May 24 07:25:11 2024 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -CC= gcc -CFLAGS= -O2 -PROGS= trau-parse - -all: ${PROGS} - -trau-parse: trau-parse.c - ${CC} ${CFLAGS} -o $@ $@.c - -clean: - rm -f *.o ${PROGS} diff -r b0dcd48a1c8a -r b2ef2c80fef1 trau-decode/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/Makefile Fri May 24 08:11:25 2024 +0000 @@ -0,0 +1,11 @@ +CC= gcc +CFLAGS= -O2 +PROGS= trau-parse + +all: ${PROGS} + +trau-parse: parse-fr.o parse-main.o + ${CC} ${CFLAGS} -o $@ $^ -lgsmfr2 + +clean: + rm -f *.o ${PROGS} diff -r b0dcd48a1c8a -r b2ef2c80fef1 trau-decode/parse-fr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/parse-fr.c Fri May 24 08:11:25 2024 +0000 @@ -0,0 +1,89 @@ +/* + * This module implements the FR decoding part of trau-parse. + */ + +#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 +print_fr_frame(d_bits) + uint8_t d_bits; +{ + int16_t params[GSMFR_NUM_PARAMS]; + uint8_t rtp_pack[GSMFR_RTP_FRAME_LEN]; + int i, j, n, sid; + + dbits_to_params(d_bits, params); + fputs(" FR frame:\n ", stdout); + n = 0; + for (i = 0; i < 8; i++) + printf(" %d", params[n++]); + putchar('\n'); + for (i = 0; i < 4; i++) { + fputs(" ", stdout); + for (j = 0; j < 17; j++) + printf(" %d", params[n++]); + putchar('\n'); + } + gsmfr_pack_from_array(params, rtp_pack); + sid = gsmfr_preproc_sid_classify(rtp_pack); + printf(" SID recompute: %d\n", sid); + if (!bcmp(rtp_pack, gsmfr_decoder_homing_frame, GSMFR_RTP_FRAME_LEN)) + puts(" Matches DHF"); +} diff -r b0dcd48a1c8a -r b2ef2c80fef1 trau-decode/parse-main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/parse-main.c Fri May 24 08:11:25 2024 +0000 @@ -0,0 +1,242 @@ +/* + * This program reads a 64 kbit/s timeslot recording file, examines one + * of the four 16 kbit/s subslots (selected), looks for GSM 08.60 TRAU + * frames, and dumps whatever it finds. + */ + +#include +#include +#include +#include +#include + +static unsigned file_offset; + +static enum { + HUNT_FOR_0, + HUNT_FOUND_0, + GOT_8_ZEROS, + SYNCED +} state; +static unsigned hunt_for_0_count, frame_pos_count; +static uint8_t in_frame_2bit[160], frame_bits[320], d_bits[260]; + +static void +unpack_dibits() +{ + int i, inb; + uint8_t *op; + + op = frame_bits; + for (i = 0; i < 160; i++) { + inb = in_frame_2bit[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() +{ + 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() +{ + unsigned c1_5, c6_11; + + printf("Frame at 0x%x:\n", file_offset - 160); + printf(" C1-C5: %u%u%u%u%u", frame_bits[17], frame_bits[18], + frame_bits[19], frame_bits[20], frame_bits[21]); + c1_5 = bits_to_num(frame_bits + 17, 5); + switch (c1_5) { + case 0x02: + fputs(" (FR UL)", stdout); + break; + case 0x1C: + fputs(" (FR DL)", stdout); + break; + case 0x1A: + fputs(" (EFR)", stdout); + break; + case 0x10: + fputs(" (idle UL)", stdout); + break; + case 0x0E: + fputs(" (idle DL)", stdout); + break; + } + putchar('\n'); + c6_11 = bits_to_num(frame_bits + 22, 6); + printf(" C6-C11: %u\n", c6_11); + printf(" C12=%u C13=%u C14=%u C15=%u\n", frame_bits[28], + frame_bits[29], frame_bits[30], frame_bits[31]); + switch (c1_5) { + case 0x02: + case 0x1C: + collect_d_bits(); + print_fr_frame(d_bits); + break; + } + printf(" C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n", + frame_bits[310], frame_bits[311], frame_bits[312], + frame_bits[313], frame_bits[314], frame_bits[315]); + printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], frame_bits[317], + frame_bits[318], frame_bits[319]); +} + +static int +check_sync_zeros() +{ + int i; + + for (i = 0; i < 16; i++) { + if (frame_bits[i]) + return 0; + } + return 1; +} + +static int +check_sync_ones() +{ + int i; + + for (i = 1; i < 20; i++) { + if (!frame_bits[i*16]) + return 0; + } + return 1; +} + +static void +check_sync() +{ + if (check_sync_zeros() && check_sync_ones()) + return; + printf("Bad frame sync, returning to hunt state\n"); + state = HUNT_FOR_0; +} + +static void +byte_input(inb) +{ + switch (state) { + case HUNT_FOR_0: + if (inb != 0) + return; + state = HUNT_FOUND_0; + hunt_for_0_count = 1; + return; + case HUNT_FOUND_0: + if (inb != 0) { + state = HUNT_FOR_0; + return; + } + hunt_for_0_count++; + if (hunt_for_0_count >= 8) + state = GOT_8_ZEROS; + return; + case GOT_8_ZEROS: + if (inb & 2) { + printf("Found frame sync at file offset 0x%x\n", + file_offset - 8); + bzero(in_frame_2bit, 8); + in_frame_2bit[8] = inb; + frame_pos_count = 9; + state = SYNCED; + return; + } + if (inb != 0) + state = HUNT_FOR_0; + return; + case SYNCED: + in_frame_2bit[frame_pos_count++] = inb; + if (frame_pos_count < 160) + return; + frame_pos_count = 0; + unpack_dibits(); + process_frame(); + check_sync(); + return; + default: + fprintf(stderr, "BUG: bad sync state\n"); + abort(); + } +} + +main(argc, argv) + char **argv; +{ + FILE *inf; + int subslot, right_shift; + int inb; + + if (argc != 3) { + fprintf(stderr, "usage: %s binfile subslot\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; + state = HUNT_FOR_0; + for (file_offset = 0; ; file_offset++) { + inb = getc(inf); + if (inb < 0) + break; + inb >>= right_shift; + inb &= 3; + byte_input(inb); + } + exit(0); +} diff -r b0dcd48a1c8a -r b2ef2c80fef1 trau-parse.c --- a/trau-parse.c Fri May 24 07:25:11 2024 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -/* - * This program reads a 64 kbit/s timeslot recording file, examines one - * of the four 16 kbit/s subslots (selected), looks for GSM 08.60 TRAU - * frames, and dumps whatever it finds. - */ - -#include -#include -#include -#include -#include - -static unsigned file_offset; - -static enum { - HUNT_FOR_0, - HUNT_FOUND_0, - GOT_8_ZEROS, - SYNCED -} state; -static unsigned hunt_for_0_count, frame_pos_count; -static uint8_t in_frame_2bit[160], frame_bits[320]; - -static void -unpack_dibits() -{ - int i, inb; - uint8_t *op; - - op = frame_bits; - for (i = 0; i < 160; i++) { - inb = in_frame_2bit[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 -process_frame() -{ - unsigned c1_5, c6_11; - - printf("Frame at 0x%x:\n", file_offset - 160); - printf(" C1-C5: %u%u%u%u%u", frame_bits[17], frame_bits[18], - frame_bits[19], frame_bits[20], frame_bits[21]); - c1_5 = bits_to_num(frame_bits + 17, 5); - switch (c1_5) { - case 0x02: - fputs(" (FR UL)", stdout); - break; - case 0x1C: - fputs(" (FR DL)", stdout); - break; - case 0x1A: - fputs(" (EFR)", stdout); - break; - case 0x10: - fputs(" (idle UL)", stdout); - break; - case 0x0E: - fputs(" (idle DL)", stdout); - break; - } - putchar('\n'); - c6_11 = bits_to_num(frame_bits + 22, 6); - printf(" C6-C11: %u\n", c6_11); - printf(" C12=%u C13=%u C14=%u C15=%u\n", frame_bits[28], - frame_bits[29], frame_bits[30], frame_bits[31]); - /* payload to be handled */ - printf(" C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n", - frame_bits[310], frame_bits[311], frame_bits[312], - frame_bits[313], frame_bits[314], frame_bits[315]); - printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], frame_bits[317], - frame_bits[318], frame_bits[319]); -} - -static int -check_sync_zeros() -{ - int i; - - for (i = 0; i < 16; i++) { - if (frame_bits[i]) - return 0; - } - return 1; -} - -static int -check_sync_ones() -{ - int i; - - for (i = 1; i < 20; i++) { - if (!frame_bits[i*16]) - return 0; - } - return 1; -} - -static void -check_sync() -{ - if (check_sync_zeros() && check_sync_ones()) - return; - printf("Bad frame sync, returning to hunt state\n"); - state = HUNT_FOR_0; -} - -static void -byte_input(inb) -{ - switch (state) { - case HUNT_FOR_0: - if (inb != 0) - return; - state = HUNT_FOUND_0; - hunt_for_0_count = 1; - return; - case HUNT_FOUND_0: - if (inb != 0) { - state = HUNT_FOR_0; - return; - } - hunt_for_0_count++; - if (hunt_for_0_count >= 8) - state = GOT_8_ZEROS; - return; - case GOT_8_ZEROS: - if (inb & 2) { - printf("Found frame sync at file offset 0x%x\n", - file_offset - 8); - bzero(in_frame_2bit, 8); - in_frame_2bit[8] = inb; - frame_pos_count = 9; - state = SYNCED; - return; - } - if (inb != 0) - state = HUNT_FOR_0; - return; - case SYNCED: - in_frame_2bit[frame_pos_count++] = inb; - if (frame_pos_count < 160) - return; - frame_pos_count = 0; - unpack_dibits(); - process_frame(); - check_sync(); - return; - default: - fprintf(stderr, "BUG: bad sync state\n"); - abort(); - } -} - -main(argc, argv) - char **argv; -{ - FILE *inf; - int subslot, right_shift; - int inb; - - if (argc != 3) { - fprintf(stderr, "usage: %s binfile subslot\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; - state = HUNT_FOR_0; - for (file_offset = 0; ; file_offset++) { - inb = getc(inf); - if (inb < 0) - break; - inb >>= right_shift; - inb &= 3; - byte_input(inb); - } - exit(0); -}