Implemented streamer code in SDL_RunAudio() but have not tested it.
1.1 --- a/src/audio/SDL_audio.c Tue Aug 12 01:03:05 2008 +0000
1.2 +++ b/src/audio/SDL_audio.c Wed Aug 13 02:50:10 2008 +0000
1.3 @@ -319,6 +319,10 @@
1.4 void *udata;
1.5 void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
1.6 int silence;
1.7 +
1.8 + /* For streaming when the buffer sizes don't match up */
1.9 + Uint8 *istream;
1.10 + int istream_len;
1.11
1.12 /* Perform any thread setup */
1.13 device->threadid = SDL_ThreadID();
1.14 @@ -341,52 +345,125 @@
1.15 }
1.16
1.17 /* Determine if the streamer is necessary here */
1.18 -
1.19 - /* Loop, filling the audio buffers */
1.20 - while (device->enabled) {
1.21 -
1.22 - /* Fill the current buffer with sound */
1.23 - if (device->convert.needed) {
1.24 - if (device->convert.buf) {
1.25 - stream = device->convert.buf;
1.26 - } else {
1.27 - continue;
1.28 - }
1.29 - } else {
1.30 - stream = current_audio.impl.GetDeviceBuf(device);
1.31 - if (stream == NULL) {
1.32 - stream = device->fake_stream;
1.33 - }
1.34 - }
1.35 + if(device->use_streamer) {
1.36 + /* This code is almost the same as the old code. The difference is, instead of reding
1.37 + directly from the callback into "stream", then converting and sending the audio off,
1.38 + we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
1.39 + However, reading and writing with streamer are done separately:
1.40 + - We only call the callback and write to the streamer when the streamer does not
1.41 + contain enough samples to output to the device.
1.42 + - We only read from the streamer and tell the device to play when the streamer
1.43 + does have enough samples to output.
1.44 + This allows us to perform resampling in the conversion step, where the output of the
1.45 + resampling process can be any number. We will have to see what a good size for the
1.46 + stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
1.47 + */
1.48 + while (device->enabled) {
1.49 + /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
1.50 + if(SDL_StreamLength(&device->streamer) < stream_len) {
1.51 + /* Read from the callback into the _input_ stream */
1.52 + if (!device->paused) {
1.53 + SDL_mutexP(device->mixer_lock);
1.54 + (*fill) (udata, istream, istream_len);
1.55 + SDL_mutexV(device->mixer_lock);
1.56 + }
1.57 +
1.58 + /* Convert the audio if necessary and write to the streamer */
1.59 + if (device->convert.needed) {
1.60 + SDL_ConvertAudio(&device->convert);
1.61 + istream = current_audio.impl.GetDeviceBuf(device);
1.62 + if (istream == NULL) {
1.63 + istream = device->fake_stream;
1.64 + }
1.65 + SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt);
1.66 + SDL_StreamWrite(&device->streamer, istream, device->convert.len_cvt);
1.67 + } else {
1.68 + SDL_StreamWrite(&device->streamer, istream, istream_len);
1.69 + }
1.70 + }
1.71 +
1.72 + /* Only output audio if the streamer has enough to output */
1.73 + if(SDL_StreamLength(&device->streamer) >= stream_len) {
1.74 + /* Set up the output stream */
1.75 + if (device->convert.needed) {
1.76 + if (device->convert.buf) {
1.77 + stream = device->convert.buf;
1.78 + } else {
1.79 + continue;
1.80 + }
1.81 + } else {
1.82 + stream = current_audio.impl.GetDeviceBuf(device);
1.83 + if (stream == NULL) {
1.84 + stream = device->fake_stream;
1.85 + }
1.86 + }
1.87 +
1.88 + /* Now read from the streamer */
1.89 + SDL_StreamRead(&device->streamer, stream, stream_len);
1.90 +
1.91 + /* Ready current buffer for play and change current buffer */
1.92 + if (stream != device->fake_stream) {
1.93 + current_audio.impl.PlayDevice(device);
1.94 + }
1.95
1.96 - if (!device->paused) {
1.97 - SDL_mutexP(device->mixer_lock);
1.98 - (*fill) (udata, stream, stream_len);
1.99 - SDL_mutexV(device->mixer_lock);
1.100 - }
1.101 + /* Wait for an audio buffer to become available */
1.102 + if (stream == device->fake_stream) {
1.103 + SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
1.104 + } else {
1.105 + current_audio.impl.WaitDevice(device);
1.106 + }
1.107 + }
1.108 +
1.109 + }
1.110 + } else {
1.111 + /* Otherwise, do not use the streamer. This is the old code. */
1.112 +
1.113 + /* Loop, filling the audio buffers */
1.114 + while (device->enabled) {
1.115 +
1.116 + /* Fill the current buffer with sound */
1.117 + if (device->convert.needed) {
1.118 + if (device->convert.buf) {
1.119 + stream = device->convert.buf;
1.120 + } else {
1.121 + continue;
1.122 + }
1.123 + } else {
1.124 + stream = current_audio.impl.GetDeviceBuf(device);
1.125 + if (stream == NULL) {
1.126 + stream = device->fake_stream;
1.127 + }
1.128 + }
1.129
1.130 - /* Convert the audio if necessary */
1.131 - if (device->convert.needed) {
1.132 - SDL_ConvertAudio(&device->convert);
1.133 - stream = current_audio.impl.GetDeviceBuf(device);
1.134 - if (stream == NULL) {
1.135 - stream = device->fake_stream;
1.136 - }
1.137 - SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
1.138 - }
1.139 + if (!device->paused) {
1.140 + SDL_mutexP(device->mixer_lock);
1.141 + (*fill) (udata, stream, stream_len);
1.142 + SDL_mutexV(device->mixer_lock);
1.143 + }
1.144
1.145 - /* Ready current buffer for play and change current buffer */
1.146 - if (stream != device->fake_stream) {
1.147 - current_audio.impl.PlayDevice(device);
1.148 - }
1.149 + /* Convert the audio if necessary */
1.150 + if (device->convert.needed) {
1.151 + SDL_ConvertAudio(&device->convert);
1.152 + stream = current_audio.impl.GetDeviceBuf(device);
1.153 + if (stream == NULL) {
1.154 + stream = device->fake_stream;
1.155 + }
1.156 + SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
1.157 + }
1.158
1.159 - /* Wait for an audio buffer to become available */
1.160 - if (stream == device->fake_stream) {
1.161 - SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
1.162 - } else {
1.163 - current_audio.impl.WaitDevice(device);
1.164 - }
1.165 - }
1.166 + /* Ready current buffer for play and change current buffer */
1.167 + if (stream != device->fake_stream) {
1.168 + current_audio.impl.PlayDevice(device);
1.169 + }
1.170 +
1.171 + /* Wait for an audio buffer to become available */
1.172 + if (stream == device->fake_stream) {
1.173 + SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
1.174 + } else {
1.175 + current_audio.impl.WaitDevice(device);
1.176 + }
1.177 + }
1.178 + }
1.179
1.180 /* Wait for the audio to drain.. */
1.181 current_audio.impl.WaitDone(device);
2.1 --- a/src/audio/SDL_sysaudio.h Tue Aug 12 01:03:05 2008 +0000
2.2 +++ b/src/audio/SDL_sysaudio.h Wed Aug 13 02:50:10 2008 +0000
2.3 @@ -68,6 +68,7 @@
2.4 SDL_AudioDriverImpl impl;
2.5 } SDL_AudioDriver;
2.6
2.7 +
2.8 /* Streamer */
2.9 typedef struct
2.10 {