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

« back to all changes in this revision

Viewing changes to sbc/sbcdec.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) decoder
 
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 <string.h>
 
34
#include <getopt.h>
 
35
#include <sys/stat.h>
 
36
#include <sys/ioctl.h>
 
37
#include <sys/soundcard.h>
 
38
 
 
39
#include "sbc.h"
 
40
 
 
41
#define BUF_SIZE 8192
 
42
 
 
43
static void decode(char *filename, char *output, int tofile)
 
44
{
 
45
        unsigned char buf[BUF_SIZE], *stream;
 
46
        struct stat st;
 
47
        off_t filesize;
 
48
        sbc_t sbc;
 
49
        int fd, ad, pos, streamlen, framelen, count, written, len;
 
50
        int format = AFMT_S16_BE, frequency, channels;
 
51
 
 
52
        if (stat(filename, &st) < 0) {
 
53
                fprintf(stderr, "Can't get size of file %s: %s\n",
 
54
                                                filename, strerror(errno));
 
55
                return;
 
56
        }
 
57
 
 
58
        filesize = st.st_size;
 
59
        stream = malloc(st.st_size);
 
60
 
 
61
        if (!stream) {
 
62
                fprintf(stderr, "Can't allocate memory for %s: %s\n",
 
63
                                                filename, strerror(errno));
 
64
                return;
 
65
        }
 
66
 
 
67
        fd = open(filename, O_RDONLY);
 
68
        if (fd < 0) {
 
69
                fprintf(stderr, "Can't open file %s: %s\n",
 
70
                                                filename, strerror(errno));
 
71
                goto free;
 
72
        }
 
73
 
 
74
        if (read(fd, stream, st.st_size) != st.st_size) {
 
75
                fprintf(stderr, "Can't read content of %s: %s\n",
 
76
                                                filename, strerror(errno));
 
77
                close(fd);
 
78
                goto free;
 
79
        }
 
80
 
 
81
        close(fd);
 
82
 
 
83
        pos = 0;
 
84
        streamlen = st.st_size;
 
85
 
 
86
        if (tofile)
 
87
                ad = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 
88
        else
 
89
                ad = open(output, O_WRONLY, 0);
 
90
 
 
91
        if (ad < 0) {
 
92
                fprintf(stderr, "Can't open output %s: %s\n",
 
93
                                                output, strerror(errno));
 
94
                goto free;
 
95
        }
 
96
 
 
97
        sbc_init(&sbc, 0L);
 
98
        sbc.endian = SBC_BE;
 
99
 
 
100
        framelen = sbc_decode(&sbc, stream, streamlen, buf, sizeof(buf), &len);
 
101
        channels = sbc.mode == SBC_MODE_MONO ? 1 : 2;
 
102
        switch (sbc.frequency) {
 
103
        case SBC_FREQ_16000:
 
104
                frequency = 16000;
 
105
                break;
 
106
 
 
107
        case SBC_FREQ_32000:
 
108
                frequency = 32000;
 
109
                break;
 
110
 
 
111
        case SBC_FREQ_44100:
 
112
                frequency = 44100;
 
113
                break;
 
114
 
 
115
        case SBC_FREQ_48000:
 
116
                frequency = 48000;
 
117
                break;
 
118
        default:
 
119
                frequency = 0;
 
120
        }
 
121
 
 
122
        printf("%d Hz, %d channels\n", frequency, channels);
 
123
        if (!tofile) {
 
124
                if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) {
 
125
                        fprintf(stderr, "Can't set audio format on %s: %s\n",
 
126
                                        output, strerror(errno));
 
127
                        goto close;
 
128
                }
 
129
                if (ioctl(ad, SNDCTL_DSP_CHANNELS, &channels) < 0) {
 
130
                        fprintf(stderr,
 
131
                                "Can't set number of channels on %s: %s\n",
 
132
                                output, strerror(errno));
 
133
                        goto close;
 
134
                }
 
135
 
 
136
                if (ioctl(ad, SNDCTL_DSP_SPEED, &frequency) < 0) {
 
137
                        fprintf(stderr, "Can't set audio rate on %s: %s\n",
 
138
                                        output, strerror(errno));
 
139
                        goto close;
 
140
                }
 
141
        }
 
142
 
 
143
        count = 0;
 
144
        while (framelen > 0) {
 
145
                /* we have completed an sbc_decode at this point sbc.len is the
 
146
                 * length of the frame we just decoded count is the number of
 
147
                 * decoded bytes yet to be written */
 
148
 
 
149
                if (count + len >= BUF_SIZE) {
 
150
                        /* buffer is too full to stuff decoded audio in so it
 
151
                         * must be written to the device */
 
152
                        written = write(ad, buf, count);
 
153
                        if (written > 0)
 
154
                                count -= written;
 
155
                }
 
156
 
 
157
                /* sanity check */
 
158
                if (count + len >= BUF_SIZE) {
 
159
                        fprintf(stderr,
 
160
                                "buffer size of %d is too small for decoded"
 
161
                                " data (%d)\n", BUF_SIZE, len + count);
 
162
                        exit(1);
 
163
                }
 
164
 
 
165
                /* increase the count */
 
166
                count += len;
 
167
 
 
168
                /* push the pointer in the file forward to the next bit to be
 
169
                 * decoded tell the decoder to decode up to the remaining
 
170
                 * length of the file (!) */
 
171
                pos += framelen;
 
172
                framelen = sbc_decode(&sbc, stream + pos, streamlen - pos,
 
173
                                        buf + count, sizeof(buf) - count,
 
174
                                        &len);
 
175
        }
 
176
 
 
177
        if (count > 0) {
 
178
                written = write(ad, buf, count);
 
179
                if (written > 0)
 
180
                        count -= written;
 
181
        }
 
182
 
 
183
close:
 
184
        sbc_finish(&sbc);
 
185
 
 
186
        close(ad);
 
187
 
 
188
free:
 
189
        free(stream);
 
190
}
 
191
 
 
192
static void usage(void)
 
193
{
 
194
        printf("SBC decoder utility ver %s\n", VERSION);
 
195
        printf("Copyright (c) 2004-2008  Marcel Holtmann\n\n");
 
196
 
 
197
        printf("Usage:\n"
 
198
                "\tsbcdec [options] file(s)\n"
 
199
                "\n");
 
200
 
 
201
        printf("Options:\n"
 
202
                "\t-h, --help           Display help\n"
 
203
                "\t-v, --verbose        Verbose mode\n"
 
204
                "\t-d, --device <dsp>   Sound device\n"
 
205
                "\t-f, --file <file>    Decode to a file\n"
 
206
                "\n");
 
207
}
 
208
 
 
209
static struct option main_options[] = {
 
210
        { "help",       0, 0, 'h' },
 
211
        { "device",     1, 0, 'd' },
 
212
        { "verbose",    0, 0, 'v' },
 
213
        { "file",       1, 0, 'f' },
 
214
        { 0, 0, 0, 0 }
 
215
};
 
216
 
 
217
int main(int argc, char *argv[])
 
218
{
 
219
        char *output = NULL;
 
220
        int i, opt, verbose = 0, tofile = 0;
 
221
 
 
222
        while ((opt = getopt_long(argc, argv, "+hvd:f:", main_options, NULL)) != -1) {
 
223
                switch(opt) {
 
224
                case 'h':
 
225
                        usage();
 
226
                        exit(0);
 
227
 
 
228
                case 'v':
 
229
                        verbose = 1;
 
230
                        break;
 
231
 
 
232
                case 'd':
 
233
                        if (output)
 
234
                                free(output);
 
235
                        output = strdup(optarg);
 
236
                        tofile = 0;
 
237
                        break;
 
238
 
 
239
                case 'f' :
 
240
                        if (output)
 
241
                                free(output);
 
242
                        output = strdup(optarg);
 
243
                        tofile = 1;
 
244
                        break;
 
245
 
 
246
                default:
 
247
                        exit(1);
 
248
                }
 
249
        }
 
250
 
 
251
        argc -= optind;
 
252
        argv += optind;
 
253
        optind = 0;
 
254
 
 
255
        if (argc < 1) {
 
256
                usage();
 
257
                exit(1);
 
258
        }
 
259
 
 
260
        for (i = 0; i < argc; i++)
 
261
                decode(argv[i], output ? output : "/dev/dsp", tofile);
 
262
 
 
263
        if (output)
 
264
                free(output);
 
265
 
 
266
        return 0;
 
267
}