3 * Bluetooth low-complexity, subband codec (SBC) encoder
5 * Copyright (C) 2008-2010 Nokia Corporation
6 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
7 * Copyright (C) 2012-2013 Intel Corporation
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
44 static int verbose = 0;
46 #define BUF_SIZE 32768
47 static unsigned char input[BUF_SIZE], output[BUF_SIZE + BUF_SIZE / 4];
49 static void encode(char *filename, int subbands, int bitpool, int joint,
50 int dualchannel, int snr, int blocks, bool msbc)
52 struct au_header au_hdr;
54 int fd, size, srate, codesize, nframes;
58 if (sizeof(au_hdr) != 24) {
59 /* Sanity check just in case */
60 fprintf(stderr, "FIXME: sizeof(au_hdr) != 24\n");
64 if (strcmp(filename, "-")) {
65 fd = open(filename, O_RDONLY);
67 fprintf(stderr, "Can't open file %s: %s\n",
68 filename, strerror(errno));
74 len = read(fd, &au_hdr, sizeof(au_hdr));
75 if (len < (ssize_t) sizeof(au_hdr)) {
76 if (fd > fileno(stderr))
77 fprintf(stderr, "Can't read header from file %s: %s\n",
78 filename, strerror(errno));
80 perror("Can't read audio header");
84 if (au_hdr.magic != AU_MAGIC ||
85 BE_INT(au_hdr.hdr_size) > 128 ||
86 BE_INT(au_hdr.hdr_size) < sizeof(au_hdr) ||
87 BE_INT(au_hdr.encoding) != AU_FMT_LIN16) {
88 fprintf(stderr, "Not in Sun/NeXT audio S16_BE format\n");
95 switch (BE_INT(au_hdr.sample_rate)) {
97 sbc.frequency = SBC_FREQ_16000;
100 sbc.frequency = SBC_FREQ_32000;
103 sbc.frequency = SBC_FREQ_44100;
106 sbc.frequency = SBC_FREQ_48000;
110 srate = BE_INT(au_hdr.sample_rate);
112 sbc.subbands = subbands == 4 ? SBC_SB_4 : SBC_SB_8;
114 if (BE_INT(au_hdr.channels) == 1) {
115 sbc.mode = SBC_MODE_MONO;
116 if (joint || dualchannel) {
117 fprintf(stderr, "Audio is mono but joint or "
118 "dualchannel mode has been specified\n");
121 } else if (joint && !dualchannel)
122 sbc.mode = SBC_MODE_JOINT_STEREO;
123 else if (!joint && dualchannel)
124 sbc.mode = SBC_MODE_DUAL_CHANNEL;
125 else if (!joint && !dualchannel)
126 sbc.mode = SBC_MODE_STEREO;
128 fprintf(stderr, "Both joint and dualchannel "
129 "mode have been specified\n");
134 sbc.bitpool = bitpool;
135 sbc.allocation = snr ? SBC_AM_SNR : SBC_AM_LOUDNESS;
136 sbc.blocks = blocks == 4 ? SBC_BLK_4 :
137 blocks == 8 ? SBC_BLK_8 :
138 blocks == 12 ? SBC_BLK_12 : SBC_BLK_16;
140 if (BE_INT(au_hdr.sample_rate) != 16000 ||
141 BE_INT(au_hdr.channels) != 1 ||
142 BE_INT(au_hdr.channels) != 1) {
143 fprintf(stderr, "mSBC requires 16 bits, 16kHz, mono "
148 sbc_init_msbc(&sbc, 0);
152 /* Skip extra bytes of the header if any */
153 if (read(fd, input, BE_INT(au_hdr.hdr_size) - len) < 0)
157 fprintf(stderr, "encoding %s with rate %d, %d blocks, "
158 "%d subbands, %d bits, allocation method %s, "
160 filename, srate, blocks, subbands, bitpool,
161 sbc.allocation == SBC_AM_SNR ? "SNR" : "LOUDNESS",
162 sbc.mode == SBC_MODE_MONO ? "MONO" :
163 sbc.mode == SBC_MODE_STEREO ?
164 "STEREO" : "JOINTSTEREO");
167 codesize = sbc_get_codesize(&sbc);
168 nframes = sizeof(input) / codesize;
170 unsigned char *inp, *outp;
171 /* read data for up to 'nframes' frames of input data */
172 size = read(fd, input, codesize * nframes);
174 /* Something really bad happened */
175 perror("Can't read audio data");
178 if (size < codesize) {
179 /* Not enough data for encoding even a single frame */
182 /* encode all the data from the input buffer in a loop */
185 while (size >= codesize) {
186 len = sbc_encode(&sbc, inp, codesize,
187 outp, sizeof(output) - (outp - output),
189 if (len != codesize || encoded <= 0) {
191 "sbc_encode fail, len=%zd, encoded=%lu\n",
192 len, (unsigned long) encoded);
199 len = write(fileno(stdout), output, outp - output);
200 if (len != outp - output) {
201 perror("Can't write SBC output");
206 * sbc_encode failure has been detected earlier or end
207 * of file reached (have trailing partial data which is
208 * insufficient to encode SBC frame)
217 if (fd > fileno(stderr))
221 static void usage(void)
223 printf("SBC encoder utility ver %s\n", VERSION);
224 printf("Copyright (c) 2004-2010 Marcel Holtmann\n\n");
227 "\tsbcenc [options] file(s)\n"
231 "\t-h, --help Display help\n"
232 "\t-v, --verbose Verbose mode\n"
233 "\t-m, --msbc mSBC codec\n"
234 "\t-s, --subbands Number of subbands to use (4 or 8)\n"
235 "\t-b, --bitpool Bitpool value (default is 32)\n"
236 "\t-j, --joint Joint stereo\n"
237 "\t-d, --dualchannel Dual channel\n"
238 "\t-S, --snr Use SNR mode (default is loudness)\n"
239 "\t-B, --blocks Number of blocks (4, 8, 12 or 16)\n"
243 static struct option main_options[] = {
244 { "help", 0, 0, 'h' },
245 { "verbose", 0, 0, 'v' },
246 { "msbc", 0, 0, 'm' },
247 { "subbands", 1, 0, 's' },
248 { "bitpool", 1, 0, 'b' },
249 { "joint", 0, 0, 'j' },
250 { "dualchannel",0, 0, 'd' },
251 { "snr", 0, 0, 'S' },
252 { "blocks", 1, 0, 'B' },
256 int main(int argc, char *argv[])
258 int i, opt, subbands = 8, bitpool = 32, joint = 0, dualchannel = 0;
259 int snr = 0, blocks = 16;
262 while ((opt = getopt_long(argc, argv, "+hmvs:b:jdSB:",
263 main_options, NULL)) != -1) {
278 subbands = atoi(optarg);
279 if (subbands != 8 && subbands != 4) {
280 fprintf(stderr, "Invalid subbands\n");
286 bitpool = atoi(optarg);
302 blocks = atoi(optarg);
303 if (blocks != 16 && blocks != 12 &&
304 blocks != 8 && blocks != 4) {
305 fprintf(stderr, "Invalid blocks\n");
325 for (i = 0; i < argc; i++)
326 encode(argv[i], subbands, bitpool, joint, dualchannel,