FreeCalypso > hg > gsm-codec-lib
changeset 570:b4c4ed4b1b91
hrutil: new program gsmhr-cod-craft
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 12 Feb 2025 04:53:08 +0000 |
parents | 0d05892150cf |
children | c6d0b1a7281e |
files | .hgignore hrutil/Makefile hrutil/cod-craft.c |
diffstat | 3 files changed, 294 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Wed Feb 12 03:43:57 2025 +0000 +++ b/.hgignore Wed Feb 12 04:53:08 2025 +0000 @@ -77,6 +77,7 @@ ^frtest/gsmfr-preproc$ ^frtest/gsmfr-tfo-xfrm$ +^hrutil/gsmhr-cod-craft$ ^hrutil/gsmhr-cod-parse$ ^hrutil/gsmhr-cod2hex$ ^hrutil/gsmhr-dec-craft$
--- a/hrutil/Makefile Wed Feb 12 03:43:57 2025 +0000 +++ b/hrutil/Makefile Wed Feb 12 04:53:08 2025 +0000 @@ -1,5 +1,6 @@ -PROGS= gsmhr-cod-parse gsmhr-cod2hex gsmhr-dec-craft gsmhr-dec-parse \ - gsmhr-dec2hex gsmhr-hex2dec gsmhr-hex2rpf gsmhr-rpf2hex tw5b-dump +PROGS= gsmhr-cod-craft gsmhr-cod-parse gsmhr-cod2hex gsmhr-dec-craft \ + gsmhr-dec-parse gsmhr-dec2hex gsmhr-hex2dec gsmhr-hex2rpf gsmhr-rpf2hex\ + tw5b-dump LIBHR1= ../libgsmhr1/libgsmhr1.a LIBTEST=../libtest/libtest.a LIBS= ${LIBHR1} ${LIBTEST} @@ -8,6 +9,9 @@ all: ${PROGS} +gsmhr-cod-craft: cod-craft.o ${LIBHR1} + ${CC} ${CFLAGS} -o $@ $^ + gsmhr-cod-parse: cod-parse.o print-frame.o read-cod.o ${LIBS} ${CC} ${CFLAGS} -o $@ $^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hrutil/cod-craft.c Wed Feb 12 04:53:08 2025 +0000 @@ -0,0 +1,287 @@ +/* + * This program facilitates hand-crafting HRv1 encoder output files (*.cod). + * It reads a line-based ASCII source and compiles it into binary *.cod 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 enc_frame[GSMHR_NUM_PARAMS_ENC]; + +static void +set_all_0() +{ + bzero(enc_frame, sizeof(int16_t) * GSMHR_NUM_PARAMS); +} + +static void +set_dhf() +{ + bcopy(gsmhr_dhf_params, enc_frame, sizeof(int16_t) * GSMHR_NUM_PARAMS); +} + +static void +set_sid_cw() +{ + /* Int_LPC and Mode */ + enc_frame[4] = 1; + enc_frame[5] = 3; + /* subframe 1 */ + enc_frame[6] = 0xFF; + enc_frame[7] = 0x1FF; + enc_frame[8] = 0x1F; + /* subframe 2 */ + enc_frame[9] = 0xF; + enc_frame[10] = 0x1FF; + enc_frame[11] = 0x1F; + /* subframe 3 */ + enc_frame[12] = 0xF; + enc_frame[13] = 0x1FF; + enc_frame[14] = 0x1F; + /* subframe 4 */ + enc_frame[15] = 0xF; + enc_frame[16] = 0x1FF; + enc_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); + } + enc_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 +set_vad_sp() +{ + if (nfields != 3) { + fprintf(stderr, "%s line %d: vad-sp takes 2 arguments\n", + infname, lineno); + exit(1); + } + if (fields[1][0] < '0' || fields[1][0] > '1' || fields[1][1]) { + fprintf(stderr, + "%s line %d: invalid VAD argument \"%s\" (must be 0 or 1)\n", + infname, lineno, fields[1]); + exit(1); + } + enc_frame[18] = fields[1][0] - '0'; + if (fields[2][0] < '0' || fields[2][0] > '1' || fields[2][1]) { + fprintf(stderr, + "%s line %d: invalid SP argument \"%s\" (must be 0 or 1)\n", + infname, lineno, fields[2]); + exit(1); + } + enc_frame[19] = fields[2][0] - '0'; + if (enc_frame[18] && !enc_frame[19]) { + fprintf(stderr, + "%s line %d: combination VAD=1 SP=0 is invalid\n", + infname, lineno); + exit(1); + } +} + +static void +emit_frame() +{ + if (gsmhr_check_common_params(enc_frame) < 0) { + fprintf(stderr, + "%s line %d: one of the preceding speech parameters is out of range\n", + infname, lineno); + exit(1); + } + fwrite(enc_frame, 2, GSMHR_NUM_PARAMS_ENC, outf); +} + +main(argc, argv) + char **argv; +{ + int rc; + + if (argc != 3) { + fprintf(stderr, "usage: %s input.src output.cod\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], "sid-cw")) + set_sid_cw(); + else if (!strcasecmp(fields[0], "vad-sp")) + set_vad_sp(); + 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); +}