From da08f8f0b8e49b49dc406cd36f81077b70394e51 Mon Sep 17 00:00:00 2001 From: Aaron Wishnick Date: Wed, 13 Aug 2008 02:50:10 +0000 Subject: [PATCH] Implemented streamer code in SDL_RunAudio() but have not tested it. --- src/audio/SDL_audio.c | 169 ++++++++++++++++++++++++++++----------- src/audio/SDL_sysaudio.h | 1 + 2 files changed, 124 insertions(+), 46 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 36fb1ff2f..ba37a64cb 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -319,6 +319,10 @@ SDL_RunAudio(void *devicep) 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 @@ SDL_RunAudio(void *devicep) } /* 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->paused) { - SDL_mutexP(device->mixer_lock); - (*fill) (udata, stream, stream_len); - SDL_mutexV(device->mixer_lock); - } - - /* 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); - } - - /* 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); - } - } + 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); + } + + /* 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; + } + } + + if (!device->paused) { + SDL_mutexP(device->mixer_lock); + (*fill) (udata, stream, stream_len); + SDL_mutexV(device->mixer_lock); + } + + /* 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); + } + + /* 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); diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index c8304e540..303dcb800 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -68,6 +68,7 @@ typedef struct SDL_AudioDriver SDL_AudioDriverImpl impl; } SDL_AudioDriver; + /* Streamer */ typedef struct {