FreeCalypso > hg > gsm-codec-lib
view hrutil/dec-craft.c @ 518:087a88d25ba2
new program gsmhr-dec-craft
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 01 Sep 2024 18:58:02 +0000 |
parents | |
children | 6f8abfe253a4 |
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() { /* Int_LPC and Mode */ dec_frame[4] = 1; dec_frame[5] = 3; /* subframe 1 */ dec_frame[6] = 0xFF; dec_frame[7] = 0x1FF; dec_frame[8] = 0x1F; /* subframe 2 */ dec_frame[9] = 0xF; dec_frame[10] = 0x1FF; dec_frame[11] = 0x1F; /* subframe 3 */ dec_frame[12] = 0xF; dec_frame[13] = 0x1FF; dec_frame[14] = 0x1F; /* subframe 4 */ dec_frame[15] = 0xF; dec_frame[16] = 0x1FF; dec_frame[17] = 0x1F; } 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] - '0'; 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_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], "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); }