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@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
calc_frame_len(struct sbc_frame_hdr * hdr)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
calc_bit_rate(struct sbc_frame_hdr * hdr)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
freq2str(uint8_t freq)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
mode2str(uint8_t mode)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
__read(int fd,void * buf,size_t count)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
analyze_file(char * filename)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, mode, 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 mode = hdr.channel_mode;
203 method = hdr.allocation_method;
204
205 count = calc_frame_len(&hdr);
206
207 bitpool[0] = hdr.bitpool;
208 frame_len[0] = count + 4;
209
210 for (n = 1; n < SIZE; n++) {
211 bitpool[n] = 0;
212 frame_len[n] = 0;
213 }
214
215 if (lseek(fd, 0, SEEK_SET) < 0) {
216 num = 1;
217 rate = calc_bit_rate(&hdr);
218 while (count) {
219 size = count > sizeof(buf) ? sizeof(buf) : count;
220 len = __read(fd, buf, size);
221 if (len < 0)
222 break;
223 count -= len;
224 }
225 } else {
226 num = 0;
227 rate = 0;
228 }
229
230 while (1) {
231 len = __read(fd, &hdr, sizeof(hdr));
232 if (len < 0) {
233 fprintf(stderr, "Unable to read frame header"
234 " (error %d)\n", errno);
235 break;
236 }
237
238 if (len == 0)
239 break;
240
241 if ((size_t) len < sizeof(hdr) || hdr.syncword != 0x9c) {
242 fprintf(stderr, "Corrupted SBC stream "
243 "(len %zd syncword 0x%02x)\n",
244 len, hdr.syncword);
245 break;
246 }
247
248 count = calc_frame_len(&hdr);
249 len = count + 4;
250
251 p1 = -1;
252 p2 = -1;
253 for (n = 0; n < SIZE; n++) {
254 if (p1 < 0 && (bitpool[n] == 0 || bitpool[n] == hdr.bitpool))
255 p1 = n;
256 if (p2 < 0 && (frame_len[n] == 0 || frame_len[n] == len))
257 p2 = n;
258 }
259 if (p1 >= 0)
260 bitpool[p1] = hdr.bitpool;
261 if (p2 >= 0)
262 frame_len[p2] = len;
263
264 while (count) {
265 size = count > sizeof(buf) ? sizeof(buf) : count;
266
267 len = __read(fd, buf, size);
268 if (len != size) {
269 fprintf(stderr, "Unable to read frame data "
270 "(error %d)\n", errno);
271 break;
272 }
273
274 count -= len;
275 }
276
277 rate += calc_bit_rate(&hdr);
278 num++;
279 }
280
281 printf("Subbands\t\t%d\n", subbands);
282 printf("Block length\t\t%d\n", blocks);
283 printf("Sampling frequency\t%s\n", freq2str(freq));
284 printf("Channel mode\t\t%s\n", mode2str(hdr.channel_mode));
285 printf("Allocation method\t%s\n", method ? "SNR" : "Loudness");
286 printf("Bitpool\t\t\t%d", bitpool[0]);
287 for (n = 1; n < SIZE; n++)
288 if (bitpool[n] > 0)
289 printf(", %d", bitpool[n]);
290 printf("\n");
291 printf("Number of frames\t%d\n", num);
292 printf("Frame length\t\t%d", frame_len[0]);
293 for (n = 1; n < SIZE; n++)
294 if (frame_len[n] > 0)
295 printf(", %d", frame_len[n]);
296 printf(" Bytes\n");
297 if (num > 0)
298 printf("Bit rate\t\t%.3f kbps\n", rate / num);
299
300 if (fd > fileno(stderr))
301 close(fd);
302
303 printf("\n");
304
305 return 0;
306 }
307
main(int argc,char * argv[])308 int main(int argc, char *argv[])
309 {
310 int i;
311
312 if (argc < 2) {
313 fprintf(stderr, "Usage: sbcinfo <file>\n");
314 exit(1);
315 }
316
317 for (i = 0; i < argc - 1; i++)
318 if (analyze_file(argv[i + 1]) < 0)
319 exit(1);
320
321 return 0;
322 }
323