[xiph-commits] r17647 - in trunk/ao/src/plugins: alsa pulse
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Thu Nov 25 04:34:19 PST 2010
Author: xiphmont
Date: 2010-11-25 04:34:19 -0800 (Thu, 25 Nov 2010)
New Revision: 17647
Modified:
trunk/ao/src/plugins/alsa/ao_alsa.c
trunk/ao/src/plugins/pulse/ao_pulse.c
Log:
Enable 24 bit playback in Pulse plugin (need to test)
Fix 24 bit playback in ALSA plugin; only padded samples are permitted.
Follow docs by putting samples in the 'low 3 bytes', even on big endian.
Modified: trunk/ao/src/plugins/alsa/ao_alsa.c
===================================================================
--- trunk/ao/src/plugins/alsa/ao_alsa.c 2010-11-24 21:11:47 UTC (rev 17646)
+++ trunk/ao/src/plugins/alsa/ao_alsa.c 2010-11-25 12:34:19 UTC (rev 17647)
@@ -98,6 +98,7 @@
snd_pcm_uframes_t period_size;
int sample_size;
snd_pcm_format_t bitformat;
+ char *pad_24_to_32;
char *dev;
int id;
ao_alsa_writei_t * writei;
@@ -464,6 +465,12 @@
internal->bitformat = err;
+ /* Alsa can only use padded formatting */
+ if(format->bits>16 && format->bits<=24)
+ internal->pad_24_to_32 = calloc(4096,1);
+ else
+ internal->pad_24_to_32 = 0;
+
/* Open the ALSA device */
err=0;
if(!internal->dev){
@@ -568,47 +575,79 @@
}
-/* play num_bytes of audio data */
-int ao_plugin_play(ao_device *device, const char *output_samples,
- uint_32 num_bytes)
+static int ao_plugin_playi(ao_device *device, const char *output_samples,
+ uint_32 num_bytes, int sample_size)
{
ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
- uint_32 len = num_bytes / internal->sample_size;
+ uint_32 len = num_bytes / sample_size;
char *ptr = (char *) output_samples;
int err;
- /* the entire buffer might not transfer at once */
- while (len > 0) {
- /* try to write the entire buffer at once */
- err = internal->writei(internal->pcm_handle, ptr, len);
+ /* the entire buffer might not transfer at once */
+ while (len > 0) {
+ /* try to write the entire buffer at once */
+ err = internal->writei(internal->pcm_handle, ptr, len);
- /* no data transferred or interrupt signal */
- if (err == -EAGAIN || err == -EINTR) {
- continue;
- }
+ /* no data transferred or interrupt signal */
+ if (err == -EAGAIN || err == -EINTR) continue;
- if (err < 0) {
- /* this might be an error, or an exception */
- err = alsa_error_recovery(internal, err, device);
- if (err < 0) {
- aerror("write error: %s\n",
+ if (err < 0) {
+ /* this might be an error, or an exception */
+ err = alsa_error_recovery(internal, err, device);
+ if (err < 0) {
+ aerror("write error: %s\n",
snd_strerror(err));
- return 0;
- }else /* recovered, continue */
- continue;
- }
+ return 0;
+ }else continue;
+ }
- /* decrement the sample counter */
- len -= err;
+ /* decrement the sample counter */
+ len -= err;
- /* adjust the start pointer */
- ptr += err * internal->sample_size;
- }
+ /* adjust the start pointer */
+ ptr += err * sample_size;
+ }
return 1;
}
+/* play num_bytes of audio data */
+int ao_plugin_play(ao_device *device, const char *output_samples,
+ uint_32 num_bytes)
+{
+ ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
+ /* eventually the 24 bit padding should be at a higher layer
+ where we're doing other permutation/swizzling, but for now
+ only ALSA has need of this... */
+ if(internal->pad_24_to_32){
+ /* pad and forward ~ a page at a time; must not hang on fractional frames*/
+ while(num_bytes>=internal->sample_size){
+ char *d = internal->pad_24_to_32;
+ int len4 = 4096/(4*device->output_channels);
+ int len3 = num_bytes/internal->sample_size;
+ int i;
+ if(len4>len3)len4=len3;
+ len4*=device->output_channels;
+
+ if(ao_is_big_endian())++d;
+
+ for(i=0;i<len4;i++){
+ memcpy(d,output_samples,3);
+ d+=4;
+ output_samples+=3;
+ }
+
+ if(!ao_plugin_playi(device,internal->pad_24_to_32,len4*4,4*device->output_channels))
+ return 0;
+ num_bytes-=len4*3;
+ }
+ return 1;
+ }else
+ return ao_plugin_playi(device,output_samples,num_bytes,internal->sample_size);
+}
+
+
/* close the audio device */
int ao_plugin_close(ao_device *device)
{
@@ -620,7 +659,7 @@
snd_pcm_drain(internal->pcm_handle);
snd_pcm_close(internal->pcm_handle);
internal->pcm_handle=NULL;
- }
+ }
} else
awarn("ao_plugin_close called with uninitialized ao_device->internal\n");
} else
@@ -641,7 +680,8 @@
free (internal->dev);
else
awarn("ao_plugin_device_clear called with uninitialized ao_device->internal->dev\n");
-
+ if (internal->pad_24_to_32)
+ free (internal->pad_24_to_32);
free(internal);
device->internal=NULL;
} else
Modified: trunk/ao/src/plugins/pulse/ao_pulse.c
===================================================================
--- trunk/ao/src/plugins/pulse/ao_pulse.c 2010-11-24 21:11:47 UTC (rev 17646)
+++ trunk/ao/src/plugins/pulse/ao_pulse.c 2010-11-25 12:34:19 UTC (rev 17647)
@@ -180,9 +180,11 @@
internal = (ao_pulse_internal *) device->internal;
if (format->bits == 8)
- ss.format = PA_SAMPLE_U8;
+ ss.format = PA_SAMPLE_U8;
else if (format->bits == 16)
- ss.format = PA_SAMPLE_S16NE;
+ ss.format = PA_SAMPLE_S16NE;
+ else if (format->bits == 24)
+ ss.format = PA_SAMPLE_S24NE;
else
return 0;
More information about the commits
mailing list