diff options
-rw-r--r-- | src/audio_out/audio_sun_out.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/src/audio_out/audio_sun_out.c b/src/audio_out/audio_sun_out.c index ae89f63a6..cca48f228 100644 --- a/src/audio_out/audio_sun_out.c +++ b/src/audio_out/audio_sun_out.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: audio_sun_out.c,v 1.8 2001/09/01 17:54:52 jkeil Exp $ + * $Id: audio_sun_out.c,v 1.9 2001/09/06 12:17:12 jkeil Exp $ */ #ifdef HAVE_CONFIG_H @@ -79,6 +79,8 @@ typedef struct sun_driver_s { RTSC_DISABLED } use_rtsc; + int convert_u8_s8; /* Builtin conversion 8-bit UNSIGNED->SIGNED */ + int static_delay; /* estimated delay for non-realtime drivers */ } sun_driver_t; @@ -208,12 +210,22 @@ error: /* * open the audio device for writing to + * + * Implicit assumptions about audio format (bits/rate/mode): + * + * bits == 16: We always get 16-bit samples in native endian format, + * using signed linear encoding + * + * bits == 8: 8-bit samples use unsigned linear encoding, + * other 8-bit formats (uLaw, aLaw, etc) are currently not supported + * by xine */ static int ao_sun_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int mode) { sun_driver_t *this = (sun_driver_t *) this_gen; audio_info_t info; + int ok; printf ("audio_sun_out: ao_sun_open rate=%d, mode=%d\n", rate, mode); @@ -257,12 +269,33 @@ static int ao_sun_open(ao_driver_t *this_gen, ? AUDIO_CHANNELS_STEREO : AUDIO_CHANNELS_MONO; info.play.precision = bits; - info.play.encoding = AUDIO_ENCODING_LINEAR; + info.play.encoding = bits == 8 + ? AUDIO_ENCODING_LINEAR8 + : AUDIO_ENCODING_LINEAR; info.play.sample_rate = this->input_sample_rate; info.play.eof = 0; info.play.samples = 0; - ioctl(this->audio_fd, AUDIO_SETINFO, &info); + this->convert_u8_s8 = 0; + ok = ioctl(this->audio_fd, AUDIO_SETINFO, &info) >= 0; + if (!ok && info.play.encoding == AUDIO_ENCODING_LINEAR8) { + /* + * Unsigned AUDIO_ENCODING_LINEAR8 not supported. + * Maybe signed AUDIO_ENCODING_LINEAR works? + */ + info.play.encoding = AUDIO_ENCODING_LINEAR; + ok = ioctl(this->audio_fd, AUDIO_SETINFO, &info) >= 0; + if (ok) this->convert_u8_s8 = 1; + } + + if (!ok) { + printf("audio_sun_out: Cannot configure audio device for " + "%dhz, %d channel, %d bits\n", + info.play.sample_rate, info.play.channels, + info.play.precision); + close(this->audio_fd); + return 0; + } this->output_sample_rate = info.play.sample_rate; this->num_channels = info.play.channels; @@ -321,6 +354,19 @@ static int ao_sun_write(ao_driver_t *this_gen, { sun_driver_t *this = (sun_driver_t *) this_gen; int num_written; + + if (this->convert_u8_s8) { + /* + * Audio hardware does not support 8-bit unsigned format, + * only 8-bit signed. Convert to 8-bit unsigned before sending + * the data to the audio device. + */ + uint8_t *p = (void *)frame_buffer; + int i; + + for (i = num_frames * this->bytes_per_frame; --i >= 0; p++) + *p ^= 0x80; + } num_written = write(this->audio_fd, frame_buffer, num_frames * this->bytes_per_frame); if (num_written > 0) { this->frames_in_buffer += num_written / this->bytes_per_frame; |