view 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 source

/*
 * 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);
}