~ubuntu-branches/ubuntu/wily/bluez/wily

« back to all changes in this revision

Viewing changes to sbc/sbcinfo.c

  • Committer: Bazaar Package Importer
  • Author(s): Mario Limonciello
  • Date: 2008-10-07 12:10:29 UTC
  • Revision ID: james.westby@ubuntu.com-20081007121029-4gup4fmmh2vfo5nh
Tags: upstream-4.12
ImportĀ upstreamĀ versionĀ 4.12

Show diffs side-by-side

added added

removed removed

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