* Adjustment: Update libsdl to address a bug in compilation on MacOS devices.

This commit is contained in:
Robert MacGregor 2022-05-21 20:25:30 -04:00
parent 516163fd5d
commit eab544c8f3
270 changed files with 9531 additions and 3704 deletions

View file

@ -1649,8 +1649,6 @@ SDL_AudioQuit(void)
#ifdef HAVE_LIBSAMPLERATE_H
UnloadLibSampleRate();
#endif
SDL_FreeResampleFilter();
}
#define NUM_FORMATS 10

View file

@ -70,11 +70,6 @@ extern SDL_AudioFilter SDL_Convert_F32_to_S16;
extern SDL_AudioFilter SDL_Convert_F32_to_U16;
extern SDL_AudioFilter SDL_Convert_F32_to_S32;
/* You need to call SDL_PrepareResampleFilter() before using the internal resampler.
SDL_AudioQuit() calls SDL_FreeResamplerFilter(), you should never call it yourself. */
extern int SDL_PrepareResampleFilter(void);
extern void SDL_FreeResampleFilter(void);
#endif /* SDL_audio_c_h_ */
/* vi: set ts=4 sw=4 expandtab: */

File diff suppressed because it is too large Load diff

View file

@ -704,97 +704,7 @@ SDL_Convert51To71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
/* SDL's resampler uses a "bandlimited interpolation" algorithm:
https://ccrma.stanford.edu/~jos/resample/ */
#define RESAMPLER_ZERO_CROSSINGS 5
#define RESAMPLER_BITS_PER_SAMPLE 16
#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING (1 << ((RESAMPLER_BITS_PER_SAMPLE / 2) + 1))
#define RESAMPLER_FILTER_SIZE ((RESAMPLER_SAMPLES_PER_ZERO_CROSSING * RESAMPLER_ZERO_CROSSINGS) + 1)
/* This is a "modified" bessel function, so you can't use POSIX j0() */
static double
bessel(const double x)
{
const double xdiv2 = x / 2.0;
double i0 = 1.0f;
double f = 1.0f;
int i = 1;
while (SDL_TRUE) {
const double diff = SDL_pow(xdiv2, i * 2) / SDL_pow(f, 2);
if (diff < 1.0e-21f) {
break;
}
i0 += diff;
i++;
f *= (double) i;
}
return i0;
}
/* build kaiser table with cardinal sine applied to it, and array of differences between elements. */
static void
kaiser_and_sinc(float *table, float *diffs, const int tablelen, const double beta)
{
const int lenm1 = tablelen - 1;
const int lenm1div2 = lenm1 / 2;
int i;
table[0] = 1.0f;
for (i = 1; i < tablelen; i++) {
const double kaiser = bessel(beta * SDL_sqrt(1.0 - SDL_pow(((i - lenm1) / 2.0) / lenm1div2, 2.0))) / bessel(beta);
table[tablelen - i] = (float) kaiser;
}
for (i = 1; i < tablelen; i++) {
const float x = (((float) i) / ((float) RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) * ((float) M_PI);
table[i] *= SDL_sinf(x) / x;
diffs[i - 1] = table[i] - table[i - 1];
}
diffs[lenm1] = 0.0f;
}
static SDL_SpinLock ResampleFilterSpinlock = 0;
static float *ResamplerFilter = NULL;
static float *ResamplerFilterDifference = NULL;
int
SDL_PrepareResampleFilter(void)
{
SDL_AtomicLock(&ResampleFilterSpinlock);
if (!ResamplerFilter) {
/* if dB > 50, beta=(0.1102 * (dB - 8.7)), according to Matlab. */
const double dB = 80.0;
const double beta = 0.1102 * (dB - 8.7);
const size_t alloclen = RESAMPLER_FILTER_SIZE * sizeof (float);
ResamplerFilter = (float *) SDL_malloc(alloclen);
if (!ResamplerFilter) {
SDL_AtomicUnlock(&ResampleFilterSpinlock);
return SDL_OutOfMemory();
}
ResamplerFilterDifference = (float *) SDL_malloc(alloclen);
if (!ResamplerFilterDifference) {
SDL_free(ResamplerFilter);
ResamplerFilter = NULL;
SDL_AtomicUnlock(&ResampleFilterSpinlock);
return SDL_OutOfMemory();
}
kaiser_and_sinc(ResamplerFilter, ResamplerFilterDifference, RESAMPLER_FILTER_SIZE, beta);
}
SDL_AtomicUnlock(&ResampleFilterSpinlock);
return 0;
}
void
SDL_FreeResampleFilter(void)
{
SDL_free(ResamplerFilter);
SDL_free(ResamplerFilterDifference);
ResamplerFilter = NULL;
ResamplerFilterDifference = NULL;
}
#include "SDL_audio_resampler_filter.h"
static int
ResamplerPadding(const int inrate, const int outrate)
@ -803,7 +713,7 @@ ResamplerPadding(const int inrate, const int outrate)
return 0;
}
if (inrate > outrate) {
return (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate)));
return (int) SDL_ceilf(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate)));
}
return RESAMPLER_SAMPLES_PER_ZERO_CROSSING;
}
@ -815,33 +725,38 @@ SDL_ResampleAudio(const int chans, const int inrate, const int outrate,
const float *inbuf, const int inbuflen,
float *outbuf, const int outbuflen)
{
const double finrate = (double) inrate;
const double outtimeincr = 1.0 / ((float) outrate);
const double ratio = ((float) outrate) / ((float) inrate);
/* Note that this used to be double, but it looks like we can get by with float in most cases at
almost twice the speed on Intel processors, and orders of magnitude more
on CPUs that need a software fallback for double calculations. */
typedef float ResampleFloatType;
const ResampleFloatType finrate = (ResampleFloatType) inrate;
const ResampleFloatType outtimeincr = ((ResampleFloatType) 1.0f) / ((ResampleFloatType) outrate);
const ResampleFloatType ratio = ((float) outrate) / ((float) inrate);
const int paddinglen = ResamplerPadding(inrate, outrate);
const int framelen = chans * (int)sizeof (float);
const int inframes = inbuflen / framelen;
const int wantedoutframes = (int) ((inbuflen / framelen) * ratio); /* outbuflen isn't total to write, it's total available. */
const int maxoutframes = outbuflen / framelen;
const int outframes = SDL_min(wantedoutframes, maxoutframes);
ResampleFloatType outtime = 0.0f;
float *dst = outbuf;
double outtime = 0.0;
int i, j, chan;
for (i = 0; i < outframes; i++) {
const int srcindex = (int) (outtime * inrate);
const double intime = ((double) srcindex) / finrate;
const double innexttime = ((double) (srcindex + 1)) / finrate;
const double interpolation1 = 1.0 - ((innexttime - outtime) / (innexttime - intime));
const ResampleFloatType intime = ((ResampleFloatType) srcindex) / finrate;
const ResampleFloatType innexttime = ((ResampleFloatType) (srcindex + 1)) / finrate;
const ResampleFloatType indeltatime = innexttime - intime;
const ResampleFloatType interpolation1 = (indeltatime == 0.0f) ? 1.0f : (1.0f - ((innexttime - outtime) / indeltatime));
const int filterindex1 = (int) (interpolation1 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
const double interpolation2 = 1.0 - interpolation1;
const ResampleFloatType interpolation2 = 1.0f - interpolation1;
const int filterindex2 = (int) (interpolation2 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
for (chan = 0; chan < chans; chan++) {
float outsample = 0.0f;
/* do this twice to calculate the sample, once for the "left wing" and then same for the right. */
/* !!! FIXME: do both wings in one loop */
for (j = 0; (filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) {
const int srcframe = srcindex - j;
/* !!! FIXME: we can bubble this conditional out of here by doing a pre loop. */
@ -849,12 +764,15 @@ SDL_ResampleAudio(const int chans, const int inrate, const int outrate,
outsample += (float)(insample * (ResamplerFilter[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation1 * ResamplerFilterDifference[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
}
/* Do the right wing! */
for (j = 0; (filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) {
const int jsamples = j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING;
const int srcframe = srcindex + 1 + j;
/* !!! FIXME: we can bubble this conditional out of here by doing a post loop. */
const float insample = (srcframe >= inframes) ? rpadding[((srcframe - inframes) * chans) + chan] : inbuf[(srcframe * chans) + chan];
outsample += (float)(insample * (ResamplerFilter[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation2 * ResamplerFilterDifference[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
outsample += (float)(insample * (ResamplerFilter[filterindex2 + jsamples] + (interpolation2 * ResamplerFilterDifference[filterindex2 + jsamples])));
}
*(dst++) = outsample;
}
@ -1119,10 +1037,6 @@ SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, const int dst_channels,
return SDL_SetError("No conversion available for these rates");
}
if (SDL_PrepareResampleFilter() < 0) {
return -1;
}
/* Update (cvt) with filter details... */
if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
return -1;
@ -1743,13 +1657,6 @@ SDL_NewAudioStream(const SDL_AudioFormat src_format,
return NULL;
}
if (SDL_PrepareResampleFilter() < 0) {
SDL_free(retval->resampler_state);
retval->resampler_state = NULL;
SDL_FreeAudioStream(retval);
return NULL;
}
retval->resampler_func = SDL_ResampleAudioStream;
retval->reset_resampler_func = SDL_ResetAudioStreamResampler;
retval->cleanup_resampler_func = SDL_CleanupAudioStreamResampler;

View file

@ -522,8 +522,12 @@ static void
outputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
{
SDL_AudioDevice *this = (SDL_AudioDevice *) inUserData;
SDL_LockMutex(this->mixer_lock);
if (SDL_AtomicGet(&this->hidden->shutdown)) {
return; /* don't do anything. */
SDL_UnlockMutex(this->mixer_lock);
return; /* don't do anything, since we don't even want to enqueue this buffer again. */
}
if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
@ -536,10 +540,8 @@ outputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffe
while (remaining > 0) {
if (SDL_AudioStreamAvailable(this->stream) == 0) {
/* Generate the data */
SDL_LockMutex(this->mixer_lock);
(*this->callbackspec.callback)(this->callbackspec.userdata,
this->hidden->buffer, this->hidden->bufferSize);
SDL_UnlockMutex(this->mixer_lock);
this->hidden->bufferOffset = 0;
SDL_AudioStreamPut(this->stream, this->hidden->buffer, this->hidden->bufferSize);
}
@ -565,10 +567,8 @@ outputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffe
UInt32 len;
if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
/* Generate the data */
SDL_LockMutex(this->mixer_lock);
(*this->callbackspec.callback)(this->callbackspec.userdata,
this->hidden->buffer, this->hidden->bufferSize);
SDL_UnlockMutex(this->mixer_lock);
this->hidden->bufferOffset = 0;
}
@ -587,6 +587,8 @@ outputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffe
AudioQueueEnqueueBuffer(this->hidden->audioQueue, inBuffer, 0, NULL);
inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity;
SDL_UnlockMutex(this->mixer_lock);
}
static void

View file

@ -28,6 +28,11 @@
#include <emscripten/emscripten.h>
/* !!! FIXME: this currently expects that the audio callback runs in the main thread,
!!! FIXME: in intervals when the application isn't running, but that may not be
!!! FIXME: true always once pthread support becomes widespread. Revisit this code
!!! FIXME: at some point and see what needs to be done for that! */
static void
FeedAudioDevice(_THIS, const void *buf, const int buflen)
{

View file

@ -49,39 +49,40 @@ FillSound(void *device, void *stream, size_t len,
SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
SDL_AudioCallback callback = audio->callbackspec.callback;
SDL_LockMutex(audio->mixer_lock);
/* Only do something if audio is enabled */
if (!SDL_AtomicGet(&audio->enabled) || SDL_AtomicGet(&audio->paused)) {
if (audio->stream) {
SDL_AudioStreamClear(audio->stream);
}
SDL_memset(stream, audio->spec.silence, len);
return;
}
} else {
SDL_assert(audio->spec.size == len);
SDL_assert(audio->spec.size == len);
if (audio->stream == NULL) { /* no conversion necessary. */
callback(audio->callbackspec.userdata, (Uint8 *) stream, len);
} else { /* streaming/converting */
const int stream_len = audio->callbackspec.size;
const int ilen = (int) len;
while (SDL_AudioStreamAvailable(audio->stream) < ilen) {
callback(audio->callbackspec.userdata, audio->work_buffer, stream_len);
if (SDL_AudioStreamPut(audio->stream, audio->work_buffer, stream_len) == -1) {
SDL_AudioStreamClear(audio->stream);
SDL_AtomicSet(&audio->enabled, 0);
break;
}
}
if (audio->stream == NULL) { /* no conversion necessary. */
SDL_LockMutex(audio->mixer_lock);
callback(audio->callbackspec.userdata, (Uint8 *) stream, len);
SDL_UnlockMutex(audio->mixer_lock);
} else { /* streaming/converting */
const int stream_len = audio->callbackspec.size;
const int ilen = (int) len;
while (SDL_AudioStreamAvailable(audio->stream) < ilen) {
callback(audio->callbackspec.userdata, audio->work_buffer, stream_len);
if (SDL_AudioStreamPut(audio->stream, audio->work_buffer, stream_len) == -1) {
SDL_AudioStreamClear(audio->stream);
SDL_AtomicSet(&audio->enabled, 0);
break;
const int got = SDL_AudioStreamGet(audio->stream, stream, ilen);
SDL_assert((got < 0) || (got == ilen));
if (got != ilen) {
SDL_memset(stream, audio->spec.silence, len);
}
}
const int got = SDL_AudioStreamGet(audio->stream, stream, ilen);
SDL_assert((got < 0) || (got == ilen));
if (got != ilen) {
SDL_memset(stream, audio->spec.silence, len);
}
}
SDL_UnlockMutex(audio->mixer_lock);
}
static void

View file

@ -49,8 +49,8 @@ static void nacl_audio_callback(void* stream, uint32_t buffer_size, PP_TimeDelta
const int len = (int) buffer_size;
SDL_AudioDevice* _this = (SDL_AudioDevice*) data;
SDL_AudioCallback callback = _this->callbackspec.callback;
SDL_LockMutex(private->mutex); /* !!! FIXME: is this mutex necessary? */
SDL_LockMutex(_this->mixer_lock);
/* Only do something if audio is enabled */
if (!SDL_AtomicGet(&_this->enabled) || SDL_AtomicGet(&_this->paused)) {
@ -58,34 +58,31 @@ static void nacl_audio_callback(void* stream, uint32_t buffer_size, PP_TimeDelta
SDL_AudioStreamClear(_this->stream);
}
SDL_memset(stream, _this->spec.silence, len);
return;
}
} else {
SDL_assert(_this->spec.size == len);
SDL_assert(_this->spec.size == len);
if (_this->stream == NULL) { /* no conversion necessary. */
callback(_this->callbackspec.userdata, stream, len);
} else { /* streaming/converting */
const int stream_len = _this->callbackspec.size;
while (SDL_AudioStreamAvailable(_this->stream) < len) {
callback(_this->callbackspec.userdata, _this->work_buffer, stream_len);
if (SDL_AudioStreamPut(_this->stream, _this->work_buffer, stream_len) == -1) {
SDL_AudioStreamClear(_this->stream);
SDL_AtomicSet(&_this->enabled, 0);
break;
}
}
if (_this->stream == NULL) { /* no conversion necessary. */
SDL_LockMutex(_this->mixer_lock);
callback(_this->callbackspec.userdata, stream, len);
SDL_UnlockMutex(_this->mixer_lock);
} else { /* streaming/converting */
const int stream_len = _this->callbackspec.size;
while (SDL_AudioStreamAvailable(_this->stream) < len) {
callback(_this->callbackspec.userdata, _this->work_buffer, stream_len);
if (SDL_AudioStreamPut(_this->stream, _this->work_buffer, stream_len) == -1) {
SDL_AudioStreamClear(_this->stream);
SDL_AtomicSet(&_this->enabled, 0);
break;
const int got = SDL_AudioStreamGet(_this->stream, stream, len);
SDL_assert((got < 0) || (got == len));
if (got != len) {
SDL_memset(stream, _this->spec.silence, len);
}
}
const int got = SDL_AudioStreamGet(_this->stream, stream, len);
SDL_assert((got < 0) || (got == len));
if (got != len) {
SDL_memset(stream, _this->spec.silence, len);
}
}
SDL_UnlockMutex(private->mutex);
SDL_UnlockMutex(_this->mixer_lock);
}
static void NACLAUDIO_CloseDevice(SDL_AudioDevice *device) {
@ -94,7 +91,6 @@ static void NACLAUDIO_CloseDevice(SDL_AudioDevice *device) {
SDL_PrivateAudioData *hidden = (SDL_PrivateAudioData *) device->hidden;
ppb_audio->StopPlayback(hidden->audio);
SDL_DestroyMutex(hidden->mutex);
core->ReleaseResource(hidden->audio);
}
@ -109,7 +105,6 @@ NACLAUDIO_OpenDevice(_THIS, const char *devname) {
return SDL_OutOfMemory();
}
private->mutex = SDL_CreateMutex();
_this->spec.freq = 44100;
_this->spec.format = AUDIO_S16LSB;
_this->spec.channels = 2;

View file

@ -34,8 +34,7 @@
#define private _this->hidden
typedef struct SDL_PrivateAudioData {
SDL_mutex* mutex;
PP_Resource audio;
PP_Resource audio;
} SDL_PrivateAudioData;
#endif /* SDL_naclaudio_h_ */

View file

@ -56,7 +56,7 @@ static void
NETBSDAUDIO_Status(_THIS)
{
#ifdef DEBUG_AUDIO
/* *INDENT-OFF* */
/* *INDENT-OFF* */ /* clang-format off */
audio_info_t info;
const struct audio_prinfo *prinfo;
@ -118,7 +118,7 @@ NETBSDAUDIO_Status(_THIS)
"",
this->spec.format,
this->spec.size);
/* *INDENT-ON* */
/* *INDENT-ON* */ /* clang-format on */
#endif /* DEBUG_AUDIO */
}

View file

@ -910,6 +910,7 @@ output_callback(void *data)
* and run the callback with the work buffer to keep the callback
* firing regularly in case the audio is being used as a timer.
*/
SDL_LockMutex(this->mixer_lock);
if (!SDL_AtomicGet(&this->paused)) {
if (SDL_AtomicGet(&this->enabled)) {
dst = spa_buf->datas[0].data;
@ -919,18 +920,13 @@ output_callback(void *data)
}
if (!this->stream) {
SDL_LockMutex(this->mixer_lock);
this->callbackspec.callback(this->callbackspec.userdata, dst, this->callbackspec.size);
SDL_UnlockMutex(this->mixer_lock);
} else {
int got;
/* Fire the callback until we have enough to fill a buffer */
while (SDL_AudioStreamAvailable(this->stream) < this->spec.size) {
SDL_LockMutex(this->mixer_lock);
this->callbackspec.callback(this->callbackspec.userdata, this->work_buffer, this->callbackspec.size);
SDL_UnlockMutex(this->mixer_lock);
SDL_AudioStreamPut(this->stream, this->work_buffer, this->callbackspec.size);
}
@ -940,6 +936,7 @@ output_callback(void *data)
} else {
SDL_memset(spa_buf->datas[0].data, this->spec.silence, this->spec.size);
}
SDL_UnlockMutex(this->mixer_lock);
spa_buf->datas[0].chunk->offset = 0;
spa_buf->datas[0].chunk->stride = this->hidden->stride;

View file

@ -107,8 +107,6 @@ static int (*PULSEAUDIO_pa_stream_connect_record) (pa_stream *, const char *,
static pa_stream_state_t (*PULSEAUDIO_pa_stream_get_state) (const pa_stream *);
static size_t (*PULSEAUDIO_pa_stream_writable_size) (const pa_stream *);
static size_t (*PULSEAUDIO_pa_stream_readable_size) (const pa_stream *);
static int (*PULSEAUDIO_pa_stream_begin_write) (pa_stream *, void **, size_t*);
static int (*PULSEAUDIO_pa_stream_cancel_write) (pa_stream *);
static int (*PULSEAUDIO_pa_stream_write) (pa_stream *, const void *, size_t,
pa_free_cb_t, int64_t, pa_seek_mode_t);
static pa_operation * (*PULSEAUDIO_pa_stream_drain) (pa_stream *,
@ -119,6 +117,7 @@ static pa_operation * (*PULSEAUDIO_pa_stream_flush) (pa_stream *,
pa_stream_success_cb_t, void *);
static int (*PULSEAUDIO_pa_stream_disconnect) (pa_stream *);
static void (*PULSEAUDIO_pa_stream_unref) (pa_stream *);
static void (*PULSEAUDIO_pa_stream_set_write_callback)(pa_stream *, pa_stream_request_cb_t, void *);
static int load_pulseaudio_syms(void);
@ -222,8 +221,6 @@ load_pulseaudio_syms(void)
SDL_PULSEAUDIO_SYM(pa_stream_writable_size);
SDL_PULSEAUDIO_SYM(pa_stream_readable_size);
SDL_PULSEAUDIO_SYM(pa_stream_write);
SDL_PULSEAUDIO_SYM(pa_stream_begin_write);
SDL_PULSEAUDIO_SYM(pa_stream_cancel_write);
SDL_PULSEAUDIO_SYM(pa_stream_drain);
SDL_PULSEAUDIO_SYM(pa_stream_disconnect);
SDL_PULSEAUDIO_SYM(pa_stream_peek);
@ -232,6 +229,7 @@ load_pulseaudio_syms(void)
SDL_PULSEAUDIO_SYM(pa_stream_unref);
SDL_PULSEAUDIO_SYM(pa_channel_map_init_auto);
SDL_PULSEAUDIO_SYM(pa_strerror);
SDL_PULSEAUDIO_SYM(pa_stream_set_write_callback);
return 0;
}
@ -359,51 +357,56 @@ ConnectToPulseServer(pa_mainloop **_mainloop, pa_context **_context)
static void
PULSEAUDIO_WaitDevice(_THIS)
{
struct SDL_PrivateAudioData *h = this->hidden;
/* this is a no-op; we wait in PULSEAUDIO_PlayDevice now. */
}
while (SDL_AtomicGet(&this->enabled)) {
static void WriteCallback(pa_stream *p, size_t nbytes, void *userdata)
{
struct SDL_PrivateAudioData *h = (struct SDL_PrivateAudioData *) userdata;
/*printf("PULSEAUDIO WRITE CALLBACK! nbytes=%u\n", (unsigned int) nbytes);*/
h->bytes_requested += nbytes;
}
static void
PULSEAUDIO_PlayDevice(_THIS)
{
struct SDL_PrivateAudioData *h = this->hidden;
int available = h->mixlen;
int written = 0;
int cpy;
/*printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available);*/
while (SDL_AtomicGet(&this->enabled) && (available > 0)) {
cpy = SDL_min(h->bytes_requested, available);
if (cpy) {
if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf + written, cpy, NULL, 0LL, PA_SEEK_RELATIVE) < 0) {
SDL_OpenedAudioDeviceDisconnected(this);
return;
}
/*printf("PULSEAUDIO FEED! nbytes=%u\n", (unsigned int) cpy);*/
h->bytes_requested -= cpy;
written += cpy;
available -= cpy;
}
/* let WriteCallback fire if necessary. */
/*printf("PULSEAUDIO ITERATE!\n");*/
if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
SDL_OpenedAudioDeviceDisconnected(this);
return;
}
if (PULSEAUDIO_pa_stream_writable_size(h->stream) >= (h->mixlen/8)) {
return;
}
}
}
static void
PULSEAUDIO_PlayDevice(_THIS)
{
/* Write the audio data */
struct SDL_PrivateAudioData *h = this->hidden;
if (SDL_AtomicGet(&this->enabled)) {
if (PULSEAUDIO_pa_stream_write(h->stream, h->pabuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) {
SDL_OpenedAudioDeviceDisconnected(this);
}
}
/*printf("PULSEAUDIO PLAYDEVICE END! written=%d\n", written);*/
}
static Uint8 *
PULSEAUDIO_GetDeviceBuf(_THIS)
{
struct SDL_PrivateAudioData *h = this->hidden;
size_t nbytes = h->mixlen;
int ret;
ret = PULSEAUDIO_pa_stream_begin_write(h->stream, &h->pabuf, &nbytes);
if (ret != 0) {
/* fall back it intermediate buffer */
h->pabuf = h->mixbuf;
} else if (nbytes < h->mixlen) {
PULSEAUDIO_pa_stream_cancel_write(h->stream);
h->pabuf = h->mixbuf;
}
return (Uint8 *)h->pabuf;
return this->hidden->mixbuf;
}
@ -604,9 +607,6 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname)
paspec.format = format;
/* Calculate the final parameters for this audio specification */
#ifdef PA_STREAM_ADJUST_LATENCY
this->spec.samples /= 2; /* Mix in smaller chunck to avoid underruns */
#endif
SDL_CalculateAudioSpec(&this->spec);
/* Allocate mixing buffer */
@ -623,22 +623,12 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname)
paspec.rate = this->spec.freq;
/* Reduced prebuffering compared to the defaults. */
#ifdef PA_STREAM_ADJUST_LATENCY
paattr.fragsize = this->spec.size;
/* 2x original requested bufsize */
paattr.tlength = h->mixlen * 4;
paattr.tlength = h->mixlen;
paattr.prebuf = -1;
paattr.maxlength = -1;
/* -1 can lead to pa_stream_writable_size() >= mixlen never being true */
paattr.minreq = h->mixlen;
flags = PA_STREAM_ADJUST_LATENCY;
#else
paattr.fragsize = this->spec.size;
paattr.tlength = h->mixlen*2;
paattr.prebuf = h->mixlen*2;
paattr.maxlength = h->mixlen*2;
paattr.minreq = h->mixlen;
#endif
paattr.minreq = -1;
flags |= PA_STREAM_ADJUST_LATENCY;
if (ConnectToPulseServer(&h->mainloop, &h->context) < 0) {
return SDL_SetError("Could not connect to PulseAudio server");
@ -675,6 +665,7 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname)
if (iscapture) {
rc = PULSEAUDIO_pa_stream_connect_record(h->stream, h->device_name, &paattr, flags);
} else {
PULSEAUDIO_pa_stream_set_write_callback(h->stream, WriteCallback, h);
rc = PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags, NULL, NULL);
}

View file

@ -43,11 +43,7 @@ struct SDL_PrivateAudioData
Uint8 *mixbuf;
int mixlen;
/* Pointer to the actual buffer in use in the current
GetDeviceBuf() -> PlayDevice() iteration.
Can be either the pointer returned by pa_stream_begin_write()
or mixbuf */
void *pabuf;
int bytes_requested; /* bytes of data the hardware wants _now_. */
const Uint8 *capturebuf;
int capturelen;

View file

@ -362,7 +362,7 @@ typedef struct
WAVEFORMATEXTENSIBLE fmt;
} EndpointItem;
static int sort_endpoints(const void *_a, const void *_b)
static int SDLCALL sort_endpoints(const void *_a, const void *_b)
{
LPWSTR a = ((const EndpointItem *) _a)->devid;
LPWSTR b = ((const EndpointItem *) _b)->devid;