Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Implemented streamer code in SDL_RunAudio() but have not tested it.
Browse files Browse the repository at this point in the history
  • Loading branch information
schnarf committed Aug 13, 2008
1 parent 96735b8 commit da08f8f
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 46 deletions.
169 changes: 123 additions & 46 deletions src/audio/SDL_audio.c
Expand Up @@ -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();
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/audio/SDL_sysaudio.h
Expand Up @@ -68,6 +68,7 @@ typedef struct SDL_AudioDriver
SDL_AudioDriverImpl impl;
} SDL_AudioDriver;


/* Streamer */
typedef struct
{
Expand Down

0 comments on commit da08f8f

Please sign in to comment.