15430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann/*
25430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *
31d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley *  Bluetooth low-complexity, subband codec (SBC) encoder
45430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *
55592142cb9383df0556b27ac59e96547b380310bJohan Hedberg *  Copyright (C) 2008-2010  Nokia Corporation
69184e2eeb7b97371c6b83b747c8984e2340d2b47Marcel Holtmann *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
75430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *
85430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *
95430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  This program is free software; you can redistribute it and/or modify
105430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  it under the terms of the GNU General Public License as published by
115430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  the Free Software Foundation; either version 2 of the License, or
125430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  (at your option) any later version.
135430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *
145430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  This program is distributed in the hope that it will be useful,
155430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  but WITHOUT ANY WARRANTY; without even the implied warranty of
165430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
175430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  GNU General Public License for more details.
185430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *
195430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  You should have received a copy of the GNU General Public License
205430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  along with this program; if not, write to the Free Software
215430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
225430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann *
235430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann */
245430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann
255430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann#ifdef HAVE_CONFIG_H
265430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann#include <config.h>
275430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann#endif
285430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann
291d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley#include <stdio.h>
301d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley#include <errno.h>
311d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley#include <fcntl.h>
321d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley#include <unistd.h>
331d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley#include <stdlib.h>
341d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley#include <stdint.h>
351d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley#include <string.h>
361d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley#include <getopt.h>
371d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley#include <sys/stat.h>
381d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
395430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann#include "sbc.h"
40f0fc782355d3cf567694e096828a9c6bf177837eMarcel Holtmann#include "formats.h"
411d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
42c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmannstatic int verbose = 0;
43c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann
44e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka#define BUF_SIZE 32768
45e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashkastatic unsigned char input[BUF_SIZE], output[BUF_SIZE + BUF_SIZE / 4];
461d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
47440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmannstatic void encode(char *filename, int subbands, int bitpool, int joint,
48440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann					int dualchannel, int snr, int blocks)
491d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley{
50e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka	struct au_header au_hdr;
511d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	sbc_t sbc;
52c43f8bdcc1d527e2d77481a66217771038be3acdLennart Poettering	int fd, size, srate, codesize, nframes;
53b3339488a913564059575d8c7f7c08f4d108bf9eJohan Hedberg	ssize_t encoded;
54ae6e4f68f37333e3dbd6b8b89445850b87bcbfe2Johan Hedberg	ssize_t len;
55906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka
56906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka	if (sizeof(au_hdr) != 24) {
57906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka		/* Sanity check just in case */
58906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka		fprintf(stderr, "FIXME: sizeof(au_hdr) != 24\n");
59906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka		return;
60906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka	}
611d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
621d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	if (strcmp(filename, "-")) {
631d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		fd = open(filename, O_RDONLY);
641d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		if (fd < 0) {
651d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			fprintf(stderr, "Can't open file %s: %s\n",
661d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley						filename, strerror(errno));
671d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			return;
681d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		}
691d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	} else
701d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		fd = fileno(stdin);
711d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
72e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka	len = read(fd, &au_hdr, sizeof(au_hdr));
73ae6e4f68f37333e3dbd6b8b89445850b87bcbfe2Johan Hedberg	if (len < (ssize_t) sizeof(au_hdr)) {
741d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		if (fd > fileno(stderr))
751d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			fprintf(stderr, "Can't read header from file %s: %s\n",
761d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley						filename, strerror(errno));
771d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		else
781d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			perror("Can't read audio header");
791d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		goto done;
801d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	}
811d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
82e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka	if (au_hdr.magic != AU_MAGIC ||
83e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			BE_INT(au_hdr.hdr_size) > 128 ||
84906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka			BE_INT(au_hdr.hdr_size) < sizeof(au_hdr) ||
85e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			BE_INT(au_hdr.encoding) != AU_FMT_LIN16) {
86440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		fprintf(stderr, "Not in Sun/NeXT audio S16_BE format\n");
871d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		goto done;
881d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	}
891d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
901d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	sbc_init(&sbc, 0L);
911d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
92e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka	switch (BE_INT(au_hdr.sample_rate)) {
93ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz	case 16000:
94ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		sbc.frequency = SBC_FREQ_16000;
95ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		break;
96ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz	case 32000:
97ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		sbc.frequency = SBC_FREQ_32000;
98ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		break;
99ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz	case 44100:
100ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		sbc.frequency = SBC_FREQ_44100;
101ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		break;
102ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz	case 48000:
103ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		sbc.frequency = SBC_FREQ_48000;
104ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		break;
105ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz	}
106ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz
107e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka	srate = BE_INT(au_hdr.sample_rate);
108c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann
109ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz	sbc.subbands = subbands == 4 ? SBC_SB_4 : SBC_SB_8;
110ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz
111e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka	if (BE_INT(au_hdr.channels) == 1) {
112ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		sbc.mode = SBC_MODE_MONO;
113440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		if (joint || dualchannel) {
114440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			fprintf(stderr, "Audio is mono but joint or "
115440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann				"dualchannel mode has been specified\n");
116440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			goto done;
117440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		}
118440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	} else if (joint && !dualchannel)
119ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		sbc.mode = SBC_MODE_JOINT_STEREO;
120440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	else if (!joint && dualchannel)
121440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		sbc.mode = SBC_MODE_DUAL_CHANNEL;
122440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	else if (!joint && !dualchannel)
123ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz		sbc.mode = SBC_MODE_STEREO;
124440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	else {
125440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		fprintf(stderr, "Both joint and dualchannel mode have been "
126440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann								"specified\n");
127440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		goto done;
128440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	}
129ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz
130ce342bf2524b69b19ea5a4ad604faf1aa40ad19cLuiz Augusto von Dentz	sbc.endian = SBC_BE;
131906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka	/* Skip extra bytes of the header if any */
132906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka	if (read(fd, input, BE_INT(au_hdr.hdr_size) - len) < 0)
133906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka		goto done;
1341d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
1350242f1216747b69686ae11fdb1de6f6badfc1f3aMarcel Holtmann	sbc.bitpool = bitpool;
136c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann	sbc.allocation = snr ? SBC_AM_SNR : SBC_AM_LOUDNESS;
137440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	sbc.blocks = blocks == 4 ? SBC_BLK_4 :
138440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			blocks == 8 ? SBC_BLK_8 :
139440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann				blocks == 12 ? SBC_BLK_12 : SBC_BLK_16;
140440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann
141440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	if (verbose) {
142440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		fprintf(stderr, "encoding %s with rate %d, %d blocks, "
143440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			"%d subbands, %d bits, allocation method %s, "
144440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann							"and mode %s\n",
145440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			filename, srate, blocks, subbands, bitpool,
146c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann			sbc.allocation == SBC_AM_SNR ? "SNR" : "LOUDNESS",
147c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann			sbc.mode == SBC_MODE_MONO ? "MONO" :
148c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann					sbc.mode == SBC_MODE_STEREO ?
149c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann						"STEREO" : "JOINTSTEREO");
150c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann	}
1510242f1216747b69686ae11fdb1de6f6badfc1f3aMarcel Holtmann
152e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka	codesize = sbc_get_codesize(&sbc);
153e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka	nframes = sizeof(input) / codesize;
1541d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	while (1) {
155e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		unsigned char *inp, *outp;
156e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		/* read data for up to 'nframes' frames of input data */
157e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		size = read(fd, input, codesize * nframes);
158e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		if (size < 0) {
159e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			/* Something really bad happened */
160e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			perror("Can't read audio data");
161e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			break;
162e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		}
163e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		if (size < codesize) {
164e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			/* Not enough data for encoding even a single frame */
165e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			break;
166e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		}
167e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		/* encode all the data from the input buffer in a loop */
168e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		inp = input;
169e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		outp = output;
170e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		while (size >= codesize) {
171e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			len = sbc_encode(&sbc, inp, codesize,
172e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka				outp, sizeof(output) - (outp - output),
173e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka				&encoded);
174e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			if (len != codesize || encoded <= 0) {
175e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka				fprintf(stderr,
176c43f8bdcc1d527e2d77481a66217771038be3acdLennart Poettering					"sbc_encode fail, len=%zd, encoded=%lu\n",
177c43f8bdcc1d527e2d77481a66217771038be3acdLennart Poettering					len, (unsigned long) encoded);
1781d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley				break;
1791d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			}
180e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			size -= len;
181e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			inp += len;
182e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			outp += encoded;
1831d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		}
184e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		len = write(fileno(stdout), output, outp - output);
185e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		if (len != outp - output) {
1861d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			perror("Can't write SBC output");
1871d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			break;
1881d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		}
189906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka		if (size != 0) {
190906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka			/*
191906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka			 * sbc_encode failure has been detected earlier or end
192906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka			 * of file reached (have trailing partial data which is
193906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka			 * insufficient to encode SBC frame)
194906a4655cc998bb4ef8f23f4e62ce916d37f7caaSiarhei Siamashka			 */
195e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka			break;
196e010fc175e9bedbd5d099f7e32068ad8a051cbecSiarhei Siamashka		}
1971d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	}
1981d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
1991d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	sbc_finish(&sbc);
2001d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
2011d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgleydone:
2021d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	if (fd > fileno(stderr))
2031d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		close(fd);
2041d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley}
2051d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
2061d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgleystatic void usage(void)
2071d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley{
2081d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	printf("SBC encoder utility ver %s\n", VERSION);
2099184e2eeb7b97371c6b83b747c8984e2340d2b47Marcel Holtmann	printf("Copyright (c) 2004-2010  Marcel Holtmann\n\n");
2101d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
2111d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	printf("Usage:\n"
2121d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		"\tsbcenc [options] file(s)\n"
2131d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		"\n");
2141d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
2151d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	printf("Options:\n"
2161d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		"\t-h, --help           Display help\n"
2171d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		"\t-v, --verbose        Verbose mode\n"
218aec1793366001cdda187e851f9e37113678d7ee8Marcel Holtmann		"\t-s, --subbands       Number of subbands to use (4 or 8)\n"
2190242f1216747b69686ae11fdb1de6f6badfc1f3aMarcel Holtmann		"\t-b, --bitpool        Bitpool value (default is 32)\n"
220aec1793366001cdda187e851f9e37113678d7ee8Marcel Holtmann		"\t-j, --joint          Joint stereo\n"
221440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		"\t-d, --dualchannel    Dual channel\n"
222c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann		"\t-S, --snr            Use SNR mode (default is loudness)\n"
223440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		"\t-B, --blocks         Number of blocks (4, 8, 12 or 16)\n"
2241d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		"\n");
2251d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley}
2261d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
2271d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgleystatic struct option main_options[] = {
2281d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	{ "help",	0, 0, 'h' },
2291d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	{ "verbose",	0, 0, 'v' },
2301d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	{ "subbands",	1, 0, 's' },
2310242f1216747b69686ae11fdb1de6f6badfc1f3aMarcel Holtmann	{ "bitpool",	1, 0, 'b' },
2321d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	{ "joint",	0, 0, 'j' },
233440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	{ "dualchannel",0, 0, 'd' },
234c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann	{ "snr",	0, 0, 'S' },
235440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	{ "blocks",	1, 0, 'B' },
2361d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	{ 0, 0, 0, 0 }
2371d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley};
2381d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
2395430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmannint main(int argc, char *argv[])
2405430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann{
241440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	int i, opt, subbands = 8, bitpool = 32, joint = 0, dualchannel = 0;
242440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	int snr = 0, blocks = 16;
2431d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
244440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann	while ((opt = getopt_long(argc, argv, "+hvs:b:jdSB:",
245c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann						main_options, NULL)) != -1) {
2461d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		switch(opt) {
2471d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		case 'h':
2481d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			usage();
2491d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			exit(0);
2501d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
2511d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		case 'v':
2521d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			verbose = 1;
2531d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			break;
254aec1793366001cdda187e851f9e37113678d7ee8Marcel Holtmann
2551d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		case 's':
2560242f1216747b69686ae11fdb1de6f6badfc1f3aMarcel Holtmann			subbands = atoi(optarg);
2571d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			if (subbands != 8 && subbands != 4) {
258440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann				fprintf(stderr, "Invalid subbands\n");
2591d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley				exit(1);
2601d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			}
2611d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			break;
262aec1793366001cdda187e851f9e37113678d7ee8Marcel Holtmann
2630242f1216747b69686ae11fdb1de6f6badfc1f3aMarcel Holtmann		case 'b':
2640242f1216747b69686ae11fdb1de6f6badfc1f3aMarcel Holtmann			bitpool = atoi(optarg);
2650242f1216747b69686ae11fdb1de6f6badfc1f3aMarcel Holtmann			break;
2660242f1216747b69686ae11fdb1de6f6badfc1f3aMarcel Holtmann
2671d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		case 'j':
2681d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			joint = 1;
2691d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			break;
2701d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
271440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		case 'd':
272440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			dualchannel = 1;
273440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			break;
274440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann
275c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann		case 'S':
276c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann			snr = 1;
277c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann			break;
278c4918c93aa30f2e3363e288989180124d3931118Marcel Holtmann
279440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		case 'B':
280440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			blocks = atoi(optarg);
281440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			if (blocks != 16 && blocks != 12 &&
282440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann						blocks != 8 && blocks != 4) {
283440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann				fprintf(stderr, "Invalid blocks\n");
284440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann				exit(1);
285440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			}
286440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			break;
287440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann
2881d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		default:
289440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann			usage();
2901d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley			exit(1);
2911d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		}
2921d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	}
2931d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
2941d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	argc -= optind;
2951d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	argv += optind;
2961d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	optind = 0;
2971d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
2981d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	if (argc < 1) {
2991d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		usage();
3001d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley		exit(1);
3011d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	}
3021d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
3031d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley	for (i = 0; i < argc; i++)
304440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann		encode(argv[i], subbands, bitpool, joint, dualchannel,
305440d5aa50c3e739927d469440395b72f739281ebMarcel Holtmann								snr, blocks);
3061d6beece31584c71a7ce730133923f2e1d0d3b7dBrad Midgley
3075430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann	return 0;
3085430ca31bc276a9d07c932383910ef600ef08c87Marcel Holtmann}
309