comparison src/audio/dma/SDL_dmaaudio.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents d910939febfa
children 3b4ce57c6215
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
22 #include "SDL_config.h" 22 #include "SDL_config.h"
23 23
24 /* Allow access to a raw mixing buffer */ 24 /* Allow access to a raw mixing buffer */
25 25
26 #include <stdio.h> 26 #include <stdio.h>
27 #include <string.h> /* For strerror() */ 27 #include <string.h> /* For strerror() */
28 #include <errno.h> 28 #include <errno.h>
29 #include <unistd.h> 29 #include <unistd.h>
30 #include <fcntl.h> 30 #include <fcntl.h>
31 #include <signal.h> 31 #include <signal.h>
32 #include <sys/types.h> 32 #include <sys/types.h>
58 58
59 /* Open the audio device for playback, and don't block if busy */ 59 /* Open the audio device for playback, and don't block if busy */
60 #define OPEN_FLAGS (O_RDWR|O_NONBLOCK) 60 #define OPEN_FLAGS (O_RDWR|O_NONBLOCK)
61 61
62 /* Audio driver functions */ 62 /* Audio driver functions */
63 static int DMA_OpenAudio(_THIS, SDL_AudioSpec *spec); 63 static int DMA_OpenAudio(_THIS, SDL_AudioSpec * spec);
64 static void DMA_WaitAudio(_THIS); 64 static void DMA_WaitAudio(_THIS);
65 static void DMA_PlayAudio(_THIS); 65 static void DMA_PlayAudio(_THIS);
66 static Uint8 *DMA_GetAudioBuf(_THIS); 66 static Uint8 *DMA_GetAudioBuf(_THIS);
67 static void DMA_CloseAudio(_THIS); 67 static void DMA_CloseAudio(_THIS);
68 68
69 /* Audio driver bootstrap functions */ 69 /* Audio driver bootstrap functions */
70 70
71 static int Audio_Available(void) 71 static int
72 { 72 Audio_Available(void)
73 int available; 73 {
74 int fd; 74 int available;
75 75 int fd;
76 available = 0; 76
77 77 available = 0;
78 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); 78
79 if ( fd >= 0 ) { 79 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
80 int caps; 80 if (fd >= 0) {
81 struct audio_buf_info info; 81 int caps;
82 82 struct audio_buf_info info;
83 if ( (ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) && 83
84 (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) && 84 if ((ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) &&
85 (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0) ) { 85 (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) &&
86 available = 1; 86 (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0)) {
87 } 87 available = 1;
88 close(fd); 88 }
89 } 89 close(fd);
90 return(available); 90 }
91 } 91 return (available);
92 92 }
93 static void Audio_DeleteDevice(SDL_AudioDevice *device) 93
94 { 94 static void
95 SDL_free(device->hidden); 95 Audio_DeleteDevice(SDL_AudioDevice * device)
96 SDL_free(device); 96 {
97 } 97 SDL_free(device->hidden);
98 98 SDL_free(device);
99 static SDL_AudioDevice *Audio_CreateDevice(int devindex) 99 }
100 { 100
101 SDL_AudioDevice *this; 101 static SDL_AudioDevice *
102 102 Audio_CreateDevice(int devindex)
103 /* Initialize all variables that we clean on shutdown */ 103 {
104 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); 104 SDL_AudioDevice *this;
105 if ( this ) { 105
106 SDL_memset(this, 0, (sizeof *this)); 106 /* Initialize all variables that we clean on shutdown */
107 this->hidden = (struct SDL_PrivateAudioData *) 107 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
108 SDL_malloc((sizeof *this->hidden)); 108 if (this) {
109 } 109 SDL_memset(this, 0, (sizeof *this));
110 if ( (this == NULL) || (this->hidden == NULL) ) { 110 this->hidden = (struct SDL_PrivateAudioData *)
111 SDL_OutOfMemory(); 111 SDL_malloc((sizeof *this->hidden));
112 if ( this ) { 112 }
113 SDL_free(this); 113 if ((this == NULL) || (this->hidden == NULL)) {
114 } 114 SDL_OutOfMemory();
115 return(0); 115 if (this) {
116 } 116 SDL_free(this);
117 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); 117 }
118 audio_fd = -1; 118 return (0);
119 119 }
120 /* Set the function pointers */ 120 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
121 this->OpenAudio = DMA_OpenAudio; 121 audio_fd = -1;
122 this->WaitAudio = DMA_WaitAudio; 122
123 this->PlayAudio = DMA_PlayAudio; 123 /* Set the function pointers */
124 this->GetAudioBuf = DMA_GetAudioBuf; 124 this->OpenAudio = DMA_OpenAudio;
125 this->CloseAudio = DMA_CloseAudio; 125 this->WaitAudio = DMA_WaitAudio;
126 126 this->PlayAudio = DMA_PlayAudio;
127 this->free = Audio_DeleteDevice; 127 this->GetAudioBuf = DMA_GetAudioBuf;
128 128 this->CloseAudio = DMA_CloseAudio;
129 return this; 129
130 this->free = Audio_DeleteDevice;
131
132 return this;
130 } 133 }
131 134
132 AudioBootStrap DMA_bootstrap = { 135 AudioBootStrap DMA_bootstrap = {
133 DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio", 136 DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio",
134 Audio_Available, Audio_CreateDevice 137 Audio_Available, Audio_CreateDevice
135 }; 138 };
136 139
137 /* This function waits until it is possible to write a full sound buffer */ 140 /* This function waits until it is possible to write a full sound buffer */
138 static void DMA_WaitAudio(_THIS) 141 static void
139 { 142 DMA_WaitAudio(_THIS)
140 fd_set fdset; 143 {
141 144 fd_set fdset;
142 /* Check to see if the thread-parent process is still alive */ 145
143 { static int cnt = 0; 146 /* Check to see if the thread-parent process is still alive */
144 /* Note that this only works with thread implementations 147 {
145 that use a different process id for each thread. 148 static int cnt = 0;
146 */ 149 /* Note that this only works with thread implementations
147 if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ 150 that use a different process id for each thread.
148 if ( kill(parent, 0) < 0 ) { 151 */
149 this->enabled = 0; 152 if (parent && (((++cnt) % 10) == 0)) { /* Check every 10 loops */
150 } 153 if (kill(parent, 0) < 0) {
151 } 154 this->enabled = 0;
152 } 155 }
153 156 }
154 /* See if we need to use timed audio synchronization */ 157 }
155 if ( frame_ticks ) { 158
156 /* Use timer for general audio synchronization */ 159 /* See if we need to use timed audio synchronization */
157 Sint32 ticks; 160 if (frame_ticks) {
158 161 /* Use timer for general audio synchronization */
159 ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; 162 Sint32 ticks;
160 if ( ticks > 0 ) { 163
161 SDL_Delay(ticks); 164 ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
162 } 165 if (ticks > 0) {
163 } else { 166 SDL_Delay(ticks);
164 /* Use select() for audio synchronization */ 167 }
165 struct timeval timeout; 168 } else {
166 FD_ZERO(&fdset); 169 /* Use select() for audio synchronization */
167 FD_SET(audio_fd, &fdset); 170 struct timeval timeout;
168 timeout.tv_sec = 10; 171 FD_ZERO(&fdset);
169 timeout.tv_usec = 0; 172 FD_SET(audio_fd, &fdset);
173 timeout.tv_sec = 10;
174 timeout.tv_usec = 0;
170 #ifdef DEBUG_AUDIO 175 #ifdef DEBUG_AUDIO
171 fprintf(stderr, "Waiting for audio to get ready\n"); 176 fprintf(stderr, "Waiting for audio to get ready\n");
172 #endif 177 #endif
173 if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) { 178 if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) {
174 const char *message = 179 const char *message =
175 #ifdef AUDIO_OSPACE_HACK 180 #ifdef AUDIO_OSPACE_HACK
176 "Audio timeout - buggy audio driver? (trying ospace)"; 181 "Audio timeout - buggy audio driver? (trying ospace)";
177 #else 182 #else
178 "Audio timeout - buggy audio driver? (disabled)"; 183 "Audio timeout - buggy audio driver? (disabled)";
179 #endif 184 #endif
180 /* In general we should never print to the screen, 185 /* In general we should never print to the screen,
181 but in this case we have no other way of letting 186 but in this case we have no other way of letting
182 the user know what happened. 187 the user know what happened.
183 */ 188 */
184 fprintf(stderr, "SDL: %s\n", message); 189 fprintf(stderr, "SDL: %s\n", message);
185 #ifdef AUDIO_OSPACE_HACK 190 #ifdef AUDIO_OSPACE_HACK
186 /* We may be able to use GET_OSPACE trick */ 191 /* We may be able to use GET_OSPACE trick */
187 frame_ticks = (float)(this->spec->samples*1000) / 192 frame_ticks = (float) (this->spec->samples * 1000) /
188 this->spec->freq; 193 this->spec->freq;
189 next_frame = SDL_GetTicks()+frame_ticks; 194 next_frame = SDL_GetTicks() + frame_ticks;
190 #else 195 #else
191 this->enabled = 0; 196 this->enabled = 0;
192 /* Don't try to close - may hang */ 197 /* Don't try to close - may hang */
193 audio_fd = -1; 198 audio_fd = -1;
194 #ifdef DEBUG_AUDIO 199 #ifdef DEBUG_AUDIO
195 fprintf(stderr, "Done disabling audio\n"); 200 fprintf(stderr, "Done disabling audio\n");
196 #endif 201 #endif
197 #endif /* AUDIO_OSPACE_HACK */ 202 #endif /* AUDIO_OSPACE_HACK */
198 } 203 }
199 #ifdef DEBUG_AUDIO 204 #ifdef DEBUG_AUDIO
200 fprintf(stderr, "Ready!\n"); 205 fprintf(stderr, "Ready!\n");
201 #endif 206 #endif
202 } 207 }
203 } 208 }
204 209
205 static void DMA_PlayAudio(_THIS) 210 static void
206 { 211 DMA_PlayAudio(_THIS)
207 /* If timer synchronization is enabled, set the next write frame */ 212 {
208 if ( frame_ticks ) { 213 /* If timer synchronization is enabled, set the next write frame */
209 next_frame += frame_ticks; 214 if (frame_ticks) {
210 } 215 next_frame += frame_ticks;
211 return; 216 }
212 } 217 return;
213 218 }
214 static Uint8 *DMA_GetAudioBuf(_THIS) 219
215 { 220 static Uint8 *
216 count_info info; 221 DMA_GetAudioBuf(_THIS)
217 int playing; 222 {
218 int filling; 223 count_info info;
219 224 int playing;
220 /* Get number of blocks, looping if we're not using select() */ 225 int filling;
221 do { 226
222 if ( ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) < 0 ) { 227 /* Get number of blocks, looping if we're not using select() */
223 /* Uh oh... */ 228 do {
224 this->enabled = 0; 229 if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
225 return(NULL); 230 /* Uh oh... */
226 } 231 this->enabled = 0;
227 } while ( frame_ticks && (info.blocks < 1) ); 232 return (NULL);
233 }
234 }
235 while (frame_ticks && (info.blocks < 1));
228 #ifdef DEBUG_AUDIO 236 #ifdef DEBUG_AUDIO
229 if ( info.blocks > 1 ) { 237 if (info.blocks > 1) {
230 printf("Warning: audio underflow (%d frags)\n", info.blocks-1); 238 printf("Warning: audio underflow (%d frags)\n", info.blocks - 1);
231 } 239 }
232 #endif 240 #endif
233 playing = info.ptr / this->spec.size; 241 playing = info.ptr / this->spec.size;
234 filling = (playing + 1)%num_buffers; 242 filling = (playing + 1) % num_buffers;
235 return (dma_buf + (filling * this->spec.size)); 243 return (dma_buf + (filling * this->spec.size));
236 } 244 }
237 245
238 static void DMA_CloseAudio(_THIS) 246 static void
239 { 247 DMA_CloseAudio(_THIS)
240 if ( dma_buf != NULL ) { 248 {
241 munmap(dma_buf, dma_len); 249 if (dma_buf != NULL) {
242 dma_buf = NULL; 250 munmap(dma_buf, dma_len);
243 } 251 dma_buf = NULL;
244 if ( audio_fd >= 0 ) { 252 }
245 close(audio_fd); 253 if (audio_fd >= 0) {
246 audio_fd = -1; 254 close(audio_fd);
247 } 255 audio_fd = -1;
248 } 256 }
249 257 }
250 static int DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo, 258
251 SDL_AudioSpec *spec) 259 static int
252 { 260 DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo,
253 int frag_spec; 261 SDL_AudioSpec * spec)
254 int value; 262 {
255 263 int frag_spec;
256 /* Close and then reopen the audio device */ 264 int value;
257 close(audio_fd); 265
258 audio_fd = open(audiodev, O_RDWR, 0); 266 /* Close and then reopen the audio device */
259 if ( audio_fd < 0 ) { 267 close(audio_fd);
260 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); 268 audio_fd = open(audiodev, O_RDWR, 0);
261 return(-1); 269 if (audio_fd < 0) {
262 } 270 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
263 271 return (-1);
264 /* Calculate the final parameters for this audio specification */ 272 }
265 SDL_CalculateAudioSpec(spec); 273
266 274 /* Calculate the final parameters for this audio specification */
267 /* Determine the power of two of the fragment size */ 275 SDL_CalculateAudioSpec(spec);
268 for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec ); 276
269 if ( (0x01<<frag_spec) != spec->size ) { 277 /* Determine the power of two of the fragment size */
270 SDL_SetError("Fragment size must be a power of two"); 278 for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec);
271 return(-1); 279 if ((0x01 << frag_spec) != spec->size) {
272 } 280 SDL_SetError("Fragment size must be a power of two");
273 281 return (-1);
274 /* Set the audio buffering parameters */ 282 }
275 if ( ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0 ) { 283
276 SDL_SetError("Couldn't set audio fragment spec"); 284 /* Set the audio buffering parameters */
277 return(-1); 285 if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
278 } 286 SDL_SetError("Couldn't set audio fragment spec");
279 287 return (-1);
280 /* Set the audio format */ 288 }
281 value = format; 289
282 if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || 290 /* Set the audio format */
283 (value != format) ) { 291 value = format;
284 SDL_SetError("Couldn't set audio format"); 292 if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
285 return(-1); 293 SDL_SetError("Couldn't set audio format");
286 } 294 return (-1);
287 295 }
288 /* Set mono or stereo audio */ 296
289 value = (spec->channels > 1); 297 /* Set mono or stereo audio */
290 if ( (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) || 298 value = (spec->channels > 1);
291 (value != stereo) ) { 299 if ((ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) ||
292 SDL_SetError("Couldn't set audio channels"); 300 (value != stereo)) {
293 return(-1); 301 SDL_SetError("Couldn't set audio channels");
294 } 302 return (-1);
295 303 }
296 /* Set the DSP frequency */ 304
297 value = spec->freq; 305 /* Set the DSP frequency */
298 if ( ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0 ) { 306 value = spec->freq;
299 SDL_SetError("Couldn't set audio frequency"); 307 if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
300 return(-1); 308 SDL_SetError("Couldn't set audio frequency");
301 } 309 return (-1);
302 spec->freq = value; 310 }
303 311 spec->freq = value;
304 /* We successfully re-opened the audio */ 312
305 return(0); 313 /* We successfully re-opened the audio */
306 } 314 return (0);
307 315 }
308 static int DMA_OpenAudio(_THIS, SDL_AudioSpec *spec) 316
309 { 317 static int
310 char audiodev[1024]; 318 DMA_OpenAudio(_THIS, SDL_AudioSpec * spec)
311 int format; 319 {
312 int stereo; 320 char audiodev[1024];
313 int value; 321 int format;
314 Uint16 test_format; 322 int stereo;
315 struct audio_buf_info info; 323 int value;
316 324 Uint16 test_format;
317 /* Reset the timer synchronization flag */ 325 struct audio_buf_info info;
318 frame_ticks = 0.0; 326
319 327 /* Reset the timer synchronization flag */
320 /* Open the audio device */ 328 frame_ticks = 0.0;
321 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); 329
322 if ( audio_fd < 0 ) { 330 /* Open the audio device */
323 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); 331 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
324 return(-1); 332 if (audio_fd < 0) {
325 } 333 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
326 dma_buf = NULL; 334 return (-1);
327 ioctl(audio_fd, SNDCTL_DSP_RESET, 0); 335 }
328 336 dma_buf = NULL;
329 /* Get a list of supported hardware formats */ 337 ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
330 if ( ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0 ) { 338
331 SDL_SetError("Couldn't get audio format list"); 339 /* Get a list of supported hardware formats */
332 return(-1); 340 if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
333 } 341 SDL_SetError("Couldn't get audio format list");
334 342 return (-1);
335 /* Try for a closest match on audio format */ 343 }
336 format = 0; 344
337 for ( test_format = SDL_FirstAudioFormat(spec->format); 345 /* Try for a closest match on audio format */
338 ! format && test_format; ) { 346 format = 0;
347 for (test_format = SDL_FirstAudioFormat(spec->format);
348 !format && test_format;) {
339 #ifdef DEBUG_AUDIO 349 #ifdef DEBUG_AUDIO
340 fprintf(stderr, "Trying format 0x%4.4x\n", test_format); 350 fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
341 #endif 351 #endif
342 switch ( test_format ) { 352 switch (test_format) {
343 case AUDIO_U8: 353 case AUDIO_U8:
344 if ( value & AFMT_U8 ) { 354 if (value & AFMT_U8) {
345 format = AFMT_U8; 355 format = AFMT_U8;
346 } 356 }
347 break; 357 break;
348 case AUDIO_S8: 358 case AUDIO_S8:
349 if ( value & AFMT_S8 ) { 359 if (value & AFMT_S8) {
350 format = AFMT_S8; 360 format = AFMT_S8;
351 } 361 }
352 break; 362 break;
353 case AUDIO_S16LSB: 363 case AUDIO_S16LSB:
354 if ( value & AFMT_S16_LE ) { 364 if (value & AFMT_S16_LE) {
355 format = AFMT_S16_LE; 365 format = AFMT_S16_LE;
356 } 366 }
357 break; 367 break;
358 case AUDIO_S16MSB: 368 case AUDIO_S16MSB:
359 if ( value & AFMT_S16_BE ) { 369 if (value & AFMT_S16_BE) {
360 format = AFMT_S16_BE; 370 format = AFMT_S16_BE;
361 } 371 }
362 break; 372 break;
363 case AUDIO_U16LSB: 373 case AUDIO_U16LSB:
364 if ( value & AFMT_U16_LE ) { 374 if (value & AFMT_U16_LE) {
365 format = AFMT_U16_LE; 375 format = AFMT_U16_LE;
366 } 376 }
367 break; 377 break;
368 case AUDIO_U16MSB: 378 case AUDIO_U16MSB:
369 if ( value & AFMT_U16_BE ) { 379 if (value & AFMT_U16_BE) {
370 format = AFMT_U16_BE; 380 format = AFMT_U16_BE;
371 } 381 }
372 break; 382 break;
373 default: 383 default:
374 format = 0; 384 format = 0;
375 break; 385 break;
376 } 386 }
377 if ( ! format ) { 387 if (!format) {
378 test_format = SDL_NextAudioFormat(); 388 test_format = SDL_NextAudioFormat();
379 } 389 }
380 } 390 }
381 if ( format == 0 ) { 391 if (format == 0) {
382 SDL_SetError("Couldn't find any hardware audio formats"); 392 SDL_SetError("Couldn't find any hardware audio formats");
383 return(-1); 393 return (-1);
384 } 394 }
385 spec->format = test_format; 395 spec->format = test_format;
386 396
387 /* Set the audio format */ 397 /* Set the audio format */
388 value = format; 398 value = format;
389 if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || 399 if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
390 (value != format) ) { 400 SDL_SetError("Couldn't set audio format");
391 SDL_SetError("Couldn't set audio format"); 401 return (-1);
392 return(-1); 402 }
393 } 403
394 404 /* Set mono or stereo audio (currently only two channels supported) */
395 /* Set mono or stereo audio (currently only two channels supported) */ 405 stereo = (spec->channels > 1);
396 stereo = (spec->channels > 1); 406 ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo);
397 ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo); 407 if (stereo) {
398 if ( stereo ) { 408 spec->channels = 2;
399 spec->channels = 2; 409 } else {
400 } else { 410 spec->channels = 1;
401 spec->channels = 1; 411 }
402 } 412
403 413 /* Because some drivers don't allow setting the buffer size
404 /* Because some drivers don't allow setting the buffer size 414 after setting the format, we must re-open the audio device
405 after setting the format, we must re-open the audio device 415 once we know what format and channels are supported
406 once we know what format and channels are supported 416 */
407 */ 417 if (DMA_ReopenAudio(this, audiodev, format, stereo, spec) < 0) {
408 if ( DMA_ReopenAudio(this, audiodev, format, stereo, spec) < 0 ) { 418 /* Error is set by DMA_ReopenAudio() */
409 /* Error is set by DMA_ReopenAudio() */ 419 return (-1);
410 return(-1); 420 }
411 } 421
412 422 /* Memory map the audio buffer */
413 /* Memory map the audio buffer */ 423 if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
414 if ( ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0 ) { 424 SDL_SetError("Couldn't get OSPACE parameters");
415 SDL_SetError("Couldn't get OSPACE parameters"); 425 return (-1);
416 return(-1); 426 }
417 } 427 spec->size = info.fragsize;
418 spec->size = info.fragsize; 428 spec->samples = spec->size / ((spec->format & 0xFF) / 8);
419 spec->samples = spec->size / ((spec->format & 0xFF) / 8); 429 spec->samples /= spec->channels;
420 spec->samples /= spec->channels; 430 num_buffers = info.fragstotal;
421 num_buffers = info.fragstotal; 431 dma_len = num_buffers * spec->size;
422 dma_len = num_buffers*spec->size; 432 dma_buf = (Uint8 *) mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED,
423 dma_buf = (Uint8 *)mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED, 433 audio_fd, 0);
424 audio_fd, 0); 434 if (dma_buf == MAP_FAILED) {
425 if ( dma_buf == MAP_FAILED ) { 435 SDL_SetError("DMA memory map failed");
426 SDL_SetError("DMA memory map failed"); 436 dma_buf = NULL;
427 dma_buf = NULL; 437 return (-1);
428 return(-1); 438 }
429 } 439 SDL_memset(dma_buf, spec->silence, dma_len);
430 SDL_memset(dma_buf, spec->silence, dma_len); 440
431 441 /* Check to see if we need to use select() workaround */
432 /* Check to see if we need to use select() workaround */ 442 {
433 { char *workaround; 443 char *workaround;
434 workaround = SDL_getenv("SDL_DSP_NOSELECT"); 444 workaround = SDL_getenv("SDL_DSP_NOSELECT");
435 if ( workaround ) { 445 if (workaround) {
436 frame_ticks = (float)(spec->samples*1000)/spec->freq; 446 frame_ticks = (float) (spec->samples * 1000) / spec->freq;
437 next_frame = SDL_GetTicks()+frame_ticks; 447 next_frame = SDL_GetTicks() + frame_ticks;
438 } 448 }
439 } 449 }
440 450
441 /* Trigger audio playback */ 451 /* Trigger audio playback */
442 value = 0; 452 value = 0;
443 ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value); 453 ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value);
444 value = PCM_ENABLE_OUTPUT; 454 value = PCM_ENABLE_OUTPUT;
445 if ( ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0 ) { 455 if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0) {
446 SDL_SetError("Couldn't trigger audio output"); 456 SDL_SetError("Couldn't trigger audio output");
447 return(-1); 457 return (-1);
448 } 458 }
449 459
450 /* Get the parent process id (we're the parent of the audio thread) */ 460 /* Get the parent process id (we're the parent of the audio thread) */
451 parent = getpid(); 461 parent = getpid();
452 462
453 /* We're ready to rock and roll. :-) */ 463 /* We're ready to rock and roll. :-) */
454 return(0); 464 return (0);
455 } 465 }
466
467 /* vi: set ts=4 sw=4 expandtab: */