zenilib: zenilib/jni/external/sdl/src/audio/sun/SDL_sunaudio.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_sunaudio.c
Go to the documentation of this file.
1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22
23 #if SDL_AUDIO_DRIVER_SUNAUDIO
24
25 /* Allow access to a raw mixing buffer */
26
27 #include <fcntl.h>
28 #include <errno.h>
29 #ifdef __NETBSD__
30 #include <sys/ioctl.h>
31 #include <sys/audioio.h>
32 #endif
33 #ifdef __SVR4
34 #include <sys/audioio.h>
35 #else
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #endif
39 #include <unistd.h>
40
41 #include "SDL_timer.h"
42 #include "SDL_audio.h"
43 #include "../SDL_audiomem.h"
44 #include "../SDL_audio_c.h"
45 #include "../SDL_audiodev_c.h"
46 #include "SDL_sunaudio.h"
47
48 /* Open the audio device for playback, and don't block if busy */
49
50 #if defined(AUDIO_GETINFO) && !defined(AUDIO_GETBUFINFO)
51 #define AUDIO_GETBUFINFO AUDIO_GETINFO
52 #endif
53
54 /* Audio driver functions */
55 static Uint8 snd2au(int sample);
56
57 /* Audio driver bootstrap functions */
58 static void
59 SUNAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
60 {
61 SDL_EnumUnixAudioDevices(iscapture, 1, (int (*)(int fd)) NULL, addfn);
62 }
63
64 #ifdef DEBUG_AUDIO
65 void
66 CheckUnderflow(_THIS)
67 {
68 #ifdef AUDIO_GETBUFINFO
69 audio_info_t info;
70 int left;
71
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");
76 }
77 #endif
78 }
79 #endif
80
81 static void
82 SUNAUDIO_WaitDevice(_THIS)
83 {
84 #ifdef AUDIO_GETBUFINFO
85 #define SLEEP_FUDGE 10 /* 10 ms scheduling fudge factor */
86 audio_info_t info;
87 Sint32 left;
88
89 ioctl(this->hidden->audio_fd, AUDIO_GETBUFINFO, &info);
90 left = (this->hidden->written - info.play.samples);
91 if (left > this->hidden->fragsize) {
92 Sint32 sleepy;
93
94 sleepy = ((left - this->hidden->fragsize) / this->hidden->frequency);
95 sleepy -= SLEEP_FUDGE;
96 if (sleepy > 0) {
97 SDL_Delay(sleepy);
98 }
99 }
100 #else
101 fd_set fdset;
102
103 FD_ZERO(&fdset);
104 FD_SET(this->hidden->audio_fd, &fdset);
105 select(this->hidden->audio_fd + 1, NULL, &fdset, NULL, NULL);
106 #endif
107 }
108
109 static void
110 SUNAUDIO_PlayDevice(_THIS)
111 {
112 /* Write the audio data */
113 if (this->hidden->ulaw_only) {
114 /* Assuming that this->spec.freq >= 8000 Hz */
115 int accum, incr, pos;
116 Uint8 *aubuf;
117
118 accum = 0;
119 incr = this->spec.freq / 8;
120 aubuf = this->hidden->ulaw_buf;
121 switch (this->hidden->audio_fmt & 0xFF) {
122 case 8:
123 {
124 Uint8 *sndbuf;
125
126 sndbuf = this->hidden->mixbuf;
127 for (pos = 0; pos < this->hidden->fragsize; ++pos) {
128 *aubuf = snd2au((0x80 - *sndbuf) * 64);
129 accum += incr;
130 while (accum > 0) {
131 accum -= 1000;
132 sndbuf += 1;
133 }
134 aubuf += 1;
135 }
136 }
137 break;
138 case 16:
139 {
140 Sint16 *sndbuf;
141
142 sndbuf = (Sint16 *) this->hidden->mixbuf;
143 for (pos = 0; pos < this->hidden->fragsize; ++pos) {
144 *aubuf = snd2au(*sndbuf / 4);
145 accum += incr;
146 while (accum > 0) {
147 accum -= 1000;
148 sndbuf += 1;
149 }
150 aubuf += 1;
151 }
152 }
153 break;
154 }
155 #ifdef DEBUG_AUDIO
156 CheckUnderflow(this);
157 #endif
158 if (write(this->hidden->audio_fd, this->hidden->ulaw_buf,
159 this->hidden->fragsize) < 0) {
160 /* Assume fatal error, for now */
161 this->enabled = 0;
162 }
163 this->hidden->written += this->hidden->fragsize;
164 } else {
165 #ifdef DEBUG_AUDIO
166 CheckUnderflow(this);
167 #endif
168 if (write(this->hidden->audio_fd, this->hidden->mixbuf,
169 this->spec.size) < 0) {
170 /* Assume fatal error, for now */
171 this->enabled = 0;
172 }
173 this->hidden->written += this->hidden->fragsize;
174 }
175 }
176
177 static Uint8 *
178 SUNAUDIO_GetDeviceBuf(_THIS)
179 {
180 return (this->hidden->mixbuf);
181 }
182
183 static void
184 SUNAUDIO_CloseDevice(_THIS)
185 {
186 if (this->hidden != NULL) {
187 SDL_FreeAudioMem(this->hidden->mixbuf);
188 this->hidden->mixbuf = NULL;
189 SDL_free(this->hidden->ulaw_buf);
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;
194 }
195 SDL_free(this->hidden);
196 this->hidden = NULL;
197 }
198 }
199
200 static int
201 SUNAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
202 {
203 const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
204 SDL_AudioFormat format = 0;
205 audio_info_t info;
206
207 /* We don't care what the devname is...we'll try to open anything. */
208 /* ...but default to first name in the list... */
209 if (devname == NULL) {
210 devname = SDL_GetAudioDeviceName(0, iscapture);
211 if (devname == NULL) {
212 return SDL_SetError("No such audio device");
213 }
214 }
215
216 /* Initialize all variables that we clean on shutdown */
217 this->hidden = (struct SDL_PrivateAudioData *)
218 SDL_malloc((sizeof *this->hidden));
219 if (this->hidden == NULL) {
220 return SDL_OutOfMemory();
221 }
222 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
223
224 /* Open the audio device */
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));
228 }
229
230 #ifdef AUDIO_SETINFO
231 int enc;
232 #endif
233 int desired_freq = this->spec.freq;
234
235 /* Determine the audio parameters from the AudioSpec */
236 switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
237
238 case 8:
239 { /* Unsigned 8 bit audio data */
240 this->spec.format = AUDIO_U8;
241 #ifdef AUDIO_SETINFO
242 enc = AUDIO_ENCODING_LINEAR8;
243 #endif
244 }
245 break;
246
247 case 16:
248 { /* Signed 16 bit audio data */
249 this->spec.format = AUDIO_S16SYS;
250 #ifdef AUDIO_SETINFO
251 enc = AUDIO_ENCODING_LINEAR;
252 #endif
253 }
254 break;
255
256 default:
257 {
258 /* !!! FIXME: fallback to conversion on unsupported types! */
259 return SDL_SetError("Unsupported audio format");
260 }
261 }
262 this->hidden->audio_fmt = this->spec.format;
263
264 this->hidden->ulaw_only = 0; /* modern Suns do support linear audio */
265 #ifdef AUDIO_SETINFO
266 for (;;) {
267 audio_info_t info;
268 AUDIO_INITINFO(&info); /* init all fields to "no change" */
269
270 /* Try to set the requested settings */
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) {
277
278 /* Check to be sure we got what we wanted */
279 if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
280 return SDL_SetError("Error getting audio parameters: %s",
281 strerror(errno));
282 }
283 if (info.play.encoding == enc
284 && info.play.precision == (this->spec.format & 0xff)
285 && info.play.channels == this->spec.channels) {
286 /* Yow! All seems to be well! */
287 this->spec.freq = info.play.sample_rate;
288 break;
289 }
290 }
291
292 switch (enc) {
293 case AUDIO_ENCODING_LINEAR8:
294 /* unsigned 8bit apparently not supported here */
295 enc = AUDIO_ENCODING_LINEAR;
296 this->spec.format = AUDIO_S16SYS;
297 break; /* try again */
298
299 case AUDIO_ENCODING_LINEAR:
300 /* linear 16bit didn't work either, resort to µ-law */
301 enc = AUDIO_ENCODING_ULAW;
302 this->spec.channels = 1;
303 this->spec.freq = 8000;
304 this->spec.format = AUDIO_U8;
305 this->hidden->ulaw_only = 1;
306 break;
307
308 default:
309 /* oh well... */
310 return SDL_SetError("Error setting audio parameters: %s",
311 strerror(errno));
312 }
313 }
314 #endif /* AUDIO_SETINFO */
315 this->hidden->written = 0;
316
317 /* We can actually convert on-the-fly to U-Law */
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;
323 this->hidden->ulaw_buf = (Uint8 *) SDL_malloc(this->hidden->fragsize);
324 if (this->hidden->ulaw_buf == NULL) {
325 return SDL_OutOfMemory();
326 }
327 this->spec.channels = 1;
328 } else {
329 this->hidden->fragsize = this->spec.samples;
330 this->hidden->frequency = this->spec.freq / 1000;
331 }
332 #ifdef DEBUG_AUDIO
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);
337 #endif
338
339 /* Update the fragment size as size in bytes */
340 SDL_CalculateAudioSpec(&this->spec);
341
342 /* Allocate mixing buffer */
343 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->spec.size);
344 if (this->hidden->mixbuf == NULL) {
345 return SDL_OutOfMemory();
346 }
347 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
348
349 /* We're ready to rock and roll. :-) */
350 return 0;
351 }
352
353 /************************************************************************/
354 /* This function (snd2au()) copyrighted: */
355 /************************************************************************/
356 /* Copyright 1989 by Rich Gopstein and Harris Corporation */
357 /* */
358 /* Permission to use, copy, modify, and distribute this software */
359 /* and its documentation for any purpose and without fee is */
360 /* hereby granted, provided that the above copyright notice */
361 /* appears in all copies and that both that copyright notice and */
362 /* this permission notice appear in supporting documentation, and */
363 /* that the name of Rich Gopstein and Harris Corporation not be */
364 /* used in advertising or publicity pertaining to distribution */
365 /* of the software without specific, written prior permission. */
366 /* Rich Gopstein and Harris Corporation make no representations */
367 /* about the suitability of this software for any purpose. It */
368 /* provided "as is" without express or implied warranty. */
369 /************************************************************************/
370
371 static Uint8
372 snd2au(int sample)
373 {
374
375 int mask;
376
377 if (sample < 0) {
378 sample = -sample;
379 mask = 0x7f;
380 } else {
381 mask = 0xff;
382 }
383
384 if (sample < 32) {
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);
400 } else {
401 sample = 0x80;
402 }
403 return (mask & sample);
404 }
405
406 static int
407 SUNAUDIO_Init(SDL_AudioDriverImpl * impl)
408 {
409 /* Set the function pointers */
410 impl->DetectDevices = SUNAUDIO_DetectDevices;
411 impl->OpenDevice = SUNAUDIO_OpenDevice;
412 impl->PlayDevice = SUNAUDIO_PlayDevice;
413 impl->WaitDevice = SUNAUDIO_WaitDevice;
414 impl->GetDeviceBuf = SUNAUDIO_GetDeviceBuf;
415 impl->CloseDevice = SUNAUDIO_CloseDevice;
416
417 return 1; /* this audio target is available. */
418 }
419
420 AudioBootStrap SUNAUDIO_bootstrap = {
421 "audio", "UNIX /dev/audio interface", SUNAUDIO_Init, 0
422 };
423
424 #endif /* SDL_AUDIO_DRIVER_SUNAUDIO */
425
426 /* vi: set ts=4 sw=4 expandtab: */
SDL_AudioDriverImpl::CloseDevice
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:45
OPEN_FLAGS_INPUT
#define OPEN_FLAGS_INPUT
Definition: SDL_audiodev_c.h:33
SUNAUDIO_bootstrap
AudioBootStrap SUNAUDIO_bootstrap
Sint32
int32_t Sint32
A signed 32-bit integer type.
Definition: SDL_stdinc.h:141
SDL_AddAudioDevice
void(* SDL_AddAudioDevice)(const char *name)
Definition: SDL_sysaudio.h:34
left
GLint left
Definition: glew.h:7291
SDL_AudioDriverImpl::WaitDevice
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:41
SDL_EnumUnixAudioDevices
void SDL_EnumUnixAudioDevices(int iscapture, int classic, int(*test)(int fd), SDL_AddAudioDevice addfn)
NULL
#define NULL
Definition: ftobjs.h:61
enabled
GLenum GLsizei const GLuint GLboolean enabled
Definition: glew.h:2538
SDL_AudioDriverImpl::GetDeviceBuf
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:43
SDL_FreeAudioMem
#define SDL_FreeAudioMem
Definition: SDL_audiomem.h:24
SDL_free
DECLSPEC void SDLCALL SDL_free(void *mem)
SDL_AudioFormat
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
AUDIO_S16SYS
#define AUDIO_S16SYS
Definition: SDL_audio.h:123
if
if(!yyg->yy_init)
Definition: glslang_lex.cpp:1037
SDL_AudioDriverImpl::OpenDevice
int(* OpenDevice)(_THIS, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:39
SDL_PrivateAudioData
Definition: SDL_alsa_audio.h:33
SDL_config.h
SDL_AudioDriverImpl::PlayDevice
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:42
AUDIO_U8
#define AUDIO_U8
Definition: SDL_audio.h:89
SDL_AudioDriverImpl::DetectDevices
void(* DetectDevices)(int iscapture, SDL_AddAudioDevice addfn)
Definition: SDL_sysaudio.h:38
AudioBootStrap
Definition: SDL_sysaudio.h:128
SDL_GetAudioDeviceName
DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index, int iscapture)
Definition: SDL_audio.c:708
SDL_sunaudio.h
for
for(;;)
Definition: glslang_tab.cpp:4773
OPEN_FLAGS_OUTPUT
#define OPEN_FLAGS_OUTPUT
Definition: SDL_audiodev_c.h:32
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_AUDIO_BITSIZE
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
SDL_AudioDriverImpl
Definition: SDL_sysaudio.h:36
SDL_Delay
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
Wait a specified number of milliseconds before returning.
Definition: SDL_systimer.c:70
SDL_memset
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
format
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
SDL_SetError
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
SDL_malloc
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
SDL_CalculateAudioSpec
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1247
SDL_AllocAudioMem
#define SDL_AllocAudioMem
Definition: SDL_audiomem.h:23
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
flags
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
SDL_audio.h
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
mask
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
Definition: gl2ext.h:961
Sint16
int16_t Sint16
A signed 16-bit integer type.
Definition: SDL_stdinc.h:133
types.h
SDL_timer.h