# HG changeset patch # User Mychaela Falconia # Date 1465872309 0 # Node ID d57f68d0568d7350e83f2dad79b6322602a46ca0 # Parent 7eaa3307e5dfaf7e0472f434b28b6256bc1ccbb4 fc-tch2fr utility written, added under miscutil diff -r 7eaa3307e5df -r d57f68d0568d .hgignore --- a/.hgignore Tue Jun 14 01:40:14 2016 +0000 +++ b/.hgignore Tue Jun 14 02:45:09 2016 +0000 @@ -19,6 +19,7 @@ ^miscutil/fc-fr2tch$ ^miscutil/fc-rgbconv$ ^miscutil/fc-serterm$ +^miscutil/fc-tch2fr$ ^miscutil/imei-luhn$ ^rvinterf/asyncshell/fc-shell$ diff -r 7eaa3307e5df -r d57f68d0568d miscutil/Makefile --- a/miscutil/Makefile Tue Jun 14 01:40:14 2016 +0000 +++ b/miscutil/Makefile Tue Jun 14 02:45:09 2016 +0000 @@ -1,11 +1,12 @@ CC= gcc CFLAGS= -O2 -PROGS= fc-fr2tch fc-rgbconv fc-serterm imei-luhn +PROGS= fc-fr2tch fc-rgbconv fc-serterm fc-tch2fr imei-luhn INSTBIN=/usr/local/bin all: ${PROGS} FR2TCH_OBJS= fc-fr2tch.o gsm0610.o +TCH2FR_OBJS= fc-tch2fr.o gsm0610.o SERTERM_OBJS= fc-serterm.o openport.o ttypassthru.o fc-fr2tch: ${FR2TCH_OBJS} @@ -20,6 +21,9 @@ ttypassthru.o: ../loadtools/ttypassthru.c ${CC} ${CFLAGS} -c -o $@ $< +fc-tch2fr: ${TCH2FR_OBJS} + ${CC} ${CFLAGS} -o $@ ${TCH2FR_OBJS} + imei-luhn: imei-luhn.c ${CC} ${CFLAGS} -o $@ $@.c diff -r 7eaa3307e5df -r d57f68d0568d miscutil/fc-tch2fr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/miscutil/fc-tch2fr.c Tue Jun 14 02:45:09 2016 +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 +#include +#include +#include + +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); +}