Mercurial > sdl-ios-xcode
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 |