From 5d67a3e03630d123887e244605534fd1988da2e7 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Mon, 13 Oct 2003 16:09:45 +0000 Subject: [PATCH] Volume control for OSS & SUN Ignore first 4 bytes of audio-packet (clicking noise) git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@490 423420c4-83ab-492f-b58f-81f9feb106b5 --- constants.h | 5 ++++- proto.h | 1 + rdpsnd.c | 16 ++++++++++++++-- rdpsnd_oss.c | 17 ++++++++++++++++- rdpsnd_sun.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 76 insertions(+), 9 deletions(-) diff --git a/constants.h b/constants.h index 101cf58..e56077b 100644 --- a/constants.h +++ b/constants.h @@ -293,7 +293,10 @@ enum RDP_INPUT_DEVICE #define CF_GDIOBJLAST 1023 /* Sound format constants */ -#define WAVE_FORMAT_PCM 1 +#define WAVE_FORMAT_PCM 1 +#define WAVE_FORMAT_ADPCM 2 +#define WAVE_FORMAT_ALAW 6 +#define WAVE_FORMAT_MULAW 7 /* Virtual channel options */ #define CHANNEL_OPTION_INITIALIZED 0x80000000 diff --git a/proto.h b/proto.h index 24f1f25..5e6ed22 100644 --- a/proto.h +++ b/proto.h @@ -89,6 +89,7 @@ BOOL wave_out_format_supported(WAVEFORMATEX *pwfx); BOOL wave_out_set_format(WAVEFORMATEX *pwfx); void wave_out_write(STREAM s, uint16 tick, uint8 index); void wave_out_play(void); +void wave_out_volume(uint16 left, uint16 right); /* secure.c */ void sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt); void sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2); diff --git a/rdpsnd.c b/rdpsnd.c index e962388..41e1b2d 100644 --- a/rdpsnd.c +++ b/rdpsnd.c @@ -78,11 +78,18 @@ rdpsnd_process_negotiate(STREAM in) unsigned int in_format_count, i; WAVEFORMATEX *format; STREAM out; + BOOL device_available = False; in_uint8s(in, 14); /* flags, volume, pitch, UDP port */ in_uint16_le(in, in_format_count); in_uint8s(in, 4); /* pad, status, pad */ + if (wave_out_open()) + { + wave_out_close(); + device_available = True; + } + format_count = 0; if (s_check_rem(in, 18*in_format_count)) { @@ -97,7 +104,7 @@ rdpsnd_process_negotiate(STREAM in) in_uint16_le(in, format->wBitsPerSample); in_uint16_le(in, format->cbSize); - if (wave_out_format_supported(format)) + if (device_available && wave_out_format_supported(format)) { format_count++; if (format_count == MAX_FORMATS) @@ -155,6 +162,7 @@ rdpsnd_process(STREAM s) { uint8 type; uint16 datalen; + uint32 volume; static uint16 tick, format; static uint8 packet_index; static BOOL awaiting_data_packet; @@ -218,7 +226,11 @@ rdpsnd_process(STREAM s) rdpsnd_process_unknown6(s); break; case RDPSND_SET_VOLUME: - /* uint32 volume */ + in_uint32(s, volume); + if ( device_open ) + { + wave_out_volume((volume & 0xffff), (volume & 0xffff0000) >> 16); + } break; default: unimpl("RDPSND packet type %d\n", type); diff --git a/rdpsnd_oss.c b/rdpsnd_oss.c index c1e89f9..29968b3 100644 --- a/rdpsnd_oss.c +++ b/rdpsnd_oss.c @@ -43,7 +43,7 @@ wave_out_open(void) { char *dsp_dev = "/dev/dsp"; - if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1) + if ((g_dsp_fd = open(dsp_dev, O_WRONLY|O_NONBLOCK)) == -1) { perror(dsp_dev); return False; @@ -112,6 +112,20 @@ wave_out_set_format(WAVEFORMATEX *pwfx) return True; } +void +wave_out_volume(uint16 left, uint16 right) +{ + uint32 volume; + + volume = left/(65536/100); + volume |= right/(65536/100) << 8; + if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1) + { + perror("MIXER_WRITE(SOUND_MIXER_PCM)"); + return; + } +} + void wave_out_write(STREAM s, uint16 tick, uint8 index) { @@ -129,6 +143,7 @@ wave_out_write(STREAM s, uint16 tick, uint8 index) packet->s = *s; packet->tick = tick; packet->index = index; + packet->s.p += 4; /* we steal the data buffer from s, give it a new one */ s->data = malloc(s->size); diff --git a/rdpsnd_sun.c b/rdpsnd_sun.c index 8f05175..bde8a9c 100644 --- a/rdpsnd_sun.c +++ b/rdpsnd_sun.c @@ -111,16 +111,16 @@ wave_out_set_format(WAVEFORMATEX *pwfx) if (pwfx->wBitsPerSample == 8) { info.play.encoding = AUDIO_ENCODING_LINEAR8; - samplewidth = 1; } else if (pwfx->wBitsPerSample == 16) { info.play.encoding = AUDIO_ENCODING_LINEAR; - samplewidth = 2; /* Do we need to swap the 16bit values? (Are we BigEndian) */ swapaudio = !(*(uint8 *) (&test)); } + samplewidth = pwfx->wBitsPerSample/8; + if (pwfx->nChannels == 1 ) { info.play.channels = AUDIO_CHANNELS_MONO; @@ -136,6 +136,7 @@ wave_out_set_format(WAVEFORMATEX *pwfx) info.play.samples = 0; info.play.eof = 0; info.play.error = 0; + reopened = True; if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1) { @@ -147,6 +148,40 @@ wave_out_set_format(WAVEFORMATEX *pwfx) return True; } +void +wave_out_volume(uint16 left, uint16 right) +{ + audio_info_t info; + uint balance; + uint volume; + + if (ioctl(g_dsp_fd, AUDIO_GETINFO, &info) == -1) + { + perror("AUDIO_GETINFO"); + return; + } + + volume = (left > right) ? left : right; + + if ( volume/AUDIO_MID_BALANCE != 0 ) + { + balance = AUDIO_MID_BALANCE - (left/(volume/AUDIO_MID_BALANCE)) + (right/(volume/AUDIO_MID_BALANCE)); + } + else + { + balance = AUDIO_MID_BALANCE; + } + + info.play.gain = volume/(65536/AUDIO_MAX_GAIN); + info.play.balance = balance; + + if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1) + { + perror("AUDIO_SETINFO"); + return; + } +} + void wave_out_write(STREAM s, uint16 tick, uint8 index) { @@ -164,6 +199,7 @@ wave_out_write(STREAM s, uint16 tick, uint8 index) packet->s = *s; packet->tick = tick; packet->index = index; + packet->s.p += 4; /* we steal the data buffer from s, give it a new one */ s->data = malloc(s->size); @@ -209,13 +245,13 @@ wave_out_play(void) /* Swap the current packet, but only once */ if ( swapaudio && ! swapped ) { - for ( i = 0; i < out->end - out->p; i+=2 ) + for ( i = 0; i < out->end - out->p; i += 2 ) { swap = *(out->p + i); - *(out->p + i ) = *(out->p + i + 1); + *(out->p + i) = *(out->p + i + 1); *(out->p + i + 1) = swap; - swapped = True; } + swapped = True; } if ( sentcompletion )