move simple resample algorithm from rdpsnd_libao.c to rdpsnd_dsp.c to

provide a base for a better resample-algorithm


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1275 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Michael Gernoth 2006-10-01 12:16:50 +00:00
parent 80ab25c473
commit b7b4327927
3 changed files with 120 additions and 67 deletions

View File

@ -26,6 +26,9 @@
static uint16 softvol_left = MAX_VOLUME;
static uint16 softvol_right = MAX_VOLUME;
static uint32 resample_to_srate = 44100;
static uint16 resample_to_bitspersample = 16;
static uint16 resample_to_channels = 2;
void
rdpsnd_dsp_softvol_set(uint16 left, uint16 right)
@ -113,9 +116,96 @@ rdpsnd_dsp_swapbytes(unsigned char *buffer, unsigned int size, WAVEFORMATEX * fo
}
}
BOOL
rdpsnd_dsp_resample_set(uint32 device_srate, uint16 device_bitspersample, uint16 device_channels)
{
if (device_srate != 44100 && device_srate != 22050)
return False;
if (device_bitspersample != 16 && device_bitspersample != 8)
return False;
if (device_channels != 1 && device_channels != 2)
return False;
resample_to_srate = device_srate;
resample_to_bitspersample = device_bitspersample;
resample_to_channels = device_channels;
return True;
}
BOOL
rdpsnd_dsp_resample_supported(WAVEFORMATEX * format)
{
if (format->wFormatTag != WAVE_FORMAT_PCM)
return False;
if ((format->nChannels != 1) && (format->nChannels != 2))
return False;
if ((format->wBitsPerSample != 8) && (format->wBitsPerSample != 16))
return False;
if ((format->nSamplesPerSec != 44100) && (format->nSamplesPerSec != 22050))
return False;
return True;
}
uint32
rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
WAVEFORMATEX * format)
{
static BOOL warned = False;
int outsize, offset;
int samplewidth = format->wBitsPerSample / 8;
int i;
if ((resample_to_bitspersample != format->wBitsPerSample) ||
(resample_to_channels != format->nChannels) ||
((format->nSamplesPerSec != 44100) && (format->nSamplesPerSec != 22050)))
{
if (!warned)
{
warning("unsupported resample-settings (%u/%u/%u), not resampling!\n",
format->nSamplesPerSec, format->wBitsPerSample, format->nChannels);
warned = True;
}
return 0;
}
if (format->nSamplesPerSec == 22050)
{
outsize = size * 2;
*out = xmalloc(outsize);
/* Resample to 44100 */
for (i = 0; i < (size / samplewidth); 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 (resample_to_channels == 2)
offset = ((i * 2) - (i & 1)) * samplewidth;
else
offset = (i * 2) * samplewidth;
memcpy(*out + offset, in + (i * samplewidth), samplewidth);
memcpy(*out + (resample_to_channels * samplewidth + offset),
in + (i * samplewidth), samplewidth);
}
}
else
{
outsize = 0;
}
return outsize;
}
STREAM
rdpsnd_dsp_process(STREAM s, struct audio_driver *current_driver, WAVEFORMATEX * format)
rdpsnd_dsp_process(STREAM s, struct audio_driver * current_driver, WAVEFORMATEX * format)
{
static struct stream out;
@ -129,11 +219,20 @@ rdpsnd_dsp_process(STREAM s, struct audio_driver *current_driver, WAVEFORMATEX *
rdpsnd_dsp_swapbytes(s->data, s->size, format);
#endif
out.data = xmalloc(s->size);
out.data = NULL;
memcpy(out.data, s->data, s->size);
if (current_driver->wave_out_format_supported == rdpsnd_dsp_resample_supported)
{
out.size = rdpsnd_dsp_resample(&out.data, s->data, s->size, format);
}
if (out.data == NULL)
{
out.data = xmalloc(s->size);
memcpy(out.data, s->data, s->size);
out.size = s->size;
}
out.size = s->size;
out.p = out.data;
out.end = out.p + out.size;

View File

@ -18,6 +18,12 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Software volume control */
void rdpsnd_dsp_softvol_set(uint16 left, uint16 right);
/* Resample control */
BOOL rdpsnd_dsp_resample_set(uint32 device_srate, uint16 device_bitspersample,
uint16 device_channels);
BOOL rdpsnd_dsp_resample_supported(WAVEFORMATEX * pwfx);
STREAM rdpsnd_dsp_process(STREAM s, struct audio_driver *current_driver, WAVEFORMATEX * format);

View File

@ -33,10 +33,7 @@
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
@ -57,9 +54,7 @@ libao_open(void)
format.bits = 16;
format.channels = 2;
audiochannels = 2;
format.rate = 44100;
samplerate = 44100;
format.byte_format = AO_FMT_LITTLE;
o_device = ao_open_live(default_driver, &format, NULL);
@ -93,23 +88,6 @@ libao_close(void)
ao_shutdown();
}
BOOL
libao_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
libao_set_format(WAVEFORMATEX * pwfx)
{
@ -117,13 +95,9 @@ libao_set_format(WAVEFORMATEX * pwfx)
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;
if (o_device != NULL)
ao_close(o_device);
@ -133,6 +107,11 @@ libao_set_format(WAVEFORMATEX * pwfx)
return False;
}
if (rdpsnd_dsp_resample_set(44100, pwfx->wBitsPerSample, pwfx->nChannels) == False)
{
return False;
}
reopened = True;
return True;
@ -143,8 +122,7 @@ 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;
@ -169,39 +147,9 @@ libao_play(void)
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 = (WAVEOUTBUF > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTBUF;
ao_play(o_device, (char *) out->p, len);
out->p += len;
gettimeofday(&tv, NULL);
@ -240,7 +188,7 @@ libao_register(char *options)
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 = libao_format_supported;
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;
@ -256,7 +204,7 @@ libao_register(char *options)
if (libao_info)
{
snprintf(description, 100, "libao output driver, default device: %s",
libao_info->short_name);
libao_info->short_name);
}
else
{