FreeCalypso > hg > gsm-codec-lib
changeset 211:78d1a6513393
amrconv: new program amr-cod-parse
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 20 Apr 2023 01:30:46 +0000 |
parents | 7e490a8efe8a |
children | 0beafaa0623f |
files | .hgignore amrconv/Makefile amrconv/amr_common_tbl.c amrconv/amr_defs.h amrconv/cod-parse.c amrconv/cod-read.c amrconv/param_asm.c amrconv/param_dump.c |
diffstat | 8 files changed, 464 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Sun Apr 16 19:00:46 2023 +0000 +++ b/.hgignore Thu Apr 20 01:30:46 2023 +0000 @@ -2,6 +2,7 @@ \.[oa]$ +^amrconv/amr-cod-parse$ ^amrconv/gsm-amr2efr$ ^amrconv/gsm-efr2amr$
--- a/amrconv/Makefile Sun Apr 16 19:00:46 2023 +0000 +++ b/amrconv/Makefile Thu Apr 20 01:30:46 2023 +0000 @@ -1,14 +1,19 @@ CC= gcc CFLAGS= -O2 -PROGS= gsm-amr2efr gsm-efr2amr +PROGS= amr-cod-parse gsm-amr2efr gsm-efr2amr LIBTEST=../libtest/libtest.a INSTBIN=/opt/freecalypso/bin AMR2EFR_OBJS= amr122bits.o bitmanip.o amr2efr.o EFR2AMR_OBJS= amr122bits.o bitmanip.o efr2amr.o +COD_PARSE_OBJS= amr_common_tbl.o cod-parse.o cod-read.o param_asm.o param_dump.o + all: ${PROGS} +amr-cod-parse: ${COD_PARSE_OBJS} + ${CC} ${CFLAGS} -o $@ ${COD_PARSE_OBJS} + gsm-amr2efr: ${AMR2EFR_OBJS} ${CC} ${CFLAGS} -o $@ ${AMR2EFR_OBJS}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/amrconv/amr_common_tbl.c Thu Apr 20 01:30:46 2023 +0000 @@ -0,0 +1,36 @@ +/* + * This C module provides some common tables for AMR parsing programs. + */ + +#include "amr_defs.h" + +char *amr_mode_names[16] = { + "MR475", + "MR515", + "MR59", + "MR67", + "MR74", + "MR795", + "MR102", + "MR122", + "SID", + "EFR-SID", + "TDMA-SID", + "PDC-SID", + "InvalidC", + "InvalidD", + "InvalidE", + "NO_DATA" +}; + +unsigned amr_bit_lengths[9] = { + AMR_NBITS_475, + AMR_NBITS_515, + AMR_NBITS_59, + AMR_NBITS_67, + AMR_NBITS_74, + AMR_NBITS_795, + AMR_NBITS_102, + AMR_NBITS_122, + AMR_NBITS_SID +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/amrconv/amr_defs.h Thu Apr 20 01:30:46 2023 +0000 @@ -0,0 +1,56 @@ +/* + * This header file holds some miscellaneous definitions for AMR, + * to be used by parsing and conversion debug utilities. + */ + +#define MAX_PRM_SIZE 57 /* max. num. of params */ +#define MAX_SERIAL_SIZE 244 /* max. num. of serial bits */ + +enum TXFrameType { + TX_SPEECH_GOOD = 0, + TX_SID_FIRST, + TX_SID_UPDATE, + TX_NO_DATA, + TX_SPEECH_DEGRADED, + TX_SPEECH_BAD, + TX_SID_BAD, + TX_ONSET, + TX_N_FRAMETYPES /* number of frame types */ +}; + +enum Mode { + MR475 = 0, + MR515, + MR59, + MR67, + MR74, + MR795, + MR102, + MR122, + MRDTX +}; + +/* number of speech bits for all modes */ +#define AMR_NBITS_475 95 +#define AMR_NBITS_515 103 +#define AMR_NBITS_59 118 +#define AMR_NBITS_67 134 +#define AMR_NBITS_74 148 +#define AMR_NBITS_795 159 +#define AMR_NBITS_102 204 +#define AMR_NBITS_122 244 +#define AMR_NBITS_SID 35 + +/* number of distinct parameters for all modes */ +#define PRMNO_MR475 17 +#define PRMNO_MR515 19 +#define PRMNO_MR59 19 +#define PRMNO_MR67 19 +#define PRMNO_MR74 19 +#define PRMNO_MR795 23 +#define PRMNO_MR102 39 +#define PRMNO_MR122 57 +#define PRMNO_MRDTX 5 + +/* ETSI/3GPP test sequence file format */ +#define COD_FORMAT_NWORDS 250
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/amrconv/cod-parse.c Thu Apr 20 01:30:46 2023 +0000 @@ -0,0 +1,78 @@ +/* + * This program reads an ETSI/3GPP AMR *.cod file and parses it into + * a human-readable form. + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "amr_defs.h" + +extern char *amr_mode_names[16]; +extern unsigned amr_bit_lengths[9]; + +static char *type_names[4] = { + "Speech", + "SID_FIRST", + "SID_UPDATE", + "NO_DATA" +}; + +main(argc, argv) + char **argv; +{ + char *infname; + FILE *inf; + int big_endian; + unsigned frame_no, type, mode; + uint8_t input_bits[COD_FORMAT_NWORDS]; + uint16_t params[MAX_PRM_SIZE]; + int rc; + + if (argc == 2 && argv[1][0] != '-') { + big_endian = 0; + infname = argv[1]; + } else if (argc == 3 && !strcmp(argv[1], "-b")) { + big_endian = 1; + infname = argv[2]; + } else { + fprintf(stderr, "usage: %s [-b] file.cod\n", argv[0]); + exit(1); + } + inf = fopen(infname, "r"); + if (!inf) { + perror(infname); + exit(1); + } + for (frame_no = 0; ; frame_no++) { + rc = read_cod_bits(inf, big_endian, input_bits, infname); + if (!rc) + break; + type = input_bits[0]; + mode = input_bits[245]; + printf("#%u: Type=%u Mode=%u", frame_no, type, mode); + if (type > TX_NO_DATA || mode > MR122) { + printf(" (unsupported)\n"); + continue; + } + printf(" (%s %s)\n", amr_mode_names[mode], type_names[type]); + switch (type) { + case TX_SPEECH_GOOD: + preen_frame_bits(input_bits+1, amr_bit_lengths[mode], + infname, frame_no); + reassemble_amr_params(input_bits+1, params, mode); + dump_amr_params(params, mode); + break; + case TX_SID_FIRST: + case TX_SID_UPDATE: + preen_frame_bits(input_bits+1, AMR_NBITS_SID, infname, + frame_no); + reassemble_amr_params(input_bits+1, params, MRDTX); + dump_amr_params(params, MRDTX); + break; + } + } + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/amrconv/cod-read.c Thu Apr 20 01:30:46 2023 +0000 @@ -0,0 +1,66 @@ +/* + * In this module we implement utility functions for reading ETSI/3GPP + * *.cod files (AMR version) in either LE or BE format. + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include "amr_defs.h" + +read_cod_bits(inf, big_endian, bitvec, filename_for_errs) + FILE *inf; + uint8_t *bitvec; + char *filename_for_errs; +{ + uint8_t file_bytes[COD_FORMAT_NWORDS * 2], *sp; + int cc; + unsigned n, upper; + + cc = fread(file_bytes, 2, COD_FORMAT_NWORDS, inf); + if (cc == 0) + return 0; + if (cc != COD_FORMAT_NWORDS) { + fprintf(stderr, "error: short read from %s\n", + filename_for_errs); + exit(1); + } + sp = file_bytes; + for (n = 0; n < COD_FORMAT_NWORDS; n++) { + if (big_endian) { + upper = sp[0]; + bitvec[n] = sp[1]; + } else { + bitvec[n] = sp[0]; + upper = sp[1]; + } + if (upper) { + fprintf(stderr, + "error in %s: non-zero in what should be %s upper byte\n", + filename_for_errs, big_endian ? "BE" : "LE"); + exit(1); + } + sp += 2; + } + return 1; +} + +void +preen_frame_bits(input_bits, nbits, filename_for_errs, frame_no) + uint8_t *input_bits; + char *filename_for_errs; + unsigned nbits, frame_no; +{ + uint8_t *sp; + unsigned nb; + + sp = input_bits; + for (nb = 0; nb < nbits; nb++) { + if (*sp > 1) { + fprintf(stderr, "error in %s frame #%u: data bit > 1\n", + filename_for_errs, frame_no); + exit(1); + } + sp++; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/amrconv/param_asm.c Thu Apr 20 01:30:46 2023 +0000 @@ -0,0 +1,143 @@ +/* + * This C module is common between amr-cod-parse and amr-ietf-parse + * utilities. It contains the function that takes an array of bits + * in the codec's natural order and reassembles these bits into + * an array of codec parameters. + */ + +#include <stdint.h> +#include "amr_defs.h" + +/* parameter sizes (# of bits), one table per mode */ + +static const uint8_t bitno_MR475[PRMNO_MR475] = { + 8, 8, 7, /* LSP VQ */ + 8, 7, 2, 8, /* first subframe */ + 4, 7, 2, /* second subframe */ + 4, 7, 2, 8, /* third subframe */ + 4, 7, 2, /* fourth subframe */ +}; + +static const uint8_t bitno_MR515[PRMNO_MR515] = { + 8, 8, 7, /* LSP VQ */ + 8, 7, 2, 6, /* first subframe */ + 4, 7, 2, 6, /* second subframe */ + 4, 7, 2, 6, /* third subframe */ + 4, 7, 2, 6, /* fourth subframe */ +}; + +static const uint8_t bitno_MR59[PRMNO_MR59] = { + 8, 9, 9, /* LSP VQ */ + 8, 9, 2, 6, /* first subframe */ + 4, 9, 2, 6, /* second subframe */ + 8, 9, 2, 6, /* third subframe */ + 4, 9, 2, 6, /* fourth subframe */ +}; + +static const uint8_t bitno_MR67[PRMNO_MR67] = { + 8, 9, 9, /* LSP VQ */ + 8, 11, 3, 7, /* first subframe */ + 4, 11, 3, 7, /* second subframe */ + 8, 11, 3, 7, /* third subframe */ + 4, 11, 3, 7, /* fourth subframe */ +}; + +static const uint8_t bitno_MR74[PRMNO_MR74] = { + 8, 9, 9, /* LSP VQ */ + 8, 13, 4, 7, /* first subframe */ + 5, 13, 4, 7, /* second subframe */ + 8, 13, 4, 7, /* third subframe */ + 5, 13, 4, 7, /* fourth subframe */ +}; + +static const uint8_t bitno_MR795[PRMNO_MR795] = { + 9, 9, 9, /* LSP VQ */ + 8, 13, 4, 4, 5, /* first subframe */ + 6, 13, 4, 4, 5, /* second subframe */ + 8, 13, 4, 4, 5, /* third subframe */ + 6, 13, 4, 4, 5, /* fourth subframe */ +}; + +static const uint8_t bitno_MR102[PRMNO_MR102] = { + 8, 9, 9, /* LSP VQ */ + 8, 1, 1, 1, 1, 10, 10, 7, 7, /* first subframe */ + 5, 1, 1, 1, 1, 10, 10, 7, 7, /* second subframe */ + 8, 1, 1, 1, 1, 10, 10, 7, 7, /* third subframe */ + 5, 1, 1, 1, 1, 10, 10, 7, 7, /* fourth subframe */ +}; + +static const uint8_t bitno_MR122[PRMNO_MR122] = { + 7, 8, 9, 8, 6, /* LSP VQ */ + 9, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5, /* first subframe */ + 6, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5, /* second subframe */ + 9, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5, /* third subframe */ + 6, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5 /* fourth subframe */ +}; + +static const uint8_t bitno_MRDTX[PRMNO_MRDTX] = { + 3, + 8, 9, 9, + 6 +}; + +static void +bits_to_params(bits, params, table, nparam) + const uint8_t *bits; + uint16_t *params; + const uint8_t *table; + unsigned nparam; +{ + const uint8_t *p = bits; + const uint8_t *t = table; + unsigned n, m, acc; + + for (n = 0; n < nparam; n++) { + acc = 0; + for (m = 0; m < *t; m++) { + acc <<= 1; + if (*p) + acc |= 1; + p++; + } + params[n] = acc; + t++; + } +} + +reassemble_amr_params(bits, params, mode) + const uint8_t *bits; + uint16_t *params; + unsigned mode; +{ + switch (mode) { + case MR475: + bits_to_params(bits, params, bitno_MR475, PRMNO_MR475); + return(0); + case MR515: + bits_to_params(bits, params, bitno_MR515, PRMNO_MR515); + return(0); + case MR59: + bits_to_params(bits, params, bitno_MR59, PRMNO_MR59); + return(0); + case MR67: + bits_to_params(bits, params, bitno_MR67, PRMNO_MR67); + return(0); + case MR74: + bits_to_params(bits, params, bitno_MR74, PRMNO_MR74); + return(0); + case MR795: + bits_to_params(bits, params, bitno_MR795, PRMNO_MR795); + return(0); + case MR102: + bits_to_params(bits, params, bitno_MR102, PRMNO_MR102); + return(0); + case MR122: + bits_to_params(bits, params, bitno_MR122, PRMNO_MR122); + return(0); + case MRDTX: + bits_to_params(bits, params, bitno_MRDTX, PRMNO_MRDTX); + return(0); + default: + return(-1); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/amrconv/param_dump.c Thu Apr 20 01:30:46 2023 +0000 @@ -0,0 +1,78 @@ +/* + * This C module is common between amr-cod-parse and amr-ietf-parse + * utilities. It contains the function that takes an array of + * extracted codec parameters and prints them out as appropriate + * for each mode. + */ + +#include <stdio.h> +#include <stdint.h> +#include "amr_defs.h" + +void +dump_amr_params(params, mode) + uint16_t *params; + unsigned mode; +{ + int i, j, n; + + switch (mode) { + case MR475: + printf(" %u %u %u\n", params[0], params[1], params[2]); + printf(" %u %u %u %u\n", params[3], params[4], params[5], + params[6]); + printf(" %u %u %u\n", params[7], params[8], params[9]); + printf(" %u %u %u %u\n", params[10], params[11], params[12], + params[13]); + printf(" %u %u %u\n", params[14], params[15], params[16]); + return; + case MR515: + case MR59: + case MR67: + case MR74: + printf(" %u %u %u\n", params[0], params[1], params[2]); + n = 3; + for (i = 0; i < 4; i++) { + putchar(' '); + for (j = 0; j < 4; j++) + printf(" %u", params[n++]); + putchar('\n'); + } + return; + case MR795: + printf(" %u %u %u\n", params[0], params[1], params[2]); + n = 3; + for (i = 0; i < 4; i++) { + putchar(' '); + for (j = 0; j < 5; j++) + printf(" %u", params[n++]); + putchar('\n'); + } + return; + case MR102: + printf(" %u %u %u\n", params[0], params[1], params[2]); + n = 3; + for (i = 0; i < 4; i++) { + putchar(' '); + for (j = 0; j < 9; j++) + printf(" %u", params[n++]); + putchar('\n'); + } + return; + case MR122: + printf(" %u %u %u %u %u\n", params[0], params[1], params[2], + params[3], params[4]); + n = 5; + for (i = 0; i < 4; i++) { + putchar(' '); + for (j = 0; j < 13; j++) + printf(" %u", params[n++]); + putchar('\n'); + } + return; + case MRDTX: + printf(" %u %u %u %u %u\n", params[0], params[1], params[2], + params[3], params[4]); + return; + } +}