FreeCalypso > hg > gsm-net-reveng
view trau-ul-compile/trau-ul-compile.c @ 60:eeb28c9c633a
d144: generate A-TRAU dump from Nokia TCSM2 capture
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 25 Sep 2024 17:55:08 +0000 |
parents | 8e9bbb83bd16 |
children |
line wrap: on
line source
/* * This program compile *.tsrc source format into *.tul binary format, * see ../doc/TRAU-UL-testing article. */ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <tw_gsmfr.h> #include <gsm_efr.h> #define MAX_FIELDS 18 static char *infname, *outfname; static FILE *inf, *outf; static int lineno; static char linebuf[256]; static char *fields[MAX_FIELDS]; static unsigned nfields; static int is_efr; static int16_t speech_params[GSMFR_NUM_PARAMS]; static int global_params_set, subframe_count; static int bfi, bfi_set, sid, sid_set; static uint8_t crc_inv, crc_inv_set; static int get_line() { char *cp; if (!fgets(linebuf, sizeof linebuf, inf)) return 1; lineno++; if (!index(linebuf, '\n')) { fprintf(stderr, "%s line %d: too long or missing newline\n", infname, lineno); exit(1); } nfields = 0; for (cp = linebuf; ; ) { while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') break; if (nfields >= MAX_FIELDS) { fprintf(stderr, "%s line %d: too many fields\n", infname, lineno); exit(1); } fields[nfields++] = cp; while (*cp && !isspace(*cp)) cp++; if (*cp) *cp++ = '\0'; } return 0; } static int get_line_nonempty() { int rc; for (;;) { rc = get_line(); if (rc) return rc; if (nfields) return 0; } } static void start_new_frame() { if (nfields != 2 || strcmp(fields[1], "{")) { fprintf(stderr, "%s line %d: invalid frame opening line\n", infname, lineno); exit(1); } global_params_set = 0; subframe_count = 0; bfi = 0; bfi_set = 0; sid_set = 0; crc_inv = 0; crc_inv_set = 0; } static void set_speech_params(start_param) unsigned start_param; { unsigned ni, no; u_long val; char *cp; no = start_param; for (ni = 1; ni < nfields; ni++) { if (!isdigit(fields[ni][0])) { inv_number: fprintf(stderr, "%s line %d: field \"%s\" is not a valid number\n", infname, lineno, fields[ni]); exit(1); } val = strtoul(fields[ni], &cp, 0); if (*cp) goto inv_number; if (val > 0x1FF) { fprintf(stderr, "%s line %d: number \"%s\" is too large for a speech parameter\n", infname, lineno, fields[ni]); exit(1); } speech_params[no++] = val; } } static void handle_larc() { if (is_efr) { fprintf(stderr, "%s line %d: LARc not valid for EFR\n", infname, lineno); exit(1); } if (nfields != 9) { fprintf(stderr, "%s line %d: wrong number of arguments for LARc\n", infname, lineno); exit(1); } if (global_params_set) { fprintf(stderr, "%s line %d: LARc already set\n", infname, lineno); exit(1); } set_speech_params(0); global_params_set = 1; } static void handle_lpc() { if (!is_efr) { fprintf(stderr, "%s line %d: LPC not valid for FR\n", infname, lineno); exit(1); } if (nfields != 6) { fprintf(stderr, "%s line %d: wrong number of arguments for LPC\n", infname, lineno); exit(1); } if (global_params_set) { fprintf(stderr, "%s line %d: LPC already set\n", infname, lineno); exit(1); } set_speech_params(0); global_params_set = 1; } static void handle_sf() { if (is_efr) { if (nfields != 14) { fprintf(stderr, "%s line %d: wrong number of arguments for EFR sf\n", infname, lineno); exit(1); } } else { if (nfields != 18) { fprintf(stderr, "%s line %d: wrong number of arguments for FR sf\n", infname, lineno); exit(1); } } if (subframe_count >= 4) { fprintf(stderr, "%s line %d: too many subframes\n", infname, lineno); exit(1); } if (is_efr) set_speech_params(5 + subframe_count * 13); else set_speech_params(8 + subframe_count * 17); subframe_count++; } static void handle_bfi() { if (nfields != 2) { fprintf(stderr, "%s line %d: BFI takes one argument\n", infname, lineno); exit(1); } if (bfi_set) { fprintf(stderr, "%s line %d: BFI already set\n", infname, lineno); exit(1); } if (fields[1][0] < '0' || fields[1][0] > '1' || fields[1][1]) { fprintf(stderr, "%s line %d: invalid BFI argument \"%s\" (must be 0 or 1)\n", infname, lineno, fields[1]); exit(1); } bfi = fields[1][0] - '0'; bfi_set = 1; } static void handle_sid() { if (nfields != 2) { fprintf(stderr, "%s line %d: SID takes one argument\n", infname, lineno); exit(1); } if (sid_set) { fprintf(stderr, "%s line %d: SID already set\n", infname, lineno); exit(1); } if (fields[1][0] < '0' || fields[1][0] > '2' || fields[1][1]) { fprintf(stderr, "%s line %d: invalid SID argument \"%s\" (must be 0, 1 or 2)\n", infname, lineno, fields[1]); exit(1); } sid = fields[1][0] - '0'; sid_set = 1; } static void handle_crc_inv() { unsigned nf; if (!is_efr) { fprintf(stderr, "%s line %d: crc-inv not valid for FR\n", infname, lineno); exit(1); } if (nfields < 2) { fprintf(stderr, "%s line %d: crc-inv requires at least 1 argument\n", infname, lineno); exit(1); } if (crc_inv_set) { fprintf(stderr, "%s line %d: crc-inv already set\n", infname, lineno); exit(1); } for (nf = 1; nf < nfields; nf++) { if (!strcasecmp(fields[nf], "all")) crc_inv = 0xF8; else if (fields[nf][0] >= '0' && fields[nf][0] <= '4' && !fields[nf][1]) crc_inv |= 0x80 >> (fields[nf][0] - '0'); else { fprintf(stderr, "%s line %d: \"%s\" is not a valid argument to crc-inv\n", infname, lineno, fields[nf]); exit(1); } } crc_inv_set = 1; } static void process_frame_interior() { int rc; for (;;) { rc = get_line_nonempty(); if (rc) { fprintf(stderr, "bad input: EOF inside frame block\n"); exit(1); } if (!strcasecmp(fields[0], "larc")) handle_larc(); else if (!strcasecmp(fields[0], "lpc")) handle_lpc(); else if (!strcasecmp(fields[0], "sf")) handle_sf(); else if (!strcasecmp(fields[0], "bfi")) handle_bfi(); else if (!strcasecmp(fields[0], "sid")) handle_sid(); else if (!strcasecmp(fields[0], "crc-inv")) handle_crc_inv(); else if (!strcmp(fields[0], "}")) { if (nfields != 1) { fprintf(stderr, "%s line %d: stuff after } not permitted\n", infname, lineno); exit(1); } return; } else { fprintf(stderr, "%s line %d: non-understood keyword \"%s\"\n", infname, lineno, fields[0]); exit(1); } } } static void finish_frame() { uint8_t bin[34]; if (!global_params_set) { fprintf(stderr, "%s line %d: LARc/LPC parameters not set\n", infname, lineno); exit(1); } if (subframe_count != 4) { fprintf(stderr, "%s line %d: subframe parameters not set\n", infname, lineno); exit(1); } if (is_efr) { EFR_params2frame(speech_params, bin); if (!sid_set) sid = EFR_sid_classify(bin); bin[31] = crc_inv; bin[32] = 0; } else { gsmfr_pack_from_array(speech_params, bin); if (!sid_set) sid = gsmfr_preproc_sid_classify(bin); } bin[33] = (bfi << 7) | sid; fwrite(bin, 1, 34, outf); } main(argc, argv) char **argv; { int rc; if (argc != 3) { fprintf(stderr, "usage: %s input.tsrc output.tul\n", argv[0]); exit(1); } infname = argv[1]; outfname = argv[2]; inf = fopen(infname, "r"); if (!inf) { perror(infname); exit(1); } outf = fopen(outfname, "w"); if (!outf) { perror(outfname); exit(1); } for (;;) { rc = get_line_nonempty(); if (rc) break; if (!strcasecmp(fields[0], "frame_fr")) { is_efr = 0; start_new_frame(); } else if (!strcasecmp(fields[0], "frame_efr")) { is_efr = 1; start_new_frame(); } else { fprintf(stderr, "%s line %d: expected frame opening line, got something else\n", infname, lineno); exit(1); } process_frame_interior(); finish_frame(); } exit(0); }