comparison src/audio/SDL_audio.c @ 2667:4174e511655f gsoc2008_audio_resampling

Streamer in SDL_RunAudio should be totally implemented, but hasn't been tested yet.
author Aaron Wishnick <schnarf@gmail.com>
date Thu, 14 Aug 2008 08:21:25 +0000
parents e12ccc6c9576
children
comparison
equal deleted inserted replaced
2666:e12ccc6c9576 2667:4174e511655f
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 int stream_max_len;
322 323
323 /* For streaming when the buffer sizes don't match up */ 324 /* For streaming when the buffer sizes don't match up */
324 Uint8 *istream; 325 Uint8 *istream;
325 int istream_len; 326 int istream_len;
326 327
329 current_audio.impl.ThreadInit(device); 330 current_audio.impl.ThreadInit(device);
330 331
331 /* Set up the mixing function */ 332 /* Set up the mixing function */
332 fill = device->spec.callback; 333 fill = device->spec.callback;
333 udata = device->spec.userdata; 334 udata = device->spec.userdata;
335
336 /* By default do not stream */
337 device->use_streamer = 0;
334 338
335 if (device->convert.needed) { 339 if (device->convert.needed) {
336 if (device->convert.src_format == AUDIO_U8) { 340 if (device->convert.src_format == AUDIO_U8) {
337 silence = 0x80; 341 silence = 0x80;
338 } else { 342 } else {
339 silence = 0; 343 silence = 0;
340 } 344 }
341 stream_len = device->convert.len; 345
346 /* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
347 if(device->convert.len_mult != 1 || device->convert.len_div != 1) {
348 /* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
349 stream_max_len = 2 * device->spec.size;
350 if(device->convert.len_mult > device->convert.len_div) {
351 stream_max_len *= device->convert.len_mult;
352 stream_max_len /= device->convert.len_div;
353 }
354 if(SDL_StreamInit(&device->streamer, stream_max_len, silence) < 0) return -1;
355 device->use_streamer = 1;
356
357 /* istream_len should be the length of what we grab from the callback and feed to conversion,
358 so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
359 */
360 istream_len = device->spec.size * device->convert.len_div / device->convert.len_mult;
361 }
362
363 /* stream_len = device->convert.len; */
364 stream_len = device->spec.size;
342 } else { 365 } else {
343 silence = device->spec.silence; 366 silence = device->spec.silence;
344 stream_len = device->spec.size; 367 stream_len = device->spec.size;
345 } 368 }
346 369
347 /* Determine if the streamer is necessary here */ 370 /* Determine if the streamer is necessary here */
348 if(device->use_streamer) { 371 if(device->use_streamer == 1) {
349 /* This code is almost the same as the old code. The difference is, instead of reding 372 /* This code is almost the same as the old code. The difference is, instead of reding
350 directly from the callback into "stream", then converting and sending the audio off, 373 directly from the callback into "stream", then converting and sending the audio off,
351 we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device. 374 we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
352 However, reading and writing with streamer are done separately: 375 However, reading and writing with streamer are done separately:
353 - We only call the callback and write to the streamer when the streamer does not 376 - We only call the callback and write to the streamer when the streamer does not
359 stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure. 382 stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
360 */ 383 */
361 while (device->enabled) { 384 while (device->enabled) {
362 /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */ 385 /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
363 if(SDL_StreamLength(&device->streamer) < stream_len) { 386 if(SDL_StreamLength(&device->streamer) < stream_len) {
387 /* Set up istream */
388 if (device->convert.needed) {
389 if (device->convert.buf) {
390 istream = device->convert.buf;
391 } else {
392 continue;
393 }
394 } else {
395 istream = current_audio.impl.GetDeviceBuf(device);
396 if (istream == NULL) {
397 istream = device->fake_stream;
398 }
399 }
400
364 /* Read from the callback into the _input_ stream */ 401 /* Read from the callback into the _input_ stream */
365 if (!device->paused) { 402 if (!device->paused) {
366 SDL_mutexP(device->mixer_lock); 403 SDL_mutexP(device->mixer_lock);
367 (*fill) (udata, istream, istream_len); 404 (*fill) (udata, istream, istream_len);
368 SDL_mutexV(device->mixer_lock); 405 SDL_mutexV(device->mixer_lock);
369 } 406 }
370 407
371 /* Convert the audio if necessary and write to the streamer */ 408 /* Convert the audio if necessary and write to the streamer */
372 if (device->convert.needed) { 409 if (device->convert.needed) {
373 SDL_ConvertAudio(&device->convert); 410 SDL_ConvertAudio(&device->convert);
374 istream = current_audio.impl.GetDeviceBuf(device);
375 if (istream == NULL) { 411 if (istream == NULL) {
376 istream = device->fake_stream; 412 istream = device->fake_stream;
377 } 413 }
378 SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); 414 /*SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt);*/
379 SDL_StreamWrite(&device->streamer, istream, device->convert.len_cvt); 415 SDL_StreamWrite(&device->streamer, device->convert.buf, device->convert.len_cvt);
380 } else { 416 } else {
381 SDL_StreamWrite(&device->streamer, istream, istream_len); 417 SDL_StreamWrite(&device->streamer, istream, istream_len);
382 } 418 }
383 } 419 }
384 420
465 } 501 }
466 } 502 }
467 503
468 /* Wait for the audio to drain.. */ 504 /* Wait for the audio to drain.. */
469 current_audio.impl.WaitDone(device); 505 current_audio.impl.WaitDone(device);
506
507 /* If necessary, deinit the streamer */
508 if(device->use_streamer == 1) SDL_StreamDeinit(&device->streamer);
470 509
471 return (0); 510 return (0);
472 } 511 }
473 512
474 513