--- sourceforge.net/trunk/rdesktop/rdpsnd_libao.c 2006/09/17 10:32:18 1254 +++ sourceforge.net/trunk/rdesktop/rdpsnd_libao.c 2006/10/01 22:30:34 1290 @@ -22,35 +22,41 @@ #include "rdesktop.h" #include "rdpsnd.h" +#include "rdpsnd_dsp.h" #include #include #include #include #include -#define WAVEOUTBUF 16 +#define WAVEOUTLEN 1024 static ao_device *o_device = NULL; static int default_driver; -static int samplerate; -static int audiochannels; static BOOL reopened; -static short samplewidth; +static char *libao_device = NULL; BOOL -wave_out_open(void) +libao_open(void) { ao_sample_format format; ao_initialize(); - default_driver = ao_default_driver_id(); + + if (libao_device) + { + default_driver = ao_driver_id(libao_device); + } + else + { + default_driver = ao_default_driver_id(); + } format.bits = 16; format.channels = 2; - audiochannels = 2; format.rate = 44100; - samplerate = 44100; - format.byte_format = AO_FMT_LITTLE; + format.byte_format = AO_FMT_NATIVE; + o_device = ao_open_live(default_driver, &format, NULL); if (o_device == NULL) @@ -67,7 +73,7 @@ } void -wave_out_close(void) +libao_close(void) { /* Ack all remaining packets */ while (!rdpsnd_queue_empty()) @@ -84,35 +90,14 @@ } BOOL -wave_out_format_supported(WAVEFORMATEX * pwfx) -{ - if (pwfx->wFormatTag != WAVE_FORMAT_PCM) - return False; - if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2)) - return False; - if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16)) - return False; - /* The only common denominator between libao output drivers is a sample-rate of - 44100, we need to upsample 22050 to it */ - if ((pwfx->nSamplesPerSec != 44100) && (pwfx->nSamplesPerSec != 22050)) - return False; - - return True; -} - -BOOL -wave_out_set_format(WAVEFORMATEX * pwfx) +libao_set_format(WAVEFORMATEX * pwfx) { ao_sample_format format; format.bits = pwfx->wBitsPerSample; format.channels = pwfx->nChannels; - audiochannels = pwfx->nChannels; format.rate = 44100; - samplerate = pwfx->nSamplesPerSec; - format.byte_format = AO_FMT_LITTLE; - - samplewidth = pwfx->wBitsPerSample / 8; + format.byte_format = AO_FMT_NATIVE; if (o_device != NULL) ao_close(o_device); @@ -123,24 +108,22 @@ return False; } + if (rdpsnd_dsp_resample_set(44100, pwfx->wBitsPerSample, pwfx->nChannels) == False) + { + return False; + } + reopened = True; return True; } void -wave_out_volume(uint16 left, uint16 right) -{ - warning("volume changes not supported with libao-output\n"); -} - -void -wave_out_play(void) +libao_play(void) { struct audio_packet *packet; STREAM out; - char outbuf[WAVEOUTBUF]; - int offset, len, i; + int len; static long prev_s, prev_us; unsigned int duration; struct timeval tv; @@ -165,39 +148,9 @@ next_tick = rdpsnd_queue_next_tick(); - len = 0; - - if (samplerate == 22050) - { - /* Resample to 44100 */ - for (i = 0; (i < ((WAVEOUTBUF / 4) * (3 - samplewidth))) && (out->p < out->end); - i++) - { - /* On a stereo-channel we must make sure that left and right - does not get mixed up, so we need to expand the sample- - data with channels in mind: 1234 -> 12123434 - If we have a mono-channel, we can expand the data by simply - doubling the sample-data: 1234 -> 11223344 */ - if (audiochannels == 2) - offset = ((i * 2) - (i & 1)) * samplewidth; - else - offset = (i * 2) * samplewidth; - - memcpy(&outbuf[offset], out->p, samplewidth); - memcpy(&outbuf[audiochannels * samplewidth + offset], out->p, samplewidth); - - out->p += samplewidth; - len += 2 * samplewidth; - } - } - else - { - len = (WAVEOUTBUF > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTBUF; - memcpy(outbuf, out->p, len); - out->p += len; - } - - ao_play(o_device, outbuf, len); + len = (WAVEOUTLEN > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTLEN; + ao_play(o_device, (char *) out->p, len); + out->p += len; gettimeofday(&tv, NULL); @@ -225,3 +178,47 @@ g_dsp_busy = 1; return; } + +struct audio_driver * +libao_register(char *options) +{ + static struct audio_driver libao_driver; + struct ao_info *libao_info; + static char description[101]; + + libao_driver.wave_out_write = rdpsnd_queue_write; + libao_driver.wave_out_open = libao_open; + libao_driver.wave_out_close = libao_close; + libao_driver.wave_out_format_supported = rdpsnd_dsp_resample_supported; + libao_driver.wave_out_set_format = libao_set_format; + libao_driver.wave_out_volume = rdpsnd_dsp_softvol_set; + libao_driver.wave_out_play = libao_play; + libao_driver.name = xstrdup("libao"); + libao_driver.description = description; + libao_driver.need_byteswap_on_be = 1; + libao_driver.need_resampling = 1; + libao_driver.next = NULL; + + ao_initialize(); + + libao_info = ao_driver_info(ao_default_driver_id()); + + if (libao_info) + { + snprintf(description, 100, "libao output driver, default device: %s", + libao_info->short_name); + } + else + { + snprintf(description, 100, "libao output driver, default device: none"); + } + + ao_shutdown(); + + if (options) + { + libao_device = xstrdup(options); + } + + return &libao_driver; +}