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