FreeCalypso > hg > gsm-net-reveng
changeset 114:4ff5c798c75d
trau-decode: new program trau-parse-n8
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Mon, 22 Dec 2025 08:28:44 +0000 |
| parents | 0d81ce87dea5 |
| children | 62b3b916c0a4 |
| files | .hgignore trau-decode/Makefile trau-decode/parse-new8.c |
| diffstat | 3 files changed, 219 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Mon Dec 22 06:59:45 2025 +0000 +++ b/.hgignore Mon Dec 22 08:28:44 2025 +0000 @@ -27,6 +27,7 @@ ^trau-decode/trau-parse$ ^trau-decode/trau-parse-hex$ ^trau-decode/trau-parse-n$ +^trau-decode/trau-parse-n8$ ^trau-decode/trau-sync8$ ^trau-files/.*\.dump$
--- a/trau-decode/Makefile Mon Dec 22 06:59:45 2025 +0000 +++ b/trau-decode/Makefile Mon Dec 22 08:28:44 2025 +0000 @@ -2,7 +2,7 @@ CFLAGS= -O2 PROGS= dump-1bit tfo-parse-fr16 trau-amr8-dump trau-amr8-dump-hex trau-extr \ trau-hr-dump trau-hr-dump-hex trau-parse trau-parse-hex trau-parse-n \ - trau-sync8 + trau-parse-n8 trau-sync8 FR_OBJS=parse-fr.o parse-fr-common.o parse-efr.o HR_OBJS=gsmhr_unpack.o hr-guts.o @@ -41,6 +41,9 @@ trau-parse-n: crc8gen.o parse-new16.o ${TRAU16_OBJS} ${CC} ${CFLAGS} -o $@ $^ -lgsmfr2 -lgsmefr +trau-parse-n8: amr8-common.o crc8gen.o parse-new8.o ${HR_OBJS} + ${CC} ${CFLAGS} -o $@ $^ + trau-sync8: trau-sync8.c ${CC} ${CFLAGS} -o $@ $@.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/parse-new8.c Mon Dec 22 08:28:44 2025 +0000 @@ -0,0 +1,214 @@ +/* + * This program reads a 64 kbit/s timeslot recording file, examines one + * of the eight 8 kbit/s subslots (selected), looks for all possible sync + * patterns (classic HR and TRAU-AMR-8k), and decodes whatever it finds. + */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +static uint8_t *filebuf; +static unsigned total_size; + +static void +read_ts_file(filename, subslot_arg) + char *filename, *subslot_arg; +{ + FILE *inf; + struct stat st; + int subslot, right_shift; + unsigned n; + uint8_t *dp; + int b; + + inf = fopen(filename, "r"); + if (!inf) { + perror(filename); + exit(1); + } + fstat(fileno(inf), &st); + if (!S_ISREG(st.st_mode)) { + fprintf(stderr, "error: %s is not a regular file\n", filename); + exit(1); + } + total_size = st.st_size; + if (total_size < 160) { + fprintf(stderr, "error: %s is too short\n", filename); + exit(1); + } + filebuf = malloc(total_size); + if (!filebuf) { + perror("malloc of file size"); + exit(1); + } + subslot = atoi(subslot_arg); + if (subslot < 0 || subslot > 7) { + fprintf(stderr, "error: invalid subslot argument\n"); + exit(1); + } + right_shift = 7 - subslot; + dp = filebuf; + for (n = 0; n < total_size; n++) { + b = getc(inf); + if (b < 0) { + fprintf(stderr, + "error: getc() returned EOF contrary to st_size\n"); + exit(1); + } + *dp++ = (b >> right_shift) & 1; + } + fclose(inf); +} + +static int +is_classic_hr(cand) + uint8_t *cand; +{ + unsigned n; + + for (n = 0; n < 8; n++) { + if (cand[n]) + return 0; + } + if (!cand[8]) + return 0; + if (cand[16]) + return 0; + if (!cand[17]) + return 0; + for (n = 3; n < 20; n++) { + if (!cand[n * 8]) + return 0; + } + return 1; +} + +static int +check_sync(pos, cont) + unsigned pos; +{ + uint8_t *cand = filebuf + pos; + + if (is_classic_hr(cand)) + return 1; + if (is_amr_low(cand)) + return 1; + if (!cont) + return 0; + if (is_amr_67(cand)) + return 1; + if (is_amr_74(cand)) + return 1; + return 0; +} + +static void +dump_raw_nibbles(bits, num_bits) + uint8_t *bits; + unsigned num_bits; +{ + uint8_t *sp = bits; + unsigned remain = num_bits; + + if (remain >= 4) { + while (remain >= 4) { + printf("%x", (sp[0] << 3) | (sp[1] << 2) | + (sp[2] << 1) | sp[3]); + sp += 4; + remain -= 4; + } + putchar('\n'); + } + if (remain) { + fputs("dribble ", stdout); + while (remain) { + printf("%u", *sp++); + remain--; + } + putchar('\n'); + } +} + +static int +process_frame(pos) + unsigned pos; +{ + uint8_t *frame = filebuf + pos; + + printf("Frame at 0x%x:\n", pos); + dump_raw_nibbles(frame, 160); + if (is_classic_hr(frame)) + return print_gsmhr_frame(frame); + else + return print_amr8_frame(frame); +} + +static void +process_filebuf() +{ + unsigned p, nf_pos = 0, nf_accum = 0; + int match, num_t_bits; + int in_sync = 0; + + for (p = 0; p < total_size; ) { + if ((total_size - p) >= 160) + match = check_sync(p, in_sync); + else + match = 0; + if (match) { + if (nf_accum) { + printf("Non-frame at 0x%x:\n", nf_pos); + dump_raw_nibbles(filebuf + nf_pos, nf_accum); + } + num_t_bits = process_frame(p); + if (num_t_bits == 2 && !filebuf[p+158] && + !filebuf[p+159]) { + puts("advance of 250 us"); + p += 158; + } else if (num_t_bits == 2 && filebuf[p+158] && + !filebuf[p+159]) { + puts("advance of 125 us"); + p += 159; + } else if (num_t_bits == 1 && !filebuf[p+159]) { + puts("advance of 125 us"); + p += 159; + } else + p += 160; + nf_pos = p; + nf_accum = 0; + in_sync = 1; + } else { + p++; + nf_accum++; + if (nf_accum >= 320) { + printf("Non-frame at 0x%x:\n", nf_pos); + dump_raw_nibbles(filebuf + nf_pos, nf_accum); + nf_pos = p; + nf_accum = 0; + } + in_sync = 0; + } + } + if (nf_accum) { + printf("Non-frame at 0x%x:\n", nf_pos); + dump_raw_nibbles(filebuf + nf_pos, nf_accum); + } +} + +main(argc, argv) + char **argv; +{ + if (argc != 3) { + fprintf(stderr, "usage: %s binfile subslot\n", argv[0]); + exit(1); + } + read_ts_file(argv[1], argv[2]); + process_filebuf(); + exit(0); +}
