1.1 --- a/src/audio/dsp/SDL_dspaudio.c Fri Nov 12 21:29:52 2004 +0000
1.2 +++ b/src/audio/dsp/SDL_dspaudio.c Fri Nov 12 21:39:04 2004 +0000
1.3 @@ -18,6 +18,9 @@
1.4
1.5 Sam Lantinga
1.6 slouken@libsdl.org
1.7 +
1.8 + Modified in Oct 2004 by Hannu Savolainen
1.9 + hannu@opensound.com
1.10 */
1.11
1.12 #ifdef SAVE_RCSID
1.13 @@ -57,7 +60,6 @@
1.14 #define DSP_DRIVER_NAME "dsp"
1.15
1.16 /* Open the audio device for playback, and don't block if busy */
1.17 -/*#define USE_BLOCKING_WRITES*/
1.18 #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK)
1.19
1.20 /* Audio driver functions */
1.21 @@ -130,94 +132,19 @@
1.22 /* This function waits until it is possible to write a full sound buffer */
1.23 static void DSP_WaitAudio(_THIS)
1.24 {
1.25 - /* Check to see if the thread-parent process is still alive */
1.26 - { static int cnt = 0;
1.27 - /* Note that this only works with thread implementations
1.28 - that use a different process id for each thread.
1.29 - */
1.30 - if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */
1.31 - if ( kill(parent, 0) < 0 ) {
1.32 - this->enabled = 0;
1.33 - }
1.34 - }
1.35 - }
1.36 -
1.37 -#ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */
1.38 - /* See if we need to use timed audio synchronization */
1.39 - if ( frame_ticks ) {
1.40 - /* Use timer for general audio synchronization */
1.41 - Sint32 ticks;
1.42 -
1.43 - ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS;
1.44 - if ( ticks > 0 ) {
1.45 - SDL_Delay(ticks);
1.46 - }
1.47 - } else {
1.48 - /* Use select() for audio synchronization */
1.49 - fd_set fdset;
1.50 - struct timeval timeout;
1.51 -
1.52 - FD_ZERO(&fdset);
1.53 - FD_SET(audio_fd, &fdset);
1.54 - timeout.tv_sec = 10;
1.55 - timeout.tv_usec = 0;
1.56 -#ifdef DEBUG_AUDIO
1.57 - fprintf(stderr, "Waiting for audio to get ready\n");
1.58 -#endif
1.59 - if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) {
1.60 - const char *message =
1.61 - "Audio timeout - buggy audio driver? (disabled)";
1.62 - /* In general we should never print to the screen,
1.63 - but in this case we have no other way of letting
1.64 - the user know what happened.
1.65 - */
1.66 - fprintf(stderr, "SDL: %s\n", message);
1.67 - this->enabled = 0;
1.68 - /* Don't try to close - may hang */
1.69 - audio_fd = -1;
1.70 -#ifdef DEBUG_AUDIO
1.71 - fprintf(stderr, "Done disabling audio\n");
1.72 -#endif
1.73 - }
1.74 -#ifdef DEBUG_AUDIO
1.75 - fprintf(stderr, "Ready!\n");
1.76 -#endif
1.77 - }
1.78 -#endif /* !USE_BLOCKING_WRITES */
1.79 + /* Not needed at all since OSS handles waiting automagically */
1.80 }
1.81
1.82 static void DSP_PlayAudio(_THIS)
1.83 {
1.84 - int written, p=0;
1.85 -
1.86 - /* Write the audio data, checking for EAGAIN on broken audio drivers */
1.87 - do {
1.88 - written = write(audio_fd, &mixbuf[p], mixlen-p);
1.89 - if (written>0)
1.90 - p += written;
1.91 - if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR)
1.92 - {
1.93 - /* Non recoverable error has occurred. It should be reported!!! */
1.94 - perror("audio");
1.95 - break;
1.96 - }
1.97 -
1.98 - if ( p < written || ((written < 0) && ((errno == 0) || (errno == EAGAIN))) ) {
1.99 - SDL_Delay(1); /* Let a little CPU time go by */
1.100 - }
1.101 - } while ( p < written );
1.102 -
1.103 - /* If timer synchronization is enabled, set the next write frame */
1.104 - if ( frame_ticks ) {
1.105 - next_frame += frame_ticks;
1.106 + if (write(audio_fd, mixbuf, mixlen)==-1)
1.107 + {
1.108 + perror("Audio write");
1.109 + this->enabled = 0;
1.110 }
1.111
1.112 - /* If we couldn't write, assume fatal error for now */
1.113 - if ( written < 0 ) {
1.114 - this->enabled = 0;
1.115 - }
1.116 #ifdef DEBUG_AUDIO
1.117 - fprintf(stderr, "Wrote %d bytes of audio data\n", written);
1.118 + fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
1.119 #endif
1.120 }
1.121
1.122 @@ -233,26 +160,128 @@
1.123 mixbuf = NULL;
1.124 }
1.125 if ( audio_fd >= 0 ) {
1.126 - int value;
1.127 - ioctl(audio_fd, SNDCTL_DSP_RESET, &value);
1.128 close(audio_fd);
1.129 audio_fd = -1;
1.130 }
1.131 }
1.132
1.133 -static int DSP_ReopenAudio(_THIS, const char *audiodev, int format,
1.134 - SDL_AudioSpec *spec)
1.135 +static int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec)
1.136 {
1.137 - int frag_spec;
1.138 + char audiodev[1024];
1.139 + int format;
1.140 int value;
1.141 + int frag_spec;
1.142 + Uint16 test_format;
1.143
1.144 - /* Close and then reopen the audio device */
1.145 - close(audio_fd);
1.146 - audio_fd = open(audiodev, O_WRONLY, 0);
1.147 + /* Open the audio device */
1.148 + audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
1.149 if ( audio_fd < 0 ) {
1.150 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
1.151 return(-1);
1.152 }
1.153 + mixbuf = NULL;
1.154 +
1.155 + /* Make the file descriptor use blocking writes with fcntl() */
1.156 + { long flags;
1.157 + flags = fcntl(audio_fd, F_GETFL);
1.158 + flags &= ~O_NONBLOCK;
1.159 + if ( fcntl(audio_fd, F_SETFL, flags) < 0 ) {
1.160 + SDL_SetError("Couldn't set audio blocking mode");
1.161 + return(-1);
1.162 + }
1.163 + }
1.164 +
1.165 + /* Get a list of supported hardware formats */
1.166 + if ( ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0 ) {
1.167 + perror("SNDCTL_DSP_GETFMTS");
1.168 + SDL_SetError("Couldn't get audio format list");
1.169 + return(-1);
1.170 + }
1.171 +
1.172 + /* Try for a closest match on audio format */
1.173 + format = 0;
1.174 + for ( test_format = SDL_FirstAudioFormat(spec->format);
1.175 + ! format && test_format; ) {
1.176 +#ifdef DEBUG_AUDIO
1.177 + fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
1.178 +#endif
1.179 + switch ( test_format ) {
1.180 + case AUDIO_U8:
1.181 + if ( value & AFMT_U8 ) {
1.182 + format = AFMT_U8;
1.183 + }
1.184 + break;
1.185 + case AUDIO_S16LSB:
1.186 + if ( value & AFMT_S16_LE ) {
1.187 + format = AFMT_S16_LE;
1.188 + }
1.189 + break;
1.190 + case AUDIO_S16MSB:
1.191 + if ( value & AFMT_S16_BE ) {
1.192 + format = AFMT_S16_BE;
1.193 + }
1.194 + break;
1.195 +#if 0
1.196 +/*
1.197 + * These formats are not used by any real life systems so they are not
1.198 + * needed here.
1.199 + */
1.200 + case AUDIO_S8:
1.201 + if ( value & AFMT_S8 ) {
1.202 + format = AFMT_S8;
1.203 + }
1.204 + break;
1.205 + case AUDIO_U16LSB:
1.206 + if ( value & AFMT_U16_LE ) {
1.207 + format = AFMT_U16_LE;
1.208 + }
1.209 + break;
1.210 + case AUDIO_U16MSB:
1.211 + if ( value & AFMT_U16_BE ) {
1.212 + format = AFMT_U16_BE;
1.213 + }
1.214 + break;
1.215 +#endif
1.216 + default:
1.217 + format = 0;
1.218 + break;
1.219 + }
1.220 + if ( ! format ) {
1.221 + test_format = SDL_NextAudioFormat();
1.222 + }
1.223 + }
1.224 + if ( format == 0 ) {
1.225 + SDL_SetError("Couldn't find any hardware audio formats");
1.226 + return(-1);
1.227 + }
1.228 + spec->format = test_format;
1.229 +
1.230 + /* Set the audio format */
1.231 + value = format;
1.232 + if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
1.233 + (value != format) ) {
1.234 + perror("SNDCTL_DSP_SETFMT");
1.235 + SDL_SetError("Couldn't set audio format");
1.236 + return(-1);
1.237 + }
1.238 +
1.239 + /* Set the number of channels of output */
1.240 + value = spec->channels;
1.241 + if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0 ) {
1.242 + perror("SNDCTL_DSP_CHANNELS");
1.243 + SDL_SetError("Cannot set the number of channels");
1.244 + return(-1);
1.245 + }
1.246 + spec->channels = value;
1.247 +
1.248 + /* Set the DSP frequency */
1.249 + value = spec->freq;
1.250 + if ( ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0 ) {
1.251 + perror("SNDCTL_DSP_SPEED");
1.252 + SDL_SetError("Couldn't set audio frequency");
1.253 + return(-1);
1.254 + }
1.255 + spec->freq = value;
1.256
1.257 /* Calculate the final parameters for this audio specification */
1.258 SDL_CalculateAudioSpec(spec);
1.259 @@ -271,6 +300,7 @@
1.260 (frag_spec >> 16), 1<<(frag_spec&0xFFFF));
1.261 #endif
1.262 if ( ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0 ) {
1.263 + perror("SNDCTL_DSP_SETFRAGMENT");
1.264 fprintf(stderr, "Warning: Couldn't set audio fragment size\n");
1.265 }
1.266 #ifdef DEBUG_AUDIO
1.267 @@ -283,160 +313,6 @@
1.268 }
1.269 #endif
1.270
1.271 - /* Set the audio format */
1.272 - value = format;
1.273 - if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
1.274 - (value != format) ) {
1.275 - SDL_SetError("Couldn't set audio format");
1.276 - return(-1);
1.277 - }
1.278 -
1.279 - /* Set the number of channels of output */
1.280 - value = spec->channels;
1.281 -#ifdef SNDCTL_DSP_CHANNELS
1.282 - if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0 ) {
1.283 -#endif
1.284 - value = (spec->channels > 1);
1.285 - ioctl(audio_fd, SNDCTL_DSP_STEREO, &value);
1.286 - value = (value ? 2 : 1);
1.287 -#ifdef SNDCTL_DSP_CHANNELS
1.288 - }
1.289 -#endif
1.290 - if ( value != spec->channels ) {
1.291 - SDL_SetError("Couldn't set audio channels");
1.292 - return(-1);
1.293 - }
1.294 -
1.295 - /* Set the DSP frequency */
1.296 - value = spec->freq;
1.297 - if ( ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0 ) {
1.298 - SDL_SetError("Couldn't set audio frequency");
1.299 - return(-1);
1.300 - }
1.301 - spec->freq = value;
1.302 -
1.303 - /* We successfully re-opened the audio */
1.304 - return(0);
1.305 -}
1.306 -
1.307 -static int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec)
1.308 -{
1.309 - char audiodev[1024];
1.310 - int format;
1.311 - int value;
1.312 - Uint16 test_format;
1.313 -
1.314 - /* Reset the timer synchronization flag */
1.315 - frame_ticks = 0.0;
1.316 -
1.317 - /* Open the audio device */
1.318 - audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
1.319 - if ( audio_fd < 0 ) {
1.320 - SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
1.321 - return(-1);
1.322 - }
1.323 - mixbuf = NULL;
1.324 -
1.325 -#ifdef USE_BLOCKING_WRITES
1.326 - /* Make the file descriptor use blocking writes with fcntl() */
1.327 - { long flags;
1.328 - flags = fcntl(audio_fd, F_GETFL);
1.329 - flags &= ~O_NONBLOCK;
1.330 - if ( fcntl(audio_fd, F_SETFL, flags) < 0 ) {
1.331 - SDL_SetError("Couldn't set audio blocking mode");
1.332 - return(-1);
1.333 - }
1.334 - }
1.335 -#endif
1.336 -
1.337 - /* Get a list of supported hardware formats */
1.338 - if ( ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0 ) {
1.339 - SDL_SetError("Couldn't get audio format list");
1.340 - return(-1);
1.341 - }
1.342 -
1.343 - /* Try for a closest match on audio format */
1.344 - format = 0;
1.345 - for ( test_format = SDL_FirstAudioFormat(spec->format);
1.346 - ! format && test_format; ) {
1.347 -#ifdef DEBUG_AUDIO
1.348 - fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
1.349 -#endif
1.350 - switch ( test_format ) {
1.351 - case AUDIO_U8:
1.352 - if ( value & AFMT_U8 ) {
1.353 - format = AFMT_U8;
1.354 - }
1.355 - break;
1.356 - case AUDIO_S8:
1.357 - if ( value & AFMT_S8 ) {
1.358 - format = AFMT_S8;
1.359 - }
1.360 - break;
1.361 - case AUDIO_S16LSB:
1.362 - if ( value & AFMT_S16_LE ) {
1.363 - format = AFMT_S16_LE;
1.364 - }
1.365 - break;
1.366 - case AUDIO_S16MSB:
1.367 - if ( value & AFMT_S16_BE ) {
1.368 - format = AFMT_S16_BE;
1.369 - }
1.370 - break;
1.371 - case AUDIO_U16LSB:
1.372 - if ( value & AFMT_U16_LE ) {
1.373 - format = AFMT_U16_LE;
1.374 - }
1.375 - break;
1.376 - case AUDIO_U16MSB:
1.377 - if ( value & AFMT_U16_BE ) {
1.378 - format = AFMT_U16_BE;
1.379 - }
1.380 - break;
1.381 - default:
1.382 - format = 0;
1.383 - break;
1.384 - }
1.385 - if ( ! format ) {
1.386 - test_format = SDL_NextAudioFormat();
1.387 - }
1.388 - }
1.389 - if ( format == 0 ) {
1.390 - SDL_SetError("Couldn't find any hardware audio formats");
1.391 - return(-1);
1.392 - }
1.393 - spec->format = test_format;
1.394 -
1.395 - /* Set the audio format */
1.396 - value = format;
1.397 - if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
1.398 - (value != format) ) {
1.399 - SDL_SetError("Couldn't set audio format");
1.400 - return(-1);
1.401 - }
1.402 -
1.403 - /* Set the number of channels of output */
1.404 - value = spec->channels;
1.405 -#ifdef SNDCTL_DSP_CHANNELS
1.406 - if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0 ) {
1.407 -#endif
1.408 - value = (spec->channels > 1);
1.409 - ioctl(audio_fd, SNDCTL_DSP_STEREO, &value);
1.410 - value = (value ? 2 : 1);
1.411 -#ifdef SNDCTL_DSP_CHANNELS
1.412 - }
1.413 -#endif
1.414 - spec->channels = value;
1.415 -
1.416 - /* Because some drivers don't allow setting the buffer size
1.417 - after setting the format, we must re-open the audio device
1.418 - once we know what format and channels are supported
1.419 - */
1.420 - if ( DSP_ReopenAudio(this, audiodev, format, spec) < 0 ) {
1.421 - /* Error is set by DSP_ReopenAudio() */
1.422 - return(-1);
1.423 - }
1.424 -
1.425 /* Allocate mixing buffer */
1.426 mixlen = spec->size;
1.427 mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen);
1.428 @@ -445,17 +321,6 @@
1.429 }
1.430 memset(mixbuf, spec->silence, spec->size);
1.431
1.432 -#ifndef USE_BLOCKING_WRITES
1.433 - /* Check to see if we need to use select() workaround */
1.434 - { char *workaround;
1.435 - workaround = getenv("SDL_DSP_NOSELECT");
1.436 - if ( workaround ) {
1.437 - frame_ticks = (float)(spec->samples*1000)/spec->freq;
1.438 - next_frame = SDL_GetTicks()+frame_ticks;
1.439 - }
1.440 - }
1.441 -#endif /* !USE_BLOCKING_WRITES */
1.442 -
1.443 /* Get the parent process id (we're the parent of the audio thread) */
1.444 parent = getpid();
1.445
2.1 --- a/src/audio/dsp/SDL_dspaudio.h Fri Nov 12 21:29:52 2004 +0000
2.2 +++ b/src/audio/dsp/SDL_dspaudio.h Fri Nov 12 21:39:04 2004 +0000
2.3 @@ -43,10 +43,6 @@
2.4 /* Raw mixing buffer */
2.5 Uint8 *mixbuf;
2.6 int mixlen;
2.7 -
2.8 - /* Support for audio timing using a timer, in addition to select() */
2.9 - float frame_ticks;
2.10 - float next_frame;
2.11 };
2.12 #define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
2.13