view frtest/dlcap-sync.c @ 522:4d2cccaeb4a7

libtest: implement TW-TS-005 reader function Spec reference: https://www.freecalypso.org/specs/tw-ts-005-v010002.txt
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 19 Sep 2024 03:08:47 +0000
parents 285381a001fc
children
line wrap: on
line source

/*
 * This program reads a TCH/FS downlink capture file from a FreeCalypso GSM MS
 * that was produced in a session in which seqsync PCMA or PCMU input
 * (seqsyn_[au].inp) was fed into the test call from IP-PSTN side.  It looks
 * for FRv1 DHF followed by specific frame patterns given by ETSI in
 * syn???_[au].cod files, and reports what it finds.  Matches indicate
 * a particular alignment between the input sequence and encoder frame
 * boundaries, if the network speech transcoder implements the encoder
 * homing feature which is optional for FRv1.
 */

#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "../libgsmfr2/tw_gsmfr.h"

extern const uint8_t sync_from_pcma[160*33];
extern const uint8_t sync_from_pcmu[160*33];

static int
check_for_match(input, table)
	const uint8_t *input, *table;
{
	unsigned n;

	for (n = 0; n < 160; n++) {
		if (!bcmp(input, table + n * 33, 33))
			return n;
	}
	return -1;
}

main(argc, argv)
	char **argv;
{
	FILE *inf;
	char linebuf[128];
	int lineno, rc;
	uint16_t status_words[3];
	uint8_t tidsp_bytes[33], libgsm_bytes[33];
	const uint8_t *match_table;
	int dhf_state;

	if (argc != 3) {
usage:		fprintf(stderr, "usage: %s dlcap-file alaw|ulaw\n", argv[0]);
		exit(1);
	}
	inf = fopen(argv[1], "r");
	if (!inf) {
		perror(argv[1]);
		exit(1);
	}
	if (!strcmp(argv[2], "alaw"))
		match_table = sync_from_pcma;
	else if (!strcmp(argv[2], "ulaw"))
		match_table = sync_from_pcmu;
	else
		goto usage;
	dhf_state = 0;
	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) {
		/* support both old and new formats */
		if (isxdigit(linebuf[0]) && isxdigit(linebuf[1]) &&
		    isxdigit(linebuf[2]) && isxdigit(linebuf[3])) {
			rc = parse_dlcap_common(linebuf, status_words,
						tidsp_bytes);
			if (rc < 0) {
invalid:			fprintf(stderr,
				"error: %s is not in the expected format\n",
					argv[1]);
				exit(1);
			}
		} else if (!strncmp(linebuf, "FR ", 3)) {
			rc = parse_dlcap_common(linebuf + 3, status_words,
						tidsp_bytes);
			if (rc < 0)
				goto invalid;
			if (linebuf[84] != ' ')
				goto invalid;
			if (!isdigit(linebuf[85]))
				goto invalid;
		} else
			goto invalid;
		if ((status_words[0] & 0xC004) != 0xC000) {
			dhf_state = 0;
			continue;
		}
		gsm0610_tidsp_to_libgsm(tidsp_bytes, libgsm_bytes);
		if (!bcmp(libgsm_bytes, gsmfr_decoder_homing_frame, 33)) {
			dhf_state = 1;
			continue;
		}
		if (!dhf_state)
			continue;
		rc = check_for_match(libgsm_bytes, match_table);
		if (rc >= 0 && rc <= 159) {
			printf(
			"line %d: match to expected sync frame for offset %d\n",
				lineno, rc);
		}
		dhf_state = 0;
	}
	exit(0);
}