--- sourceforge.net/trunk/rdesktop/rdpsnd_libao.c 2005/03/08 03:33:36 833 +++ sourceforge.net/trunk/rdesktop/rdpsnd_libao.c 2005/03/08 17:23:26 841 @@ -27,10 +27,13 @@ #include #define MAX_QUEUE 10 +#define WAVEOUTBUF 64 int g_dsp_fd; ao_device *o_device = NULL; int default_driver; +int g_samplerate; +int g_channels; BOOL g_dsp_busy = False; static short g_samplewidth; @@ -52,7 +55,9 @@ format.bits = 16; format.channels = 2; + g_channels = 2; format.rate = 44100; + g_samplerate = 44100; format.byte_format = AO_FMT_LITTLE; o_device = ao_open_live(default_driver, &format, NULL); @@ -80,6 +85,7 @@ if (o_device != NULL) ao_close(o_device); + ao_shutdown(); } @@ -93,9 +99,8 @@ if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16)) return False; /* The only common denominator between libao output drivers is a sample-rate of - 44100, windows gives a max of 22050. we need to upsample that... - TODO: support 11025, too */ - if (pwfx->nSamplesPerSec != 22050) + 44100, we need to upsample 22050 to it */ + if ((pwfx->nSamplesPerSec != 44100) && (pwfx->nSamplesPerSec != 22050)) return False; return True; @@ -106,15 +111,16 @@ { ao_sample_format format; - printf("%d\n",pwfx->wBitsPerSample); format.bits = pwfx->wBitsPerSample; format.channels = pwfx->nChannels; + g_channels = pwfx->nChannels; format.rate = 44100; + g_samplerate = pwfx->nSamplesPerSec; format.byte_format = AO_FMT_LITTLE; g_samplewidth = pwfx->wBitsPerSample / 8; - if(o_device != NULL) + if (o_device != NULL) ao_close(o_device); o_device = ao_open_live(default_driver, &format, NULL); @@ -130,6 +136,7 @@ void wave_out_volume(uint16 left, uint16 right) { + warning("volume changes not supported with libao-output\n"); } void @@ -163,38 +170,59 @@ { struct audio_packet *packet; STREAM out; - unsigned char expanded[8]; + unsigned char outbuf[WAVEOUTBUF]; + int offset, len, i; - while (1) + if (queue_lo == queue_hi) { - if (queue_lo == queue_hi) - { - g_dsp_busy = 0; - return; - } - - packet = &packet_queue[queue_lo]; - out = &packet->s; + g_dsp_busy = 0; + return; + } - /* Resample 22050 -> 44100 */ - /* TODO: Do this for 11025, too... */ - memcpy(&expanded[0],out->p,g_samplewidth); - memcpy(&expanded[2*g_samplewidth],out->p,g_samplewidth); - out->p += 2; - memcpy(&expanded[1*g_samplewidth],out->p,g_samplewidth); - memcpy(&expanded[3*g_samplewidth],out->p,g_samplewidth); - out->p += 2; + packet = &packet_queue[queue_lo]; + out = &packet->s; - ao_play(o_device, expanded, g_samplewidth*4); + len = 0; - if (out->p == out->end) + if (g_samplerate == 22050) + { + /* Resample to 44100 */ + for (i = 0; (i < ((WAVEOUTBUF / 4) * (3 - g_samplewidth))) && (out->p < out->end); + i++) { - rdpsnd_send_completion(packet->tick, packet->index); - free(out->data); - queue_lo = (queue_lo + 1) % MAX_QUEUE; - } else { - g_dsp_busy = 1; - return; + /* 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 (g_channels == 2) + offset = ((i * 2) - (i & 1)) * g_samplewidth; + else + offset = (i * 2) * g_samplewidth; + + memcpy(&outbuf[offset], out->p, g_samplewidth); + memcpy(&outbuf[g_channels * g_samplewidth + offset], out->p, g_samplewidth); + + out->p += g_samplewidth; + len += 2 * g_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); + + if (out->p == out->end) + { + rdpsnd_send_completion(packet->tick, packet->index); + free(out->data); + queue_lo = (queue_lo + 1) % MAX_QUEUE; + } + + g_dsp_busy = 1; + return; }