comparison src/audio/SDL_audio.c @ 2666:e12ccc6c9576 gsoc2008_audio_resampling

Implemented streamer code in SDL_RunAudio() but have not tested it.
author Aaron Wishnick <schnarf@gmail.com>
date Wed, 13 Aug 2008 02:50:10 +0000
parents f39a056aec8b
children 4174e511655f
comparison
equal deleted inserted replaced
2665:f39a056aec8b 2666:e12ccc6c9576
317 Uint8 *stream; 317 Uint8 *stream;
318 int stream_len; 318 int stream_len;
319 void *udata; 319 void *udata;
320 void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len); 320 void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
321 int silence; 321 int silence;
322
323 /* For streaming when the buffer sizes don't match up */
324 Uint8 *istream;
325 int istream_len;
322 326
323 /* Perform any thread setup */ 327 /* Perform any thread setup */
324 device->threadid = SDL_ThreadID(); 328 device->threadid = SDL_ThreadID();
325 current_audio.impl.ThreadInit(device); 329 current_audio.impl.ThreadInit(device);
326 330
339 silence = device->spec.silence; 343 silence = device->spec.silence;
340 stream_len = device->spec.size; 344 stream_len = device->spec.size;
341 } 345 }
342 346
343 /* Determine if the streamer is necessary here */ 347 /* Determine if the streamer is necessary here */
344 348 if(device->use_streamer) {
345 /* Loop, filling the audio buffers */ 349 /* This code is almost the same as the old code. The difference is, instead of reding
346 while (device->enabled) { 350 directly from the callback into "stream", then converting and sending the audio off,
347 351 we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
348 /* Fill the current buffer with sound */ 352 However, reading and writing with streamer are done separately:
349 if (device->convert.needed) { 353 - We only call the callback and write to the streamer when the streamer does not
350 if (device->convert.buf) { 354 contain enough samples to output to the device.
351 stream = device->convert.buf; 355 - We only read from the streamer and tell the device to play when the streamer
352 } else { 356 does have enough samples to output.
353 continue; 357 This allows us to perform resampling in the conversion step, where the output of the
354 } 358 resampling process can be any number. We will have to see what a good size for the
355 } else { 359 stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
356 stream = current_audio.impl.GetDeviceBuf(device); 360 */
357 if (stream == NULL) { 361 while (device->enabled) {
358 stream = device->fake_stream; 362 /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
359 } 363 if(SDL_StreamLength(&device->streamer) < stream_len) {
360 } 364 /* Read from the callback into the _input_ stream */
361 365 if (!device->paused) {
362 if (!device->paused) { 366 SDL_mutexP(device->mixer_lock);
363 SDL_mutexP(device->mixer_lock); 367 (*fill) (udata, istream, istream_len);
364 (*fill) (udata, stream, stream_len); 368 SDL_mutexV(device->mixer_lock);
365 SDL_mutexV(device->mixer_lock); 369 }
366 } 370
367 371 /* Convert the audio if necessary and write to the streamer */
368 /* Convert the audio if necessary */ 372 if (device->convert.needed) {
369 if (device->convert.needed) { 373 SDL_ConvertAudio(&device->convert);
370 SDL_ConvertAudio(&device->convert); 374 istream = current_audio.impl.GetDeviceBuf(device);
371 stream = current_audio.impl.GetDeviceBuf(device); 375 if (istream == NULL) {
372 if (stream == NULL) { 376 istream = device->fake_stream;
373 stream = device->fake_stream; 377 }
374 } 378 SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt);
375 SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt); 379 SDL_StreamWrite(&device->streamer, istream, device->convert.len_cvt);
376 } 380 } else {
377 381 SDL_StreamWrite(&device->streamer, istream, istream_len);
378 /* Ready current buffer for play and change current buffer */ 382 }
379 if (stream != device->fake_stream) { 383 }
380 current_audio.impl.PlayDevice(device); 384
381 } 385 /* Only output audio if the streamer has enough to output */
382 386 if(SDL_StreamLength(&device->streamer) >= stream_len) {
383 /* Wait for an audio buffer to become available */ 387 /* Set up the output stream */
384 if (stream == device->fake_stream) { 388 if (device->convert.needed) {
385 SDL_Delay((device->spec.samples * 1000) / device->spec.freq); 389 if (device->convert.buf) {
386 } else { 390 stream = device->convert.buf;
387 current_audio.impl.WaitDevice(device); 391 } else {
388 } 392 continue;
389 } 393 }
394 } else {
395 stream = current_audio.impl.GetDeviceBuf(device);
396 if (stream == NULL) {
397 stream = device->fake_stream;
398 }
399 }
400
401 /* Now read from the streamer */
402 SDL_StreamRead(&device->streamer, stream, stream_len);
403
404 /* Ready current buffer for play and change current buffer */
405 if (stream != device->fake_stream) {
406 current_audio.impl.PlayDevice(device);
407 }
408
409 /* Wait for an audio buffer to become available */
410 if (stream == device->fake_stream) {
411 SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
412 } else {
413 current_audio.impl.WaitDevice(device);
414 }
415 }
416
417 }
418 } else {
419 /* Otherwise, do not use the streamer. This is the old code. */
420
421 /* Loop, filling the audio buffers */
422 while (device->enabled) {
423
424 /* Fill the current buffer with sound */
425 if (device->convert.needed) {
426 if (device->convert.buf) {
427 stream = device->convert.buf;
428 } else {
429 continue;
430 }
431 } else {
432 stream = current_audio.impl.GetDeviceBuf(device);
433 if (stream == NULL) {
434 stream = device->fake_stream;
435 }
436 }
437
438 if (!device->paused) {
439 SDL_mutexP(device->mixer_lock);
440 (*fill) (udata, stream, stream_len);
441 SDL_mutexV(device->mixer_lock);
442 }
443
444 /* Convert the audio if necessary */
445 if (device->convert.needed) {
446 SDL_ConvertAudio(&device->convert);
447 stream = current_audio.impl.GetDeviceBuf(device);
448 if (stream == NULL) {
449 stream = device->fake_stream;
450 }
451 SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
452 }
453
454 /* Ready current buffer for play and change current buffer */
455 if (stream != device->fake_stream) {
456 current_audio.impl.PlayDevice(device);
457 }
458
459 /* Wait for an audio buffer to become available */
460 if (stream == device->fake_stream) {
461 SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
462 } else {
463 current_audio.impl.WaitDevice(device);
464 }
465 }
466 }
390 467
391 /* Wait for the audio to drain.. */ 468 /* Wait for the audio to drain.. */
392 current_audio.impl.WaitDone(device); 469 current_audio.impl.WaitDone(device);
393 470
394 return (0); 471 return (0);