diff amrconv/cod2ietf.c @ 215:4c4649a5fec3

amrconv: new program amr-cod2ietf
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 21 Apr 2023 06:30:29 +0000
parents amrconv/cod-parse.c@0beafaa0623f
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/amrconv/cod2ietf.c	Fri Apr 21 06:30:29 2023 +0000
@@ -0,0 +1,103 @@
+/*
+ * This program converts an AMR-encoded speech recording from the .cod
+ * format used by 3GPP test sequences into the more common .amr format
+ * of IETF RFC 4867.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include "amr_defs.h"
+
+extern unsigned amr_bit_lengths[9];
+extern const char amr_file_hdr[IETF_HDR_LEN];
+extern const uint8_t extra_bytes_per_ft[9];
+
+main(argc, argv)
+	char **argv;
+{
+	char *infname, *outfname;
+	FILE *inf, *outf;
+	int big_endian;
+	unsigned frame_no, type, mode, outlen;
+	uint8_t input_bits[COD_FORMAT_NWORDS], frm_out[MAX_IF1_BYTES+1];
+	int rc;
+
+	if (argc == 3 && argv[1][0] != '-') {
+		big_endian = 0;
+		infname = argv[1];
+		outfname = argv[2];
+	} else if (argc == 4 && !strcmp(argv[1], "-b")) {
+		big_endian = 1;
+		infname = argv[2];
+		outfname = argv[3];
+	} else {
+		fprintf(stderr, "usage: %s [-b] input.cod output.amr\n",
+			argv[0]);
+		exit(1);
+	}
+	inf = fopen(infname, "r");
+	if (!inf) {
+		perror(infname);
+		exit(1);
+	}
+	outf = fopen(outfname, "w");
+	if (!outf) {
+		perror(outfname);
+		exit(1);
+	}
+	fwrite(amr_file_hdr, 1, IETF_HDR_LEN, outf);
+	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];
+		switch (type) {
+		case TX_SPEECH_GOOD:
+			if (mode > MR122) {
+invalid_mode:			fprintf(stderr,
+					"error in %s frame #%u: invalid mode\n",
+					infname, frame_no);
+				exit(1);
+			}
+			preen_frame_bits(input_bits+1, amr_bit_lengths[mode],
+					 infname, frame_no);
+			frm_out[0] = (mode << 3) | 0x04;
+			amr_if1_pack(frm_out+1, input_bits+1, mode);
+			outlen = extra_bytes_per_ft[mode] + 1;
+			break;
+		case TX_SID_FIRST:
+		case TX_SID_UPDATE:
+			if (mode > MR122)
+				goto invalid_mode;
+			preen_frame_bits(input_bits+1, AMR_NBITS_SID, infname,
+					 frame_no);
+			frm_out[0] = 0x44;
+			amr_if1_pack(frm_out+1, input_bits+1, MRDTX);
+			if (type == TX_SID_UPDATE)
+				frm_out[5] |= 0x10;
+			if (mode & 1)
+				frm_out[5] |= 0x08;
+			if (mode & 2)
+				frm_out[5] |= 0x04;
+			if (mode & 4)
+				frm_out[5] |= 0x02;
+			outlen = 6;
+			break;
+		case TX_NO_DATA:
+			frm_out[0] = 0x7C;
+			outlen = 1;
+			break;
+		default:
+			fprintf(stderr, "error in %s frame #%u: invalid type\n",
+				infname, frame_no);
+			exit(1);
+		}
+		fwrite(frm_out, 1, outlen, outf);
+	}
+	fclose(outf);
+	exit(0);
+}