public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
* [Bluez-devel] FW: REALLY Bad encoding performance of Linux SBC audio codec
@ 2008-10-30 14:54 Christian Hoene
  2008-10-30 15:20 ` Christian Hoene
  0 siblings, 1 reply; 10+ messages in thread
From: Christian Hoene @ 2008-10-30 14:54 UTC (permalink / raw)
  To: 'Frans de Bont'; +Cc: 'BlueZ development'


[-- Attachment #1.1: Type: text/plain, Size: 3566 bytes --]

Hello Frans,

 

thank you for the patch!!

 

Christian

 

 

From: Frans de Bont [mailto:frans.de.bont@philips.com] 
Sent: Thursday, October 30, 2008 2:34 PM
To: Christian Hoene
Subject: RE: [Bluez-devel] REALLY Bad encoding performance of Linux SBC
audio codec

 


Hello Christian, 

I had a quick look into the bluez sbc decoder test application. 
I discovered that the buffering was not correct. 
Attached a modified version. 

Please note that the output level of the decoder is still 6 dB too low. 
This wouldn't be too difficult to fix for the bluez developers. 

Best regards, 
Frans 










"Christian Hoene" <hoene@uni-tuebingen.de> 

2008-10-29 04:30 PM 


To

"'BlueZ development'" <bluez-devel@lists.sourceforge.net> 


cc

Frans de Bont/EHV/APPTECH/PHILIPS@PHILIPS 


Subject

RE: [Bluez-devel] REALLY Bad encoding performance of Linux SBC         audio
codec 


Classification

	

 

		




Hello,

Sorry Bad news. 
the encoding and decodng performance of bluez's SBC is really bad. 
I just used the latest sbcenc program from bluez-4.17 and compared it to the
reference

Attached you will find wav-files encoded with the Bluetooth reference
implementation and bluez

Filelist
========
compare.sh                         is the scrip that I use to compare both
codec
versions
refsop01.wav        the original sample
tmp.ref.sbc         with reference encoded
tmp.bluez.sbc       with bluez encoded
tmp.ref.sw.wav      with reference encoded and decoded (has good quality)
tmp.bluez.sw.wav    with bluez encoded and decoded (has bad quality ODG=)
tmp.refbluez.sw.wav with reference encoded and with bluez decoded (has bad
quality)
tmp.bluezref.sw.wav with bluez encoded and with reference decoded (has
medium quality)

Both the bluez encoder and decoder do not work as good as the reference
implementation.

I also conducted some perceptual audio tests with ITU BS.1387 (PEAQ), which
confirm these results.

With best regards,

Christian

PS:
Attached also an enhanced version for sbc/sbcenc.c, which considers more
command line options.



> -----Original Message-----
> From: Marcel Holtmann [mailto:marcel@holtmann.org]
> Sent: Monday, October 27, 2008 8:42 PM
> To: BlueZ development
> Subject: Re: [Bluez-devel] Bad encoding performance of Linux SBC audio
> codec
> 
> Hi Brad,
> 
> > > I am sorry to say that the audio quality of the open source version
> of SBC
> > > is far worse than the reference implementation.
> >
> > If you are using the standalone "sbc" project at sourceforge, then
> you
> > should try the version inside bluez. The standalone used to simply be
> > slower, but we identified & fixed some quality issues too that should
> > be backported.
> 
> the standalone version should not be used at all at the moment. All
> efforts should go into the version included in bluez-4.x.tar.gz.
> 
> Regards
> 
> Marcel
> 
> 
> 
> -----------------------------------------------------------------------
> --
> This SF.Net email is sponsored by the Moblin Your Move Developer's
> challenge
> Build the coolest Linux based applications with Moblin SDK & win great
> prizes
> Grand prize is a trip for two to an Open Source event anywhere in the
> world
> http://moblin-contest.org/redirect.php?banner_id=100&url=/
> _______________________________________________
> Bluez-devel mailing list
> Bluez-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/bluez-devel
[attachment "sbcenc.c" deleted by Frans de Bont/EHV/APPTECH/PHILIPS]
[attachment "compare.tar.gz" deleted by Frans de Bont/EHV/APPTECH/PHILIPS] 


[-- Attachment #1.2: Type: text/html, Size: 11613 bytes --]

[-- Attachment #2: sbcdec.c --]
[-- Type: application/octet-stream, Size: 6411 bytes --]

/*
 *
 *  Bluetooth low-complexity, subband codec (SBC) decoder
 *
 *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>

#include "sbc.h"
#include "formats.h"

#define BUF_SIZE 8192

static void decode(char *filename, char *output, int tofile)
{
	unsigned char buf[BUF_SIZE], *stream;
	struct stat st;
	off_t filesize;
	sbc_t sbc;
	int fd, ad, pos, streamlen, framelen, count, written, len;
	int format = AFMT_S16_BE, frequency, channels;

	if (stat(filename, &st) < 0) {
		fprintf(stderr, "Can't get size of file %s: %s\n",
						filename, strerror(errno));
		return;
	}

	filesize = st.st_size;
	stream = malloc(st.st_size);

	if (!stream) {
		fprintf(stderr, "Can't allocate memory for %s: %s\n",
						filename, strerror(errno));
		return;
	}

	fd = open(filename, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Can't open file %s: %s\n",
						filename, strerror(errno));
		goto free;
	}

	if (read(fd, stream, st.st_size) != st.st_size) {
		fprintf(stderr, "Can't read content of %s: %s\n",
						filename, strerror(errno));
		close(fd);
		goto free;
	}

	close(fd);

	pos = 0;
	streamlen = st.st_size;

	if (tofile)
		ad = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0644);
	else
		ad = open(output, O_WRONLY, 0);

	if (ad < 0) {
		fprintf(stderr, "Can't open output %s: %s\n",
						output, strerror(errno));
		goto free;
	}

	sbc_init(&sbc, 0L);
	sbc.endian = SBC_BE;

	framelen = sbc_decode(&sbc, stream, streamlen, buf, sizeof(buf), &len);
	channels = sbc.mode == SBC_MODE_MONO ? 1 : 2;
	switch (sbc.frequency) {
	case SBC_FREQ_16000:
		frequency = 16000;
		break;

	case SBC_FREQ_32000:
		frequency = 32000;
		break;

	case SBC_FREQ_44100:
		frequency = 44100;
		break;

	case SBC_FREQ_48000:
		frequency = 48000;
		break;
	default:
		frequency = 0;
	}

	printf("%d Hz, %d channels\n", frequency, channels);
	if (tofile) {
		struct au_header au_hdr;

		au_hdr.magic       = AU_MAGIC;
		au_hdr.hdr_size    = BE_INT(24);
		au_hdr.data_size   = BE_INT(0);
		au_hdr.encoding    = BE_INT(AU_FMT_LIN16);
		au_hdr.sample_rate = BE_INT(frequency);
		au_hdr.channels    = BE_INT(channels);

		written = write(ad, &au_hdr, sizeof(au_hdr));
		if (written < sizeof(au_hdr)) {
			fprintf(stderr, "Failed to write header\n");
			goto close;
		}
	} else {
		if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) {
			fprintf(stderr, "Can't set audio format on %s: %s\n",
					output, strerror(errno));
			goto close;
		}

		if (ioctl(ad, SNDCTL_DSP_CHANNELS, &channels) < 0) {
			fprintf(stderr,
				"Can't set number of channels on %s: %s\n",
				output, strerror(errno));
			goto close;
		}

		if (ioctl(ad, SNDCTL_DSP_SPEED, &frequency) < 0) {
			fprintf(stderr, "Can't set audio rate on %s: %s\n",
					output, strerror(errno));
			goto close;
		}
	}

	count = len;
	while (framelen > 0) {
		/* we have completed an sbc_decode at this point sbc.len is the
		 * length of the frame we just decoded count is the number of
		 * decoded bytes yet to be written */

		if (count + len >= BUF_SIZE) {
			/* buffer is too full to stuff decoded audio in so it
			 * must be written to the device */
			written = write(ad, buf, count);
			if (written > 0)
				count -= written;
		}

		/* sanity check */
		if (count + len >= BUF_SIZE) {
			fprintf(stderr,
				"buffer size of %d is too small for decoded"
				" data (%d)\n", BUF_SIZE, len + count);
			exit(1);
		}

		/* push the pointer in the file forward to the next bit to be
		 * decoded tell the decoder to decode up to the remaining
		 * length of the file (!) */
		pos += framelen;
		framelen = sbc_decode(&sbc, stream + pos, streamlen - pos,
					buf + count, sizeof(buf) - count, &len);

		/* increase the count */
		count += len;
	}

	if (count > 0) {
		written = write(ad, buf, count);
		if (written > 0)
			count -= written;
	}

close:
	sbc_finish(&sbc);

	close(ad);

free:
	free(stream);
}

static void usage(void)
{
	printf("SBC decoder utility ver %s\n", VERSION);
	printf("Copyright (c) 2004-2008  Marcel Holtmann\n\n");

	printf("Usage:\n"
		"\tsbcdec [options] file(s)\n"
		"\n");

	printf("Options:\n"
		"\t-h, --help           Display help\n"
		"\t-v, --verbose        Verbose mode\n"
		"\t-d, --device <dsp>   Sound device\n"
		"\t-f, --file <file>    Decode to a file\n"
		"\n");
}

static struct option main_options[] = {
	{ "help",	0, 0, 'h' },
	{ "device",	1, 0, 'd' },
	{ "verbose",	0, 0, 'v' },
	{ "file",	1, 0, 'f' },
	{ 0, 0, 0, 0 }
};

int main(int argc, char *argv[])
{
	char *output = NULL;
	int i, opt, verbose = 0, tofile = 0;

	while ((opt = getopt_long(argc, argv, "+hvd:f:", main_options, NULL)) != -1) {
		switch(opt) {
		case 'h':
			usage();
			exit(0);

		case 'v':
			verbose = 1;
			break;

		case 'd':
			if (output)
				free(output);
			output = strdup(optarg);
			tofile = 0;
			break;

		case 'f' :
			if (output)
				free(output);
			output = strdup(optarg);
			tofile = 1;
			break;

		default:
			exit(1);
		}
	}

	argc -= optind;
	argv += optind;
	optind = 0;

	if (argc < 1) {
		usage();
		exit(1);
	}

	for (i = 0; i < argc; i++)
		decode(argv[i], output ? output : "/dev/dsp", tofile);

	if (output)
		free(output);

	return 0;
}

[-- Attachment #3: Type: text/plain, Size: 363 bytes --]

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

[-- Attachment #4: Type: text/plain, Size: 164 bytes --]

_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2008-10-31 18:50 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-30 14:54 [Bluez-devel] FW: REALLY Bad encoding performance of Linux SBC audio codec Christian Hoene
2008-10-30 15:20 ` Christian Hoene
2008-10-30 15:46   ` Luiz Augusto von Dentz
2008-10-30 16:07     ` Christian Hoene
2008-10-30 18:02       ` Marcel Holtmann
2008-10-30 18:03   ` Marcel Holtmann
2008-10-30 18:48   ` Brad Midgley
2008-10-31 10:23     ` Christian Hoene
2008-10-31 11:10       ` Craig Southeren
2008-10-31 18:50       ` Marcel Holtmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox