early-access version 2847

This commit is contained in:
pineappleEA
2022-07-19 05:48:31 +02:00
parent ba74a2373c
commit 05e3c38e7f
498 changed files with 16027 additions and 27028 deletions

View File

@@ -245,6 +245,11 @@ SDL_AudioThreadDeinit_Default(_THIS)
{ /* no-op. */
}
static void
SDL_AudioBeginLoopIteration_Default(_THIS)
{ /* no-op. */
}
static void
SDL_AudioWaitDevice_Default(_THIS)
{ /* no-op. */
@@ -272,6 +277,11 @@ SDL_AudioFlushCapture_Default(_THIS)
{ /* no-op. */
}
static void
SDL_AudioPrepareToClose_Default(_THIS)
{ /* no-op. */
}
static void
SDL_AudioCloseDevice_Default(_THIS)
{ /* no-op. */
@@ -289,7 +299,7 @@ SDL_AudioFreeDeviceHandle_Default(void *handle)
static int
SDL_AudioOpenDevice_Default(_THIS, const char *devname)
SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
{
return SDL_Unsupported();
}
@@ -324,6 +334,11 @@ SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
}
}
static void
SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice * device)
{
}
static void
finish_audio_entry_points_init(void)
{
@@ -332,6 +347,14 @@ finish_audio_entry_points_init(void)
* blindly call them without having to check for validity first.
*/
if (current_audio.impl.SkipMixerLock) {
if (current_audio.impl.LockDevice == NULL) {
current_audio.impl.LockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
}
if (current_audio.impl.UnlockDevice == NULL) {
current_audio.impl.UnlockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
}
}
#define FILL_STUB(x) \
if (current_audio.impl.x == NULL) { \
@@ -341,11 +364,13 @@ finish_audio_entry_points_init(void)
FILL_STUB(OpenDevice);
FILL_STUB(ThreadInit);
FILL_STUB(ThreadDeinit);
FILL_STUB(BeginLoopIteration);
FILL_STUB(WaitDevice);
FILL_STUB(PlayDevice);
FILL_STUB(GetDeviceBuf);
FILL_STUB(CaptureFromDevice);
FILL_STUB(FlushCapture);
FILL_STUB(PrepareToClose);
FILL_STUB(CloseDevice);
FILL_STUB(LockDevice);
FILL_STUB(UnlockDevice);
@@ -404,7 +429,8 @@ add_audio_device(const char *name, SDL_AudioSpec *spec, void *handle, SDL_AudioD
SDL_UnlockMutex(current_audio.detectionLock);
SDL_free(item->original_name);
SDL_free(item);
return SDL_OutOfMemory();
SDL_OutOfMemory();
return -1;
}
SDL_snprintf(replacement, len, "%s (%d)", name, dupenum + 1);
@@ -457,7 +483,7 @@ free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
/* The audio backends call this when a new device is plugged in. */
void
SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, SDL_AudioSpec *spec, void *handle)
SDL_AddAudioDevice(const int iscapture, const char *name, SDL_AudioSpec *spec, void *handle)
{
const int device_index = iscapture ? add_capture_device(name, spec, handle) : add_output_device(name, spec, handle);
if (device_index != -1) {
@@ -519,7 +545,7 @@ mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *remove
/* The audio backends call this when a device is removed from the system. */
void
SDL_RemoveAudioDevice(const SDL_bool iscapture, void *handle)
SDL_RemoveAudioDevice(const int iscapture, void *handle)
{
int device_index;
SDL_AudioDevice *device = NULL;
@@ -697,6 +723,7 @@ SDL_RunAudio(void *devicep)
/* Loop, filling the audio buffers */
while (!SDL_AtomicGet(&device->shutdown)) {
current_audio.impl.BeginLoopIteration(device);
data_len = device->callbackspec.size;
/* Fill the current buffer with sound */
@@ -759,6 +786,8 @@ SDL_RunAudio(void *devicep)
}
}
current_audio.impl.PrepareToClose(device);
/* Wait for the audio to drain. */
SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2);
@@ -802,6 +831,8 @@ SDL_CaptureAudio(void *devicep)
int still_need;
Uint8 *ptr;
current_audio.impl.BeginLoopIteration(device);
if (SDL_AtomicGet(&device->paused)) {
SDL_Delay(delay); /* just so we don't cook the CPU. */
if (device->stream) {
@@ -925,18 +956,20 @@ SDL_GetAudioDriver(int index)
int
SDL_AudioInit(const char *driver_name)
{
int i;
SDL_bool initialized = SDL_FALSE, tried_to_init = SDL_FALSE;
int i = 0;
int initialized = 0;
int tried_to_init = 0;
if (SDL_GetCurrentAudioDriver()) {
SDL_AudioQuit(); /* shutdown driver if already running. */
}
SDL_zero(current_audio);
SDL_zeroa(open_devices);
/* Select the proper audio driver */
if (driver_name == NULL) {
driver_name = SDL_GetHint(SDL_HINT_AUDIODRIVER);
driver_name = SDL_getenv("SDL_AUDIODRIVER");
}
if (driver_name != NULL && *driver_name != 0) {
@@ -957,7 +990,7 @@ SDL_AudioInit(const char *driver_name)
for (i = 0; bootstrap[i]; ++i) {
if ((driver_attempt_len == SDL_strlen(bootstrap[i]->name)) &&
(SDL_strncasecmp(bootstrap[i]->name, driver_attempt, driver_attempt_len) == 0)) {
tried_to_init = SDL_TRUE;
tried_to_init = 1;
SDL_zero(current_audio);
current_audio.name = bootstrap[i]->name;
current_audio.desc = bootstrap[i]->desc;
@@ -974,7 +1007,7 @@ SDL_AudioInit(const char *driver_name)
continue;
}
tried_to_init = SDL_TRUE;
tried_to_init = 1;
SDL_zero(current_audio);
current_audio.name = bootstrap[i]->name;
current_audio.desc = bootstrap[i]->desc;
@@ -1081,29 +1114,38 @@ SDL_GetNumAudioDevices(int iscapture)
const char *
SDL_GetAudioDeviceName(int index, int iscapture)
{
SDL_AudioDeviceItem *item;
int i;
const char *retval;
const char *retval = NULL;
if (!SDL_GetCurrentAudioDriver()) {
SDL_SetError("Audio subsystem is not initialized");
return NULL;
}
SDL_LockMutex(current_audio.detectionLock);
item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
if (index >= 0 && index < i) {
for (i--; i > index; i--, item = item->next) {
SDL_assert(item != NULL);
}
SDL_assert(item != NULL);
retval = item->name;
} else {
SDL_InvalidParamError("index");
retval = NULL;
if (iscapture && !current_audio.impl.HasCaptureSupport) {
SDL_SetError("No capture support");
return NULL;
}
if (index >= 0) {
SDL_AudioDeviceItem *item;
int i;
SDL_LockMutex(current_audio.detectionLock);
item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
if (index < i) {
for (i--; i > index; i--, item = item->next) {
SDL_assert(item != NULL);
}
SDL_assert(item != NULL);
retval = item->name;
}
SDL_UnlockMutex(current_audio.detectionLock);
}
if (retval == NULL) {
SDL_SetError("No such device");
}
SDL_UnlockMutex(current_audio.detectionLock);
return retval;
}
@@ -1112,33 +1154,38 @@ SDL_GetAudioDeviceName(int index, int iscapture)
int
SDL_GetAudioDeviceSpec(int index, int iscapture, SDL_AudioSpec *spec)
{
SDL_AudioDeviceItem *item;
int i, retval;
if (spec == NULL) {
return SDL_InvalidParamError("spec");
}
SDL_zerop(spec);
if (!SDL_GetCurrentAudioDriver()) {
return SDL_SetError("Audio subsystem is not initialized");
}
SDL_LockMutex(current_audio.detectionLock);
item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
if (index >= 0 && index < i) {
for (i--; i > index; i--, item = item->next) {
SDL_assert(item != NULL);
}
SDL_assert(item != NULL);
SDL_memcpy(spec, &item->spec, sizeof(SDL_AudioSpec));
retval = 0;
} else {
retval = SDL_InvalidParamError("index");
if (iscapture && !current_audio.impl.HasCaptureSupport) {
return SDL_SetError("No capture support");
}
SDL_UnlockMutex(current_audio.detectionLock);
return retval;
if (index >= 0) {
SDL_AudioDeviceItem *item;
int i;
SDL_LockMutex(current_audio.detectionLock);
item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
if (index < i) {
for (i--; i > index; i--, item = item->next) {
SDL_assert(item != NULL);
}
SDL_assert(item != NULL);
SDL_memcpy(spec, &item->spec, sizeof(SDL_AudioSpec));
}
SDL_UnlockMutex(current_audio.detectionLock);
}
return 0;
}
@@ -1374,7 +1421,7 @@ open_audio_device(const char *devname, int iscapture,
SDL_AtomicSet(&device->enabled, 1);
/* Create a mutex for locking the sound buffers */
if (current_audio.impl.LockDevice == SDL_AudioLockDevice_Default) {
if (!current_audio.impl.SkipMixerLock) {
device->mixer_lock = SDL_CreateMutex();
if (device->mixer_lock == NULL) {
close_audio_device(device);
@@ -1383,7 +1430,7 @@ open_audio_device(const char *devname, int iscapture,
}
}
if (current_audio.impl.OpenDevice(device, devname) < 0) {
if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
close_audio_device(device);
return 0;
}
@@ -1508,7 +1555,8 @@ SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
/* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
if (open_devices[0] != NULL) {
return SDL_SetError("Audio device is already opened");
SDL_SetError("Audio device is already opened");
return -1;
}
if (obtained) {
@@ -1649,6 +1697,8 @@ SDL_AudioQuit(void)
#ifdef HAVE_LIBSAMPLERATE_H
UnloadLibSampleRate();
#endif
SDL_FreeResampleFilter();
}
#define NUM_FORMATS 10

View File

@@ -70,6 +70,11 @@ 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: */

View File

@@ -80,7 +80,7 @@ SDL_ConvertStereoToMono_SSE3(SDL_AudioCVT * cvt, SDL_AudioFormat format)
Just use unaligned load/stores, if the memory at runtime is
aligned it'll be just as fast on modern processors */
while (i >= 4) { /* 4 * float32 */
_mm_storeu_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_loadu_ps(src), _mm_loadu_ps(src+4)), divby2));
_mm_storeu_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_load_ps(src), _mm_loadu_ps(src+4)), divby2));
i -= 4; src += 8; dst += 4;
}
@@ -369,11 +369,11 @@ SDL_Convert71To51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
const float surround_left_distributed = src[6] * 0.5f;
const float surround_right_distributed = src[7] * 0.5f;
dst[0] = (src[0] + surround_left_distributed) * two_thirds; /* FL */
dst[1] = (src[1] + surround_right_distributed) * two_thirds; /* FR */
dst[1] = (src[1] + surround_right_distributed) * two_thirds; /* FR */
dst[2] = src[2] * two_thirds; /* CC */
dst[3] = src[3] * two_thirds; /* LFE */
dst[4] = (src[4] + surround_left_distributed) * two_thirds; /* BL */
dst[5] = (src[5] + surround_right_distributed) * two_thirds; /* BR */
dst[5] = (src[5] + surround_right_distributed) * two_thirds; /* BR */
}
cvt->len_cvt /= 8;
@@ -398,12 +398,12 @@ SDL_Convert71To61(SDL_AudioCVT * cvt, SDL_AudioFormat format)
for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8, dst += 7) {
dst[0] = src[3]; /* LFE */
dst[1] = src[2]; /* FC */
dst[1] = src[2]; /* FC */
dst[2] = src[1]; /* FR */
dst[3] = src[7]; /* SR */
dst[4] = (src[4] + src[5]) / 0.2f; /* BackSurround */
dst[5] = src[6]; /* SL */
dst[6] = src[0]; /* FL */
dst[6] = src[0]; /* FL */
}
cvt->len_cvt /= 8;
@@ -428,13 +428,13 @@ SDL_Convert61To71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7, dst += 8) {
dst[0] = src[6]; /* FL */
dst[1] = src[2]; /* FR */
dst[1] = src[2]; /* FR */
dst[2] = src[1]; /* FC */
dst[3] = src[0]; /* LFE */
dst[4] = src[4]; /* BL */
dst[5] = src[4]; /* BR */
dst[6] = src[5]; /* SL */
dst[7] = src[3]; /* SR */
dst[6] = src[5]; /* SL */
dst[7] = src[3]; /* SR */
}
cvt->len_cvt /= 7;
@@ -459,12 +459,12 @@ SDL_Convert51To61(SDL_AudioCVT * cvt, SDL_AudioFormat format)
for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 7) {
dst[0] = src[3]; /* LFE */
dst[1] = src[2]; /* FC */
dst[1] = src[2]; /* FC */
dst[2] = src[1]; /* FR */
dst[3] = src[5]; /* SR */
dst[4] = (src[4] + src[5]) / 0.2f; /* BackSurround */
dst[5] = src[4]; /* SL */
dst[6] = src[0]; /* FL */
dst[6] = src[0]; /* FL */
}
cvt->len_cvt /= 6;
@@ -489,7 +489,7 @@ SDL_Convert61To51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7, dst += 6) {
dst[0] = src[6]; /* FL */
dst[1] = src[2]; /* FR */
dst[1] = src[2]; /* FR */
dst[2] = src[1]; /* FC */
dst[3] = src[0]; /* LFE */
dst[4] = src[5]; /* BL */
@@ -614,7 +614,7 @@ SDL_ConvertQuadTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
ce = (lf + rf) * 0.5f;
/* Constant 0.571f is approx 4/7 not to saturate */
dst[0] = 0.571f * (lf + (lf - 0.5f * ce)); /* FL */
dst[1] = 0.571f * (rf + (rf - 0.5f * ce)); /* FR */
dst[1] = 0.571f * (rf + (rf - 0.5f * ce)); /* FR */
dst[2] = ce; /* FC */
dst[3] = 0; /* LFE (only meant for special LFE effects) */
dst[4] = lb; /* BL */
@@ -704,16 +704,105 @@ SDL_Convert51To71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
/* SDL's resampler uses a "bandlimited interpolation" algorithm:
https://ccrma.stanford.edu/~jos/resample/ */
#include "SDL_audio_resampler_filter.h"
#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;
}
static int
ResamplerPadding(const int inrate, const int outrate)
{
if (inrate == outrate) {
return 0;
}
if (inrate > outrate) {
return (int) SDL_ceilf(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate)));
} else if (inrate > outrate) {
return (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate)));
}
return RESAMPLER_SAMPLES_PER_ZERO_CROSSING;
}
@@ -725,38 +814,33 @@ SDL_ResampleAudio(const int chans, const int inrate, const int outrate,
const float *inbuf, const int inbuflen,
float *outbuf, const int outbuflen)
{
/* 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 double finrate = (double) inrate;
const double outtimeincr = 1.0 / ((float) outrate);
const double 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 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 double intime = ((double) srcindex) / finrate;
const double innexttime = ((double) (srcindex + 1)) / finrate;
const double interpolation1 = 1.0 - ((innexttime - outtime) / (innexttime - intime));
const int filterindex1 = (int) (interpolation1 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
const ResampleFloatType interpolation2 = 1.0f - interpolation1;
const double interpolation2 = 1.0 - 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. */
@@ -764,15 +848,12 @@ 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 + jsamples] + (interpolation2 * ResamplerFilterDifference[filterindex2 + jsamples])));
outsample += (float)(insample * (ResamplerFilter[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation2 * ResamplerFilterDifference[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
}
*(dst++) = outsample;
}
@@ -849,7 +930,9 @@ SDL_AddAudioCVTFilter(SDL_AudioCVT *cvt, const SDL_AudioFilter filter)
if (cvt->filter_index >= SDL_AUDIOCVT_MAX_FILTERS) {
return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS);
}
SDL_assert(filter != NULL);
if (filter == NULL) {
return SDL_SetError("Audio filter pointer is NULL");
}
cvt->filters[cvt->filter_index++] = filter;
cvt->filters[cvt->filter_index] = NULL; /* Moving terminator */
return 0;
@@ -860,7 +943,7 @@ SDL_BuildAudioTypeCVTToFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat src_fmt)
{
int retval = 0; /* 0 == no conversion necessary. */
if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN) && SDL_AUDIO_BITSIZE(src_fmt) > 8) {
if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) {
return -1;
}
@@ -937,7 +1020,7 @@ SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt)
retval = 1; /* added a converter. */
}
if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN) && SDL_AUDIO_BITSIZE(dst_fmt) > 8) {
if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) {
return -1;
}
@@ -1037,6 +1120,10 @@ 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;
@@ -1130,26 +1217,19 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
if (!SDL_SupportedAudioFormat(src_fmt)) {
return SDL_SetError("Invalid source format");
}
if (!SDL_SupportedAudioFormat(dst_fmt)) {
} else if (!SDL_SupportedAudioFormat(dst_fmt)) {
return SDL_SetError("Invalid destination format");
}
if (!SDL_SupportedChannelCount(src_channels)) {
} else if (!SDL_SupportedChannelCount(src_channels)) {
return SDL_SetError("Invalid source channels");
}
if (!SDL_SupportedChannelCount(dst_channels)) {
} else if (!SDL_SupportedChannelCount(dst_channels)) {
return SDL_SetError("Invalid destination channels");
}
if (src_rate <= 0) {
} else if (src_rate <= 0) {
return SDL_SetError("Source rate is equal to or less than zero");
}
if (dst_rate <= 0) {
} else if (dst_rate <= 0) {
return SDL_SetError("Destination rate is equal to or less than zero");
}
if (src_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
} else if (src_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
return SDL_SetError("Source rate is too high");
}
if (dst_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
} else if (dst_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
return SDL_SetError("Destination rate is too high");
}
@@ -1193,9 +1273,6 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
/* just a byteswap needed? */
if ((src_fmt & ~SDL_AUDIO_MASK_ENDIAN) == (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN)) {
if (SDL_AUDIO_BITSIZE(dst_fmt) == 8) {
return 0;
}
if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) {
return -1;
}
@@ -1589,7 +1666,6 @@ SDL_NewAudioStream(const SDL_AudioFormat src_format,
retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream));
if (!retval) {
SDL_OutOfMemory();
return NULL;
}
@@ -1657,6 +1733,13 @@ 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;
@@ -1824,14 +1907,11 @@ SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len)
if (!stream) {
return SDL_InvalidParamError("stream");
}
if (!buf) {
} else if (!buf) {
return SDL_InvalidParamError("buf");
}
if (len == 0) {
} else if (len == 0) {
return 0; /* nothing to do. */
}
if ((len % stream->src_sample_frame_size) != 0) {
} else if ((len % stream->src_sample_frame_size) != 0) {
return SDL_SetError("Can't add partial sample frames");
}
@@ -1937,14 +2017,11 @@ SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len)
if (!stream) {
return SDL_InvalidParamError("stream");
}
if (!buf) {
} else if (!buf) {
return SDL_InvalidParamError("buf");
}
if (len <= 0) {
} else if (len <= 0) {
return 0; /* nothing to do. */
}
if ((len % stream->dst_sample_frame_size) != 0) {
} else if ((len % stream->dst_sample_frame_size) != 0) {
return SDL_SetError("Can't request partial sample frames");
}
@@ -1990,3 +2067,4 @@ SDL_FreeAudioStream(SDL_AudioStream *stream)
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -29,6 +29,7 @@
/* This table is used to add two sound values together and pin
* the value to avoid overflow. (used with permission from ARDI)
* Changed to use 0xFE instead of 0xFF for better sound quality.
*/
static const Uint8 mix8[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -65,25 +66,24 @@ static const Uint8 mix8[] = {
0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE
};
/* The volume ranges from 0 - 128 */
#define ADJUST_VOLUME(s, v) (s = (s*v)/SDL_MIX_MAXVOLUME)
#define ADJUST_VOLUME_U8(s, v) (s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128)
#define ADJUST_VOLUME_U16(s, v) (s = (((s-32768)*v)/SDL_MIX_MAXVOLUME)+32768)
void
@@ -115,8 +115,8 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
Sint8 *dst8, *src8;
Sint8 src_sample;
int dst_sample;
const int max_audioval = SDL_MAX_SINT8;
const int min_audioval = SDL_MIN_SINT8;
const int max_audioval = ((1 << (8 - 1)) - 1);
const int min_audioval = -(1 << (8 - 1));
src8 = (Sint8 *) src;
dst8 = (Sint8 *) dst;
@@ -125,11 +125,12 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
ADJUST_VOLUME(src_sample, volume);
dst_sample = *dst8 + src_sample;
if (dst_sample > max_audioval) {
dst_sample = max_audioval;
*dst8 = max_audioval;
} else if (dst_sample < min_audioval) {
dst_sample = min_audioval;
*dst8 = min_audioval;
} else {
*dst8 = dst_sample;
}
*dst8 = dst_sample;
++dst8;
++src8;
}
@@ -140,14 +141,14 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
{
Sint16 src1, src2;
int dst_sample;
const int max_audioval = SDL_MAX_SINT16;
const int min_audioval = SDL_MIN_SINT16;
const int max_audioval = ((1 << (16 - 1)) - 1);
const int min_audioval = -(1 << (16 - 1));
len /= 2;
while (len--) {
src1 = SDL_SwapLE16(*(Sint16 *)src);
src1 = ((src[1]) << 8 | src[0]);
ADJUST_VOLUME(src1, volume);
src2 = SDL_SwapLE16(*(Sint16 *)dst);
src2 = ((dst[1]) << 8 | dst[0]);
src += 2;
dst_sample = src1 + src2;
if (dst_sample > max_audioval) {
@@ -155,7 +156,9 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
} else if (dst_sample < min_audioval) {
dst_sample = min_audioval;
}
*(Sint16 *)dst = SDL_SwapLE16(dst_sample);
dst[0] = dst_sample & 0xFF;
dst_sample >>= 8;
dst[1] = dst_sample & 0xFF;
dst += 2;
}
}
@@ -165,14 +168,14 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
{
Sint16 src1, src2;
int dst_sample;
const int max_audioval = SDL_MAX_SINT16;
const int min_audioval = SDL_MIN_SINT16;
const int max_audioval = ((1 << (16 - 1)) - 1);
const int min_audioval = -(1 << (16 - 1));
len /= 2;
while (len--) {
src1 = SDL_SwapBE16(*(Sint16 *)src);
src1 = ((src[0]) << 8 | src[1]);
ADJUST_VOLUME(src1, volume);
src2 = SDL_SwapBE16(*(Sint16 *)dst);
src2 = ((dst[0]) << 8 | dst[1]);
src += 2;
dst_sample = src1 + src2;
if (dst_sample > max_audioval) {
@@ -180,7 +183,9 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
} else if (dst_sample < min_audioval) {
dst_sample = min_audioval;
}
*(Sint16 *)dst = SDL_SwapBE16(dst_sample);
dst[1] = dst_sample & 0xFF;
dst_sample >>= 8;
dst[0] = dst_sample & 0xFF;
dst += 2;
}
}
@@ -190,23 +195,21 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
{
Uint16 src1, src2;
int dst_sample;
const int max_audioval = SDL_MAX_SINT16;
const int min_audioval = SDL_MIN_SINT16;
const int max_audioval = 0xFFFF;
len /= 2;
while (len--) {
src1 = SDL_SwapLE16(*(Uint16 *)src);
ADJUST_VOLUME_U16(src1, volume);
src2 = SDL_SwapLE16(*(Uint16 *)dst);
src1 = ((src[1]) << 8 | src[0]);
ADJUST_VOLUME(src1, volume);
src2 = ((dst[1]) << 8 | dst[0]);
src += 2;
dst_sample = src1 + src2 - 32768 * 2;
dst_sample = src1 + src2;
if (dst_sample > max_audioval) {
dst_sample = max_audioval;
} else if (dst_sample < min_audioval) {
dst_sample = min_audioval;
}
dst_sample += 32768;
*(Uint16 *)dst = SDL_SwapLE16(dst_sample);
dst[0] = dst_sample & 0xFF;
dst_sample >>= 8;
dst[1] = dst_sample & 0xFF;
dst += 2;
}
}
@@ -216,23 +219,21 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
{
Uint16 src1, src2;
int dst_sample;
const int max_audioval = SDL_MAX_SINT16;
const int min_audioval = SDL_MIN_SINT16;
const int max_audioval = 0xFFFF;
len /= 2;
while (len--) {
src1 = SDL_SwapBE16(*(Uint16 *)src);
ADJUST_VOLUME_U16(src1, volume);
src2 = SDL_SwapBE16(*(Uint16 *)dst);
src1 = ((src[0]) << 8 | src[1]);
ADJUST_VOLUME(src1, volume);
src2 = ((dst[0]) << 8 | dst[1]);
src += 2;
dst_sample = src1 + src2 - 32768 * 2;
dst_sample = src1 + src2;
if (dst_sample > max_audioval) {
dst_sample = max_audioval;
} else if (dst_sample < min_audioval) {
dst_sample = min_audioval;
}
dst_sample += 32768;
*(Uint16 *)dst = SDL_SwapBE16(dst_sample);
dst[1] = dst_sample & 0xFF;
dst_sample >>= 8;
dst[0] = dst_sample & 0xFF;
dst += 2;
}
}
@@ -244,8 +245,8 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
Uint32 *dst32 = (Uint32 *) dst;
Sint64 src1, src2;
Sint64 dst_sample;
const Sint64 max_audioval = SDL_MAX_SINT32;
const Sint64 min_audioval = SDL_MIN_SINT32;
const Sint64 max_audioval = ((((Sint64) 1) << (32 - 1)) - 1);
const Sint64 min_audioval = -(((Sint64) 1) << (32 - 1));
len /= 4;
while (len--) {
@@ -270,8 +271,8 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
Uint32 *dst32 = (Uint32 *) dst;
Sint64 src1, src2;
Sint64 dst_sample;
const Sint64 max_audioval = SDL_MAX_SINT32;
const Sint64 min_audioval = SDL_MIN_SINT32;
const Sint64 max_audioval = ((((Sint64) 1) << (32 - 1)) - 1);
const Sint64 min_audioval = -(((Sint64) 1) << (32 - 1));
len /= 4;
while (len--) {

View File

@@ -39,11 +39,11 @@ typedef struct SDL_AudioDevice SDL_AudioDevice;
/* Audio targets should call this as devices are added to the system (such as
a USB headset being plugged in), and should also be called for
for every device found during DetectDevices(). */
extern void SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, SDL_AudioSpec *spec, void *handle);
extern void SDL_AddAudioDevice(const int iscapture, const char *name, SDL_AudioSpec *spec, void *handle);
/* Audio targets should call this as devices are removed, so SDL can update
its list of available devices. */
extern void SDL_RemoveAudioDevice(const SDL_bool iscapture, void *handle);
extern void SDL_RemoveAudioDevice(const int iscapture, void *handle);
/* Audio targets should call this if an opened audio device is lost while
being used. This can happen due to i/o errors, or a device being unplugged,
@@ -65,14 +65,16 @@ extern void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device);
typedef struct SDL_AudioDriverImpl
{
void (*DetectDevices) (void);
int (*OpenDevice) (_THIS, const char *devname);
int (*OpenDevice) (_THIS, void *handle, const char *devname, int iscapture);
void (*ThreadInit) (_THIS); /* Called by audio thread at start */
void (*ThreadDeinit) (_THIS); /* Called by audio thread at end */
void (*BeginLoopIteration)(_THIS); /* Called by audio thread at top of loop */
void (*WaitDevice) (_THIS);
void (*PlayDevice) (_THIS);
Uint8 *(*GetDeviceBuf) (_THIS);
int (*CaptureFromDevice) (_THIS, void *buffer, int buflen);
void (*FlushCapture) (_THIS);
void (*PrepareToClose) (_THIS); /**< Called between run and draining wait for playback devices */
void (*CloseDevice) (_THIS);
void (*LockDevice) (_THIS);
void (*UnlockDevice) (_THIS);
@@ -82,11 +84,13 @@ typedef struct SDL_AudioDriverImpl
/* !!! FIXME: add pause(), so we can optimize instead of mixing silence. */
/* Some flags to push duplicate code into the core and reduce #ifdefs. */
SDL_bool ProvidesOwnCallbackThread;
SDL_bool HasCaptureSupport;
SDL_bool OnlyHasDefaultOutputDevice;
SDL_bool OnlyHasDefaultCaptureDevice;
SDL_bool AllowsArbitraryDeviceNames;
/* !!! FIXME: these should be SDL_bool */
int ProvidesOwnCallbackThread;
int SkipMixerLock;
int HasCaptureSupport;
int OnlyHasDefaultOutputDevice;
int OnlyHasDefaultCaptureDevice;
int AllowsArbitraryDeviceNames;
} SDL_AudioDriverImpl;
@@ -174,8 +178,8 @@ typedef struct AudioBootStrap
{
const char *name;
const char *desc;
SDL_bool (*init) (SDL_AudioDriverImpl * impl);
SDL_bool demand_only; /* 1==request explicitly, or it won't be available. */
int (*init) (SDL_AudioDriverImpl * impl);
int demand_only; /* 1==request explicitly, or it won't be available. */
} AudioBootStrap;
/* Not all of these are available in a given build. Use #ifdefs, etc. */

View File

@@ -685,7 +685,7 @@ MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
state.output.pos = 0;
state.output.size = outputsize / sizeof(Sint16);
state.output.data = (Sint16 *)SDL_calloc(1, outputsize);
state.output.data = (Sint16 *)SDL_malloc(outputsize);
if (state.output.data == NULL) {
return SDL_OutOfMemory();
}

View File

@@ -71,10 +71,9 @@ void aaudio_errorCallback( AAudioStream *stream, void *userData, aaudio_result_t
#define LIB_AAUDIO_SO "libaaudio.so"
static int
aaudio_OpenDevice(_THIS, const char *devname)
aaudio_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
struct SDL_PrivateAudioData *private;
SDL_bool iscapture = this->iscapture;
aaudio_result_t res;
LOGI(__func__);
@@ -269,7 +268,7 @@ aaudio_Deinitialize(void)
LOGI("End AAUDIO %s", SDL_GetError());
}
static SDL_bool
static int
aaudio_Init(SDL_AudioDriverImpl *impl)
{
aaudio_result_t res;
@@ -281,7 +280,7 @@ aaudio_Init(SDL_AudioDriverImpl *impl)
* See https://github.com/google/oboe/issues/40 for more information.
*/
if (SDL_GetAndroidSDKVersion() < 27) {
return SDL_FALSE;
return 0;
}
SDL_zero(ctx);
@@ -316,12 +315,12 @@ aaudio_Init(SDL_AudioDriverImpl *impl)
/* and the capabilities */
impl->HasCaptureSupport = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
impl->OnlyHasDefaultCaptureDevice = 1;
/* this audio target is available. */
LOGI("SDL aaudio_Init OK");
return SDL_TRUE;
return 1;
failure:
if (ctx.handle) {
@@ -332,11 +331,11 @@ failure:
}
ctx.handle = NULL;
ctx.builder = NULL;
return SDL_FALSE;
return 0;
}
AudioBootStrap aaudio_bootstrap = {
"AAudio", "AAudio audio driver", aaudio_Init, SDL_FALSE
"AAudio", "AAudio audio driver", aaudio_Init, 0
};
/* Pause (block) all non already paused audio devices by taking their mixer lock */

View File

@@ -543,10 +543,9 @@ ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params)
}
static int
ALSA_OpenDevice(_THIS, const char *devname)
ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int status = 0;
SDL_bool iscapture = this->iscapture;
snd_pcm_t *pcm_handle = NULL;
snd_pcm_hw_params_t *hwparams = NULL;
snd_pcm_sw_params_t *swparams = NULL;
@@ -570,7 +569,7 @@ ALSA_OpenDevice(_THIS, const char *devname)
/* Open the audio device */
/* Name of device should depend on # channels in spec */
status = ALSA_snd_pcm_open(&pcm_handle,
get_audio_device(this->handle, this->spec.channels),
get_audio_device(handle, this->spec.channels),
iscapture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
SND_PCM_NONBLOCK);
@@ -598,7 +597,10 @@ ALSA_OpenDevice(_THIS, const char *devname)
}
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
status = -1;
for (test_format = SDL_FirstAudioFormat(this->spec.format);
test_format && (status < 0);) {
status = 0; /* if we can't support a format, it'll become -1. */
switch (test_format) {
case AUDIO_U8:
format = SND_PCM_FORMAT_U8;
@@ -631,14 +633,19 @@ ALSA_OpenDevice(_THIS, const char *devname)
format = SND_PCM_FORMAT_FLOAT_BE;
break;
default:
continue;
}
if (ALSA_snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) >= 0) {
status = -1;
break;
}
if (status >= 0) {
status = ALSA_snd_pcm_hw_params_set_format(pcm_handle,
hwparams, format);
}
if (status < 0) {
test_format = SDL_NextAudioFormat();
}
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "alsa");
if (status < 0) {
return SDL_SetError("ALSA: Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
@@ -990,11 +997,11 @@ ALSA_Deinitialize(void)
UnloadALSALibrary();
}
static SDL_bool
static int
ALSA_Init(SDL_AudioDriverImpl * impl)
{
if (LoadALSALibrary() < 0) {
return SDL_FALSE;
return 0;
}
/* Set the function pointers */
@@ -1010,12 +1017,12 @@ ALSA_Init(SDL_AudioDriverImpl * impl)
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap ALSA_bootstrap = {
"alsa", "ALSA PCM audio", ALSA_Init, SDL_FALSE
"alsa", "ALSA PCM audio", ALSA_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_ALSA */

View File

@@ -36,10 +36,9 @@ static SDL_AudioDevice* audioDevice = NULL;
static SDL_AudioDevice* captureDevice = NULL;
static int
ANDROIDAUDIO_OpenDevice(_THIS, const char *devname)
ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_AudioFormat test_format;
SDL_bool iscapture = this->iscapture;
SDL_assert((captureDevice == NULL) || !iscapture);
SDL_assert((audioDevice == NULL) || iscapture);
@@ -55,18 +54,20 @@ ANDROIDAUDIO_OpenDevice(_THIS, const char *devname)
return SDL_OutOfMemory();
}
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
test_format = SDL_FirstAudioFormat(this->spec.format);
while (test_format != 0) { /* no "UNKNOWN" constant */
if ((test_format == AUDIO_U8) ||
(test_format == AUDIO_S16) ||
(test_format == AUDIO_F32)) {
this->spec.format = test_format;
break;
}
test_format = SDL_NextAudioFormat();
}
if (!test_format) {
if (test_format == 0) {
/* Didn't find a compatible format :( */
return SDL_SetError("%s: Unsupported audio format", "android");
return SDL_SetError("No compatible audio format!");
}
if (Android_JNI_OpenAudioDevice(iscapture, &this->spec) < 0) {
@@ -119,7 +120,7 @@ ANDROIDAUDIO_CloseDevice(_THIS)
SDL_free(this->hidden);
}
static SDL_bool
static int
ANDROIDAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
@@ -132,14 +133,14 @@ ANDROIDAUDIO_Init(SDL_AudioDriverImpl * impl)
/* and the capabilities */
impl->HasCaptureSupport = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
impl->OnlyHasDefaultCaptureDevice = 1;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap ANDROIDAUDIO_bootstrap = {
"android", "SDL Android audio driver", ANDROIDAUDIO_Init, SDL_FALSE
"android", "SDL Android audio driver", ANDROIDAUDIO_Init, 0
};
/* Pause (block) all non already paused audio devices by taking their mixer lock */

View File

@@ -216,11 +216,11 @@ ARTS_Suspend(void)
}
static int
ARTS_OpenDevice(_THIS, const char *devname)
ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int rc = 0;
int bits, frag_spec = 0;
SDL_AudioFormat test_format = 0;
int bits = 0, frag_spec = 0;
SDL_AudioFormat test_format = 0, format = 0;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
@@ -231,24 +231,32 @@ ARTS_OpenDevice(_THIS, const char *devname)
SDL_zerop(this->hidden);
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
for (test_format = SDL_FirstAudioFormat(this->spec.format);
!format && test_format;) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
switch (test_format) {
case AUDIO_U8:
bits = 8;
format = 1;
break;
case AUDIO_S16LSB:
bits = 16;
format = 1;
break;
default:
continue;
format = 0;
break;
}
if (!format) {
test_format = SDL_NextAudioFormat();
}
break;
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "arts");
if (format == 0) {
return SDL_SetError("Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
bits = SDL_AUDIO_BITSIZE(test_format);
if ((rc = SDL_NAME(arts_init) ()) != 0) {
return SDL_SetError("Unable to initialize ARTS: %s",
@@ -312,16 +320,16 @@ ARTS_Deinitialize(void)
}
static SDL_bool
static int
ARTS_Init(SDL_AudioDriverImpl * impl)
{
if (LoadARTSLibrary() < 0) {
return SDL_FALSE;
return 0;
} else {
if (SDL_NAME(arts_init) () != 0) {
UnloadARTSLibrary();
SDL_SetError("ARTS: arts_init failed (no audio server?)");
return SDL_FALSE;
return 0;
}
/* Play a stream so aRts doesn't crash */
@@ -342,14 +350,14 @@ ARTS_Init(SDL_AudioDriverImpl * impl)
impl->GetDeviceBuf = ARTS_GetDeviceBuf;
impl->CloseDevice = ARTS_CloseDevice;
impl->Deinitialize = ARTS_Deinitialize;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap ARTS_bootstrap = {
"arts", "Analog RealTime Synthesizer", ARTS_Init, SDL_FALSE
"arts", "Analog RealTime Synthesizer", ARTS_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_ARTS */

View File

@@ -522,12 +522,8 @@ 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)) {
SDL_UnlockMutex(this->mixer_lock);
return; /* don't do anything, since we don't even want to enqueue this buffer again. */
return; /* don't do anything. */
}
if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
@@ -540,8 +536,10 @@ 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);
}
@@ -567,8 +565,10 @@ 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,8 +587,6 @@ 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
@@ -743,10 +741,8 @@ COREAUDIO_CloseDevice(_THIS)
#if MACOSX_COREAUDIO
static int
prepare_device(_THIS)
prepare_device(_THIS, void *handle, int iscapture)
{
void *handle = this->handle;
SDL_bool iscapture = this->iscapture;
AudioDeviceID devid = (AudioDeviceID) ((size_t) handle);
OSStatus result = noErr;
UInt32 size = 0;
@@ -987,7 +983,7 @@ audioqueue_thread(void *arg)
and quits (flagging the audioqueue for shutdown), or toggles to some other system
output device (in which case we'll try again). */
const AudioDeviceID prev_devid = this->hidden->deviceID;
if (prepare_device(this) && (prev_devid != this->hidden->deviceID)) {
if (prepare_device(this, this->handle, this->iscapture) && (prev_devid != this->hidden->deviceID)) {
AudioQueueStop(this->hidden->audioQueue, 1);
if (assign_device_to_audioqueue(this)) {
int i;
@@ -1019,11 +1015,11 @@ audioqueue_thread(void *arg)
}
static int
COREAUDIO_OpenDevice(_THIS, const char *devname)
COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
AudioStreamBasicDescription *strdesc;
SDL_AudioFormat test_format;
SDL_bool iscapture = this->iscapture;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
int valid_datatype = 0;
SDL_AudioDevice **new_open_devices;
/* Initialize all variables that we clean on shutdown */
@@ -1080,7 +1076,8 @@ COREAUDIO_OpenDevice(_THIS, const char *devname)
strdesc->mSampleRate = this->spec.freq;
strdesc->mFramesPerPacket = 1;
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
while ((!valid_datatype) && (test_format)) {
this->spec.format = test_format;
/* CoreAudio handles most of SDL's formats natively, but not U16, apparently. */
switch (test_format) {
case AUDIO_U8:
@@ -1091,32 +1088,32 @@ COREAUDIO_OpenDevice(_THIS, const char *devname)
case AUDIO_S32MSB:
case AUDIO_F32LSB:
case AUDIO_F32MSB:
valid_datatype = 1;
strdesc->mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format);
if (SDL_AUDIO_ISBIGENDIAN(this->spec.format))
strdesc->mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
if (SDL_AUDIO_ISFLOAT(this->spec.format))
strdesc->mFormatFlags |= kLinearPCMFormatFlagIsFloat;
else if (SDL_AUDIO_ISSIGNED(this->spec.format))
strdesc->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
break;
default:
continue;
test_format = SDL_NextAudioFormat();
break;
}
break;
}
if (!test_format) { /* shouldn't happen, but just in case... */
return SDL_SetError("%s: Unsupported audio format", "coreaudio");
if (!valid_datatype) { /* shouldn't happen, but just in case... */
return SDL_SetError("Unsupported audio format");
}
this->spec.format = test_format;
strdesc->mBitsPerChannel = SDL_AUDIO_BITSIZE(test_format);
if (SDL_AUDIO_ISBIGENDIAN(test_format))
strdesc->mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
if (SDL_AUDIO_ISFLOAT(test_format))
strdesc->mFormatFlags |= kLinearPCMFormatFlagIsFloat;
else if (SDL_AUDIO_ISSIGNED(test_format))
strdesc->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
strdesc->mBytesPerFrame = strdesc->mChannelsPerFrame * strdesc->mBitsPerChannel / 8;
strdesc->mBytesPerPacket = strdesc->mBytesPerFrame * strdesc->mFramesPerPacket;
#if MACOSX_COREAUDIO
if (!prepare_device(this)) {
if (!prepare_device(this, handle, iscapture)) {
return -1;
}
#endif
@@ -1138,7 +1135,8 @@ COREAUDIO_OpenDevice(_THIS, const char *devname)
this->hidden->ready_semaphore = NULL;
if ((this->hidden->thread != NULL) && (this->hidden->thread_error != NULL)) {
return SDL_SetError("%s", this->hidden->thread_error);
SDL_SetError("%s", this->hidden->thread_error);
return -1;
}
return (this->hidden->thread != NULL) ? 0 : -1;
@@ -1154,7 +1152,7 @@ COREAUDIO_Deinitialize(void)
#endif
}
static SDL_bool
static int
COREAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
@@ -1166,18 +1164,18 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->DetectDevices = COREAUDIO_DetectDevices;
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
#else
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
impl->OnlyHasDefaultCaptureDevice = 1;
#endif
impl->ProvidesOwnCallbackThread = SDL_TRUE;
impl->HasCaptureSupport = SDL_TRUE;
impl->ProvidesOwnCallbackThread = 1;
impl->HasCaptureSupport = 1;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap COREAUDIO_bootstrap = {
"coreaudio", "CoreAudio", COREAUDIO_Init, SDL_FALSE
"coreaudio", "CoreAudio", COREAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_COREAUDIO */

View File

@@ -98,8 +98,10 @@ DSOUND_Load(void)
static int
SetDSerror(const char *function, int code)
{
const char *error;
static const char *error;
static char errbuf[1024];
errbuf[0] = 0;
switch (code) {
case E_NOINTERFACE:
error = "Unsupported interface -- Is DirectX 8.0 or later installed?";
@@ -135,11 +137,15 @@ SetDSerror(const char *function, int code)
error = "Function not supported";
break;
default:
error = "Unknown DirectSound error";
SDL_snprintf(errbuf, SDL_arraysize(errbuf),
"%s: Unknown DirectSound error: 0x%x", function, code);
break;
}
return SDL_SetError("%s: %s (0x%x)", function, error, code);
if (!errbuf[0]) {
SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function,
error);
}
return SDL_SetError("%s", errbuf);
}
static void
@@ -467,14 +473,14 @@ CreateCaptureBuffer(_THIS, const DWORD bufsize, WAVEFORMATEX *wfmt)
}
static int
DSOUND_OpenDevice(_THIS, const char *devname)
DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
const DWORD numchunks = 8;
HRESULT result;
SDL_bool valid_format = SDL_FALSE;
SDL_bool tried_format = SDL_FALSE;
SDL_bool iscapture = this->iscapture;
SDL_AudioFormat test_format;
LPGUID guid = (LPGUID) this->handle;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
LPGUID guid = (LPGUID) handle;
DWORD bufsize;
/* Initialize all variables that we clean on shutdown */
@@ -504,7 +510,7 @@ DSOUND_OpenDevice(_THIS, const char *devname)
}
}
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
while ((!valid_format) && (test_format)) {
switch (test_format) {
case AUDIO_U8:
case AUDIO_S16:
@@ -541,21 +547,19 @@ DSOUND_OpenDevice(_THIS, const char *devname)
rc = iscapture ? CreateCaptureBuffer(this, bufsize, &wfmt) : CreateSecondary(this, bufsize, &wfmt);
if (rc == 0) {
this->hidden->num_buffers = numchunks;
break;
valid_format = SDL_TRUE;
}
}
continue;
default:
continue;
break;
}
break;
test_format = SDL_NextAudioFormat();
}
if (!test_format) {
if (!valid_format) {
if (tried_format) {
return -1; /* CreateSecondary() should have called SDL_SetError(). */
}
return SDL_SetError("%s: Unsupported audio format", "directsound");
return SDL_SetError("DirectSound: Unsupported audio format");
}
/* Playback buffers will auto-start playing in DSOUND_WaitDevice() */
@@ -571,11 +575,11 @@ DSOUND_Deinitialize(void)
}
static SDL_bool
static int
DSOUND_Init(SDL_AudioDriverImpl * impl)
{
if (!DSOUND_Load()) {
return SDL_FALSE;
return 0;
}
/* Set the function pointers */
@@ -592,11 +596,11 @@ DSOUND_Init(SDL_AudioDriverImpl * impl)
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap DSOUND_bootstrap = {
"directsound", "DirectSound", DSOUND_Init, SDL_FALSE
"directsound", "DirectSound", DSOUND_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_DSOUND */

View File

@@ -114,7 +114,7 @@ DISKAUDIO_CloseDevice(_THIS)
static const char *
get_filename(const SDL_bool iscapture, const char *devname)
get_filename(const int iscapture, const char *devname)
{
if (devname == NULL) {
devname = SDL_getenv(iscapture ? DISKENVR_INFILE : DISKENVR_OUTFILE);
@@ -126,11 +126,9 @@ get_filename(const SDL_bool iscapture, const char *devname)
}
static int
DISKAUDIO_OpenDevice(_THIS, const char *devname)
DISKAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
void *handle = _this->handle;
/* handle != NULL means "user specified the placeholder name on the fake detected device list" */
SDL_bool iscapture = _this->iscapture;
const char *fname = get_filename(iscapture, handle ? NULL : devname);
const char *envr = SDL_getenv(DISKENVR_IODELAY);
@@ -179,7 +177,7 @@ DISKAUDIO_DetectDevices(void)
SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, NULL, (void *) 0x2);
}
static SDL_bool
static int
DISKAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
@@ -193,14 +191,14 @@ DISKAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->CloseDevice = DISKAUDIO_CloseDevice;
impl->DetectDevices = DISKAUDIO_DetectDevices;
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
impl->AllowsArbitraryDeviceNames = 1;
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap DISKAUDIO_bootstrap = {
"disk", "direct-to-disk audio", DISKAUDIO_Init, SDL_TRUE
"disk", "direct-to-disk audio", DISKAUDIO_Init, 1
};
#endif /* SDL_AUDIO_DRIVER_DISK */

View File

@@ -68,9 +68,8 @@ DSP_CloseDevice(_THIS)
static int
DSP_OpenDevice(_THIS, const char *devname)
DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_bool iscapture = this->iscapture;
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
int format;
int value;
@@ -302,14 +301,13 @@ look_for_devices_test(int fd)
return 0;
}
static SDL_bool
static int
DSP_Init(SDL_AudioDriverImpl * impl)
{
InitTimeDevicesExist = SDL_FALSE;
SDL_EnumUnixAudioDevices(0, look_for_devices_test);
if (!InitTimeDevicesExist) {
SDL_SetError("dsp: No such audio device");
return SDL_FALSE; /* maybe try a different backend. */
return 0; /* maybe try a different backend. */
}
/* Set the function pointers */
@@ -321,15 +319,15 @@ DSP_Init(SDL_AudioDriverImpl * impl)
impl->CaptureFromDevice = DSP_CaptureFromDevice;
impl->FlushCapture = DSP_FlushCapture;
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
impl->AllowsArbitraryDeviceNames = 1;
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap DSP_bootstrap = {
"dsp", "OSS /dev/dsp standard audio", DSP_Init, SDL_FALSE
"dsp", "OSS /dev/dsp standard audio", DSP_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_OSS */

View File

@@ -28,7 +28,7 @@
#include "SDL_dummyaudio.h"
static int
DUMMYAUDIO_OpenDevice(_THIS, const char *devname)
DUMMYAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
_this->hidden = (void *) 0x1; /* just something non-NULL */
return 0; /* always succeeds. */
@@ -45,22 +45,22 @@ DUMMYAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
return buflen;
}
static SDL_bool
static int
DUMMYAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
impl->OpenDevice = DUMMYAUDIO_OpenDevice;
impl->CaptureFromDevice = DUMMYAUDIO_CaptureFromDevice;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
impl->OnlyHasDefaultCaptureDevice = 1;
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap DUMMYAUDIO_bootstrap = {
"dummy", "SDL dummy audio driver", DUMMYAUDIO_Init, SDL_TRUE
"dummy", "SDL dummy audio driver", DUMMYAUDIO_Init, 1
};
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -28,16 +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)
{
const int framelen = (SDL_AUDIO_BITSIZE(this->spec.format) / 8) * this->spec.channels;
MAIN_THREAD_EM_ASM({
EM_ASM_ARGS({
var SDL2 = Module['SDL2'];
var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels'];
for (var c = 0; c < numChannels; ++c) {
@@ -106,7 +101,7 @@ HandleCaptureProcess(_THIS)
return;
}
MAIN_THREAD_EM_ASM({
EM_ASM_ARGS({
var SDL2 = Module['SDL2'];
var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels;
for (var c = 0; c < numChannels; ++c) {
@@ -152,7 +147,7 @@ HandleCaptureProcess(_THIS)
static void
EMSCRIPTENAUDIO_CloseDevice(_THIS)
{
MAIN_THREAD_EM_ASM({
EM_ASM_({
var SDL2 = Module['SDL2'];
if ($0) {
if (SDL2.capture.silenceTimer !== undefined) {
@@ -197,16 +192,16 @@ EMSCRIPTENAUDIO_CloseDevice(_THIS)
}
static int
EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
EMSCRIPTENAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_bool valid_format = SDL_FALSE;
SDL_AudioFormat test_format;
SDL_bool iscapture = this->iscapture;
int result;
/* based on parts of library_sdl.js */
/* create context */
result = MAIN_THREAD_EM_ASM_INT({
result = EM_ASM_INT({
if(typeof(Module['SDL2']) === 'undefined') {
Module['SDL2'] = {};
}
@@ -233,21 +228,22 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
return SDL_SetError("Web Audio API is not available!");
}
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
test_format = SDL_FirstAudioFormat(this->spec.format);
while ((!valid_format) && (test_format)) {
switch (test_format) {
case AUDIO_F32: /* web audio only supports floats */
this->spec.format = test_format;
valid_format = SDL_TRUE;
break;
default:
continue;
}
break;
test_format = SDL_NextAudioFormat();
}
if (!test_format) {
if (!valid_format) {
/* Didn't find a compatible format :( */
return SDL_SetError("%s: Unsupported audio format", "emscripten");
return SDL_SetError("No compatible audio format!");
}
this->spec.format = test_format;
/* Initialize all variables that we clean on shutdown */
#if 0 /* !!! FIXME: currently not used. Can we move some stuff off the SDL2 namespace? --ryan. */
@@ -285,7 +281,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
feels like it's a pretty inefficient tapdance in similar ways,
to be honest. */
MAIN_THREAD_EM_ASM({
EM_ASM_({
var SDL2 = Module['SDL2'];
var have_microphone = function(stream) {
//console.log('SDL audio capture: we have a microphone! Replacing silence callback.');
@@ -328,7 +324,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
}, this->spec.channels, this->spec.samples, HandleCaptureProcess, this);
} else {
/* setup a ScriptProcessorNode */
MAIN_THREAD_EM_ASM({
EM_ASM_ARGS({
var SDL2 = Module['SDL2'];
SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
@@ -343,47 +339,43 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
return 0;
}
static void
EMSCRIPTENAUDIO_LockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice * device)
{
}
static SDL_bool
static int
EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl * impl)
{
SDL_bool available, capture_available;
int available;
int capture_available;
/* Set the function pointers */
impl->OpenDevice = EMSCRIPTENAUDIO_OpenDevice;
impl->CloseDevice = EMSCRIPTENAUDIO_CloseDevice;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
/* no threads here */
impl->LockDevice = impl->UnlockDevice = EMSCRIPTENAUDIO_LockOrUnlockDeviceWithNoMixerLock;
impl->ProvidesOwnCallbackThread = SDL_TRUE;
impl->SkipMixerLock = 1;
impl->ProvidesOwnCallbackThread = 1;
/* check availability */
available = MAIN_THREAD_EM_ASM_INT({
available = EM_ASM_INT_V({
if (typeof(AudioContext) !== 'undefined') {
return true;
return 1;
} else if (typeof(webkitAudioContext) !== 'undefined') {
return true;
return 1;
}
return false;
return 0;
});
if (!available) {
SDL_SetError("No audio context available");
}
capture_available = available && MAIN_THREAD_EM_ASM_INT({
capture_available = available && EM_ASM_INT_V({
if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) {
return true;
return 1;
} else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') {
return true;
return 1;
}
return false;
return 0;
});
impl->HasCaptureSupport = capture_available ? SDL_TRUE : SDL_FALSE;
@@ -393,7 +385,7 @@ EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl * impl)
}
AudioBootStrap EMSCRIPTENAUDIO_bootstrap = {
"emscripten", "SDL emscripten audio driver", EMSCRIPTENAUDIO_Init, SDL_FALSE
"emscripten", "SDL emscripten audio driver", EMSCRIPTENAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_EMSCRIPTEN */

View File

@@ -208,7 +208,7 @@ get_progname(void)
static int
ESD_OpenDevice(_THIS, const char *devname)
ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
esd_format_t format = (ESD_STREAM | ESD_PLAY);
SDL_AudioFormat test_format = 0;
@@ -293,11 +293,11 @@ ESD_Deinitialize(void)
UnloadESDLibrary();
}
static SDL_bool
static int
ESD_Init(SDL_AudioDriverImpl * impl)
{
if (LoadESDLibrary() < 0) {
return SDL_FALSE;
return 0;
} else {
int connection = 0;
@@ -308,7 +308,7 @@ ESD_Init(SDL_AudioDriverImpl * impl)
if (connection < 0) {
UnloadESDLibrary();
SDL_SetError("ESD: esd_open_sound failed (no audio server?)");
return SDL_FALSE;
return 0;
}
SDL_NAME(esd_close) (connection);
}
@@ -320,14 +320,14 @@ ESD_Init(SDL_AudioDriverImpl * impl)
impl->GetDeviceBuf = ESD_GetDeviceBuf;
impl->CloseDevice = ESD_CloseDevice;
impl->Deinitialize = ESD_Deinitialize;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap ESD_bootstrap = {
"esd", "Enlightened Sound Daemon", ESD_Init, SDL_FALSE
"esd", "Enlightened Sound Daemon", ESD_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_ESD */

View File

@@ -174,10 +174,10 @@ SDL_FS_CloseDevice(_THIS)
static int
SDL_FS_OpenDevice(_THIS, const char *devname)
SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int bytes;
SDL_AudioFormat test_format;
SDL_AudioFormat test_format = 0, format = 0;
FSSampleFormat fs_format;
FSStreamDescription desc;
DirectResult ret;
@@ -191,34 +191,45 @@ SDL_FS_OpenDevice(_THIS, const char *devname)
SDL_zerop(this->hidden);
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
for (test_format = SDL_FirstAudioFormat(this->spec.format);
!format && test_format;) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
switch (test_format) {
case AUDIO_U8:
fs_format = FSSF_U8;
bytes = 1;
format = 1;
break;
case AUDIO_S16SYS:
fs_format = FSSF_S16;
bytes = 2;
format = 1;
break;
case AUDIO_S32SYS:
fs_format = FSSF_S32;
bytes = 4;
format = 1;
break;
case AUDIO_F32SYS:
fs_format = FSSF_FLOAT;
bytes = 4;
format = 1;
break;
default:
continue;
format = 0;
break;
}
if (!format) {
test_format = SDL_NextAudioFormat();
}
break;
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "fusionsound");
if (format == 0) {
return SDL_SetError("Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
bytes = SDL_AUDIO_BITSIZE(test_format) / 8;
/* Retrieve the main sound interface. */
ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
@@ -277,11 +288,11 @@ SDL_FS_Deinitialize(void)
}
static SDL_bool
static int
SDL_FS_Init(SDL_AudioDriverImpl * impl)
{
if (LoadFusionSoundLibrary() < 0) {
return SDL_FALSE;
return 0;
} else {
DirectResult ret;
@@ -291,7 +302,7 @@ SDL_FS_Init(SDL_AudioDriverImpl * impl)
SDL_SetError
("FusionSound: SDL_FS_init failed (FusionSoundInit: %d)",
ret);
return SDL_FALSE;
return 0;
}
}
@@ -302,14 +313,14 @@ SDL_FS_Init(SDL_AudioDriverImpl * impl)
impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
impl->CloseDevice = SDL_FS_CloseDevice;
impl->Deinitialize = SDL_FS_Deinitialize;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap FUSIONSOUND_bootstrap = {
"fusionsound", "FusionSound", SDL_FS_Init, SDL_FALSE
"fusionsound", "FusionSound", SDL_FS_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_FUSIONSOUND */

View File

@@ -49,40 +49,39 @@ 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);
} else {
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;
}
}
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);
}
}
return;
}
SDL_UnlockMutex(audio->mixer_lock);
SDL_assert(audio->spec.size == len);
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);
}
}
}
static void
@@ -121,10 +120,11 @@ UnmaskSignals(sigset_t * omask)
static int
HAIKUAUDIO_OpenDevice(_THIS, const char *devname)
HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int valid_datatype = 0;
media_raw_audio_format format;
SDL_AudioFormat test_format;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
/* Initialize all variables that we clean on shutdown */
_this->hidden = new SDL_PrivateAudioData;
@@ -138,7 +138,9 @@ HAIKUAUDIO_OpenDevice(_THIS, const char *devname)
format.byte_order = B_MEDIA_LITTLE_ENDIAN;
format.frame_rate = (float) _this->spec.freq;
format.channel_count = _this->spec.channels; /* !!! FIXME: support > 2? */
for (test_format = SDL_FirstAudioFormat(_this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
while ((!valid_datatype) && (test_format)) {
valid_datatype = 1;
_this->spec.format = test_format;
switch (test_format) {
case AUDIO_S8:
format.format = media_raw_audio_format::B_AUDIO_CHAR;
@@ -176,15 +178,15 @@ HAIKUAUDIO_OpenDevice(_THIS, const char *devname)
break;
default:
continue;
valid_datatype = 0;
test_format = SDL_NextAudioFormat();
break;
}
break;
}
if (!test_format) { /* shouldn't happen, but just in case... */
return SDL_SetError("%s: Unsupported audio format", "haiku");
if (!valid_datatype) { /* shouldn't happen, but just in case... */
return SDL_SetError("Unsupported audio format");
}
_this->spec.format = test_format;
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&_this->spec);
@@ -214,22 +216,22 @@ HAIKUAUDIO_Deinitialize(void)
SDL_QuitBeApp();
}
static SDL_bool
static int
HAIKUAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Initialize the Be Application, if it's not already started */
if (SDL_InitBeApp() < 0) {
return SDL_FALSE;
return 0;
}
/* Set the function pointers */
impl->OpenDevice = HAIKUAUDIO_OpenDevice;
impl->CloseDevice = HAIKUAUDIO_CloseDevice;
impl->Deinitialize = HAIKUAUDIO_Deinitialize;
impl->ProvidesOwnCallbackThread = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->ProvidesOwnCallbackThread = 1;
impl->OnlyHasDefaultOutputDevice = 1;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
extern "C"
@@ -237,7 +239,7 @@ extern "C"
extern AudioBootStrap HAIKUAUDIO_bootstrap;
}
AudioBootStrap HAIKUAUDIO_bootstrap = {
"haiku", "Haiku BSoundPlayer", HAIKUAUDIO_Init, SDL_FALSE
"haiku", "Haiku BSoundPlayer", HAIKUAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_HAIKU */

View File

@@ -280,13 +280,12 @@ JACK_CloseDevice(_THIS)
}
static int
JACK_OpenDevice(_THIS, const char *devname)
JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
/* Note that JACK uses "output" for capture devices (they output audio
data to us) and "input" for playback (we input audio data to them).
Likewise, SDL's playback port will be "output" (we write data out)
and capture will be "input" (we read data in). */
SDL_bool iscapture = this->iscapture;
const unsigned long sysportflags = iscapture ? JackPortIsOutput : JackPortIsInput;
const unsigned long sdlportflags = iscapture ? JackPortIsInput : JackPortIsOutput;
const JackProcessCallback callback = iscapture ? jackProcessCaptureCallback : jackProcessPlaybackCallback;
@@ -406,18 +405,18 @@ JACK_Deinitialize(void)
UnloadJackLibrary();
}
static SDL_bool
static int
JACK_Init(SDL_AudioDriverImpl * impl)
{
if (LoadJackLibrary() < 0) {
return SDL_FALSE;
return 0;
} else {
/* Make sure a JACK server is running and available. */
jack_status_t status;
jack_client_t *client = JACK_jack_client_open("SDL", JackNoStartServer, &status, NULL);
if (client == NULL) {
UnloadJackLibrary();
return SDL_FALSE;
return 0;
}
JACK_jack_client_close(client);
}
@@ -434,11 +433,11 @@ JACK_Init(SDL_AudioDriverImpl * impl)
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap JACK_bootstrap = {
"jack", "JACK Audio Connection Kit", JACK_Init, SDL_FALSE
"jack", "JACK Audio Connection Kit", JACK_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_JACK */

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(_this->mixer_lock);
SDL_LockMutex(private->mutex); /* !!! FIXME: is this mutex necessary? */
/* Only do something if audio is enabled */
if (!SDL_AtomicGet(&_this->enabled) || SDL_AtomicGet(&_this->paused)) {
@@ -58,31 +58,34 @@ static void nacl_audio_callback(void* stream, uint32_t buffer_size, PP_TimeDelta
SDL_AudioStreamClear(_this->stream);
}
SDL_memset(stream, _this->spec.silence, len);
} else {
SDL_assert(_this->spec.size == len);
return;
}
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;
}
}
SDL_assert(_this->spec.size == 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);
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);
}
}
SDL_UnlockMutex(_this->mixer_lock);
SDL_UnlockMutex(private->mutex);
}
static void NACLAUDIO_CloseDevice(SDL_AudioDevice *device) {
@@ -91,11 +94,12 @@ 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);
}
static int
NACLAUDIO_OpenDevice(_THIS, const char *devname) {
NACLAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
PP_Instance instance = PSGetInstanceId();
const PPB_Audio *ppb_audio = PSInterfaceAudio();
const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig();
@@ -105,6 +109,7 @@ 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;
@@ -128,18 +133,18 @@ NACLAUDIO_OpenDevice(_THIS, const char *devname) {
return 0;
}
static SDL_bool
static int
NACLAUDIO_Init(SDL_AudioDriverImpl * impl)
{
if (PSGetInstanceId() == 0) {
return SDL_FALSE;
return 0;
}
/* Set the function pointers */
impl->OpenDevice = NACLAUDIO_OpenDevice;
impl->CloseDevice = NACLAUDIO_CloseDevice;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->ProvidesOwnCallbackThread = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
impl->ProvidesOwnCallbackThread = 1;
/*
* impl->WaitDevice = NACLAUDIO_WaitDevice;
* impl->GetDeviceBuf = NACLAUDIO_GetDeviceBuf;
@@ -147,12 +152,12 @@ NACLAUDIO_Init(SDL_AudioDriverImpl * impl)
* impl->Deinitialize = NACLAUDIO_Deinitialize;
*/
return SDL_TRUE;
return 1;
}
AudioBootStrap NACLAUDIO_bootstrap = {
NACLAUDIO_DRIVER_NAME, "SDL NaCl Audio Driver",
NACLAUDIO_Init, SDL_FALSE
NACLAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_NACL */

View File

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

View File

@@ -237,6 +237,26 @@ NAS_CloseDevice(_THIS)
SDL_free(this->hidden);
}
static unsigned char
sdlformat_to_auformat(unsigned int fmt)
{
switch (fmt) {
case AUDIO_U8:
return AuFormatLinearUnsigned8;
case AUDIO_S8:
return AuFormatLinearSigned8;
case AUDIO_U16LSB:
return AuFormatLinearUnsigned16LSB;
case AUDIO_U16MSB:
return AuFormatLinearUnsigned16MSB;
case AUDIO_S16LSB:
return AuFormatLinearSigned16LSB;
case AUDIO_S16MSB:
return AuFormatLinearSigned16MSB;
}
return AuNone;
}
static AuBool
event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
{
@@ -311,12 +331,11 @@ find_device(_THIS)
}
static int
NAS_OpenDevice(_THIS, const char *devname)
NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
AuElement elms[3];
int buffer_size;
SDL_bool iscapture = this->iscapture;
SDL_AudioFormat test_format, format = 0;
SDL_AudioFormat test_format, format;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
@@ -327,33 +346,16 @@ NAS_OpenDevice(_THIS, const char *devname)
SDL_zerop(this->hidden);
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
switch (test_format) {
case AUDIO_U8:
format = AuFormatLinearUnsigned8;
break;
case AUDIO_S8:
format = AuFormatLinearSigned8;
break;
case AUDIO_U16LSB:
format = AuFormatLinearUnsigned16LSB;
break;
case AUDIO_U16MSB:
format = AuFormatLinearUnsigned16MSB;
break;
case AUDIO_S16LSB:
format = AuFormatLinearSigned16LSB;
break;
case AUDIO_S16MSB:
format = AuFormatLinearSigned16MSB;
break;
default:
continue;
format = 0;
for (test_format = SDL_FirstAudioFormat(this->spec.format);
!format && test_format;) {
format = sdlformat_to_auformat(test_format);
if (format == AuNone) {
test_format = SDL_NextAudioFormat();
}
break;
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "nas");
if (format == 0) {
return SDL_SetError("NAS: Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
@@ -421,16 +423,16 @@ NAS_Deinitialize(void)
UnloadNASLibrary();
}
static SDL_bool
static int
NAS_Init(SDL_AudioDriverImpl * impl)
{
if (LoadNASLibrary() < 0) {
return SDL_FALSE;
return 0;
} else {
AuServer *aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
if (aud == NULL) {
SDL_SetError("NAS: AuOpenServer() failed (no audio server?)");
return SDL_FALSE;
return 0;
}
NAS_AuCloseServer(aud);
}
@@ -445,15 +447,15 @@ NAS_Init(SDL_AudioDriverImpl * impl)
impl->CloseDevice = NAS_CloseDevice;
impl->Deinitialize = NAS_Deinitialize;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
impl->OnlyHasDefaultCaptureDevice = 1;
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap NAS_bootstrap = {
"nas", "Network Audio System", NAS_Init, SDL_FALSE
"nas", "Network Audio System", NAS_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_NAS */

View File

@@ -56,7 +56,7 @@ static void
NETBSDAUDIO_Status(_THIS)
{
#ifdef DEBUG_AUDIO
/* *INDENT-OFF* */ /* clang-format off */
/* *INDENT-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* */ /* clang-format on */
/* *INDENT-ON* */
#endif /* DEBUG_AUDIO */
}
@@ -202,11 +202,9 @@ NETBSDAUDIO_CloseDevice(_THIS)
}
static int
NETBSDAUDIO_OpenDevice(_THIS, const char *devname)
NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_bool iscapture = this->iscapture;
SDL_AudioFormat test_format;
int encoding = AUDIO_ENCODING_NONE;
SDL_AudioFormat format = 0;
audio_info_t info, hwinfo;
struct audio_prinfo *prinfo = iscapture ? &info.record : &info.play;
@@ -246,46 +244,54 @@ NETBSDAUDIO_OpenDevice(_THIS, const char *devname)
}
#endif
prinfo->encoding = AUDIO_ENCODING_NONE;
prinfo->sample_rate = this->spec.freq;
prinfo->channels = this->spec.channels;
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
switch (test_format) {
for (format = SDL_FirstAudioFormat(this->spec.format); format;) {
switch (format) {
case AUDIO_U8:
encoding = AUDIO_ENCODING_ULINEAR;
prinfo->encoding = AUDIO_ENCODING_ULINEAR;
prinfo->precision = 8;
break;
case AUDIO_S8:
encoding = AUDIO_ENCODING_SLINEAR;
prinfo->encoding = AUDIO_ENCODING_SLINEAR;
prinfo->precision = 8;
break;
case AUDIO_S16LSB:
encoding = AUDIO_ENCODING_SLINEAR_LE;
prinfo->encoding = AUDIO_ENCODING_SLINEAR_LE;
prinfo->precision = 16;
break;
case AUDIO_S16MSB:
encoding = AUDIO_ENCODING_SLINEAR_BE;
prinfo->encoding = AUDIO_ENCODING_SLINEAR_BE;
prinfo->precision = 16;
break;
case AUDIO_U16LSB:
encoding = AUDIO_ENCODING_ULINEAR_LE;
prinfo->encoding = AUDIO_ENCODING_ULINEAR_LE;
prinfo->precision = 16;
break;
case AUDIO_U16MSB:
encoding = AUDIO_ENCODING_ULINEAR_BE;
prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE;
prinfo->precision = 16;
break;
case AUDIO_S32LSB:
encoding = AUDIO_ENCODING_SLINEAR_LE;
prinfo->encoding = AUDIO_ENCODING_SLINEAR_LE;
prinfo->precision = 32;
break;
case AUDIO_S32MSB:
encoding = AUDIO_ENCODING_SLINEAR_BE;
prinfo->encoding = AUDIO_ENCODING_SLINEAR_BE;
prinfo->precision = 32;
break;
default:
continue;
}
break;
if (prinfo->encoding != AUDIO_ENCODING_NONE) {
break;
}
format = SDL_NextAudioFormat();
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "netbsd");
if (prinfo->encoding == AUDIO_ENCODING_NONE) {
return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
}
prinfo->encoding = encoding;
prinfo->precision = SDL_AUDIO_BITSIZE(test_format);
info.hiwat = 5;
info.lowat = 3;
@@ -298,7 +304,7 @@ NETBSDAUDIO_OpenDevice(_THIS, const char *devname)
}
/* Final spec used for the device. */
this->spec.format = test_format;
this->spec.format = format;
this->spec.freq = prinfo->sample_rate;
this->spec.channels = prinfo->channels;
@@ -320,7 +326,7 @@ NETBSDAUDIO_OpenDevice(_THIS, const char *devname)
return 0;
}
static SDL_bool
static int
NETBSDAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
@@ -333,14 +339,14 @@ NETBSDAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->FlushCapture = NETBSDAUDIO_FlushCapture;
impl->HasCaptureSupport = SDL_TRUE;
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
impl->AllowsArbitraryDeviceNames = 1;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap NETBSDAUDIO_bootstrap = {
"netbsd", "NetBSD audio", NETBSDAUDIO_Init, SDL_FALSE
"netbsd", "NetBSD audio", NETBSDAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_NETBSD */

View File

@@ -407,7 +407,6 @@ openslES_CreatePCMPlayer(_THIS)
{
struct SDL_PrivateAudioData *audiodata = this->hidden;
SLDataFormat_PCM format_pcm;
SLAndroidDataFormat_PCM_EX format_pcm_ex;
SLresult result;
int i;
@@ -415,30 +414,31 @@ openslES_CreatePCMPlayer(_THIS)
it can be done as described here:
https://developer.android.com/ndk/guides/audio/opensl/android-extensions.html#floating-point
*/
if(SDL_GetAndroidSDKVersion() >= 21) {
SDL_AudioFormat test_format;
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
if (SDL_AUDIO_ISSIGNED(test_format)) {
break;
}
#if 1
/* Just go with signed 16-bit audio as it's the most compatible */
this->spec.format = AUDIO_S16SYS;
#else
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
while (test_format != 0) {
if (SDL_AUDIO_ISSIGNED(test_format) && SDL_AUDIO_ISINT(test_format)) {
break;
}
if (!test_format) {
/* Didn't find a compatible format : */
LOGI( "No compatible audio format, using signed 16-bit audio" );
test_format = AUDIO_S16SYS;
}
this->spec.format = test_format;
} else {
/* Just go with signed 16-bit audio as it's the most compatible */
this->spec.format = AUDIO_S16SYS;
test_format = SDL_NextAudioFormat();
}
if (test_format == 0) {
/* Didn't find a compatible format : */
LOGI( "No compatible audio format, using signed 16-bit audio" );
test_format = AUDIO_S16SYS;
}
this->spec.format = test_format;
#endif
/* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(&this->spec);
LOGI("Try to open %u hz %s %u bit chan %u %s samples %u",
this->spec.freq, SDL_AUDIO_ISFLOAT(this->spec.format) ? "float" : "pcm", SDL_AUDIO_BITSIZE(this->spec.format),
LOGI("Try to open %u hz %u bit chan %u %s samples %u",
this->spec.freq, SDL_AUDIO_BITSIZE(this->spec.format),
this->spec.channels, (this->spec.format & 0x1000) ? "BE" : "LE", this->spec.samples);
/* configure audio source */
@@ -489,19 +489,7 @@ openslES_CreatePCMPlayer(_THIS)
break;
}
if(SDL_AUDIO_ISFLOAT(this->spec.format)) {
/* Copy all setup into PCM EX structure */
format_pcm_ex.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
format_pcm_ex.endianness = format_pcm.endianness;
format_pcm_ex.channelMask = format_pcm.channelMask;
format_pcm_ex.numChannels = format_pcm.numChannels;
format_pcm_ex.sampleRate = format_pcm.samplesPerSec;
format_pcm_ex.bitsPerSample = format_pcm.bitsPerSample;
format_pcm_ex.containerSize = format_pcm.containerSize;
format_pcm_ex.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
}
SLDataSource audioSrc = { &loc_bufq, SDL_AUDIO_ISFLOAT(this->spec.format) ? (void*)&format_pcm_ex : (void*)&format_pcm };
SLDataSource audioSrc = { &loc_bufq, &format_pcm };
/* configure audio sink */
SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
@@ -595,14 +583,14 @@ failed:
}
static int
openslES_OpenDevice(_THIS, const char *devname)
openslES_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
if (this->iscapture) {
if (iscapture) {
LOGI("openslES_OpenDevice() %s for capture", devname);
return openslES_CreatePCMRecorder(this);
} else {
@@ -726,13 +714,13 @@ openslES_CloseDevice(_THIS)
SDL_free(this->hidden);
}
static SDL_bool
static int
openslES_Init(SDL_AudioDriverImpl * impl)
{
LOGI("openslES_Init() called");
if (!openslES_CreateEngine()) {
return SDL_FALSE;
return 0;
}
LOGI("openslES_Init() - set pointers");
@@ -748,18 +736,18 @@ openslES_Init(SDL_AudioDriverImpl * impl)
impl->Deinitialize = openslES_DestroyEngine;
/* and the capabilities */
impl->HasCaptureSupport = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
impl->HasCaptureSupport = 1;
impl->OnlyHasDefaultOutputDevice = 1;
impl->OnlyHasDefaultCaptureDevice = 1;
LOGI("openslES_Init() - success");
/* this audio target is available. */
return SDL_TRUE;
return 1;
}
AudioBootStrap openslES_bootstrap = {
"openslES", "opensl ES audio driver", openslES_Init, SDL_FALSE
"openslES", "opensl ES audio driver", openslES_Init, 0
};
void openslES_ResumeDevices(void)

View File

@@ -248,28 +248,29 @@ static void OS2_CloseDevice(_THIS)
SDL_free(pAData);
}
static int OS2_OpenDevice(_THIS, const char *devname)
static int OS2_OpenDevice(_THIS, void *handle, const char *devname,
int iscapture)
{
SDL_PrivateAudioData *pAData;
SDL_AudioFormat test_format;
SDL_AudioFormat SDLAudioFmt;
MCI_AMP_OPEN_PARMS stMCIAmpOpen;
MCI_BUFFER_PARMS stMCIBuffer;
ULONG ulRC;
ULONG ulIdx;
BOOL new_freq;
SDL_bool iscapture = _this->iscapture;
new_freq = FALSE;
SDL_zero(stMCIAmpOpen);
SDL_zero(stMCIBuffer);
for (test_format = SDL_FirstAudioFormat(_this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
if (test_format == AUDIO_U8 || test_format == AUDIO_S16)
for (SDLAudioFmt = SDL_FirstAudioFormat(_this->spec.format);
SDLAudioFmt != 0; SDLAudioFmt = SDL_NextAudioFormat()) {
if (SDLAudioFmt == AUDIO_U8 || SDLAudioFmt == AUDIO_S16)
break;
}
if (!test_format) {
if (SDLAudioFmt == 0) {
debug_os2("Unsupported audio format, AUDIO_S16 used");
test_format = AUDIO_S16;
SDLAudioFmt = AUDIO_S16;
}
pAData = (SDL_PrivateAudioData *) SDL_calloc(1, sizeof(struct SDL_PrivateAudioData));
@@ -284,7 +285,7 @@ static int OS2_OpenDevice(_THIS, const char *devname)
}
/* Open audio device */
stMCIAmpOpen.usDeviceID = (_this->handle != NULL) ? ((ULONG)_this->handle - 1) : 0;
stMCIAmpOpen.usDeviceID = (handle != NULL) ? ((ULONG)handle - 1) : 0;
stMCIAmpOpen.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
ulRC = mciSendCommand(0, MCI_OPEN,
(_getEnvULong("SDL_AUDIO_SHARE", 1, 0) != 0)?
@@ -297,7 +298,7 @@ static int OS2_OpenDevice(_THIS, const char *devname)
}
pAData->usDeviceId = stMCIAmpOpen.usDeviceID;
if (iscapture) {
if (iscapture != 0) {
MCI_CONNECTOR_PARMS stMCIConnector;
MCI_AMP_SET_PARMS stMCIAmpSet;
BOOL fLineIn = _getEnvULong("SDL_AUDIO_LINEIN", 1, 0);
@@ -329,7 +330,7 @@ static int OS2_OpenDevice(_THIS, const char *devname)
&stMCIAmpSet, 0);
}
_this->spec.format = test_format;
_this->spec.format = SDLAudioFmt;
_this->spec.channels = _this->spec.channels > 1 ? 2 : 1;
if (_this->spec.freq < 8000) {
_this->spec.freq = 8000;
@@ -341,11 +342,11 @@ static int OS2_OpenDevice(_THIS, const char *devname)
/* Setup mixer. */
pAData->stMCIMixSetup.ulFormatTag = MCI_WAVE_FORMAT_PCM;
pAData->stMCIMixSetup.ulBitsPerSample = SDL_AUDIO_BITSIZE(test_format);
pAData->stMCIMixSetup.ulBitsPerSample = SDL_AUDIO_BITSIZE(SDLAudioFmt);
pAData->stMCIMixSetup.ulSamplesPerSec = _this->spec.freq;
pAData->stMCIMixSetup.ulChannels = _this->spec.channels;
pAData->stMCIMixSetup.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
if (!iscapture) {
if (iscapture == 0) {
pAData->stMCIMixSetup.ulFormatMode= MCI_PLAY;
pAData->stMCIMixSetup.pmixEvent = cbAudioWriteEvent;
} else {
@@ -422,7 +423,7 @@ static int OS2_OpenDevice(_THIS, const char *devname)
}
static SDL_bool OS2_Init(SDL_AudioDriverImpl * impl)
static int OS2_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
impl->DetectDevices = OS2_DetectDevices;
@@ -437,12 +438,12 @@ static SDL_bool OS2_Init(SDL_AudioDriverImpl * impl)
impl->FlushCapture = ;
impl->HasCaptureSupport = SDL_TRUE;
*/
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap OS2AUDIO_bootstrap = {
"DART", "OS/2 DART", OS2_Init, SDL_FALSE
"DART", "OS/2 DART", OS2_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_OS2 */

View File

@@ -223,12 +223,12 @@ PAUDIO_CloseDevice(_THIS)
}
static int
PAUDIO_OpenDevice(_THIS, const char *devname)
PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
const char *workaround = SDL_getenv("SDL_DSP_NOSELECT");
char audiodev[1024];
const char *err = NULL;
int flags;
int format;
int bytes_per_sample;
SDL_AudioFormat test_format;
audio_init paud_init;
@@ -316,44 +316,63 @@ PAUDIO_OpenDevice(_THIS, const char *devname)
paud_init.channels = this->spec.channels;
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
format = 0;
for (test_format = SDL_FirstAudioFormat(this->spec.format);
!format && test_format;) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
switch (test_format) {
case AUDIO_U8:
flags = TWOS_COMPLEMENT | FIXED;
bytes_per_sample = 1;
paud_init.bits_per_sample = 8;
paud_init.flags = TWOS_COMPLEMENT | FIXED;
format = 1;
break;
case AUDIO_S8:
flags = SIGNED | TWOS_COMPLEMENT | FIXED;
bytes_per_sample = 1;
paud_init.bits_per_sample = 8;
paud_init.flags = SIGNED | TWOS_COMPLEMENT | FIXED;
format = 1;
break;
case AUDIO_S16LSB:
flags = SIGNED | TWOS_COMPLEMENT | FIXED;
bytes_per_sample = 2;
paud_init.bits_per_sample = 16;
paud_init.flags = SIGNED | TWOS_COMPLEMENT | FIXED;
format = 1;
break;
case AUDIO_S16MSB:
flags = BIG_ENDIAN | SIGNED | TWOS_COMPLEMENT | FIXED;
bytes_per_sample = 2;
paud_init.bits_per_sample = 16;
paud_init.flags = BIG_ENDIAN | SIGNED | TWOS_COMPLEMENT | FIXED;
format = 1;
break;
case AUDIO_U16LSB:
flags = TWOS_COMPLEMENT | FIXED;
bytes_per_sample = 2;
paud_init.bits_per_sample = 16;
paud_init.flags = TWOS_COMPLEMENT | FIXED;
format = 1;
break;
case AUDIO_U16MSB:
flags = BIG_ENDIAN | TWOS_COMPLEMENT | FIXED;
bytes_per_sample = 2;
paud_init.bits_per_sample = 16;
paud_init.flags = BIG_ENDIAN | TWOS_COMPLEMENT | FIXED;
format = 1;
break;
default:
continue;
break;
}
if (!format) {
test_format = SDL_NextAudioFormat();
}
break;
}
if (!test_format) {
if (format == 0) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Couldn't find any hardware audio formats\n");
#endif
return SDL_SetError("%s: Unsupported audio format", "paud");
return SDL_SetError("Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
paud_init.bits_per_sample = SDL_AUDIO_BITSIZE(test_format);
bytes_per_sample = SDL_AUDIO_BITSIZE(test_format) / 8;
paud_init.flags = flags;
/*
* We know the buffer size and the max number of subsequent writes
@@ -387,25 +406,28 @@ PAUDIO_OpenDevice(_THIS, const char *devname)
if (ioctl(fd, AUDIO_INIT, &paud_init) < 0) {
switch (paud_init.rc) {
case 1:
err = "DSP can't do play requests";
err = "Couldn't set audio format: DSP can't do play requests";
break;
case 2:
err = "DSP can't do record requests";
err = "Couldn't set audio format: DSP can't do record requests";
break;
case 4:
err = "request was invalid";
err = "Couldn't set audio format: request was invalid";
break;
case 5:
err = "conflict with open's flags";
err = "Couldn't set audio format: conflict with open's flags";
break;
case 6:
err = "out of DSP MIPS or memory";
err = "Couldn't set audio format: out of DSP MIPS or memory";
break;
default:
err = "not documented in sys/audio.h";
err = "Couldn't set audio format: not documented in sys/audio.h";
break;
}
return SDL_SetError("paud: Couldn't set audio format (%s)", err);
}
if (err != NULL) {
return SDL_SetError("Paudio: %s", err);
}
/* Allocate mixing buffer */
@@ -463,14 +485,14 @@ PAUDIO_OpenDevice(_THIS, const char *devname)
return 0;
}
static SDL_bool
static int
PAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* !!! FIXME: not right for device enum? */
int fd = OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
if (fd < 0) {
SDL_SetError("PAUDIO: Couldn't open audio device");
return SDL_FALSE;
return 0;
}
close(fd);
@@ -480,13 +502,13 @@ PAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->PlayDevice = PAUDIO_WaitDevice;
impl->GetDeviceBuf = PAUDIO_GetDeviceBuf;
impl->CloseDevice = PAUDIO_CloseDevice;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; /* !!! FIXME: add device enum! */
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: add device enum! */
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap PAUDIO_bootstrap = {
"paud", "AIX Paudio", PAUDIO_Init, SDL_FALSE
"paud", "AIX Paudio", PAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_PAUDIO */

View File

@@ -31,22 +31,8 @@
#include <pipewire/extensions/metadata.h>
#include <spa/param/audio/format-utils.h>
/*
* The following keys are defined for compatability when building against older versions of Pipewire
* prior to their introduction and can be removed if the minimum required Pipewire version is increased
* to or beyond their point of introduction.
*/
/*
* Introduced in 0.3.22
* Taken from /src/pipewire/keys.h
*/
#ifndef PW_KEY_CONFIG_NAME
#define PW_KEY_CONFIG_NAME "config.name"
#endif
/*
* Introduced in 0.3.33
/* Older versions of Pipewire may not define this, but it's safe to pass at
* runtime even if older installations don't recognize it.
* Taken from src/pipewire/keys.h
*/
#ifndef PW_KEY_NODE_RATE
@@ -54,22 +40,19 @@
#endif
/*
* This seems to be a sane lower limit as Pipewire
* uses it in several of it's own modules.
* These seem to be sane limits as Pipewire
* uses them in several of it's own modules.
*
* NOTE: 8192 is a hard upper limit in Pipewire and
* increasing this value can lead to buffer overflows.
*/
#define PW_MIN_SAMPLES 32 /* About 0.67ms at 48kHz */
#define PW_MIN_SAMPLES 32 /* About 0.67ms at 48kHz */
#define PW_MAX_SAMPLES 8192 /* About 170.6ms at 48kHz */
#define PW_BASE_CLOCK_RATE 48000
#define PW_POD_BUFFER_LENGTH 1024
#define PW_THREAD_NAME_BUFFER_LENGTH 128
enum PW_READY_FLAGS
{
PW_READY_FLAG_BUFFER_ADDED = 0x1,
PW_READY_FLAG_STREAM_READY = 0x2,
PW_READY_FLAG_ALL_BITS = 0x3
};
#define PW_ID_TO_HANDLE(x) (void *)((uintptr_t)x)
#define PW_HANDLE_TO_ID(x) (uint32_t)((uintptr_t)x)
@@ -103,13 +86,14 @@ static enum pw_stream_state (*PIPEWIRE_pw_stream_get_state)(struct pw_stream *st
static struct pw_buffer *(*PIPEWIRE_pw_stream_dequeue_buffer)(struct pw_stream *);
static int (*PIPEWIRE_pw_stream_queue_buffer)(struct pw_stream *, struct pw_buffer *);
static struct pw_properties *(*PIPEWIRE_pw_properties_new)(const char *, ...)SPA_SENTINEL;
static void (*PIPEWIRE_pw_properties_free)(struct pw_properties *);
static int (*PIPEWIRE_pw_properties_set)(struct pw_properties *, const char *, const char *);
static int (*PIPEWIRE_pw_properties_setf)(struct pw_properties *, const char *, const char *, ...) SPA_PRINTF_FUNC(3, 4);
#ifdef SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC
static const char *pipewire_library = SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC;
static void *pipewire_handle = NULL;
static void * pipewire_handle = NULL;
static int
pipewire_dlsym(const char *fn, void **addr)
@@ -192,6 +176,7 @@ load_pipewire_syms()
SDL_PIPEWIRE_SYM(pw_stream_dequeue_buffer);
SDL_PIPEWIRE_SYM(pw_stream_queue_buffer);
SDL_PIPEWIRE_SYM(pw_properties_new);
SDL_PIPEWIRE_SYM(pw_properties_free);
SDL_PIPEWIRE_SYM(pw_properties_set);
SDL_PIPEWIRE_SYM(pw_properties_setf);
@@ -254,16 +239,16 @@ struct io_node
/* The global hotplug thread and associated objects. */
static struct pw_thread_loop *hotplug_loop;
static struct pw_core *hotplug_core;
static struct pw_context *hotplug_context;
static struct pw_registry *hotplug_registry;
static struct pw_core * hotplug_core;
static struct pw_context * hotplug_context;
static struct pw_registry * hotplug_registry;
static struct spa_hook hotplug_registry_listener;
static struct spa_hook hotplug_core_listener;
static struct spa_list hotplug_pending_list;
static struct spa_list hotplug_io_list;
static int hotplug_init_seq_val;
static SDL_bool hotplug_init_complete;
static SDL_bool hotplug_events_enabled;
static SDL_atomic_t hotplug_init_complete;
static SDL_atomic_t hotplug_events_enabled;
static Uint32 pipewire_default_sink_id = SPA_ID_INVALID;
static Uint32 pipewire_default_source_id = SPA_ID_INVALID;
@@ -275,6 +260,8 @@ io_list_check_add(struct io_node *node)
struct io_node *n;
SDL_bool ret = SDL_TRUE;
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
/* See if the node is already in the list */
spa_list_for_each (n, &hotplug_io_list, link) {
if (n->id == node->id) {
@@ -286,12 +273,14 @@ io_list_check_add(struct io_node *node)
/* Add to the list if the node doesn't already exist */
spa_list_append(&hotplug_io_list, &node->link);
if (hotplug_events_enabled) {
if (SDL_AtomicGet(&hotplug_events_enabled)) {
SDL_AddAudioDevice(node->is_capture, node->name, &node->spec, PW_ID_TO_HANDLE(node->id));
}
dup_found:
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
return ret;
}
@@ -300,12 +289,14 @@ io_list_remove(Uint32 id)
{
struct io_node *n, *temp;
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
/* Find and remove the node from the list */
spa_list_for_each_safe (n, temp, &hotplug_io_list, link) {
if (n->id == id) {
spa_list_remove(&n->link);
if (hotplug_events_enabled) {
if (SDL_AtomicGet(&hotplug_events_enabled)) {
SDL_RemoveAudioDevice(n->is_capture, PW_ID_TO_HANDLE(id));
}
@@ -314,6 +305,8 @@ io_list_remove(Uint32 id)
break;
}
}
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
}
static void
@@ -322,6 +315,8 @@ io_list_sort()
struct io_node *default_sink = NULL, *default_source = NULL;
struct io_node *n, *temp;
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
/* Find and move the default nodes to the beginning of the list */
spa_list_for_each_safe (n, temp, &hotplug_io_list, link) {
if (n->id == pipewire_default_sink_id) {
@@ -340,6 +335,8 @@ io_list_sort()
if (default_sink) {
spa_list_prepend(&hotplug_io_list, &default_sink->link);
}
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
}
static void
@@ -398,7 +395,7 @@ pending_list_clear()
static void *
node_object_new(Uint32 id, const char *type, Uint32 version, const void *funcs, const struct pw_core_events *core_events)
{
struct pw_proxy *proxy;
struct pw_proxy * proxy;
struct node_object *node;
/* Create the proxy object */
@@ -433,7 +430,7 @@ core_events_hotplug_init_callback(void *object, uint32_t id, int seq)
spa_hook_remove(&hotplug_core_listener);
/* Signal that the initial I/O list is populated */
hotplug_init_complete = SDL_TRUE;
SDL_AtomicSet(&hotplug_init_complete, 1);
PIPEWIRE_pw_thread_loop_signal(hotplug_loop, false);
}
}
@@ -442,7 +439,7 @@ static void
core_events_interface_callback(void *object, uint32_t id, int seq)
{
struct node_object *node = object;
struct io_node *io = node->userdata;
struct io_node * io = node->userdata;
if (id == PW_ID_CORE && seq == node->seq) {
/*
@@ -482,7 +479,7 @@ hotplug_core_sync(struct node_object *node)
node->seq = pw_core_sync(hotplug_core, PW_ID_CORE, node->seq);
}
if (!hotplug_init_complete) {
if (!SDL_AtomicGet(&hotplug_init_complete)) {
hotplug_init_seq_val = pw_core_sync(hotplug_core, PW_ID_CORE, hotplug_init_seq_val);
}
}
@@ -492,7 +489,7 @@ static SDL_bool
get_range_param(const struct spa_pod *param, Uint32 key, int *def, int *min, int *max)
{
const struct spa_pod_prop *prop;
struct spa_pod *value;
struct spa_pod * value;
Uint32 n_values, choice;
prop = spa_pod_find_prop(param, NULL, key);
@@ -546,8 +543,8 @@ static void
node_event_info(void *object, const struct pw_node_info *info)
{
struct node_object *node = object;
struct io_node *io = node->userdata;
const char *prop_val;
struct io_node * io = node->userdata;
const char * prop_val;
Uint32 i;
if (info) {
@@ -569,7 +566,7 @@ static void
node_event_param(void *object, int seq, uint32_t id, uint32_t index, uint32_t next, const struct spa_pod *param)
{
struct node_object *node = object;
struct io_node *io = node->userdata;
struct io_node * io = node->userdata;
/* Get the default frequency */
if (io->spec.freq == 0) {
@@ -622,7 +619,7 @@ registry_event_global_callback(void *object, uint32_t id, uint32_t permissions,
const char *media_class = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS);
if (media_class) {
const char *node_desc;
const char * node_desc;
struct io_node *io;
SDL_bool is_capture;
int str_buffer_len;
@@ -741,30 +738,23 @@ hotplug_loop_destroy()
pending_list_clear();
io_list_clear();
hotplug_init_complete = SDL_FALSE;
hotplug_events_enabled = SDL_FALSE;
pipewire_default_sink_id = SPA_ID_INVALID;
pipewire_default_source_id = SPA_ID_INVALID;
SDL_AtomicSet(&hotplug_init_complete, 0);
SDL_AtomicSet(&hotplug_events_enabled, 0);
if (hotplug_registry) {
PIPEWIRE_pw_proxy_destroy((struct pw_proxy *)hotplug_registry);
hotplug_registry = NULL;
}
if (hotplug_core) {
PIPEWIRE_pw_core_disconnect(hotplug_core);
hotplug_core = NULL;
}
if (hotplug_context) {
PIPEWIRE_pw_context_destroy(hotplug_context);
hotplug_context = NULL;
}
if (hotplug_loop) {
PIPEWIRE_pw_thread_loop_destroy(hotplug_loop);
hotplug_loop = NULL;
}
}
@@ -776,7 +766,7 @@ PIPEWIRE_DetectDevices()
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
/* Wait until the initial registry enumeration is complete */
if (!hotplug_init_complete) {
if (!SDL_AtomicGet(&hotplug_init_complete)) {
PIPEWIRE_pw_thread_loop_wait(hotplug_loop);
}
@@ -787,7 +777,7 @@ PIPEWIRE_DetectDevices()
SDL_AddAudioDevice(io->is_capture, io->name, &io->spec, PW_ID_TO_HANDLE(io->id));
}
hotplug_events_enabled = SDL_TRUE;
SDL_AtomicSet(&hotplug_events_enabled, 1);
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
}
@@ -800,14 +790,14 @@ static const enum spa_audio_channel PIPEWIRE_channel_map_4[] = { SPA_AUDIO_CHANN
SPA_AUDIO_CHANNEL_RR };
static const enum spa_audio_channel PIPEWIRE_channel_map_5[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC,
SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR };
static const enum spa_audio_channel PIPEWIRE_channel_map_6[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC,
static const enum spa_audio_channel PIPEWIRE_channel_map_6[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC,
SPA_AUDIO_CHANNEL_LFE, SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR };
static const enum spa_audio_channel PIPEWIRE_channel_map_7[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC,
static const enum spa_audio_channel PIPEWIRE_channel_map_7[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC,
SPA_AUDIO_CHANNEL_LFE, SPA_AUDIO_CHANNEL_RC, SPA_AUDIO_CHANNEL_RL,
SPA_AUDIO_CHANNEL_RR };
static const enum spa_audio_channel PIPEWIRE_channel_map_8[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC,
static const enum spa_audio_channel PIPEWIRE_channel_map_8[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC,
SPA_AUDIO_CHANNEL_LFE, SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR,
SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR };
SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR };
#define COPY_CHANNEL_MAP(c) SDL_memcpy(info->position, PIPEWIRE_channel_map_##c, sizeof(PIPEWIRE_channel_map_##c))
@@ -882,9 +872,9 @@ initialize_spa_info(const SDL_AudioSpec *spec, struct spa_audio_info_raw *info)
static void
output_callback(void *data)
{
struct pw_buffer *pw_buf;
struct pw_buffer * pw_buf;
struct spa_buffer *spa_buf;
Uint8 *dst;
Uint8 * dst;
_THIS = (SDL_AudioDevice *)data;
struct pw_stream *stream = this->hidden->stream;
@@ -910,7 +900,6 @@ 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;
@@ -920,13 +909,18 @@ 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);
}
@@ -936,7 +930,6 @@ 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;
@@ -948,9 +941,9 @@ output_callback(void *data)
static void
input_callback(void *data)
{
struct pw_buffer *pw_buf;
struct pw_buffer * pw_buf;
struct spa_buffer *spa_buf;
Uint8 *src;
Uint8 * src;
_THIS = (SDL_AudioDevice *)data;
struct pw_stream *stream = this->hidden->stream;
@@ -992,71 +985,35 @@ input_callback(void *data)
this->callbackspec.callback(this->callbackspec.userdata, this->work_buffer, this->callbackspec.size);
SDL_UnlockMutex(this->mixer_lock);
}
} else if (this->hidden->buffer) { /* Flush the buffer when paused */
} else { /* Flush the buffer when paused */
if (SDL_CountDataQueue(this->hidden->buffer) != 0) {
SDL_ClearDataQueue(this->hidden->buffer, this->hidden->input_buffer_packet_size);
SDL_ClearDataQueue(this->hidden->buffer, this->hidden->buffer_period_size * 2);
}
}
PIPEWIRE_pw_stream_queue_buffer(stream, pw_buf);
}
static void
stream_add_buffer_callback(void *data, struct pw_buffer *buffer)
{
_THIS = data;
if (this->iscapture == SDL_FALSE) {
/*
* Clamp the output spec samples and size to the max size of the Pipewire buffer.
* If they exceed the maximum size of the Pipewire buffer, double buffering will be used.
*/
if (this->spec.size > buffer->buffer->datas[0].maxsize) {
this->spec.samples = buffer->buffer->datas[0].maxsize / this->hidden->stride;
this->spec.size = buffer->buffer->datas[0].maxsize;
}
} else if (this->hidden->buffer == NULL) {
/*
* The latency of source nodes can change, so buffering is always required.
*
* Ensure that the intermediate input buffer is large enough to hold the requested
* application packet size or a full buffer of data from Pipewire, whichever is larger.
*
* A packet size of 2 periods should be more than is ever needed.
*/
this->hidden->input_buffer_packet_size = SPA_MAX(this->spec.size, buffer->buffer->datas[0].maxsize) * 2;
this->hidden->buffer = SDL_NewDataQueue(this->hidden->input_buffer_packet_size, this->hidden->input_buffer_packet_size);
}
this->hidden->stream_init_status |= PW_READY_FLAG_BUFFER_ADDED;
PIPEWIRE_pw_thread_loop_signal(this->hidden->loop, false);
}
static void
stream_state_changed_callback(void *data, enum pw_stream_state old, enum pw_stream_state state, const char *error)
{
_THIS = data;
if (state == PW_STREAM_STATE_STREAMING) {
this->hidden->stream_init_status |= PW_READY_FLAG_STREAM_READY;
}
if (state == PW_STREAM_STATE_STREAMING || state == PW_STREAM_STATE_ERROR) {
SDL_AtomicSet(&this->hidden->stream_initialized, 1);
PIPEWIRE_pw_thread_loop_signal(this->hidden->loop, false);
}
}
static const struct pw_stream_events stream_output_events = { PW_VERSION_STREAM_EVENTS,
.state_changed = stream_state_changed_callback,
.add_buffer = stream_add_buffer_callback,
.process = output_callback };
static const struct pw_stream_events stream_input_events = { PW_VERSION_STREAM_EVENTS,
.state_changed = stream_state_changed_callback,
.add_buffer = stream_add_buffer_callback,
.process = input_callback };
.state_changed = stream_state_changed_callback,
.process = input_callback };
static int
PIPEWIRE_OpenDevice(_THIS, const char *devname)
PIPEWIRE_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
/*
* NOTE: The PW_STREAM_FLAG_RT_PROCESS flag can be set to call the stream
@@ -1071,22 +1028,23 @@ PIPEWIRE_OpenDevice(_THIS, const char *devname)
Uint8 pod_buffer[PW_POD_BUFFER_LENGTH];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(pod_buffer, sizeof(pod_buffer));
struct spa_audio_info_raw spa_info = { 0 };
const struct spa_pod *params = NULL;
const struct spa_pod * params = NULL;
struct SDL_PrivateAudioData *priv;
struct pw_properties *props;
const char *app_name, *stream_name, *stream_role, *error;
const Uint32 node_id = this->handle == NULL ? PW_ID_ANY : PW_HANDLE_TO_ID(this->handle);
SDL_bool iscapture = this->iscapture;
struct pw_properties * props;
const char * app_name, *stream_name, *stream_role, *error;
const Uint32 node_id = this->handle == NULL ? PW_ID_ANY : PW_HANDLE_TO_ID(this->handle);
enum pw_stream_state state;
int res;
/* Clamp the period size to sane values */
const int min_period = PW_MIN_SAMPLES * SPA_MAX(this->spec.freq / PW_BASE_CLOCK_RATE, 1);
const int min_period = PW_MIN_SAMPLES * SPA_MAX(this->spec.freq / PW_BASE_CLOCK_RATE, 1);
const int adjusted_samples = SPA_CLAMP(this->spec.samples, min_period, PW_MAX_SAMPLES);
/* Get the hints for the application name, stream name and role */
app_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME);
if (!app_name || *app_name == '\0') {
app_name = SDL_GetHint(SDL_HINT_APP_NAME);
if (!app_name || *app_name == '\0') {
if (!app_name || *app_name == '\0') {
app_name = "SDL Application";
}
}
@@ -1119,34 +1077,38 @@ PIPEWIRE_OpenDevice(_THIS, const char *devname)
/* Size of a single audio frame in bytes */
priv->stride = (SDL_AUDIO_BITSIZE(this->spec.format) >> 3) * this->spec.channels;
if (this->spec.samples < min_period) {
this->spec.samples = min_period;
if (this->spec.samples != adjusted_samples && !iscapture) {
this->spec.samples = adjusted_samples;
this->spec.size = this->spec.samples * priv->stride;
}
SDL_snprintf(thread_name, sizeof(thread_name), "SDLAudio%c%ld", (iscapture) ? 'C' : 'P', (long)this->handle);
/* The latency of source nodes can change, so buffering is required. */
if (iscapture) {
priv->buffer_period_size = SPA_MAX(this->spec.samples, adjusted_samples) * priv->stride;
/* A packet size of 4 periods should be more than is ever needed (no more than 2 should be queued in practice). */
priv->buffer = SDL_NewDataQueue(priv->buffer_period_size * 4, priv->buffer_period_size * 2);
if (priv->buffer == NULL) {
return SDL_SetError("Pipewire: Failed to allocate source buffer");
}
}
SDL_snprintf(thread_name, sizeof(thread_name), "SDLAudio%c%ld", (iscapture) ? 'C' : 'P', (long)handle);
priv->loop = PIPEWIRE_pw_thread_loop_new(thread_name, NULL);
if (priv->loop == NULL) {
return SDL_SetError("Pipewire: Failed to create stream loop (%i)", errno);
}
/*
* Load the realtime module so Pipewire can set the loop thread to the appropriate priority.
*
* NOTE: Pipewire versions 0.3.22 or higher require the PW_KEY_CONFIG_NAME property (with client-rt.conf),
* lower versions require explicitly specifying the 'rtkit' module.
*
* PW_KEY_CONTEXT_PROFILE_MODULES is deprecated and can be safely removed if the minimum required
* Pipewire version is increased to 0.3.22 or higher at some point.
*/
props = PIPEWIRE_pw_properties_new(PW_KEY_CONFIG_NAME, "client-rt.conf",
PW_KEY_CONTEXT_PROFILE_MODULES, "default,rtkit", NULL);
/* Load the rtkit module so Pipewire can set the loop thread to the appropriate priority */
props = PIPEWIRE_pw_properties_new(PW_KEY_CONTEXT_PROFILE_MODULES, "default,rtkit", NULL);
if (props == NULL) {
return SDL_SetError("Pipewire: Failed to create stream context properties (%i)", errno);
}
/* On success, the context owns the properties object and will free it at destruction time. */
priv->context = PIPEWIRE_pw_context_new(PIPEWIRE_pw_thread_loop_get_loop(priv->loop), props, 0);
if (priv->context == NULL) {
PIPEWIRE_pw_properties_free(props);
return SDL_SetError("Pipewire: Failed to create stream context (%i)", errno);
}
@@ -1161,14 +1123,18 @@ PIPEWIRE_OpenDevice(_THIS, const char *devname)
PIPEWIRE_pw_properties_set(props, PW_KEY_APP_NAME, app_name);
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_NAME, stream_name);
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, stream_name);
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%i", this->spec.samples, this->spec.freq);
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%i", adjusted_samples, this->spec.freq);
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", this->spec.freq);
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true");
/* Create the new stream */
/*
* Create the new stream
* On success, the stream owns the properties object and will free it at destruction time.
*/
priv->stream = PIPEWIRE_pw_stream_new_simple(PIPEWIRE_pw_thread_loop_get_loop(priv->loop), stream_name, props,
iscapture ? &stream_input_events : &stream_output_events, this);
if (priv->stream == NULL) {
PIPEWIRE_pw_properties_free(props);
return SDL_SetError("Pipewire: Failed to create stream (%i)", errno);
}
@@ -1183,21 +1149,17 @@ PIPEWIRE_OpenDevice(_THIS, const char *devname)
return SDL_SetError("Pipewire: Failed to start stream loop");
}
/* Wait until all init flags are set or the stream has failed. */
/* Wait until the stream is either running or failed */
PIPEWIRE_pw_thread_loop_lock(priv->loop);
while (priv->stream_init_status != PW_READY_FLAG_ALL_BITS &&
PIPEWIRE_pw_stream_get_state(priv->stream, NULL) != PW_STREAM_STATE_ERROR) {
if (!SDL_AtomicGet(&priv->stream_initialized)) {
PIPEWIRE_pw_thread_loop_wait(priv->loop);
}
PIPEWIRE_pw_thread_loop_unlock(priv->loop);
if (PIPEWIRE_pw_stream_get_state(priv->stream, &error) == PW_STREAM_STATE_ERROR) {
return SDL_SetError("Pipewire: Stream error: %s", error);
}
state = PIPEWIRE_pw_stream_get_state(priv->stream, &error);
/* If this is a capture stream, make sure the intermediate buffer was successfully allocated. */
if (iscapture && priv->buffer == NULL) {
return SDL_SetError("Pipewire: Failed to allocate source buffer");
if (state == PW_STREAM_STATE_ERROR) {
return SDL_SetError("Pipewire: Stream error: %s", error);
}
return 0;
@@ -1238,19 +1200,19 @@ PIPEWIRE_Deinitialize()
}
}
static SDL_bool
static int
PIPEWIRE_Init(SDL_AudioDriverImpl *impl)
{
if (!pipewire_initialized) {
if (init_pipewire_library() < 0) {
return SDL_FALSE;
return 0;
}
pipewire_initialized = SDL_TRUE;
if (hotplug_loop_init() < 0) {
PIPEWIRE_Deinitialize();
return SDL_FALSE;
return 0;
}
}
@@ -1260,13 +1222,13 @@ PIPEWIRE_Init(SDL_AudioDriverImpl *impl)
impl->CloseDevice = PIPEWIRE_CloseDevice;
impl->Deinitialize = PIPEWIRE_Deinitialize;
impl->HasCaptureSupport = SDL_TRUE;
impl->ProvidesOwnCallbackThread = SDL_TRUE;
impl->HasCaptureSupport = 1;
impl->ProvidesOwnCallbackThread = 1;
return SDL_TRUE;
return 1;
}
AudioBootStrap PIPEWIRE_bootstrap = { "pipewire", "Pipewire", PIPEWIRE_Init, SDL_FALSE };
AudioBootStrap PIPEWIRE_bootstrap = { "pipewire", "Pipewire", PIPEWIRE_Init, 0 };
#endif /* SDL_AUDIO_DRIVER_PIPEWIRE */

View File

@@ -37,9 +37,9 @@ struct SDL_PrivateAudioData
struct pw_context *context;
struct SDL_DataQueue *buffer;
size_t input_buffer_packet_size;
Sint32 stride; /* Bytes-per-frame */
int stream_init_status;
size_t buffer_period_size;
Sint32 stride; /* Bytes-per-frame */
SDL_atomic_t stream_initialized;
};
#endif /* SDL_pipewire_h_ */

View File

@@ -42,7 +42,7 @@
#define PSPAUDIO_DRIVER_NAME "psp"
static int
PSPAUDIO_OpenDevice(_THIS, const char *devname)
PSPAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int format, mixlen, i;
@@ -158,7 +158,7 @@ static void PSPAUDIO_ThreadInit(_THIS)
}
}
static SDL_bool
static int
PSPAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
@@ -170,16 +170,16 @@ PSPAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->ThreadInit = PSPAUDIO_ThreadInit;
/* PSP audio device */
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
/*
impl->HasCaptureSupport = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
impl->HasCaptureSupport = 1;
impl->OnlyHasDefaultCaptureDevice = 1;
*/
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap PSPAUDIO_bootstrap = {
"psp", "PSP audio driver", PSPAUDIO_Init, SDL_FALSE
"psp", "PSP audio driver", PSPAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_PSP */

View File

@@ -107,6 +107,8 @@ 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 *,
@@ -117,7 +119,6 @@ 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);
@@ -221,6 +222,8 @@ 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);
@@ -229,7 +232,6 @@ 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;
}
@@ -356,57 +358,52 @@ ConnectToPulseServer(pa_mainloop **_mainloop, pa_context **_context)
/* This function waits until it is possible to write a full sound buffer */
static void
PULSEAUDIO_WaitDevice(_THIS)
{
/* this is a no-op; we wait in PULSEAUDIO_PlayDevice now. */
}
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");*/
while (SDL_AtomicGet(&this->enabled)) {
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;
}
}
}
/*printf("PULSEAUDIO PLAYDEVICE END! written=%d\n", written);*/
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);
}
}
}
static Uint8 *
PULSEAUDIO_GetDeviceBuf(_THIS)
{
return this->hidden->mixbuf;
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;
}
@@ -525,7 +522,7 @@ SourceDeviceNameCallback(pa_context *c, const pa_source_info *i, int is_last, vo
}
static SDL_bool
FindDeviceName(struct SDL_PrivateAudioData *h, const SDL_bool iscapture, void *handle)
FindDeviceName(struct SDL_PrivateAudioData *h, const int iscapture, void *handle)
{
const uint32_t idx = ((uint32_t) ((size_t) handle)) - 1;
@@ -547,17 +544,16 @@ FindDeviceName(struct SDL_PrivateAudioData *h, const SDL_bool iscapture, void *h
}
static int
PULSEAUDIO_OpenDevice(_THIS, const char *devname)
PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
struct SDL_PrivateAudioData *h = NULL;
SDL_AudioFormat test_format;
Uint16 test_format = 0;
pa_sample_spec paspec;
pa_buffer_attr paattr;
pa_channel_map pacmap;
pa_stream_flags_t flags = 0;
const char *name = NULL;
SDL_bool iscapture = this->iscapture;
int state = 0, format = PA_SAMPLE_INVALID;
int state = 0;
int rc = 0;
/* Initialize all variables that we clean on shutdown */
@@ -568,45 +564,53 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname)
}
SDL_zerop(this->hidden);
paspec.format = PA_SAMPLE_INVALID;
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
for (test_format = SDL_FirstAudioFormat(this->spec.format);
(paspec.format == PA_SAMPLE_INVALID) && test_format;) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
switch (test_format) {
case AUDIO_U8:
format = PA_SAMPLE_U8;
paspec.format = PA_SAMPLE_U8;
break;
case AUDIO_S16LSB:
format = PA_SAMPLE_S16LE;
paspec.format = PA_SAMPLE_S16LE;
break;
case AUDIO_S16MSB:
format = PA_SAMPLE_S16BE;
paspec.format = PA_SAMPLE_S16BE;
break;
case AUDIO_S32LSB:
format = PA_SAMPLE_S32LE;
paspec.format = PA_SAMPLE_S32LE;
break;
case AUDIO_S32MSB:
format = PA_SAMPLE_S32BE;
paspec.format = PA_SAMPLE_S32BE;
break;
case AUDIO_F32LSB:
format = PA_SAMPLE_FLOAT32LE;
paspec.format = PA_SAMPLE_FLOAT32LE;
break;
case AUDIO_F32MSB:
format = PA_SAMPLE_FLOAT32BE;
paspec.format = PA_SAMPLE_FLOAT32BE;
break;
default:
continue;
paspec.format = PA_SAMPLE_INVALID;
break;
}
if (paspec.format == PA_SAMPLE_INVALID) {
test_format = SDL_NextAudioFormat();
}
break;
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "pulseaudio");
if (paspec.format == PA_SAMPLE_INVALID) {
return SDL_SetError("Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
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,18 +627,28 @@ 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;
paattr.tlength = h->mixlen;
/* 2x original requested bufsize */
paattr.tlength = h->mixlen * 4;
paattr.prebuf = -1;
paattr.maxlength = -1;
paattr.minreq = -1;
flags |= PA_STREAM_ADJUST_LATENCY;
/* -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
if (ConnectToPulseServer(&h->mainloop, &h->context) < 0) {
return SDL_SetError("Could not connect to PulseAudio server");
}
if (!FindDeviceName(h, iscapture, this->handle)) {
if (!FindDeviceName(h, iscapture, handle)) {
return SDL_SetError("Requested PulseAudio sink/source missing?");
}
@@ -665,7 +679,6 @@ 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);
}
@@ -819,16 +832,16 @@ PULSEAUDIO_Deinitialize(void)
UnloadPulseAudioLibrary();
}
static SDL_bool
static int
PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
{
if (LoadPulseAudioLibrary() < 0) {
return SDL_FALSE;
return 0;
}
if (ConnectToPulseServer(&hotplug_mainloop, &hotplug_context) < 0) {
UnloadPulseAudioLibrary();
return SDL_FALSE;
return 0;
}
include_monitors = SDL_GetHintBoolean(SDL_HINT_AUDIO_INCLUDE_MONITORS, SDL_FALSE);
@@ -846,11 +859,11 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap PULSEAUDIO_bootstrap = {
"pulseaudio", "PulseAudio", PULSEAUDIO_Init, SDL_FALSE
"pulseaudio", "PulseAudio", PULSEAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_PULSEAUDIO */

View File

@@ -43,7 +43,11 @@ struct SDL_PrivateAudioData
Uint8 *mixbuf;
int mixlen;
int bytes_requested; /* bytes of data the hardware wants _now_. */
/* 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;
const Uint8 *capturebuf;
int capturelen;

View File

@@ -121,7 +121,7 @@ QSA_WaitDevice(_THIS)
/* For example, Vortex 8820 audio driver stucks on second DAC because */
/* it doesn't exist ! */
result = SDL_IOReady(this->hidden->audio_fd,
this->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE,
this->hidden->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE,
2 * 1000);
switch (result) {
case -1:
@@ -180,7 +180,7 @@ QSA_PlayDevice(_THIS)
} else {
if ((errno == EINVAL) || (errno == EIO)) {
SDL_zero(cstatus);
if (!this->iscapture) {
if (!this->hidden->iscapture) {
cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
} else {
cstatus.channel = SND_PCM_CHANNEL_CAPTURE;
@@ -196,7 +196,7 @@ QSA_PlayDevice(_THIS)
if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) ||
(cstatus.status == SND_PCM_STATUS_READY)) {
if (!this->iscapture) {
if (!this->hidden->iscapture) {
status =
snd_pcm_plugin_prepare(this->hidden->
audio_handle,
@@ -240,7 +240,7 @@ static void
QSA_CloseDevice(_THIS)
{
if (this->hidden->audio_handle != NULL) {
if (!this->iscapture) {
if (!this->hidden->iscapture) {
/* Finish playing available samples */
snd_pcm_plugin_flush(this->hidden->audio_handle,
SND_PCM_CHANNEL_PLAYBACK);
@@ -257,13 +257,13 @@ QSA_CloseDevice(_THIS)
}
static int
QSA_OpenDevice(_THIS, const char *devname)
QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
const QSA_Device *device = (const QSA_Device *) this->handle;
SDL_Bool iscapture = this->iscapture;
const QSA_Device *device = (const QSA_Device *) handle;
int status = 0;
int format = 0;
SDL_AudioFormat test_format;
SDL_AudioFormat test_format = 0;
int found = 0;
snd_pcm_channel_setup_t csetup;
snd_pcm_channel_params_t cparams;
@@ -280,6 +280,9 @@ QSA_OpenDevice(_THIS, const char *devname)
/* Initialize channel transfer parameters to default */
QSA_InitAudioParams(&cparams);
/* Initialize channel direction: capture or playback */
this->hidden->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
if (device != NULL) {
/* Open requested audio device */
this->hidden->deviceno = device->deviceno;
@@ -302,49 +305,89 @@ QSA_OpenDevice(_THIS, const char *devname)
}
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
format = 0;
/* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */
found = 0;
for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) {
/* if match found set format to equivalent QSA format */
switch (test_format) {
case AUDIO_U8:
format = SND_PCM_SFMT_U8;
{
format = SND_PCM_SFMT_U8;
found = 1;
}
break;
case AUDIO_S8:
format = SND_PCM_SFMT_S8;
{
format = SND_PCM_SFMT_S8;
found = 1;
}
break;
case AUDIO_S16LSB:
format = SND_PCM_SFMT_S16_LE;
{
format = SND_PCM_SFMT_S16_LE;
found = 1;
}
break;
case AUDIO_S16MSB:
format = SND_PCM_SFMT_S16_BE;
{
format = SND_PCM_SFMT_S16_BE;
found = 1;
}
break;
case AUDIO_U16LSB:
format = SND_PCM_SFMT_U16_LE;
{
format = SND_PCM_SFMT_U16_LE;
found = 1;
}
break;
case AUDIO_U16MSB:
format = SND_PCM_SFMT_U16_BE;
{
format = SND_PCM_SFMT_U16_BE;
found = 1;
}
break;
case AUDIO_S32LSB:
format = SND_PCM_SFMT_S32_LE;
{
format = SND_PCM_SFMT_S32_LE;
found = 1;
}
break;
case AUDIO_S32MSB:
format = SND_PCM_SFMT_S32_BE;
{
format = SND_PCM_SFMT_S32_BE;
found = 1;
}
break;
case AUDIO_F32LSB:
format = SND_PCM_SFMT_FLOAT_LE;
{
format = SND_PCM_SFMT_FLOAT_LE;
found = 1;
}
break;
case AUDIO_F32MSB:
format = SND_PCM_SFMT_FLOAT_BE;
{
format = SND_PCM_SFMT_FLOAT_BE;
found = 1;
}
break;
default:
continue;
{
break;
}
}
if (!found) {
test_format = SDL_NextAudioFormat();
}
break;
}
/* assumes test_format not 0 on success */
/* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "qsa");
if (test_format == 0) {
return SDL_SetError("QSA: Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
/* Set the audio format */
@@ -364,7 +407,7 @@ QSA_OpenDevice(_THIS, const char *devname)
/* Make sure channel is setup right one last time */
SDL_zero(csetup);
if (!this->iscapture) {
if (!this->hidden->iscapture) {
csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
} else {
csetup.channel = SND_PCM_CHANNEL_CAPTURE;
@@ -400,7 +443,7 @@ QSA_OpenDevice(_THIS, const char *devname)
this->hidden->pcm_len);
/* get the file descriptor */
if (!this->iscapture) {
if (!this->hidden->iscapture) {
this->hidden->audio_fd =
snd_pcm_file_descriptor(this->hidden->audio_handle,
SND_PCM_CHANNEL_PLAYBACK);
@@ -415,7 +458,7 @@ QSA_OpenDevice(_THIS, const char *devname)
}
/* Prepare an audio channel */
if (!this->iscapture) {
if (!this->hidden->iscapture) {
/* Prepare audio playback */
status =
snd_pcm_plugin_prepare(this->hidden->audio_handle,
@@ -592,7 +635,7 @@ QSA_Deinitialize(void)
qsa_capture_devices = 0;
}
static SDL_bool
static int
QSA_Init(SDL_AudioDriverImpl * impl)
{
/* Clear devices array */
@@ -612,14 +655,20 @@ QSA_Init(SDL_AudioDriverImpl * impl)
impl->GetDeviceBuf = QSA_GetDeviceBuf;
impl->CloseDevice = QSA_CloseDevice;
impl->Deinitialize = QSA_Deinitialize;
impl->LockDevice = NULL;
impl->UnlockDevice = NULL;
impl->HasCaptureSupport = SDL_TRUE;
impl->ProvidesOwnCallbackThread = 0;
impl->SkipMixerLock = 0;
impl->HasCaptureSupport = 1;
impl->OnlyHasDefaultOutputDevice = 0;
impl->OnlyHasDefaultCaptureDevice = 0;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap QSAAUDIO_bootstrap = {
"qsa", "QNX QSA Audio", QSA_Init, SDL_FALSE
"qsa", "QNX QSA Audio", QSA_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_QSA */

View File

@@ -33,6 +33,9 @@
struct SDL_PrivateAudioData
{
/* SDL capture state */
SDL_bool iscapture;
/* The audio device handle */
int cardno;
int deviceno;

View File

@@ -237,11 +237,11 @@ SNDIO_CloseDevice(_THIS)
}
static int
SNDIO_OpenDevice(_THIS, const char *devname)
SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_AudioFormat test_format;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
struct sio_par par;
SDL_bool iscapture = this->iscapture;
int status;
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc(sizeof(*this->hidden));
@@ -273,7 +273,8 @@ SNDIO_OpenDevice(_THIS, const char *devname)
par.appbufsz = par.round * 2;
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
status = -1;
while (test_format && (status < 0)) {
if (!SDL_AUDIO_ISFLOAT(test_format)) {
par.le = SDL_AUDIO_ISLITTLEENDIAN(test_format) ? 1 : 0;
par.sig = SDL_AUDIO_ISSIGNED(test_format) ? 1 : 0;
@@ -289,13 +290,15 @@ SNDIO_OpenDevice(_THIS, const char *devname)
continue;
}
if ((par.bits == 8 * par.bps) || (par.msb)) {
status = 0;
break;
}
}
test_format = SDL_NextAudioFormat();
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "sndio");
if (status < 0) {
return SDL_SetError("sndio: Couldn't find any hardware audio formats");
}
if ((par.bps == 4) && (par.sig) && (par.le))
@@ -354,11 +357,11 @@ SNDIO_DetectDevices(void)
SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, NULL, (void *) 0x2);
}
static SDL_bool
static int
SNDIO_Init(SDL_AudioDriverImpl * impl)
{
if (LoadSNDIOLibrary() < 0) {
return SDL_FALSE;
return 0;
}
/* Set the function pointers */
@@ -372,14 +375,14 @@ SNDIO_Init(SDL_AudioDriverImpl * impl)
impl->Deinitialize = SNDIO_Deinitialize;
impl->DetectDevices = SNDIO_DetectDevices;
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
impl->AllowsArbitraryDeviceNames = 1;
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap SNDIO_bootstrap = {
"sndio", "OpenBSD sndio", SNDIO_Init, SDL_FALSE
"sndio", "OpenBSD sndio", SNDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_SNDIO */

View File

@@ -188,12 +188,11 @@ SUNAUDIO_CloseDevice(_THIS)
}
static int
SUNAUDIO_OpenDevice(_THIS, const char *devname)
SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
#ifdef AUDIO_SETINFO
int enc;
#endif
SDL_bool iscapture = this->iscapture;
int desired_freq = 0;
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
SDL_AudioFormat format = 0;
@@ -395,7 +394,7 @@ snd2au(int sample)
return (mask & sample);
}
static SDL_bool
static int
SUNAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
@@ -406,13 +405,13 @@ SUNAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->GetDeviceBuf = SUNAUDIO_GetDeviceBuf;
impl->CloseDevice = SUNAUDIO_CloseDevice;
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
impl->AllowsArbitraryDeviceNames = 1;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap SUNAUDIO_bootstrap = {
"audio", "UNIX /dev/audio interface", SUNAUDIO_Init, SDL_FALSE
"audio", "UNIX /dev/audio interface", SUNAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_SUNAUDIO */

View File

@@ -37,35 +37,18 @@
#include <psp2/kernel/threadmgr.h>
#include <psp2/audioout.h>
#include <psp2/audioin.h>
#define SCE_AUDIO_SAMPLE_ALIGN(s) (((s) + 63) & ~63)
#define SCE_AUDIO_MAX_VOLUME 0x8000
static int
VITAAUD_OpenCaptureDevice(_THIS)
{
this->spec.freq = 16000;
this->spec.samples = 512;
this->spec.channels = 1;
SDL_CalculateAudioSpec(&this->spec);
this->hidden->port = sceAudioInOpenPort(SCE_AUDIO_IN_PORT_TYPE_VOICE , 512, 16000, SCE_AUDIO_IN_PARAM_FORMAT_S16_MONO);
if (this->hidden->port < 0) {
return SDL_SetError("Couldn't open audio in port: %x", this->hidden->port);
}
return 0;
}
/* The tag name used by VITA audio */
#define VITAAUD_DRIVER_NAME "vita"
static int
VITAAUD_OpenDevice(_THIS, const char *devname)
VITAAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int format, mixlen, i, port = SCE_AUDIO_OUT_PORT_TYPE_MAIN;
int vols[2] = {SCE_AUDIO_MAX_VOLUME, SCE_AUDIO_MAX_VOLUME};
SDL_AudioFormat test_format;
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc(sizeof(*this->hidden));
@@ -73,20 +56,13 @@ VITAAUD_OpenDevice(_THIS, const char *devname)
return SDL_OutOfMemory();
}
SDL_memset(this->hidden, 0, sizeof(*this->hidden));
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
if (test_format == AUDIO_S16LSB) {
this->spec.format = test_format;
switch (this->spec.format & 0xff) {
case 8:
case 16:
this->spec.format = AUDIO_S16LSB;
break;
}
}
if(!test_format) {
return SDL_SetError("Unsupported audio format");
}
if (this->iscapture) {
return VITAAUD_OpenCaptureDevice(this);
default:
return SDL_SetError("Unsupported audio format");
}
/* The sample count must be a multiple of 64. */
@@ -115,14 +91,14 @@ VITAAUD_OpenDevice(_THIS, const char *devname)
port = SCE_AUDIO_OUT_PORT_TYPE_BGM;
}
this->hidden->port = sceAudioOutOpenPort(port, this->spec.samples, this->spec.freq, format);
if (this->hidden->port < 0) {
this->hidden->channel = sceAudioOutOpenPort(port, this->spec.samples, this->spec.freq, format);
if (this->hidden->channel < 0) {
free(this->hidden->rawbuf);
this->hidden->rawbuf = NULL;
return SDL_SetError("Couldn't open audio out port: %x", this->hidden->port);
return SDL_SetError("Couldn't reserve hardware channel");
}
sceAudioOutSetVolume(this->hidden->port, SCE_AUDIO_VOLUME_FLAG_L_CH|SCE_AUDIO_VOLUME_FLAG_R_CH, vols);
sceAudioOutSetVolume(this->hidden->channel, SCE_AUDIO_VOLUME_FLAG_L_CH|SCE_AUDIO_VOLUME_FLAG_R_CH, vols);
SDL_memset(this->hidden->rawbuf, 0, mixlen);
for (i = 0; i < NUM_BUFFERS; i++) {
@@ -137,7 +113,7 @@ static void VITAAUD_PlayDevice(_THIS)
{
Uint8 *mixbuf = this->hidden->mixbufs[this->hidden->next_buffer];
sceAudioOutOutput(this->hidden->port, mixbuf);
sceAudioOutOutput(this->hidden->channel, mixbuf);
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
}
@@ -147,7 +123,6 @@ static void VITAAUD_WaitDevice(_THIS)
{
/* Because we block when sending audio, there's no need for this function to do anything. */
}
static Uint8 *VITAAUD_GetDeviceBuf(_THIS)
{
return this->hidden->mixbufs[this->hidden->next_buffer];
@@ -155,32 +130,17 @@ static Uint8 *VITAAUD_GetDeviceBuf(_THIS)
static void VITAAUD_CloseDevice(_THIS)
{
if (this->hidden->port >= 0) {
if (this->iscapture) {
sceAudioInReleasePort(this->hidden->port);
} else {
sceAudioOutReleasePort(this->hidden->port);
}
this->hidden->port = -1;
if (this->hidden->channel >= 0) {
sceAudioOutReleasePort(this->hidden->channel);
this->hidden->channel = -1;
}
if (!this->iscapture && this->hidden->rawbuf != NULL) {
if (this->hidden->rawbuf != NULL) {
free(this->hidden->rawbuf); /* this uses memalign(), not SDL_malloc(). */
this->hidden->rawbuf = NULL;
}
}
static int VITAAUD_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
int ret;
SDL_assert(buflen == this->spec.size);
ret = sceAudioInInput(this->hidden->port, buffer);
if (ret < 0) {
return SDL_SetError("Failed to capture from device: %x", ret);
}
return this->spec.size;
}
static void VITAAUD_ThreadInit(_THIS)
{
/* Increase the priority of this audio thread by 1 to put it
@@ -194,7 +154,7 @@ static void VITAAUD_ThreadInit(_THIS)
}
}
static SDL_bool
static int
VITAAUD_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
@@ -205,18 +165,17 @@ VITAAUD_Init(SDL_AudioDriverImpl * impl)
impl->CloseDevice = VITAAUD_CloseDevice;
impl->ThreadInit = VITAAUD_ThreadInit;
impl->CaptureFromDevice = VITAAUD_CaptureFromDevice;
/* and the capabilities */
impl->HasCaptureSupport = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
/* VITA audio device */
impl->OnlyHasDefaultOutputDevice = 1;
/*
impl->HasCaptureSupport = 1;
impl->OnlyHasDefaultInputDevice = 1;
*/
return 1; /* this audio target is available. */
}
AudioBootStrap VITAAUD_bootstrap = {
"vita", "VITA audio driver", VITAAUD_Init, SDL_FALSE
"vita", "VITA audio driver", VITAAUD_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_VITA */

View File

@@ -30,8 +30,8 @@
#define NUM_BUFFERS 2
struct SDL_PrivateAudioData {
/* The hardware input/output port. */
int port;
/* The hardware output channel. */
int channel;
/* The raw allocated mixing buffer. */
Uint8 *rawbuf;
/* Individual mixing buffers. */

View File

@@ -209,7 +209,7 @@ UpdateAudioStream(_THIS, const SDL_AudioSpec *oldspec)
}
if (!this->stream) {
return -1; /* SDL_NewAudioStream should have called SDL_SetError. */
return -1;
}
}
@@ -512,8 +512,9 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
IAudioRenderClient *render = NULL;
IAudioCaptureClient *capture = NULL;
WAVEFORMATEX *waveformat = NULL;
SDL_AudioFormat test_format;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
SDL_AudioFormat wasapi_format = 0;
SDL_bool valid_format = SDL_FALSE;
HRESULT ret = S_OK;
DWORD streamflags = 0;
@@ -542,15 +543,17 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
/* Make sure we have a valid format that we can convert to whatever WASAPI wants. */
wasapi_format = WaveFormatToSDLFormat(waveformat);
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
while ((!valid_format) && (test_format)) {
if (test_format == wasapi_format) {
this->spec.format = test_format;
valid_format = SDL_TRUE;
break;
}
test_format = SDL_NextAudioFormat();
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "wasapi");
if (!valid_format) {
return SDL_SetError("WASAPI: Unsupported audio format");
}
ret = IAudioClient_GetDevicePeriod(client, &default_period, NULL);
@@ -558,16 +561,12 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
return WIN_SetErrorFromHRESULT("WASAPI can't determine minimum device period", ret);
}
#if 1 /* we're getting reports that WASAPI's resampler introduces distortions, so it's disabled for now. --ryan. */
this->spec.freq = waveformat->nSamplesPerSec; /* force sampling rate so our resampler kicks in, if necessary. */
#else
/* favor WASAPI's resampler over our own */
if (this->spec.freq != waveformat->nSamplesPerSec) {
streamflags |= (AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY);
waveformat->nSamplesPerSec = this->spec.freq;
waveformat->nAvgBytesPerSec = waveformat->nSamplesPerSec * waveformat->nChannels * (waveformat->wBitsPerSample / 8);
}
#endif
streamflags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
ret = IAudioClient_Initialize(client, sharemode, streamflags, 0, 0, waveformat, NULL);
@@ -632,7 +631,9 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
}
if (updatestream) {
return UpdateAudioStream(this, &oldspec);
if (UpdateAudioStream(this, &oldspec) == -1) {
return -1;
}
}
return 0; /* good to go. */
@@ -640,9 +641,9 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
static int
WASAPI_OpenDevice(_THIS, const char *devname)
WASAPI_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
LPCWSTR devid = (LPCWSTR) this->handle;
LPCWSTR devid = (LPCWSTR) handle;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
@@ -655,7 +656,7 @@ WASAPI_OpenDevice(_THIS, const char *devname)
WASAPI_RefDevice(this); /* so CloseDevice() will unref to zero. */
if (!devid) { /* is default device? */
this->hidden->default_device_generation = SDL_AtomicGet(this->iscapture ? &WASAPI_DefaultCaptureGeneration : &WASAPI_DefaultPlaybackGeneration);
this->hidden->default_device_generation = SDL_AtomicGet(iscapture ? &WASAPI_DefaultCaptureGeneration : &WASAPI_DefaultPlaybackGeneration);
} else {
this->hidden->devid = SDL_wcsdup(devid);
if (!this->hidden->devid) {
@@ -690,6 +691,12 @@ WASAPI_ThreadDeinit(_THIS)
WASAPI_PlatformThreadDeinit(this);
}
void
WASAPI_BeginLoopIteration(_THIS)
{
/* no-op. */
}
static void
WASAPI_Deinitialize(void)
{
@@ -706,20 +713,21 @@ WASAPI_Deinitialize(void)
deviceid_list = NULL;
}
static SDL_bool
static int
WASAPI_Init(SDL_AudioDriverImpl * impl)
{
SDL_AtomicSet(&WASAPI_DefaultPlaybackGeneration, 1);
SDL_AtomicSet(&WASAPI_DefaultCaptureGeneration, 1);
if (WASAPI_PlatformInit() == -1) {
return SDL_FALSE;
return 0;
}
/* Set the function pointers */
impl->DetectDevices = WASAPI_DetectDevices;
impl->ThreadInit = WASAPI_ThreadInit;
impl->ThreadDeinit = WASAPI_ThreadDeinit;
impl->BeginLoopIteration = WASAPI_BeginLoopIteration;
impl->OpenDevice = WASAPI_OpenDevice;
impl->PlayDevice = WASAPI_PlayDevice;
impl->WaitDevice = WASAPI_WaitDevice;
@@ -728,13 +736,13 @@ WASAPI_Init(SDL_AudioDriverImpl * impl)
impl->FlushCapture = WASAPI_FlushCapture;
impl->CloseDevice = WASAPI_CloseDevice;
impl->Deinitialize = WASAPI_Deinitialize;
impl->HasCaptureSupport = SDL_TRUE;
impl->HasCaptureSupport = 1;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap WASAPI_bootstrap = {
"wasapi", "WASAPI", WASAPI_Init, SDL_FALSE
"wasapi", "WASAPI", WASAPI_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_WASAPI */

View File

@@ -74,6 +74,7 @@ int WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery);
void WASAPI_PlatformThreadInit(_THIS);
void WASAPI_PlatformThreadDeinit(_THIS);
void WASAPI_PlatformDeleteActivationHandler(void *handler);
void WASAPI_BeginLoopIteration(_THIS);
#ifdef __cplusplus
}

View File

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

View File

@@ -283,11 +283,10 @@ PrepWaveFormat(_THIS, UINT devId, WAVEFORMATEX *pfmt, const int iscapture)
}
static int
WINMM_OpenDevice(_THIS, const char *devname)
WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_AudioFormat test_format;
SDL_bool iscapture = this->iscapture;
void *handle = this->handle;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
int valid_datatype = 0;
MMRESULT result;
WAVEFORMATEX waveformat;
UINT devId = WAVE_MAPPER; /* WAVE_MAPPER == choose system's default */
@@ -314,7 +313,7 @@ WINMM_OpenDevice(_THIS, const char *devname)
if (this->spec.channels > 2)
this->spec.channels = 2; /* !!! FIXME: is this right? */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
while ((!valid_datatype) && (test_format)) {
switch (test_format) {
case AUDIO_U8:
case AUDIO_S16:
@@ -322,17 +321,20 @@ WINMM_OpenDevice(_THIS, const char *devname)
case AUDIO_F32:
this->spec.format = test_format;
if (PrepWaveFormat(this, devId, &waveformat, iscapture)) {
break;
valid_datatype = 1;
} else {
test_format = SDL_NextAudioFormat();
}
continue;
break;
default:
continue;
test_format = SDL_NextAudioFormat();
break;
}
break;
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "winmm");
if (!valid_datatype) {
return SDL_SetError("Unsupported audio format");
}
/* Update the fragment size as size in bytes */
@@ -432,7 +434,7 @@ WINMM_OpenDevice(_THIS, const char *devname)
return 0; /* Ready to go! */
}
static SDL_bool
static int
WINMM_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
@@ -447,11 +449,11 @@ WINMM_Init(SDL_AudioDriverImpl * impl)
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
return 1; /* this audio target is available. */
}
AudioBootStrap WINMM_bootstrap = {
"winmm", "Windows Waveform Audio", WINMM_Init, SDL_FALSE
"winmm", "Windows Waveform Audio", WINMM_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_WINMM */