FreeCalypso > hg > gsm-codec-lib
view hrutil/dec-craft.c @ 585:3c6bf0d26ee7 default tip
TW-TS-005 reader: fix maximum line length bug
TW-TS-005 section 4.1 states:
The maximum allowed length of each line is 80 characters, not
including the OS-specific newline encoding.
The implementation of this line length limit in the TW-TS-005 hex file
reader function in the present suite was wrong, such that lines of
the full maximum length could not be read. Fix it.
Note that this bug affects comment lines too, not just actual RTP
payloads. Neither Annex A nor Annex B features an RTP payload format
that goes to the maximum of 40 bytes, but if a comment line goes to
the maximum allowed length of 80 characters not including the
terminating newline, the bug will be triggered, necessitating
the present fix.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 25 Feb 2025 07:49:28 +0000 |
parents | 94f0cc85ad50 |
children |
line wrap: on
line source
/* * This program facilitates hand-crafting HRv1 decoder input files (*.dec). * It reads a line-based ASCII source and compiles it into binary *.dec format. */ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "../libgsmhr1/tw_gsmhr.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 int16_t dec_frame[GSMHR_NUM_PARAMS_DEC]; static unsigned taf_count; static void set_all_0() { bzero(dec_frame, sizeof(int16_t) * GSMHR_NUM_PARAMS); } static void set_dhf() { bcopy(gsmhr_dhf_params, dec_frame, sizeof(int16_t) * GSMHR_NUM_PARAMS); } static void set_sid_cw() { gsmhr_set_sid_cw_params(dec_frame); } 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 set_speech_params(start_param, start_arg) unsigned start_param, start_arg; { unsigned ni, no; u_long val; char *cp; no = start_param; for (ni = start_arg; ni < nfields; ni++) { if (!isxdigit(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, 16); if (*cp) goto inv_number; if (val > 0x7FF) { fprintf(stderr, "%s line %d: number \"%s\" is too large for a speech parameter\n", infname, lineno, fields[ni]); exit(1); } dec_frame[no++] = val; } } static void handle_r0() { if (nfields != 2) { fprintf(stderr, "%s line %d: R0 takes one argument\n", infname, lineno); exit(1); } set_speech_params(0, 1); } static void handle_lpc() { if (nfields != 5) { fprintf(stderr, "%s line %d: LPC takes 4 arguments\n", infname, lineno); exit(1); } set_speech_params(1, 1); } static void handle_mode() { if (nfields != 2) { fprintf(stderr, "%s line %d: Mode takes one argument\n", infname, lineno); exit(1); } set_speech_params(5, 1); } static void handle_sf() { unsigned sf_0_based; if (nfields != 5) { fprintf(stderr, "%s line %d: sf takes 4 arguments\n", infname, lineno); exit(1); } if (fields[1][0] < '1' || fields[1][0] > '4' || fields[1][1]) { fprintf(stderr, "%s line %d: first argument to sf must be in range [1,4]\n", infname, lineno); exit(1); } sf_0_based = fields[1][0] - '1'; set_speech_params(6 + sf_0_based * 3, 2); } static void handle_bfi() { if (nfields != 2) { fprintf(stderr, "%s line %d: BFI takes one argument\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); } dec_frame[18] = fields[1][0] - '0'; } static void handle_bfi_nodata() { dec_frame[18] = 2; } static void handle_ufi() { if (nfields != 2) { fprintf(stderr, "%s line %d: UFI takes one argument\n", infname, lineno); exit(1); } if (fields[1][0] < '0' || fields[1][0] > '1' || fields[1][1]) { fprintf(stderr, "%s line %d: invalid UFI argument \"%s\" (must be 0 or 1)\n", infname, lineno, fields[1]); exit(1); } dec_frame[19] = fields[1][0] - '0'; } static void handle_sid() { if (nfields != 2) { fprintf(stderr, "%s line %d: SID takes one argument\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); } dec_frame[20] = fields[1][0] - '0'; } static void set_taf_count() { if (nfields != 2) { fprintf(stderr, "%s line %d: taf-count takes one argument\n", infname, lineno); exit(1); } taf_count = atoi(fields[1]); if (taf_count > 11) { fprintf(stderr, "%s line %d: taf-count argument \"%s\" is invalid\n", infname, lineno, fields[1]); exit(1); } } static void emit_frame() { if (gsmhr_check_common_params(dec_frame) < 0) { fprintf(stderr, "%s line %d: one of the preceding speech parameters is out of range\n", infname, lineno); exit(1); } dec_frame[21] = (taf_count == 11); fwrite(dec_frame, 2, GSMHR_NUM_PARAMS_DEC, outf); taf_count++; if (taf_count >= 12) taf_count = 0; } main(argc, argv) char **argv; { int rc; if (argc != 3) { fprintf(stderr, "usage: %s input.src output.dec\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], "all-0")) set_all_0(); else if (!strcasecmp(fields[0], "dhf")) set_dhf(); else if (!strcasecmp(fields[0], "r0")) handle_r0(); else if (!strcasecmp(fields[0], "lpc")) handle_lpc(); else if (!strcasecmp(fields[0], "mode")) handle_mode(); else if (!strcasecmp(fields[0], "sf")) handle_sf(); else if (!strcasecmp(fields[0], "bfi")) handle_bfi(); else if (!strcasecmp(fields[0], "bfi-nodata")) handle_bfi_nodata(); else if (!strcasecmp(fields[0], "ufi")) handle_ufi(); else if (!strcasecmp(fields[0], "sid")) handle_sid(); else if (!strcasecmp(fields[0], "sid-cw")) set_sid_cw(); else if (!strcasecmp(fields[0], "taf-count")) set_taf_count(); else if (!strcasecmp(fields[0], "emit-frame")) emit_frame(); else { fprintf(stderr, "%s line %d: non-understood keyword \"%s\"\n", infname, lineno, fields[0]); exit(1); } } exit(0); }