OSDN Git Service

sbc: Update Nokia copyrights
[android-x86/external-bluetooth-sbc.git] / sbc / sbcinfo.c
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
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, 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
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 }