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:
parent
80ab25c473
commit
b7b4327927
107
rdpsnd_dsp.c
107
rdpsnd_dsp.c
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user