view amrconv/ietf-parse.c @ 214:934cf92a1c45

amrconv: new program amr-ietf-parse
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 20 Apr 2023 22:48:22 +0000
parents
children
line wrap: on
line source

/*
 * This program reads an AMR recording in IETF RFC 4867 format 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 const char amr_file_hdr[IETF_HDR_LEN];
extern const uint8_t extra_bytes_per_ft[9];

main(argc, argv)
	char **argv;
{
	char *infname;
	FILE *inf;
	uint8_t frm_in[MAX_IF1_BYTES];
	unsigned frame_no, mode, qbit, sti, sid_mode;
	uint8_t ser_bits[MAX_SERIAL_SIZE];
	uint16_t params[MAX_PRM_SIZE];
	int rc;

	if (argc != 2) {
		fprintf(stderr, "usage: %s amr_file\n", argv[0]);
		exit(1);
	}
	infname = argv[1];
	inf = fopen(infname, "r");
	if (!inf) {
		perror(infname);
		exit(1);
	}
	if (fread(frm_in, 1, IETF_HDR_LEN, inf) != IETF_HDR_LEN ||
	    bcmp(frm_in, amr_file_hdr, IETF_HDR_LEN)) {
		fprintf(stderr, "error: %s is not in IETF AMR format\n",
			infname);
		exit(1);
	}
	for (frame_no = 0; ; frame_no++) {
		rc = getc(inf);
		if (rc < 0)
			break;
		mode = (rc & 0x78) >> 3;
		qbit = (rc & 4) >> 2;
		printf("#%u: FT=%u (%s) Q=%u\n", frame_no, mode,
			amr_mode_names[mode], qbit);
		if (mode == MODE_NO_DATA)
			continue;
		if (mode > MRDTX) {
			fprintf(stderr, "error in frame #%u: invalid FT=%u\n",
				frame_no, mode);
			exit(1);
		}
		rc = fread(frm_in, 1, extra_bytes_per_ft[mode], inf);
		if (rc != extra_bytes_per_ft[mode]) {
			fprintf(stderr,
				"error: short read from %s on frame #%u\n",
				infname, frame_no);
			exit(1);
		}
		amr_if1_unpack(frm_in, ser_bits, mode);
		reassemble_amr_params(ser_bits, params, mode);
		dump_amr_params(params, mode);
		if (mode == MRDTX) {
			sti = (frm_in[4] & 0x10) >> 4;
			sid_mode = 0;
			if (frm_in[4] & 0x08)
				sid_mode |= 1;
			if (frm_in[4] & 0x04)
				sid_mode |= 2;
			if (frm_in[4] & 0x02)
				sid_mode |= 4;
			printf("  SID_%s Mode=%u\n", sti ? "UPDATE" : "FIRST",
				sid_mode);
		}
	}
	exit(0);
}