Home | History | Annotate | Download | only in sbc
      1 /*
      2  *
      3  *  Bluetooth low-complexity, subband codec (SBC) library
      4  *
      5  *  Copyright (C) 2008-2010  Nokia Corporation
      6  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel (at) holtmann.org>
      7  *
      8  *
      9  *  This program is free software; you can redistribute it and/or modify
     10  *  it under the terms of the GNU General Public License as published by
     11  *  the Free Software Foundation; either version 2 of the License, or
     12  *  (at your option) any later version.
     13  *
     14  *  This program is distributed in the hope that it will be useful,
     15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  *  GNU General Public License for more details.
     18  *
     19  *  You should have received a copy of the GNU General Public License
     20  *  along with this program; if not, write to the Free Software
     21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 #ifdef HAVE_CONFIG_H
     26 #include <config.h>
     27 #endif
     28 
     29 #include <stdio.h>
     30 #include <errno.h>
     31 #include <fcntl.h>
     32 #include <unistd.h>
     33 #include <stdlib.h>
     34 #include <stdint.h>
     35 #include <string.h>
     36 #include <libgen.h>
     37 
     38 #if __BYTE_ORDER == __LITTLE_ENDIAN
     39 struct sbc_frame_hdr {
     40 	uint8_t syncword:8;		/* Sync word */
     41 	uint8_t subbands:1;		/* Subbands */
     42 	uint8_t allocation_method:1;	/* Allocation method */
     43 	uint8_t channel_mode:2;		/* Channel mode */
     44 	uint8_t blocks:2;		/* Blocks */
     45 	uint8_t sampling_frequency:2;	/* Sampling frequency */
     46 	uint8_t bitpool:8;		/* Bitpool */
     47 	uint8_t crc_check:8;		/* CRC check */
     48 } __attribute__ ((packed));
     49 #elif __BYTE_ORDER == __BIG_ENDIAN
     50 struct sbc_frame_hdr {
     51 	uint8_t syncword:8;		/* Sync word */
     52 	uint8_t sampling_frequency:2;	/* Sampling frequency */
     53 	uint8_t blocks:2;		/* Blocks */
     54 	uint8_t channel_mode:2;		/* Channel mode */
     55 	uint8_t allocation_method:1;	/* Allocation method */
     56 	uint8_t subbands:1;		/* Subbands */
     57 	uint8_t bitpool:8;		/* Bitpool */
     58 	uint8_t crc_check:8;		/* CRC check */
     59 } __attribute__ ((packed));
     60 #else
     61 #error "Unknown byte order"
     62 #endif
     63 
     64 static int calc_frame_len(struct sbc_frame_hdr *hdr)
     65 {
     66 	int tmp, nrof_subbands, nrof_blocks;
     67 
     68 	nrof_subbands = (hdr->subbands + 1) * 4;
     69 	nrof_blocks = (hdr->blocks + 1) * 4;
     70 
     71 	switch (hdr->channel_mode) {
     72 	case 0x00:
     73 		nrof_subbands /= 2;
     74 		tmp = nrof_blocks * hdr->bitpool;
     75 		break;
     76 	case 0x01:
     77 		tmp = nrof_blocks * hdr->bitpool * 2;
     78 		break;
     79 	case 0x02:
     80 		tmp = nrof_blocks * hdr->bitpool;
     81 		break;
     82 	case 0x03:
     83 		tmp = nrof_blocks * hdr->bitpool + nrof_subbands;
     84 		break;
     85 	default:
     86 		return 0;
     87 	}
     88 
     89 	return (nrof_subbands + ((tmp + 7) / 8));
     90 }
     91 
     92 static double calc_bit_rate(struct sbc_frame_hdr *hdr)
     93 {
     94 	int nrof_subbands, nrof_blocks;
     95 	double f;
     96 
     97 	nrof_subbands = (hdr->subbands + 1) * 4;
     98 	nrof_blocks = (hdr->blocks + 1) * 4;
     99 
    100 	switch (hdr->sampling_frequency) {
    101 	case 0:
    102 		f = 16;
    103 		break;
    104 	case 1:
    105 		f = 32;
    106 		break;
    107 	case 2:
    108 		f = 44.1;
    109 		break;
    110 	case 3:
    111 		f = 48;
    112 		break;
    113 	default:
    114 		return 0;
    115 	}
    116 
    117 	return ((8 * (calc_frame_len(hdr) + 4) * f) /
    118 			(nrof_subbands * nrof_blocks));
    119 }
    120 
    121 static char *freq2str(uint8_t freq)
    122 {
    123 	switch (freq) {
    124 	case 0:
    125 		return "16 kHz";
    126 	case 1:
    127 		return "32 kHz";
    128 	case 2:
    129 		return "44.1 kHz";
    130 	case 3:
    131 		return "48 kHz";
    132 	default:
    133 		return "Unknown";
    134 	}
    135 }
    136 
    137 static char *mode2str(uint8_t mode)
    138 {
    139 	switch (mode) {
    140 	case 0:
    141 		return "Mono";
    142 	case 1:
    143 		return "Dual Channel";
    144 	case 2:
    145 		return "Stereo";
    146 	case 3:
    147 		return "Joint Stereo";
    148 	default:
    149 		return "Unknown";
    150 	}
    151 }
    152 
    153 static ssize_t __read(int fd, void *buf, size_t count)
    154 {
    155 	ssize_t len, pos = 0;
    156 
    157 	while (count > 0) {
    158 		len = read(fd, buf + pos, count);
    159 		if (len <= 0)
    160 			return len;
    161 
    162 		count -= len;
    163 		pos   += len;
    164 	}
    165 
    166 	return pos;
    167 }
    168 
    169 #define SIZE 32
    170 
    171 static int analyze_file(char *filename)
    172 {
    173 	struct sbc_frame_hdr hdr;
    174 	unsigned char buf[64];
    175 	double rate;
    176 	int bitpool[SIZE], frame_len[SIZE];
    177 	int subbands, blocks, freq, method;
    178 	int n, p1, p2, fd, size, num;
    179 	ssize_t len;
    180 	unsigned int count;
    181 
    182 	if (strcmp(filename, "-")) {
    183 		printf("Filename\t\t%s\n", basename(filename));
    184 
    185 		fd = open(filename, O_RDONLY);
    186 		if (fd < 0) {
    187 			perror("Can't open file");
    188 			return -1;
    189 		}
    190 	} else
    191 		fd = fileno(stdin);
    192 
    193 	len = __read(fd, &hdr, sizeof(hdr));
    194 	if (len != sizeof(hdr) || hdr.syncword != 0x9c) {
    195 		fprintf(stderr, "Not a SBC audio file\n");
    196 		return -1;
    197 	}
    198 
    199 	subbands = (hdr.subbands + 1) * 4;
    200 	blocks = (hdr.blocks + 1) * 4;
    201 	freq = hdr.sampling_frequency;
    202 	method = hdr.allocation_method;
    203 
    204 	count = calc_frame_len(&hdr);
    205 
    206 	bitpool[0] = hdr.bitpool;
    207 	frame_len[0] = count + 4;
    208 
    209 	for (n = 1; n < SIZE; n++) {
    210 		bitpool[n] = 0;
    211 		frame_len[n] = 0;
    212 	}
    213 
    214 	if (lseek(fd, 0, SEEK_SET) < 0) {
    215 		num = 1;
    216 		rate = calc_bit_rate(&hdr);
    217 		while (count) {
    218 			size = count > sizeof(buf) ? sizeof(buf) : count;
    219 			len = __read(fd, buf, size);
    220 			if (len < 0)
    221 				break;
    222 			count -= len;
    223 		}
    224 	} else {
    225 		num = 0;
    226 		rate = 0;
    227 	}
    228 
    229 	while (1) {
    230 		len = __read(fd, &hdr, sizeof(hdr));
    231 		if (len < 0) {
    232 			fprintf(stderr, "Unable to read frame header"
    233 					" (error %d)\n", errno);
    234 			break;
    235 		}
    236 
    237 		if (len == 0)
    238 			break;
    239 
    240 		if ((size_t) len < sizeof(hdr) || hdr.syncword != 0x9c) {
    241 			fprintf(stderr, "Corrupted SBC stream "
    242 					"(len %zd syncword 0x%02x)\n",
    243 					len, hdr.syncword);
    244 			break;
    245 		}
    246 
    247 		count = calc_frame_len(&hdr);
    248 		len = count + 4;
    249 
    250 		p1 = -1;
    251 		p2 = -1;
    252 		for (n = 0; n < SIZE; n++) {
    253 			if (p1 < 0 && (bitpool[n] == 0 || bitpool[n] == hdr.bitpool))
    254 				p1 = n;
    255 			if (p2 < 0 && (frame_len[n] == 0 || frame_len[n] == len))
    256 				p2 = n;
    257 		}
    258 		if (p1 >= 0)
    259 			bitpool[p1] = hdr.bitpool;
    260 		if (p2 >= 0)
    261 			frame_len[p2] = len;
    262 
    263 		while (count) {
    264 			size = count > sizeof(buf) ? sizeof(buf) : count;
    265 
    266 			len = __read(fd, buf, size);
    267 			if (len != size) {
    268 				fprintf(stderr, "Unable to read frame data "
    269 						"(error %d)\n", errno);
    270 				break;
    271 			}
    272 
    273 			count -= len;
    274 		}
    275 
    276 		rate += calc_bit_rate(&hdr);
    277 		num++;
    278 	}
    279 
    280 	printf("Subbands\t\t%d\n", subbands);
    281 	printf("Block length\t\t%d\n", blocks);
    282 	printf("Sampling frequency\t%s\n", freq2str(freq));
    283 	printf("Channel mode\t\t%s\n", mode2str(hdr.channel_mode));
    284 	printf("Allocation method\t%s\n", method ? "SNR" : "Loudness");
    285 	printf("Bitpool\t\t\t%d", bitpool[0]);
    286 	for (n = 1; n < SIZE; n++)
    287 		if (bitpool[n] > 0)
    288 			printf(", %d", bitpool[n]);
    289 	printf("\n");
    290 	printf("Number of frames\t%d\n", num);
    291 	printf("Frame length\t\t%d", frame_len[0]);
    292 	for (n = 1; n < SIZE; n++)
    293 		if (frame_len[n] > 0)
    294 			printf(", %d", frame_len[n]);
    295 	printf(" Bytes\n");
    296 	if (num > 0)
    297 		printf("Bit rate\t\t%.3f kbps\n", rate / num);
    298 
    299 	if (fd > fileno(stderr))
    300 		close(fd);
    301 
    302 	printf("\n");
    303 
    304 	return 0;
    305 }
    306 
    307 int main(int argc, char *argv[])
    308 {
    309 	int i;
    310 
    311 	if (argc < 2) {
    312 		fprintf(stderr, "Usage: sbcinfo <file>\n");
    313 		exit(1);
    314 	}
    315 
    316 	for (i = 0; i < argc - 1; i++)
    317 		if (analyze_file(argv[i + 1]) < 0)
    318 			exit(1);
    319 
    320 	return 0;
    321 }
    322