comparison src/audio/SDL_audio.c @ 3336:00fab0ebfe54

Fixed a bug where when the audio starts paused all the DirectSound buffers will end up getting locked and never unlocked and sound will never play. Added a FIXME for Ryan to look at, too. :)
author Sam Lantinga <slouken@libsdl.org>
date Sun, 04 Oct 2009 09:18:48 +0000
parents 1ed5d432e468
children e897a4a9f578
comparison
equal deleted inserted replaced
3335:b8d313de8a65 3336:00fab0ebfe54
324 Uint8 *stream; 324 Uint8 *stream;
325 int stream_len; 325 int stream_len;
326 void *udata; 326 void *udata;
327 void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len); 327 void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
328 int silence; 328 int silence;
329 Uint32 delay;
329 330
330 /* For streaming when the buffer sizes don't match up */ 331 /* For streaming when the buffer sizes don't match up */
331 Uint8 *istream; 332 Uint8 *istream;
332 int istream_len; 333 int istream_len;
333 334
377 } else { 378 } else {
378 silence = device->spec.silence; 379 silence = device->spec.silence;
379 stream_len = device->spec.size; 380 stream_len = device->spec.size;
380 } 381 }
381 382
383 /* Calculate the delay while paused */
384 delay = ((device->spec.samples * 1000) / device->spec.freq);
385
382 /* Determine if the streamer is necessary here */ 386 /* Determine if the streamer is necessary here */
383 if (device->use_streamer == 1) { 387 if (device->use_streamer == 1) {
384 /* This code is almost the same as the old code. The difference is, instead of reding 388 /* This code is almost the same as the old code. The difference is, instead of reading
385 directly from the callback into "stream", then converting and sending the audio off, 389 directly from the callback into "stream", then converting and sending the audio off,
386 we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device. 390 we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
387 However, reading and writing with streamer are done separately: 391 However, reading and writing with streamer are done separately:
388 - We only call the callback and write to the streamer when the streamer does not 392 - We only call the callback and write to the streamer when the streamer does not
389 contain enough samples to output to the device. 393 contain enough samples to output to the device.
392 This allows us to perform resampling in the conversion step, where the output of the 396 This allows us to perform resampling in the conversion step, where the output of the
393 resampling process can be any number. We will have to see what a good size for the 397 resampling process can be any number. We will have to see what a good size for the
394 stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure. 398 stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
395 */ 399 */
396 while (device->enabled) { 400 while (device->enabled) {
401
402 if (device->paused) {
403 SDL_Delay(delay);
404 continue;
405 }
406
397 /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */ 407 /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
398 if (SDL_StreamLength(&device->streamer) < stream_len) { 408 if (SDL_StreamLength(&device->streamer) < stream_len) {
399 /* Set up istream */ 409 /* Set up istream */
400 if (device->convert.needed) { 410 if (device->convert.needed) {
401 if (device->convert.buf) { 411 if (device->convert.buf) {
402 istream = device->convert.buf; 412 istream = device->convert.buf;
403 } else { 413 } else {
404 continue; 414 continue;
405 } 415 }
406 } else { 416 } else {
417 /* FIXME: Ryan, this is probably wrong. I imagine we don't want to get
418 * a device buffer both here and below in the stream output.
419 */
407 istream = current_audio.impl.GetDeviceBuf(device); 420 istream = current_audio.impl.GetDeviceBuf(device);
408 if (istream == NULL) { 421 if (istream == NULL) {
409 istream = device->fake_stream; 422 istream = device->fake_stream;
410 } 423 }
411 } 424 }
412 425
413 /* Read from the callback into the _input_ stream */ 426 /* Read from the callback into the _input_ stream */
414 if (!device->paused) { 427 SDL_mutexP(device->mixer_lock);
415 SDL_mutexP(device->mixer_lock); 428 (*fill) (udata, istream, istream_len);
416 (*fill) (udata, istream, istream_len); 429 SDL_mutexV(device->mixer_lock);
417 SDL_mutexV(device->mixer_lock);
418 }
419 430
420 /* Convert the audio if necessary and write to the streamer */ 431 /* Convert the audio if necessary and write to the streamer */
421 if (device->convert.needed) { 432 if (device->convert.needed) {
422 SDL_ConvertAudio(&device->convert); 433 SDL_ConvertAudio(&device->convert);
423 if (istream == NULL) { 434 if (istream == NULL) {
449 460
450 /* Now read from the streamer */ 461 /* Now read from the streamer */
451 SDL_StreamRead(&device->streamer, stream, stream_len); 462 SDL_StreamRead(&device->streamer, stream, stream_len);
452 463
453 /* Ready current buffer for play and change current buffer */ 464 /* Ready current buffer for play and change current buffer */
454 if (stream != device->fake_stream && !device->paused) { 465 if (stream != device->fake_stream) {
455 current_audio.impl.PlayDevice(device); 466 current_audio.impl.PlayDevice(device);
456 /* Wait for an audio buffer to become available */ 467 /* Wait for an audio buffer to become available */
457 current_audio.impl.WaitDevice(device); 468 current_audio.impl.WaitDevice(device);
458 } else { 469 } else {
459 SDL_Delay((device->spec.samples * 1000) / 470 SDL_Delay(delay);
460 device->spec.freq);
461 } 471 }
462 } 472 }
463 473
464 } 474 }
465 } else { 475 } else {
466 /* Otherwise, do not use the streamer. This is the old code. */ 476 /* Otherwise, do not use the streamer. This is the old code. */
467 477
468 /* Loop, filling the audio buffers */ 478 /* Loop, filling the audio buffers */
469 while (device->enabled) { 479 while (device->enabled) {
480
481 if (device->paused) {
482 SDL_Delay(delay);
483 continue;
484 }
470 485
471 /* Fill the current buffer with sound */ 486 /* Fill the current buffer with sound */
472 if (device->convert.needed) { 487 if (device->convert.needed) {
473 if (device->convert.buf) { 488 if (device->convert.buf) {
474 stream = device->convert.buf; 489 stream = device->convert.buf;
480 if (stream == NULL) { 495 if (stream == NULL) {
481 stream = device->fake_stream; 496 stream = device->fake_stream;
482 } 497 }
483 } 498 }
484 499
485 if (!device->paused) { 500 SDL_mutexP(device->mixer_lock);
486 SDL_mutexP(device->mixer_lock); 501 (*fill) (udata, stream, stream_len);
487 (*fill) (udata, stream, stream_len); 502 SDL_mutexV(device->mixer_lock);
488 SDL_mutexV(device->mixer_lock);
489 }
490 503
491 /* Convert the audio if necessary */ 504 /* Convert the audio if necessary */
492 if (device->convert.needed) { 505 if (device->convert.needed) {
493 SDL_ConvertAudio(&device->convert); 506 SDL_ConvertAudio(&device->convert);
494 stream = current_audio.impl.GetDeviceBuf(device); 507 stream = current_audio.impl.GetDeviceBuf(device);
498 SDL_memcpy(stream, device->convert.buf, 511 SDL_memcpy(stream, device->convert.buf,
499 device->convert.len_cvt); 512 device->convert.len_cvt);
500 } 513 }
501 514
502 /* Ready current buffer for play and change current buffer */ 515 /* Ready current buffer for play and change current buffer */
503 if (stream != device->fake_stream && !device->paused) { 516 if (stream != device->fake_stream) {
504 current_audio.impl.PlayDevice(device); 517 current_audio.impl.PlayDevice(device);
505 /* Wait for an audio buffer to become available */ 518 /* Wait for an audio buffer to become available */
506 current_audio.impl.WaitDevice(device); 519 current_audio.impl.WaitDevice(device);
507 } else { 520 } else {
508 SDL_Delay((device->spec.samples * 1000) / device->spec.freq); 521 SDL_Delay(delay);
509 } 522 }
510 } 523 }
511 } 524 }
512 525
513 /* Wait for the audio to drain.. */ 526 /* Wait for the audio to drain.. */