23 #if SDL_AUDIO_DRIVER_SUNAUDIO
30 #include <sys/ioctl.h>
31 #include <sys/audioio.h>
34 #include <sys/audioio.h>
43 #include "../SDL_audiomem.h"
44 #include "../SDL_audio_c.h"
45 #include "../SDL_audiodev_c.h"
50 #if defined(AUDIO_GETINFO) && !defined(AUDIO_GETBUFINFO)
51 #define AUDIO_GETBUFINFO AUDIO_GETINFO
55 static Uint8 snd2au(
int sample);
68 #ifdef AUDIO_GETBUFINFO
72 ioctl(this->hidden->audio_fd, AUDIO_GETBUFINFO, &info);
73 left = (this->hidden->written - info.play.samples);
74 if (this->hidden->written && (left == 0)) {
75 fprintf(stderr,
"audio underflow!\n");
82 SUNAUDIO_WaitDevice(
_THIS)
84 #ifdef AUDIO_GETBUFINFO
85 #define SLEEP_FUDGE 10
89 ioctl(this->hidden->audio_fd, AUDIO_GETBUFINFO, &info);
90 left = (this->hidden->written - info.play.samples);
91 if (left > this->hidden->fragsize) {
94 sleepy = ((left - this->hidden->fragsize) / this->hidden->frequency);
95 sleepy -= SLEEP_FUDGE;
104 FD_SET(this->hidden->audio_fd, &fdset);
105 select(this->hidden->audio_fd + 1,
NULL, &fdset,
NULL,
NULL);
110 SUNAUDIO_PlayDevice(
_THIS)
113 if (this->hidden->ulaw_only) {
115 int accum, incr, pos;
119 incr = this->spec.freq / 8;
120 aubuf = this->hidden->ulaw_buf;
121 switch (this->hidden->audio_fmt & 0xFF) {
126 sndbuf = this->hidden->mixbuf;
127 for (pos = 0; pos < this->hidden->fragsize; ++pos) {
128 *aubuf = snd2au((0x80 - *sndbuf) * 64);
142 sndbuf = (
Sint16 *) this->hidden->mixbuf;
143 for (pos = 0; pos < this->hidden->fragsize; ++pos) {
144 *aubuf = snd2au(*sndbuf / 4);
156 CheckUnderflow(
this);
158 if (write(this->hidden->audio_fd, this->hidden->ulaw_buf,
159 this->hidden->fragsize) < 0) {
163 this->hidden->written += this->hidden->fragsize;
166 CheckUnderflow(
this);
168 if (write(this->hidden->audio_fd, this->hidden->mixbuf,
169 this->spec.size) < 0) {
173 this->hidden->written += this->hidden->fragsize;
178 SUNAUDIO_GetDeviceBuf(
_THIS)
180 return (this->hidden->mixbuf);
184 SUNAUDIO_CloseDevice(
_THIS)
186 if (this->hidden !=
NULL) {
188 this->hidden->mixbuf =
NULL;
190 this->hidden->ulaw_buf =
NULL;
191 if (this->hidden->audio_fd >= 0) {
192 close(this->hidden->audio_fd);
193 this->hidden->audio_fd = -1;
201 SUNAUDIO_OpenDevice(
_THIS,
const char *devname,
int iscapture)
209 if (devname ==
NULL) {
211 if (devname ==
NULL) {
219 if (this->hidden ==
NULL) {
222 SDL_memset(this->hidden, 0, (
sizeof *this->hidden));
225 this->hidden->audio_fd = open(devname, flags, 0);
226 if (this->hidden->audio_fd < 0) {
227 return SDL_SetError(
"Couldn't open %s: %s", devname, strerror(errno));
233 int desired_freq = this->spec.freq;
242 enc = AUDIO_ENCODING_LINEAR8;
251 enc = AUDIO_ENCODING_LINEAR;
262 this->hidden->audio_fmt = this->spec.format;
264 this->hidden->ulaw_only = 0;
268 AUDIO_INITINFO(&info);
271 info.play.sample_rate = this->spec.freq;
272 info.play.channels = this->spec.channels;
273 info.play.precision = (enc == AUDIO_ENCODING_ULAW)
274 ? 8 : this->spec.format & 0xff;
275 info.play.encoding = enc;
276 if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) {
279 if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
280 return SDL_SetError(
"Error getting audio parameters: %s",
283 if (info.play.encoding == enc
284 && info.play.precision == (this->spec.format & 0xff)
285 && info.play.channels == this->spec.channels) {
287 this->spec.freq = info.play.sample_rate;
293 case AUDIO_ENCODING_LINEAR8:
295 enc = AUDIO_ENCODING_LINEAR;
299 case AUDIO_ENCODING_LINEAR:
301 enc = AUDIO_ENCODING_ULAW;
302 this->spec.channels = 1;
303 this->spec.freq = 8000;
305 this->hidden->ulaw_only = 1;
310 return SDL_SetError(
"Error setting audio parameters: %s",
315 this->hidden->written = 0;
318 if (this->hidden->ulaw_only) {
319 this->spec.freq = desired_freq;
320 this->hidden->fragsize = (this->spec.samples * 1000) /
321 (this->spec.freq / 8);
322 this->hidden->frequency = 8;
324 if (this->hidden->ulaw_buf ==
NULL) {
327 this->spec.channels = 1;
329 this->hidden->fragsize = this->spec.samples;
330 this->hidden->frequency = this->spec.freq / 1000;
333 fprintf(stderr,
"Audio device %s U-Law only\n",
334 this->hidden->ulaw_only ?
"is" :
"is not");
335 fprintf(stderr,
"format=0x%x chan=%d freq=%d\n",
336 this->spec.format, this->spec.channels, this->spec.freq);
344 if (this->hidden->mixbuf ==
NULL) {
347 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
385 sample = 0xF0 | (15 - sample / 2);
386 }
else if (sample < 96) {
387 sample = 0xE0 | (15 - (sample - 32) / 4);
388 }
else if (sample < 224) {
389 sample = 0xD0 | (15 - (sample - 96) / 8);
390 }
else if (sample < 480) {
391 sample = 0xC0 | (15 - (sample - 224) / 16);
392 }
else if (sample < 992) {
393 sample = 0xB0 | (15 - (sample - 480) / 32);
394 }
else if (sample < 2016) {
395 sample = 0xA0 | (15 - (sample - 992) / 64);
396 }
else if (sample < 4064) {
397 sample = 0x90 | (15 - (sample - 2016) / 128);
398 }
else if (sample < 8160) {
399 sample = 0x80 | (15 - (sample - 4064) / 256);
403 return (mask & sample);
421 "audio",
"UNIX /dev/audio interface", SUNAUDIO_Init, 0
void(* CloseDevice)(_THIS)
AudioBootStrap SUNAUDIO_bootstrap
int32_t Sint32
A signed 32-bit integer type.
void(* SDL_AddAudioDevice)(const char *name)
void(* WaitDevice)(_THIS)
void SDL_EnumUnixAudioDevices(int iscapture, int classic, int(*test)(int fd), SDL_AddAudioDevice addfn)
GLenum GLsizei const GLuint GLboolean enabled
Uint8 *(* GetDeviceBuf)(_THIS)
DECLSPEC void SDLCALL SDL_free(void *mem)
Uint16 SDL_AudioFormat
Audio format flags.
int(* OpenDevice)(_THIS, const char *devname, int iscapture)
void(* PlayDevice)(_THIS)
void(* DetectDevices)(int iscapture, SDL_AddAudioDevice addfn)
DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index, int iscapture)
#define OPEN_FLAGS_OUTPUT
#define SDL_AUDIO_BITSIZE(x)
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
Wait a specified number of milliseconds before returning.
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
#define SDL_AllocAudioMem
#define SDL_OutOfMemory()
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
uint8_t Uint8
An unsigned 8-bit integer type.
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
int16_t Sint16
A signed 16-bit integer type.