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;
+	}
+}