/*
 *
 *  Bluetooth low-complexity, subband codec (SBC) library
 *
 *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <libgen.h>

struct sbc_frame_hdr {
	uint8_t syncword:8;		/* Sync word */
	uint8_t subbands:1;		/* Subbands */
	uint8_t allocation_method:1;	/* Allocation method */
	uint8_t channel_mode:2;		/* Channel mode */
	uint8_t blocks:2;		/* Blocks */
	uint8_t sampling_frequency:2;	/* Sampling frequency */
	uint8_t bitpool:8;		/* Bitpool */
	uint8_t crc_check:8;		/* CRC check */
} __attribute__ ((packed));

static int calc_frame_len(struct sbc_frame_hdr *hdr)
{
	int tmp, nrof_subbands, nrof_blocks;

	nrof_subbands = (hdr->subbands + 1) * 4;
	nrof_blocks = (hdr->blocks + 1) * 4;

	switch (hdr->channel_mode) {
	case 0x00:
		nrof_subbands /= 2;
		tmp = nrof_blocks * hdr->bitpool;
		break;
	case 0x01:
		tmp = nrof_blocks * hdr->bitpool * 2;
		break;
	case 0x02:
		tmp = nrof_blocks * hdr->bitpool;
		break;
	case 0x03:
		tmp = nrof_blocks * hdr->bitpool + nrof_subbands;
		break;
	default:
		return 0;
	}

	return (nrof_subbands + ((tmp + 7) / 8));
}

static double calc_bit_rate(struct sbc_frame_hdr *hdr)
{
	int nrof_subbands, nrof_blocks;
	double f;

	nrof_subbands = (hdr->subbands + 1) * 4;
	nrof_blocks = (hdr->blocks + 1) * 4;

	switch (hdr->sampling_frequency) {
	case 0:
		f = 16;
		break;
	case 1:
		f = 32;
		break;
	case 2:
		f = 44.1;
		break;
	case 3:
		f = 48;
		break;
	default:
		return 0;
	}

	return ((8 * (calc_frame_len(hdr) + 4) * f) / (nrof_subbands * nrof_blocks));
}

static char *freq2str(uint8_t freq)
{
	switch (freq) {
	case 0:
		return "16 kHz";
	case 1:
		return "32 kHz";
	case 2:
		return "44.1 kHz";
	case 3:
		return "48 kHz";
	default:
		return "Unknown";
	}
}

static char *mode2str(uint8_t mode)
{
	switch (mode) {
	case 0:
		return "Mono";
	case 1:
		return "Dual Channel";
	case 2:
		return "Stereo";
	case 3:
		return "Joint Stereo";
	default:
		return "Unknown";
	}
}

static ssize_t __read(int fd, void *buf, size_t count)
{
	ssize_t len, pos = 0;

	while (count > 0) {
		len = read(fd, buf + pos, count);
		if (len <= 0)
			return len;

		count -= len;
		pos   += len;
	}

	return pos;
}

#define SIZE 32

static int analyze_file(char *filename)
{
	struct sbc_frame_hdr hdr;
	unsigned char buf[64];
	double rate;
	int bitpool[SIZE], frame_len[SIZE];
	int subbands, blocks, freq, mode, method;
	int n, p1, p2, fd, len, size, count, num;

	if (strcmp(filename, "-")) {
		printf("Filename\t\t%s\n", basename(filename));

		fd = open(filename, O_RDONLY);
		if (fd < 0) {
			perror("Can't open file");
			return -1;
		}
	} else
		fd = fileno(stdin);

	len = __read(fd, &hdr, sizeof(hdr));
	if (len != sizeof(hdr) || hdr.syncword != 0x9c) {
		fprintf(stderr, "Not a SBC audio file\n");
		return -1;
	}

	subbands = (hdr.subbands + 1) * 4;
	blocks = (hdr.blocks + 1) * 4;
	freq = hdr.sampling_frequency;
	mode = hdr.channel_mode;
	method = hdr.allocation_method;

	count = calc_frame_len(&hdr);

	bitpool[0] = hdr.bitpool;
	frame_len[0] = count + 4;

	for (n = 1; n < SIZE; n++) {
		bitpool[n] = 0;
		frame_len[n] = 0;
	}

	if (lseek(fd, 0, SEEK_SET) < 0) {
		num = 1;
		rate = calc_bit_rate(&hdr);
		while (count) {
			size = count > sizeof(buf) ? sizeof(buf) : count;
			len = __read(fd, buf, size);
			if (len < 0)
				break;
			count -= len;
		}
	} else {
		num = 0;
		rate = 0;
	}

	while (1) {
		len = __read(fd, &hdr, sizeof(hdr));
		if (len < 0) {
			fprintf(stderr, "Unable to read frame header (error %d)\n", errno);
			break;
		}

		if (len == 0)
			break;

		if (len < sizeof(hdr) || hdr.syncword != 0x9c) {
			fprintf(stderr, "Corrupted SBC stream (len %d syncword 0x%02x)\n",
								len, hdr.syncword);
			break;
		}

		count = calc_frame_len(&hdr);
		len = count + 4;

		p1 = -1;
		p2 = -1;
		for (n = 0; n < SIZE; n++) {
			if (p1 < 0 && (bitpool[n] == 0 || bitpool[n] == hdr.bitpool))
				p1 = n;
			if (p2 < 0 && (frame_len[n] == 0 || frame_len[n] == len))
				p2 = n;
		}
		if (p1 >= 0)
			bitpool[p1] = hdr.bitpool;
		if (p2 >= 0)
			frame_len[p2] = len;

		while (count) {
			size = count > sizeof(buf) ? sizeof(buf) : count;

			len = __read(fd, buf, size);
			if (len != size) {
				fprintf(stderr, "Unable to read frame data (error %d)\n", errno);
				break;
			}

			count -= len;
		}

		rate += calc_bit_rate(&hdr);
		num++;
	}

	printf("Subbands\t\t%d\n", subbands);
	printf("Block length\t\t%d\n", blocks);
	printf("Sampling frequency\t%s\n", freq2str(freq));
	printf("Channel mode\t\t%s\n", mode2str(hdr.channel_mode));
	printf("Allocation method\t%s\n", method ? "SNR" : "Loudness");
	printf("Bitpool\t\t\t%d", bitpool[0]);
	for (n = 1; n < SIZE; n++)
		if (bitpool[n] > 0)
			printf(", %d", bitpool[n]);
	printf("\n");
	printf("Number of frames\t%d\n", num);
	printf("Frame length\t\t%d", frame_len[0]);
	for (n = 1; n < SIZE; n++)
		if (frame_len[n] > 0)
			printf(", %d", frame_len[n]);
	printf(" Bytes\n");
	if (num > 0)
		printf("Bit rate\t\t%.3f kbps\n", rate / num);

	if (fd > fileno(stderr))
		close(fd);

	printf("\n");

	return 0;
}

int main(int argc, char *argv[])
{
	int i;

	if (argc < 2) {
		fprintf(stderr, "Usage: sbcinfo <file>\n");
		exit(1);
	}

	for (i = 0; i < argc - 1; i++)
		if (analyze_file(argv[i + 1]) < 0)
			exit(1);

	return 0;
}
