OSDN Git Service

sbc: Add bitpool option to encoder
[android-x86/external-bluetooth-sbc.git] / sbc / sbcenc.c
1 /*
2  *
3  *  Bluetooth low-complexity, subband codec (SBC) encoder
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 <getopt.h>
36 #include <byteswap.h>
37 #include <sys/stat.h>
38
39 #include "sbc.h"
40
41 #if __BYTE_ORDER == __LITTLE_ENDIAN
42 #define COMPOSE_ID(a,b,c,d)     ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
43 #define LE_SHORT(v)             (v)
44 #define LE_INT(v)               (v)
45 #define BE_SHORT(v)             bswap_16(v)
46 #define BE_INT(v)               bswap_32(v)
47 #elif __BYTE_ORDER == __BIG_ENDIAN
48 #define COMPOSE_ID(a,b,c,d)     ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
49 #define LE_SHORT(v)             bswap_16(v)
50 #define LE_INT(v)               bswap_32(v)
51 #define BE_SHORT(v)             (v)
52 #define BE_INT(v)               (v)
53 #else
54 #error "Wrong endian"
55 #endif
56
57 #define AU_MAGIC                COMPOSE_ID('.','s','n','d')
58
59 #define AU_FMT_ULAW             1
60 #define AU_FMT_LIN8             2
61 #define AU_FMT_LIN16            3
62
63 struct au_header {
64         uint32_t magic;         /* '.snd' */
65         uint32_t hdr_size;      /* size of header (min 24) */
66         uint32_t data_size;     /* size of data */
67         uint32_t encoding;      /* see to AU_FMT_XXXX */
68         uint32_t sample_rate;   /* sample rate */
69         uint32_t channels;      /* number of channels (voices) */
70 };
71
72 static ssize_t __read(int fd, void *buf, size_t count)
73 {
74         ssize_t len, pos = 0;
75
76         while (count > 0) {
77                 len = read(fd, buf + pos, count);
78                 if (len <= 0)
79                         return len;
80
81                 count -= len;
82                 pos   += len;
83         }
84
85         return pos;
86 }
87
88 static ssize_t __write(int fd, const void *buf, size_t count)
89 {
90         ssize_t len, pos = 0;
91
92         while (count > 0) {
93                 len = write(fd, buf + pos, count);
94                 if (len <= 0)
95                         return len;
96
97                 count -= len;
98                 pos   += len;
99         }
100
101         return pos;
102 }
103
104 static void encode(char *filename, int subbands, int bitpool, int joint)
105 {
106         struct au_header *au_hdr;
107         unsigned char input[2048], output[2048];
108         sbc_t sbc;
109         int fd, len, size, count, encoded;
110
111         if (strcmp(filename, "-")) {
112                 fd = open(filename, O_RDONLY);
113                 if (fd < 0) {
114                         fprintf(stderr, "Can't open file %s: %s\n",
115                                                 filename, strerror(errno));
116                         return;
117                 }
118         } else
119                 fd = fileno(stdin);
120
121         len = __read(fd, input, sizeof(input));
122         if (len < sizeof(*au_hdr)) {
123                 if (fd > fileno(stderr))
124                         fprintf(stderr, "Can't read header from file %s: %s\n",
125                                                 filename, strerror(errno));
126                 else
127                         perror("Can't read audio header");
128                 goto done;
129         }
130
131         au_hdr = (struct au_header *) input;
132
133         if (au_hdr->magic != AU_MAGIC ||
134                         BE_INT(au_hdr->hdr_size) > 128 ||
135                         BE_INT(au_hdr->hdr_size) < 24 ||
136                         BE_INT(au_hdr->encoding) != AU_FMT_LIN16) {
137                 fprintf(stderr, "Data is not in Sun/NeXT audio S16_BE format\n");
138                 goto done;
139         }
140
141         sbc_init(&sbc, 0L);
142
143         switch (BE_INT(au_hdr->sample_rate)) {
144         case 16000:
145                 sbc.frequency = SBC_FREQ_16000;
146                 break;
147         case 32000:
148                 sbc.frequency = SBC_FREQ_32000;
149                 break;
150         case 44100:
151                 sbc.frequency = SBC_FREQ_44100;
152                 break;
153         case 48000:
154                 sbc.frequency = SBC_FREQ_48000;
155                 break;
156         }
157
158         sbc.subbands = subbands == 4 ? SBC_SB_4 : SBC_SB_8;
159
160         if (BE_INT(au_hdr->channels) == 1)
161                 sbc.mode = SBC_MODE_MONO;
162         else if (joint)
163                 sbc.mode = SBC_MODE_JOINT_STEREO;
164         else
165                 sbc.mode = SBC_MODE_STEREO;
166
167         sbc.endian = SBC_BE;
168         count = BE_INT(au_hdr->data_size);
169         size = len - BE_INT(au_hdr->hdr_size);
170         memmove(input, input + BE_INT(au_hdr->hdr_size), size);
171
172         sbc.bitpool = bitpool;
173
174         while (1) {
175                 if (size < sizeof(input)) {
176                         len = __read(fd, input + size, sizeof(input) - size);
177                         if (len == 0 && size == 0)
178                                 break;
179
180                         if (len < 0) {
181                                 perror("Can't read audio data");
182                                 break;
183                         }
184
185                         size += len;
186                 }
187
188                 len = sbc_encode(&sbc, input, size,
189                                         output, sizeof(output), &encoded);
190                 if (len < size)
191                         memmove(input, input + len, size - len);
192
193                 size -= len;
194
195                 len = __write(fileno(stdout), output, encoded);
196                 if (len == 0)
197                         break;
198
199                 if (len < 0 || len != encoded) {
200                         perror("Can't write SBC output");
201                         break;
202                 }
203         }
204
205         sbc_finish(&sbc);
206
207 done:
208         if (fd > fileno(stderr))
209                 close(fd);
210 }
211
212 static void usage(void)
213 {
214         printf("SBC encoder utility ver %s\n", VERSION);
215         printf("Copyright (c) 2004-2008  Marcel Holtmann\n\n");
216
217         printf("Usage:\n"
218                 "\tsbcenc [options] file(s)\n"
219                 "\n");
220
221         printf("Options:\n"
222                 "\t-h, --help           Display help\n"
223                 "\t-v, --verbose        Verbose mode\n"
224                 "\t-s, --subbands       Number of subbands to use (4 or 8)\n"
225                 "\t-b, --bitpool        Bitpool value (default is 32)\n"
226                 "\t-j, --joint          Joint stereo\n"
227                 "\n");
228 }
229
230 static struct option main_options[] = {
231         { "help",       0, 0, 'h' },
232         { "verbose",    0, 0, 'v' },
233         { "subbands",   1, 0, 's' },
234         { "bitpool",    1, 0, 'b' },
235         { "joint",      0, 0, 'j' },
236         { 0, 0, 0, 0 }
237 };
238
239 int main(int argc, char *argv[])
240 {
241         int i, opt, verbose = 0, subbands = 8, bitpool = 32, joint = 0;
242
243         while ((opt = getopt_long(argc, argv, "+hvs:b:j", main_options, NULL)) != -1) {
244                 switch(opt) {
245                 case 'h':
246                         usage();
247                         exit(0);
248
249                 case 'v':
250                         verbose = 1;
251                         break;
252
253                 case 's':
254                         subbands = atoi(optarg);
255                         if (subbands != 8 && subbands != 4) {
256                                 fprintf(stderr, "Invalid subbands %d!\n",
257                                                 subbands);
258                                 exit(1);
259                         }
260                         break;
261
262                 case 'b':
263                         bitpool = atoi(optarg);
264                         break;
265
266                 case 'j':
267                         joint = 1;
268                         break;
269
270                 default:
271                         exit(1);
272                 }
273         }
274
275         argc -= optind;
276         argv += optind;
277         optind = 0;
278
279         if (argc < 1) {
280                 usage();
281                 exit(1);
282         }
283
284         for (i = 0; i < argc; i++)
285                 encode(argv[i], subbands, bitpool, joint);
286
287         return 0;
288 }