FreeCalypso > hg > freecalypso-tools
diff tchtools/fc-tch2fr.c @ 902:8ddb16a37273
tree org: move TCH and VM utils from miscutil to tchtools
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 28 Dec 2022 07:52:30 +0000 |
parents | miscutil/fc-tch2fr.c@d57f68d0568d |
children | a7ad6b39e01b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tchtools/fc-tch2fr.c Wed Dec 28 07:52:30 2022 +0000 @@ -0,0 +1,94 @@ +/* + * Our experimental Calypso firmware enables us to capture the output of + * the GSM 05.03 channel decoder in the DSP, i.e., the bits leaving the + * channel decoder and going into the speech decoder. Our fc-shell utility + * allows saving this capture to a file; the captured booty includes not only + * the expected 260 bits per frame, but also some DSP status words which are + * not fully understood, but which are believed to contain indications as to + * whether the decoded speech frame is good or bad. + * + * My first naive thought was to save the captured speech frames in libgsm + * format so I could then play them with the 'play' command (SoX package) + * under Linux, but the problem with this naive approach is that the bad frames + * indication is lost, and some of the saved "speech" frames will contain + * utter garbage, resulting in very unkind-on-ears noises if that file is + * then played. I don't know what the proper solution should be; I don't know + * what the commercial cellphone implementations of the GSM 06.10 speech decoder + * (buried in black box DSPs) do when they get bad frames from the channel + * decoder. + * + * The present utility reproduces the naive behaviour of my previous + * implementation of fc-shell's tch record command: it takes hex files written + * by the current implementation of tch record in fc-shell, DISREGARDS the + * DSP status words, and blindly converts each 260-bit frame (good or bad) + * into libgsm format. + */ + +#include <sys/types.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> + +static +decode_hex_digit(ch) +{ + if (isdigit(ch)) + return(ch - '0'); + else if (isupper(ch)) + return(ch - 'A' + 10); + else + return(ch - 'a' + 10); +} + +main(argc, argv) + char **argv; +{ + FILE *inf, *outf; + char linebuf[128]; + int lineno; + char *cp; + int i, j; + u_char tidsp_bytes[33], libgsm_bytes[33]; + + if (argc != 3) { + fprintf(stderr, "usage: %s infile outfile\n", argv[0]); + exit(1); + } + inf = fopen(argv[1], "r"); + if (!inf) { + perror(argv[1]); + exit(1); + } + outf = fopen(argv[2], "w"); + if (!outf) { + perror(argv[2]); + exit(1); + } + for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) { + /* skip DSP status words */ + cp = linebuf; + for (i = 0; i < 3; i++) { + for (j = 0; j < 4; j++) { + if (!isxdigit(*cp++)) { +invalid: fprintf(stderr, + "error: %s is not in the expected format\n", + argv[1]); + exit(1); + } + } + if (*cp++ != ' ') + goto invalid; + } + /* read the frame bits */ + for (i = 0; i < 33; i++) { + if (!isxdigit(cp[0]) || !isxdigit(cp[1])) + goto invalid; + tidsp_bytes[i] = (decode_hex_digit(cp[0]) << 4) | + decode_hex_digit(cp[1]); + cp += 2; + } + gsm0610_tidsp_to_libgsm(tidsp_bytes, libgsm_bytes); + fwrite(libgsm_bytes, 1, 33, outf); + } + exit(0); +}