Mercurial > sdl-ios-xcode
changeset 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 |
files | src/audio/SDL_audio.c src/audio/SDL_sysaudio.h |
diffstat | 2 files changed, 120 insertions(+), 42 deletions(-) [+] |
line wrap: on
line diff
--- a/src/audio/SDL_audio.c Tue Aug 12 01:03:05 2008 +0000 +++ b/src/audio/SDL_audio.c Wed Aug 13 02:50:10 2008 +0000 @@ -319,6 +319,10 @@ void *udata; void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len); int silence; + + /* For streaming when the buffer sizes don't match up */ + Uint8 *istream; + int istream_len; /* Perform any thread setup */ device->threadid = SDL_ThreadID(); @@ -341,52 +345,125 @@ } /* Determine if the streamer is necessary here */ - - /* Loop, filling the audio buffers */ - while (device->enabled) { - - /* Fill the current buffer with sound */ - if (device->convert.needed) { - if (device->convert.buf) { - stream = device->convert.buf; - } else { - continue; - } - } else { - stream = current_audio.impl.GetDeviceBuf(device); - if (stream == NULL) { - stream = device->fake_stream; - } - } + if(device->use_streamer) { + /* This code is almost the same as the old code. The difference is, instead of reding + directly from the callback into "stream", then converting and sending the audio off, + we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device. + However, reading and writing with streamer are done separately: + - We only call the callback and write to the streamer when the streamer does not + contain enough samples to output to the device. + - We only read from the streamer and tell the device to play when the streamer + does have enough samples to output. + This allows us to perform resampling in the conversion step, where the output of the + resampling process can be any number. We will have to see what a good size for the + stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure. + */ + while (device->enabled) { + /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */ + if(SDL_StreamLength(&device->streamer) < stream_len) { + /* Read from the callback into the _input_ stream */ + if (!device->paused) { + SDL_mutexP(device->mixer_lock); + (*fill) (udata, istream, istream_len); + SDL_mutexV(device->mixer_lock); + } + + /* Convert the audio if necessary and write to the streamer */ + if (device->convert.needed) { + SDL_ConvertAudio(&device->convert); + istream = current_audio.impl.GetDeviceBuf(device); + if (istream == NULL) { + istream = device->fake_stream; + } + SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); + SDL_StreamWrite(&device->streamer, istream, device->convert.len_cvt); + } else { + SDL_StreamWrite(&device->streamer, istream, istream_len); + } + } + + /* Only output audio if the streamer has enough to output */ + if(SDL_StreamLength(&device->streamer) >= stream_len) { + /* Set up the output stream */ + if (device->convert.needed) { + if (device->convert.buf) { + stream = device->convert.buf; + } else { + continue; + } + } else { + stream = current_audio.impl.GetDeviceBuf(device); + if (stream == NULL) { + stream = device->fake_stream; + } + } + + /* Now read from the streamer */ + SDL_StreamRead(&device->streamer, stream, stream_len); + + /* Ready current buffer for play and change current buffer */ + if (stream != device->fake_stream) { + current_audio.impl.PlayDevice(device); + } - if (!device->paused) { - SDL_mutexP(device->mixer_lock); - (*fill) (udata, stream, stream_len); - SDL_mutexV(device->mixer_lock); - } + /* Wait for an audio buffer to become available */ + if (stream == device->fake_stream) { + SDL_Delay((device->spec.samples * 1000) / device->spec.freq); + } else { + current_audio.impl.WaitDevice(device); + } + } + + } + } else { + /* Otherwise, do not use the streamer. This is the old code. */ + + /* Loop, filling the audio buffers */ + while (device->enabled) { + + /* Fill the current buffer with sound */ + if (device->convert.needed) { + if (device->convert.buf) { + stream = device->convert.buf; + } else { + continue; + } + } else { + stream = current_audio.impl.GetDeviceBuf(device); + if (stream == NULL) { + stream = device->fake_stream; + } + } - /* Convert the audio if necessary */ - if (device->convert.needed) { - SDL_ConvertAudio(&device->convert); - stream = current_audio.impl.GetDeviceBuf(device); - if (stream == NULL) { - stream = device->fake_stream; - } - SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt); - } + if (!device->paused) { + SDL_mutexP(device->mixer_lock); + (*fill) (udata, stream, stream_len); + SDL_mutexV(device->mixer_lock); + } - /* Ready current buffer for play and change current buffer */ - if (stream != device->fake_stream) { - current_audio.impl.PlayDevice(device); - } + /* Convert the audio if necessary */ + if (device->convert.needed) { + SDL_ConvertAudio(&device->convert); + stream = current_audio.impl.GetDeviceBuf(device); + if (stream == NULL) { + stream = device->fake_stream; + } + SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt); + } - /* Wait for an audio buffer to become available */ - if (stream == device->fake_stream) { - SDL_Delay((device->spec.samples * 1000) / device->spec.freq); - } else { - current_audio.impl.WaitDevice(device); - } - } + /* Ready current buffer for play and change current buffer */ + if (stream != device->fake_stream) { + current_audio.impl.PlayDevice(device); + } + + /* Wait for an audio buffer to become available */ + if (stream == device->fake_stream) { + SDL_Delay((device->spec.samples * 1000) / device->spec.freq); + } else { + current_audio.impl.WaitDevice(device); + } + } + } /* Wait for the audio to drain.. */ current_audio.impl.WaitDone(device);