add software volume control (currently only for libao but will be

used for alsa, too)


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1257 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Michael Gernoth 2006-09-17 14:41:16 +00:00
parent 66e7247196
commit 76459e4005
6 changed files with 160 additions and 20 deletions

View File

@ -194,26 +194,26 @@ fi
if test "$sound" = no; then
break
elif test "$sound" = auto; then
SOUNDOBJ="$SOUNDOBJ rdpsnd.o"
SOUNDOBJ="$SOUNDOBJ rdpsnd.o rdpsnd_dsp.o"
AC_DEFINE(WITH_RDPSND)
elif test "$sound" = oss; then
SOUNDOBJ="rdpsnd.o rdpsnd_oss.o"
SOUNDOBJ="rdpsnd.o rdpsnd_dsp.o rdpsnd_oss.o"
AC_DEFINE(WITH_RDPSND)
elif test "$sound" = sgi; then
SOUNDOBJ="rdpsnd.o rdpsnd_sgi.o"
SOUNDOBJ="rdpsnd.o rdpsnd_dsp.o rdpsnd_sgi.o"
LDFLAGS="$LDFLAGS -laudio"
elif test "$sound" = yes; then
SOUNDOBJ="$SOUNDOBJ rdpsnd.o"
SOUNDOBJ="$SOUNDOBJ rdpsnd.o rdpsnd_dsp.o"
AC_DEFINE(WITH_RDPSND)
elif test "$sound" = sun; then
SOUNDOBJ="rdpsnd.o rdpsnd_sun.o"
SOUNDOBJ="rdpsnd.o rdpsnd_dsp.o rdpsnd_sun.o"
AC_DEFINE(WITH_RDPSND)
elif test "$sound" = libao; then
SOUNDOBJ="rdpsnd.o rdpsnd_libao.o"
SOUNDOBJ="rdpsnd.o rdpsnd_dsp.o rdpsnd_libao.o"
LDFLAGS="$LDFLAGS -lao"
AC_DEFINE(RDPSND_SUN)
elif test "$sound" = alsa; then
SOUNDOBJ="rdpsnd.o rdpsnd_alsa.o"
SOUNDOBJ="rdpsnd.o rdpsnd_dsp.o rdpsnd_alsa.o"
LDFLAGS="$LDFLAGS -lasound"
AC_DEFINE(WITH_RDPSND)
AC_DEFINE(RDPSND_ALSA)

View File

@ -21,6 +21,7 @@
#include "rdesktop.h"
#include "rdpsnd.h"
#include "rdpsnd_dsp.h"
#define RDPSND_CLOSE 1
#define RDPSND_WRITE 2
@ -393,12 +394,17 @@ rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
queue_hi = next_hi;
packet->s = *s;
packet->s.data =
rdpsnd_dsp_process(s->data, s->size, current_driver, &formats[current_format]);
packet->s.p = packet->s.data + 4;
packet->s.end = packet->s.data + s->size;
packet->tick = tick;
packet->index = index;
packet->s.p += 4;
#if 0 /* Handled by DSP */
/* we steal the data buffer from s, give it a new one */
s->data = malloc(s->size);
s->data = xmalloc(s->size);
#endif
if (!g_dsp_busy)
current_driver->wave_out_play();
@ -425,7 +431,7 @@ rdpsnd_queue_init(void)
inline void
rdpsnd_queue_next(void)
{
free(packet_queue[queue_lo].s.data);
xfree(packet_queue[queue_lo].s.data);
queue_lo = (queue_lo + 1) % MAX_QUEUE;
}

116
rdpsnd_dsp.c Normal file
View File

@ -0,0 +1,116 @@
/*
rdesktop: A Remote Desktop Protocol client.
Sound DSP routines
Copyright (C) Michael Gernoth 2006
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rdesktop.h"
#include "rdpsnd.h"
#include "rdpsnd_dsp.h"
#define MAX_VOLUME 65535
static uint16 softvol_left = MAX_VOLUME;
static uint16 softvol_right = MAX_VOLUME;
void
rdpsnd_dsp_softvol_set(uint16 left, uint16 right)
{
softvol_left = left;
softvol_right = right;
DEBUG(("rdpsnd_dsp_softvol_set: left: %u, right: %u\n", left, right));
}
inline void
rdpsnd_dsp_softvol(unsigned char *inbuffer, unsigned char *outbuffer, unsigned int size,
WAVEFORMATEX * format)
{
unsigned int factor_left, factor_right;
unsigned char *posin = inbuffer;
unsigned char *posout = outbuffer;
factor_left = (softvol_left * 256) / 65535;
factor_right = (softvol_right * 256) / 65535;
if (format->nChannels == 1)
{
factor_left = factor_right = (factor_left + factor_right) / 2;
}
if (format->wBitsPerSample == 8)
{
char val;
while (posout < outbuffer + size)
{
/* Left */
val = *posin++;
val = (val * factor_left) >> 8;
*posout++ = val;
/* Right */
val = *posin++;
val = (val * factor_right) >> 8;
*posout++ = val;
}
}
else
{
short val;
while (posout < outbuffer + size)
{
/* Left */
val = *posin++;
val |= *posin++ << 8;
val = (val * factor_left) >> 8;
*posout++ = val & 0xff;
*posout++ = val >> 8;
/* Right */
val = *posin++;
val |= *posin++ << 8;
val = (val * factor_right) >> 8;
*posout++ = val & 0xff;
*posout++ = val >> 8;
}
}
DEBUG(("using softvol with shifts left: %d, right: %d (%d/%d)\n", factor_left, factor_right,
format->wBitsPerSample, format->nChannels));
}
unsigned char *
rdpsnd_dsp_process(unsigned char *inbuffer, unsigned int size, struct audio_driver *current_driver,
WAVEFORMATEX * format)
{
unsigned char *outbuffer;
outbuffer = xmalloc(size);
/* Software volume control */
if (current_driver->wave_out_volume == rdpsnd_dsp_softvol_set)
{
rdpsnd_dsp_softvol(inbuffer, outbuffer, size, format);
}
else
{
memcpy(outbuffer, inbuffer, size);
}
return outbuffer;
}

23
rdpsnd_dsp.h Normal file
View File

@ -0,0 +1,23 @@
/*
rdesktop: A Remote Desktop Protocol client.
Sound DSP routines
Copyright (C) Michael Gernoth 2006
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
void rdpsnd_dsp_softvol_set(uint16 left, uint16 right);
unsigned char *rdpsnd_dsp_process(unsigned char *inbuffer, unsigned int size,
struct audio_driver *current_driver, WAVEFORMATEX * format);

View File

@ -22,6 +22,7 @@
#include "rdesktop.h"
#include "rdpsnd.h"
#include "rdpsnd_dsp.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
@ -136,12 +137,6 @@ libao_set_format(WAVEFORMATEX * pwfx)
return True;
}
void
libao_volume(uint16 left, uint16 right)
{
warning("volume changes not supported with libao-output\n");
}
void
libao_play(void)
{
@ -244,7 +239,7 @@ libao_register(char *options)
libao_driver.wave_out_close = libao_close;
libao_driver.wave_out_format_supported = libao_format_supported;
libao_driver.wave_out_set_format = libao_set_format;
libao_driver.wave_out_volume = libao_volume;
libao_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
libao_driver.wave_out_play = libao_play;
libao_driver.name = xstrdup("libao");
libao_driver.description = xstrdup("libao output driver");