mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-13 07:34:45 +00:00
Revert "Updated SDL, Bullet and OpenAL soft libs"
This reverts commit 370161cfb1.
This commit is contained in:
parent
63be684474
commit
bc77ff0833
1102 changed files with 62741 additions and 204988 deletions
|
|
@ -378,57 +378,21 @@ static int
|
|||
add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
|
||||
{
|
||||
int retval = -1;
|
||||
SDL_AudioDeviceItem *item;
|
||||
const SDL_AudioDeviceItem *i;
|
||||
int dupenum = 0;
|
||||
const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
|
||||
SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
|
||||
if (item == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
|
||||
SDL_assert(name != NULL);
|
||||
|
||||
item = (SDL_AudioDeviceItem *) SDL_malloc(sizeof (SDL_AudioDeviceItem));
|
||||
if (!item) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
item->original_name = SDL_strdup(name);
|
||||
if (!item->original_name) {
|
||||
SDL_free(item);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
item->dupenum = 0;
|
||||
item->name = item->original_name;
|
||||
item->handle = handle;
|
||||
SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
|
||||
|
||||
SDL_LockMutex(current_audio.detectionLock);
|
||||
|
||||
for (i = *devices; i != NULL; i = i->next) {
|
||||
if (SDL_strcmp(name, i->original_name) == 0) {
|
||||
dupenum = i->dupenum + 1;
|
||||
break; /* stop at the highest-numbered dupe. */
|
||||
}
|
||||
}
|
||||
|
||||
if (dupenum) {
|
||||
const size_t len = SDL_strlen(name) + 16;
|
||||
char *replacement = (char *) SDL_malloc(len);
|
||||
if (!replacement) {
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
SDL_free(item->original_name);
|
||||
SDL_free(item);
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_snprintf(replacement, len, "%s (%d)", name, dupenum + 1);
|
||||
item->dupenum = dupenum;
|
||||
item->name = replacement;
|
||||
}
|
||||
|
||||
item->next = *devices;
|
||||
*devices = item;
|
||||
retval = (*devCount)++; /* !!! FIXME: this should be an atomic increment */
|
||||
|
||||
retval = (*devCount)++;
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
|
||||
return retval;
|
||||
|
|
@ -456,11 +420,6 @@ free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
|
|||
if (item->handle != NULL) {
|
||||
current_audio.impl.FreeDeviceHandle(item->handle);
|
||||
}
|
||||
/* these two pointers are the same if not a duplicate devname */
|
||||
if (item->name != item->original_name) {
|
||||
SDL_free(item->name);
|
||||
}
|
||||
SDL_free(item->original_name);
|
||||
SDL_free(item);
|
||||
}
|
||||
*devices = NULL;
|
||||
|
|
@ -492,11 +451,7 @@ void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
|
|||
SDL_assert(get_audio_device(device->id) == device);
|
||||
|
||||
if (!SDL_AtomicGet(&device->enabled)) {
|
||||
return; /* don't report disconnects more than once. */
|
||||
}
|
||||
|
||||
if (SDL_AtomicGet(&device->shutdown)) {
|
||||
return; /* don't report disconnect if we're trying to close device. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ends the audio callback and mark the device as STOPPED, but the
|
||||
|
|
@ -696,7 +651,7 @@ SDL_RunAudio(void *devicep)
|
|||
SDL_assert(!device->iscapture);
|
||||
|
||||
/* The audio mixing is always a high priority thread */
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_TIME_CRITICAL);
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
|
||||
|
||||
/* Perform any thread setup */
|
||||
device->threadid = SDL_ThreadID();
|
||||
|
|
@ -877,8 +832,6 @@ SDL_CaptureAudio(void *devicep)
|
|||
}
|
||||
}
|
||||
|
||||
current_audio.impl.PrepareToClose(device);
|
||||
|
||||
current_audio.impl.FlushCapture(device);
|
||||
|
||||
current_audio.impl.ThreadDeinit(device);
|
||||
|
|
@ -1018,11 +971,6 @@ clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *re
|
|||
} else {
|
||||
*devices = next;
|
||||
}
|
||||
/* these two pointers are the same if not a duplicate devname */
|
||||
if (item->name != item->original_name) {
|
||||
SDL_free(item->name);
|
||||
}
|
||||
SDL_free(item->original_name);
|
||||
SDL_free(item);
|
||||
}
|
||||
item = next;
|
||||
|
|
@ -1049,6 +997,7 @@ SDL_GetNumAudioDevices(int iscapture)
|
|||
|
||||
if (!iscapture && current_audio.outputDevicesRemoved) {
|
||||
clean_out_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount, ¤t_audio.outputDevicesRemoved);
|
||||
current_audio.outputDevicesRemoved = SDL_FALSE;
|
||||
}
|
||||
|
||||
retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
|
||||
|
|
@ -1105,14 +1054,16 @@ close_audio_device(SDL_AudioDevice * device)
|
|||
return;
|
||||
}
|
||||
|
||||
/* make sure the device is paused before we do anything else, so the
|
||||
audio callback definitely won't fire again. */
|
||||
current_audio.impl.LockDevice(device);
|
||||
SDL_AtomicSet(&device->paused, 1);
|
||||
if (device->id > 0) {
|
||||
SDL_AudioDevice *opendev = open_devices[device->id - 1];
|
||||
SDL_assert((opendev == device) || (opendev == NULL));
|
||||
if (opendev == device) {
|
||||
open_devices[device->id - 1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_AtomicSet(&device->shutdown, 1);
|
||||
SDL_AtomicSet(&device->enabled, 0);
|
||||
current_audio.impl.UnlockDevice(device);
|
||||
|
||||
if (device->thread != NULL) {
|
||||
SDL_WaitThread(device->thread, NULL);
|
||||
}
|
||||
|
|
@ -1123,14 +1074,6 @@ close_audio_device(SDL_AudioDevice * device)
|
|||
SDL_free(device->work_buffer);
|
||||
SDL_FreeAudioStream(device->stream);
|
||||
|
||||
if (device->id > 0) {
|
||||
SDL_AudioDevice *opendev = open_devices[device->id - 1];
|
||||
SDL_assert((opendev == device) || (opendev == NULL));
|
||||
if (opendev == device) {
|
||||
open_devices[device->id - 1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (device->hidden != NULL) {
|
||||
current_audio.impl.CloseDevice(device);
|
||||
}
|
||||
|
|
@ -1175,9 +1118,8 @@ prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
|
|||
}
|
||||
case 1: /* Mono */
|
||||
case 2: /* Stereo */
|
||||
case 4: /* Quadrophonic */
|
||||
case 6: /* 5.1 surround */
|
||||
case 8: /* 7.1 surround */
|
||||
case 4: /* surround */
|
||||
case 6: /* surround with center and lfe */
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Unsupported number of audio channels.");
|
||||
|
|
@ -1370,12 +1312,15 @@ open_audio_device(const char *devname, int iscapture,
|
|||
build_stream = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* !!! FIXME in 2.1: add SDL_AUDIO_ALLOW_SAMPLES_CHANGE flag?
|
||||
As of 2.0.6, we will build a stream to buffer the difference between
|
||||
what the app wants to feed and the device wants to eat, so everyone
|
||||
gets their way. In prior releases, SDL would force the callback to
|
||||
feed at the rate the device requested, adjusted for resampling.
|
||||
*/
|
||||
if (device->spec.samples != obtained->samples) {
|
||||
if (allowed_changes & SDL_AUDIO_ALLOW_SAMPLES_CHANGE) {
|
||||
obtained->samples = device->spec.samples;
|
||||
} else {
|
||||
build_stream = SDL_TRUE;
|
||||
}
|
||||
build_stream = SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(obtained); /* recalc after possible changes. */
|
||||
|
|
|
|||
|
|
@ -724,7 +724,7 @@ SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format
|
|||
SDL_assert(format == AUDIO_F32SYS);
|
||||
|
||||
/* we keep no streaming state here, so pad with silence on both ends. */
|
||||
padding = (float *) SDL_calloc(paddingsamples ? paddingsamples : 1, sizeof (float));
|
||||
padding = (float *) SDL_calloc(paddingsamples, sizeof (float));
|
||||
if (!padding) {
|
||||
SDL_OutOfMemory();
|
||||
return;
|
||||
|
|
@ -1291,7 +1291,7 @@ SDL_NewAudioStream(const SDL_AudioFormat src_format,
|
|||
retval->packetlen = packetlen;
|
||||
retval->rate_incr = ((double) dst_rate) / ((double) src_rate);
|
||||
retval->resampler_padding_samples = ResamplerPadding(retval->src_rate, retval->dst_rate) * pre_resample_channels;
|
||||
retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples ? retval->resampler_padding_samples : 1, sizeof (float));
|
||||
retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples, sizeof (float));
|
||||
|
||||
if (retval->resampler_padding == NULL) {
|
||||
SDL_FreeAudioStream(retval);
|
||||
|
|
|
|||
|
|
@ -18,10 +18,6 @@
|
|||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_audiodev_c_h_
|
||||
#define SDL_audiodev_c_h_
|
||||
|
||||
#include "SDL.h"
|
||||
#include "../SDL_internal.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
|
@ -39,6 +35,4 @@
|
|||
|
||||
extern void SDL_EnumUnixAudioDevices(const int classic, int (*test)(int));
|
||||
|
||||
#endif /* SDL_audiodev_c_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -25,10 +25,8 @@
|
|||
#include "SDL_cpuinfo.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
/* !!! FIXME: disabled until we fix https://bugzilla.libsdl.org/show_bug.cgi?id=4186 */
|
||||
#if 0 /*def __ARM_NEON__*/
|
||||
#define HAVE_NEON_INTRINSICS 1
|
||||
#endif
|
||||
/* !!! FIXME: write NEON code. */
|
||||
#define HAVE_NEON_INTRINSICS 0
|
||||
|
||||
#ifdef __SSE2__
|
||||
#define HAVE_SSE2_INTRINSICS 1
|
||||
|
|
@ -64,7 +62,7 @@ SDL_AudioFilter SDL_Convert_F32_to_S32 = NULL;
|
|||
|
||||
#define DIVBY128 0.0078125f
|
||||
#define DIVBY32768 0.000030517578125f
|
||||
#define DIVBY8388607 0.00000011920930376163766f
|
||||
#define DIVBY2147483648 0.00000000046566128730773926
|
||||
|
||||
|
||||
#if NEED_SCALAR_CONVERTER_FALLBACKS
|
||||
|
|
@ -154,7 +152,7 @@ SDL_Convert_S32_to_F32_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
LOG_DEBUG_CONVERT("AUDIO_S32", "AUDIO_F32");
|
||||
|
||||
for (i = cvt->len_cvt / sizeof (Sint32); i; --i, ++src, ++dst) {
|
||||
*dst = ((float) (*src>>8)) * DIVBY8388607;
|
||||
*dst = (float) (((double) *src) * DIVBY2147483648);
|
||||
}
|
||||
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
|
|
@ -173,10 +171,10 @@ SDL_Convert_F32_to_S8_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
if (sample > 1.0f) {
|
||||
*dst = 127;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -128;
|
||||
} else if (sample < -1.0f) {
|
||||
*dst = -127;
|
||||
} else {
|
||||
*dst = (Sint8)(sample * 127.0f);
|
||||
}
|
||||
|
|
@ -199,9 +197,9 @@ SDL_Convert_F32_to_U8_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
if (sample > 1.0f) {
|
||||
*dst = 255;
|
||||
} else if (sample <= -1.0f) {
|
||||
} else if (sample < -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint8)((sample + 1.0f) * 127.0f);
|
||||
|
|
@ -225,10 +223,10 @@ SDL_Convert_F32_to_S16_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
if (sample > 1.0f) {
|
||||
*dst = 32767;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -32768;
|
||||
} else if (sample < -1.0f) {
|
||||
*dst = -32767;
|
||||
} else {
|
||||
*dst = (Sint16)(sample * 32767.0f);
|
||||
}
|
||||
|
|
@ -251,9 +249,9 @@ SDL_Convert_F32_to_U16_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 65535;
|
||||
} else if (sample <= -1.0f) {
|
||||
if (sample > 1.0f) {
|
||||
*dst = 65534;
|
||||
} else if (sample < -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint16)((sample + 1.0f) * 32767.0f);
|
||||
|
|
@ -277,12 +275,12 @@ SDL_Convert_F32_to_S32_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
if (sample > 1.0f) {
|
||||
*dst = 2147483647;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = (Sint32) -2147483648LL;
|
||||
} else if (sample < -1.0f) {
|
||||
*dst = -2147483647;
|
||||
} else {
|
||||
*dst = ((Sint32)(sample * 8388607.0f)) << 8;
|
||||
*dst = (Sint32)((double)sample * 2147483647.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -511,6 +509,16 @@ SDL_Convert_U16_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ < 4)
|
||||
/* these were added as of gcc-4.0: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19418 */
|
||||
static inline __m128 _mm_castsi128_ps(__m128i __A) {
|
||||
return (__m128) __A;
|
||||
}
|
||||
static inline __m128i _mm_castps_si128(__m128 __A) {
|
||||
return (__m128i) __A;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_S32_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
|
|
@ -522,7 +530,7 @@ SDL_Convert_S32_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (Sint32); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
*dst = ((float) (*src>>8)) * DIVBY8388607;
|
||||
*dst = (float) (((double) *src) * DIVBY2147483648);
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -530,11 +538,15 @@ SDL_Convert_S32_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
{
|
||||
/* Aligned! Do SSE blocks as long as we have 16 bytes available. */
|
||||
const __m128 divby8388607 = _mm_set1_ps(DIVBY8388607);
|
||||
const __m128d divby2147483648 = _mm_set1_pd(DIVBY2147483648);
|
||||
const __m128i *mmsrc = (const __m128i *) src;
|
||||
while (i >= 4) { /* 4 * sint32 */
|
||||
/* shift out lowest bits so int fits in a float32. Small precision loss, but much faster. */
|
||||
_mm_store_ps(dst, _mm_mul_ps(_mm_cvtepi32_ps(_mm_srai_epi32(_mm_load_si128(mmsrc), 8)), divby8388607));
|
||||
const __m128i ints = _mm_load_si128(mmsrc);
|
||||
/* bitshift the whole register over, so _mm_cvtepi32_pd can read the top ints in the bottom of the vector. */
|
||||
const __m128d doubles1 = _mm_mul_pd(_mm_cvtepi32_pd(_mm_srli_si128(ints, 8)), divby2147483648);
|
||||
const __m128d doubles2 = _mm_mul_pd(_mm_cvtepi32_pd(ints), divby2147483648);
|
||||
/* convert to float32, bitshift/or to get these into a vector to store. */
|
||||
_mm_store_ps(dst, _mm_castsi128_ps(_mm_or_si128(_mm_slli_si128(_mm_castps_si128(_mm_cvtpd_ps(doubles1)), 8), _mm_castps_si128(_mm_cvtpd_ps(doubles2)))));
|
||||
i -= 4; mmsrc++; dst += 4;
|
||||
}
|
||||
src = (const Sint32 *) mmsrc;
|
||||
|
|
@ -542,7 +554,7 @@ SDL_Convert_S32_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = ((float) (*src>>8)) * DIVBY8388607;
|
||||
*dst = (float) (((double) *src) * DIVBY2147483648);
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -562,14 +574,7 @@ SDL_Convert_F32_to_S8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 127;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -128;
|
||||
} else {
|
||||
*dst = (Sint8)(sample * 127.0f);
|
||||
}
|
||||
*dst = (Sint8) (*src * 127.0f);
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -577,15 +582,13 @@ SDL_Convert_F32_to_S8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do SSE blocks as long as we have 16 bytes available. */
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 negone = _mm_set1_ps(-1.0f);
|
||||
const __m128 mulby127 = _mm_set1_ps(127.0f);
|
||||
__m128i *mmdst = (__m128i *) dst;
|
||||
while (i >= 16) { /* 16 * float32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+4)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+8)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+12)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src+4), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src+8), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src+12), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
_mm_store_si128(mmdst, _mm_packs_epi16(_mm_packs_epi32(ints1, ints2), _mm_packs_epi32(ints3, ints4))); /* pack down, store out. */
|
||||
i -= 16; src += 16; mmdst++;
|
||||
}
|
||||
|
|
@ -594,14 +597,7 @@ SDL_Convert_F32_to_S8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 127;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -128;
|
||||
} else {
|
||||
*dst = (Sint8)(sample * 127.0f);
|
||||
}
|
||||
*dst = (Sint8) (*src * 127.0f);
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -622,14 +618,7 @@ SDL_Convert_F32_to_U8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 255;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint8)((sample + 1.0f) * 127.0f);
|
||||
}
|
||||
*dst = (Uint8) ((*src + 1.0f) * 127.0f);
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -637,15 +626,14 @@ SDL_Convert_F32_to_U8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do SSE blocks as long as we have 16 bytes available. */
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 negone = _mm_set1_ps(-1.0f);
|
||||
const __m128 add1 = _mm_set1_ps(1.0f);
|
||||
const __m128 mulby127 = _mm_set1_ps(127.0f);
|
||||
__m128i *mmdst = (__m128i *) dst;
|
||||
while (i >= 16) { /* 16 * float32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+4)), one), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+8)), one), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+12)), one), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_load_ps(src), add1), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_load_ps(src+4), add1), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_load_ps(src+8), add1), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_load_ps(src+12), add1), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
_mm_store_si128(mmdst, _mm_packus_epi16(_mm_packs_epi32(ints1, ints2), _mm_packs_epi32(ints3, ints4))); /* pack down, store out. */
|
||||
i -= 16; src += 16; mmdst++;
|
||||
}
|
||||
|
|
@ -654,14 +642,7 @@ SDL_Convert_F32_to_U8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 255;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint8)((sample + 1.0f) * 127.0f);
|
||||
}
|
||||
*dst = (Uint8) ((*src + 1.0f) * 127.0f);
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -682,14 +663,7 @@ SDL_Convert_F32_to_S16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 32767;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -32768;
|
||||
} else {
|
||||
*dst = (Sint16)(sample * 32767.0f);
|
||||
}
|
||||
*dst = (Sint16) (*src * 32767.0f);
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -697,13 +671,11 @@ SDL_Convert_F32_to_S16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do SSE blocks as long as we have 16 bytes available. */
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 negone = _mm_set1_ps(-1.0f);
|
||||
const __m128 mulby32767 = _mm_set1_ps(32767.0f);
|
||||
__m128i *mmdst = (__m128i *) dst;
|
||||
while (i >= 8) { /* 8 * float32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+4)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src), mulby32767)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src+4), mulby32767)); /* load 4 floats, convert to sint32 */
|
||||
_mm_store_si128(mmdst, _mm_packs_epi32(ints1, ints2)); /* pack to sint16, store out. */
|
||||
i -= 8; src += 8; mmdst++;
|
||||
}
|
||||
|
|
@ -712,14 +684,7 @@ SDL_Convert_F32_to_S16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 32767;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -32768;
|
||||
} else {
|
||||
*dst = (Sint16)(sample * 32767.0f);
|
||||
}
|
||||
*dst = (Sint16) (*src * 32767.0f);
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -740,14 +705,7 @@ SDL_Convert_F32_to_U16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 65535;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint16)((sample + 1.0f) * 32767.0f);
|
||||
}
|
||||
*dst = (Uint16) ((*src + 1.0f) * 32767.0f);
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -764,12 +722,10 @@ SDL_Convert_F32_to_U16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
though it looks like dark magic. */
|
||||
const __m128 mulby32767 = _mm_set1_ps(32767.0f);
|
||||
const __m128i topbit = _mm_set1_epi16(-32768);
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 negone = _mm_set1_ps(-1.0f);
|
||||
__m128i *mmdst = (__m128i *) dst;
|
||||
while (i >= 8) { /* 8 * float32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+4)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src), mulby32767)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src+4), mulby32767)); /* load 4 floats, convert to sint32 */
|
||||
_mm_store_si128(mmdst, _mm_xor_si128(_mm_packs_epi32(ints1, ints2), topbit)); /* pack to sint16, xor top bit, store out. */
|
||||
i -= 8; src += 8; mmdst++;
|
||||
}
|
||||
|
|
@ -778,14 +734,7 @@ SDL_Convert_F32_to_U16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 65535;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint16)((sample + 1.0f) * 32767.0f);
|
||||
}
|
||||
*dst = (Uint16) ((*src + 1.0f) * 32767.0f);
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -806,14 +755,7 @@ SDL_Convert_F32_to_S32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 2147483647;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = (Sint32) -2147483648LL;
|
||||
} else {
|
||||
*dst = ((Sint32)(sample * 8388607.0f)) << 8;
|
||||
}
|
||||
*dst = (Sint32) (((double) *src) * 2147483647.0);
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -821,12 +763,14 @@ SDL_Convert_F32_to_S32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
{
|
||||
/* Aligned! Do SSE blocks as long as we have 16 bytes available. */
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 negone = _mm_set1_ps(-1.0f);
|
||||
const __m128 mulby8388607 = _mm_set1_ps(8388607.0f);
|
||||
const __m128d mulby2147483647 = _mm_set1_pd(2147483647.0);
|
||||
__m128i *mmdst = (__m128i *) dst;
|
||||
while (i >= 4) { /* 4 * float32 */
|
||||
_mm_store_si128(mmdst, _mm_slli_epi32(_mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), mulby8388607)), 8)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128 floats = _mm_load_ps(src);
|
||||
/* bitshift the whole register over, so _mm_cvtps_pd can read the top floats in the bottom of the vector. */
|
||||
const __m128d doubles1 = _mm_mul_pd(_mm_cvtps_pd(_mm_castsi128_ps(_mm_srli_si128(_mm_castps_si128(floats), 8))), mulby2147483647);
|
||||
const __m128d doubles2 = _mm_mul_pd(_mm_cvtps_pd(floats), mulby2147483647);
|
||||
_mm_store_si128(mmdst, _mm_or_si128(_mm_slli_si128(_mm_cvtpd_epi32(doubles1), 8), _mm_cvtpd_epi32(doubles2)));
|
||||
i -= 4; src += 4; mmdst++;
|
||||
}
|
||||
dst = (Sint32 *) mmdst;
|
||||
|
|
@ -834,14 +778,7 @@ SDL_Convert_F32_to_S32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 2147483647;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = (Sint32) -2147483648LL;
|
||||
} else {
|
||||
*dst = ((Sint32)(sample * 8388607.0f)) << 8;
|
||||
}
|
||||
*dst = (Sint32) (((double) *src) * 2147483647.0);
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -852,538 +789,6 @@ SDL_Convert_F32_to_S32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
#endif
|
||||
|
||||
|
||||
#if HAVE_NEON_INTRINSICS
|
||||
static void SDLCALL
|
||||
SDL_Convert_S8_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const Sint8 *src = ((const Sint8 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
float *dst = ((float *) (cvt->buf + cvt->len_cvt * 4)) - 1;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_S8", "AUDIO_F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
for (i = cvt->len_cvt; i && (((size_t) (dst-15)) & 15); --i, --src, --dst) {
|
||||
*dst = ((float) *src) * DIVBY128;
|
||||
}
|
||||
|
||||
src -= 15; dst -= 15; /* adjust to read NEON blocks from the start. */
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const int8_t *mmsrc = (const int8_t *) src;
|
||||
const float32x4_t divby128 = vdupq_n_f32(DIVBY128);
|
||||
while (i >= 16) { /* 16 * 8-bit */
|
||||
const int8x16_t bytes = vld1q_s8(mmsrc); /* get 16 sint8 into a NEON register. */
|
||||
const int16x8_t int16hi = vmovl_s8(vget_high_s8(bytes)); /* convert top 8 bytes to 8 int16 */
|
||||
const int16x8_t int16lo = vmovl_s8(vget_low_s8(bytes)); /* convert bottom 8 bytes to 8 int16 */
|
||||
/* split int16 to two int32, then convert to float, then multiply to normalize, store. */
|
||||
vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16hi))), divby128));
|
||||
vst1q_f32(dst+4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16hi))), divby128));
|
||||
vst1q_f32(dst+8, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16lo))), divby128));
|
||||
vst1q_f32(dst+12, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16lo))), divby128));
|
||||
i -= 16; mmsrc -= 16; dst -= 16;
|
||||
}
|
||||
|
||||
src = (const Sint8 *) mmsrc;
|
||||
}
|
||||
|
||||
src += 15; dst += 15; /* adjust for any scalar finishing. */
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = ((float) *src) * DIVBY128;
|
||||
i--; src--; dst--;
|
||||
}
|
||||
|
||||
cvt->len_cvt *= 4;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_U8_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const Uint8 *src = ((const Uint8 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
float *dst = ((float *) (cvt->buf + cvt->len_cvt * 4)) - 1;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_U8", "AUDIO_F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
for (i = cvt->len_cvt; i && (((size_t) (dst-15)) & 15); --i, --src, --dst) {
|
||||
*dst = (((float) *src) * DIVBY128) - 1.0f;
|
||||
}
|
||||
|
||||
src -= 15; dst -= 15; /* adjust to read NEON blocks from the start. */
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const uint8_t *mmsrc = (const uint8_t *) src;
|
||||
const float32x4_t divby128 = vdupq_n_f32(DIVBY128);
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
while (i >= 16) { /* 16 * 8-bit */
|
||||
const uint8x16_t bytes = vld1q_u8(mmsrc); /* get 16 uint8 into a NEON register. */
|
||||
const uint16x8_t uint16hi = vmovl_u8(vget_high_u8(bytes)); /* convert top 8 bytes to 8 uint16 */
|
||||
const uint16x8_t uint16lo = vmovl_u8(vget_low_u8(bytes)); /* convert bottom 8 bytes to 8 uint16 */
|
||||
/* split uint16 to two uint32, then convert to float, then multiply to normalize, subtract to adjust for sign, store. */
|
||||
vst1q_f32(dst, vmlsq_f32(vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16hi))), divby128, one));
|
||||
vst1q_f32(dst+4, vmlsq_f32(vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16hi))), divby128, one));
|
||||
vst1q_f32(dst+8, vmlsq_f32(vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16lo))), divby128, one));
|
||||
vst1q_f32(dst+12, vmlsq_f32(vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16lo))), divby128, one));
|
||||
i -= 16; mmsrc -= 16; dst -= 16;
|
||||
}
|
||||
|
||||
src = (const Uint8 *) mmsrc;
|
||||
}
|
||||
|
||||
src += 15; dst += 15; /* adjust for any scalar finishing. */
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = (((float) *src) * DIVBY128) - 1.0f;
|
||||
i--; src--; dst--;
|
||||
}
|
||||
|
||||
cvt->len_cvt *= 4;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_S16_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const Sint16 *src = ((const Sint16 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
float *dst = ((float *) (cvt->buf + cvt->len_cvt * 2)) - 1;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_S16", "AUDIO_F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
for (i = cvt->len_cvt / sizeof (Sint16); i && (((size_t) (dst-7)) & 15); --i, --src, --dst) {
|
||||
*dst = ((float) *src) * DIVBY32768;
|
||||
}
|
||||
|
||||
src -= 7; dst -= 7; /* adjust to read NEON blocks from the start. */
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t divby32768 = vdupq_n_f32(DIVBY32768);
|
||||
while (i >= 8) { /* 8 * 16-bit */
|
||||
const int16x8_t ints = vld1q_s16((int16_t const *) src); /* get 8 sint16 into a NEON register. */
|
||||
/* split int16 to two int32, then convert to float, then multiply to normalize, store. */
|
||||
vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(ints))), divby32768));
|
||||
vst1q_f32(dst+4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(ints))), divby32768));
|
||||
i -= 8; src -= 8; dst -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
src += 7; dst += 7; /* adjust for any scalar finishing. */
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = ((float) *src) * DIVBY32768;
|
||||
i--; src--; dst--;
|
||||
}
|
||||
|
||||
cvt->len_cvt *= 2;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_U16_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const Uint16 *src = ((const Uint16 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
float *dst = ((float *) (cvt->buf + cvt->len_cvt * 2)) - 1;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_U16", "AUDIO_F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
for (i = cvt->len_cvt / sizeof (Sint16); i && (((size_t) (dst-7)) & 15); --i, --src, --dst) {
|
||||
*dst = (((float) *src) * DIVBY32768) - 1.0f;
|
||||
}
|
||||
|
||||
src -= 7; dst -= 7; /* adjust to read NEON blocks from the start. */
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t divby32768 = vdupq_n_f32(DIVBY32768);
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
while (i >= 8) { /* 8 * 16-bit */
|
||||
const uint16x8_t uints = vld1q_u16((uint16_t const *) src); /* get 8 uint16 into a NEON register. */
|
||||
/* split uint16 to two int32, then convert to float, then multiply to normalize, subtract for sign, store. */
|
||||
vst1q_f32(dst, vmlsq_f32(one, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uints))), divby32768));
|
||||
vst1q_f32(dst+4, vmlsq_f32(one, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uints))), divby32768));
|
||||
i -= 8; src -= 8; dst -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
src += 7; dst += 7; /* adjust for any scalar finishing. */
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = (((float) *src) * DIVBY32768) - 1.0f;
|
||||
i--; src--; dst--;
|
||||
}
|
||||
|
||||
cvt->len_cvt *= 2;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_S32_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const Sint32 *src = (const Sint32 *) cvt->buf;
|
||||
float *dst = (float *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_S32", "AUDIO_F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (Sint32); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
*dst = ((float) (*src>>8)) * DIVBY8388607;
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
SDL_assert(!i || ((((size_t) src) & 15) == 0));
|
||||
|
||||
{
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t divby8388607 = vdupq_n_f32(DIVBY8388607);
|
||||
const int32_t *mmsrc = (const int32_t *) src;
|
||||
while (i >= 4) { /* 4 * sint32 */
|
||||
/* shift out lowest bits so int fits in a float32. Small precision loss, but much faster. */
|
||||
vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vshrq_n_s32(vld1q_s32(mmsrc), 8)), divby8388607));
|
||||
i -= 4; mmsrc += 4; dst += 4;
|
||||
}
|
||||
src = (const Sint32 *) mmsrc;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = ((float) (*src>>8)) * DIVBY8388607;
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_F32_to_S8_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const float *src = (const float *) cvt->buf;
|
||||
Sint8 *dst = (Sint8 *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_S8 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 127;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -128;
|
||||
} else {
|
||||
*dst = (Sint8)(sample * 127.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby127 = vdupq_n_f32(127.0f);
|
||||
int8_t *mmdst = (int8_t *) dst;
|
||||
while (i >= 16) { /* 16 * float32 */
|
||||
const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+4)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints3 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+8)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints4 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+12)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int8x8_t i8lo = vmovn_s16(vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); /* narrow to sint16, combine, narrow to sint8 */
|
||||
const int8x8_t i8hi = vmovn_s16(vcombine_s16(vmovn_s32(ints3), vmovn_s32(ints4))); /* narrow to sint16, combine, narrow to sint8 */
|
||||
vst1q_s8(mmdst, vcombine_s8(i8lo, i8hi)); /* combine to int8x16_t, store out */
|
||||
i -= 16; src += 16; mmdst += 16;
|
||||
}
|
||||
dst = (Sint8 *) mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 127;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -128;
|
||||
} else {
|
||||
*dst = (Sint8)(sample * 127.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
cvt->len_cvt /= 4;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_S8);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_F32_to_U8_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const float *src = (const float *) cvt->buf;
|
||||
Uint8 *dst = (Uint8 *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_U8 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 255;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint8)((sample + 1.0f) * 127.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby127 = vdupq_n_f32(127.0f);
|
||||
uint8_t *mmdst = (uint8_t *) dst;
|
||||
while (i >= 16) { /* 16 * float32 */
|
||||
const uint32x4_t uints1 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints2 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+4)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints3 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+8)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints4 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+12)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint8x8_t ui8lo = vmovn_u16(vcombine_u16(vmovn_u32(uints1), vmovn_u32(uints2))); /* narrow to uint16, combine, narrow to uint8 */
|
||||
const uint8x8_t ui8hi = vmovn_u16(vcombine_u16(vmovn_u32(uints3), vmovn_u32(uints4))); /* narrow to uint16, combine, narrow to uint8 */
|
||||
vst1q_u8(mmdst, vcombine_u8(ui8lo, ui8hi)); /* combine to uint8x16_t, store out */
|
||||
i -= 16; src += 16; mmdst += 16;
|
||||
}
|
||||
|
||||
dst = (Uint8 *) mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 255;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint8)((sample + 1.0f) * 127.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
cvt->len_cvt /= 4;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_U8);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_F32_to_S16_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const float *src = (const float *) cvt->buf;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_S16 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 32767;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -32768;
|
||||
} else {
|
||||
*dst = (Sint16)(sample * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby32767 = vdupq_n_f32(32767.0f);
|
||||
int16_t *mmdst = (int16_t *) dst;
|
||||
while (i >= 8) { /* 8 * float32 */
|
||||
const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+4)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
vst1q_s16(mmdst, vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); /* narrow to sint16, combine, store out. */
|
||||
i -= 8; src += 8; mmdst += 8;
|
||||
}
|
||||
dst = (Sint16 *) mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 32767;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -32768;
|
||||
} else {
|
||||
*dst = (Sint16)(sample * 32767.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
cvt->len_cvt /= 2;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_S16SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_F32_to_U16_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const float *src = (const float *) cvt->buf;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_U16 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 65535;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint16)((sample + 1.0f) * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby32767 = vdupq_n_f32(32767.0f);
|
||||
uint16_t *mmdst = (uint16_t *) dst;
|
||||
while (i >= 8) { /* 8 * float32 */
|
||||
const uint32x4_t uints1 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), one), mulby32767)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints2 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+4)), one), one), mulby32767)); /* load 4 floats, clamp, convert to uint32 */
|
||||
vst1q_u16(mmdst, vcombine_u16(vmovn_u32(uints1), vmovn_u32(uints2))); /* narrow to uint16, combine, store out. */
|
||||
i -= 8; src += 8; mmdst += 8;
|
||||
}
|
||||
dst = (Uint16 *) mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 65535;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint16)((sample + 1.0f) * 32767.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
cvt->len_cvt /= 2;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_U16SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_F32_to_S32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const float *src = (const float *) cvt->buf;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_S32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 2147483647;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -2147483648;
|
||||
} else {
|
||||
*dst = ((Sint32)(sample * 8388607.0f)) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
SDL_assert(!i || ((((size_t) src) & 15) == 0));
|
||||
|
||||
{
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby8388607 = vdupq_n_f32(8388607.0f);
|
||||
int32_t *mmdst = (int32_t *) dst;
|
||||
while (i >= 4) { /* 4 * float32 */
|
||||
vst1q_s32(mmdst, vshlq_n_s32(vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby8388607)), 8));
|
||||
i -= 4; src += 4; mmdst += 4;
|
||||
}
|
||||
dst = (Sint32 *) mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 2147483647;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -2147483648;
|
||||
} else {
|
||||
*dst = ((Sint32)(sample * 8388607.0f)) << 8;
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_S32SYS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void SDL_ChooseAudioConverters(void)
|
||||
{
|
||||
static SDL_bool converters_chosen = SDL_FALSE;
|
||||
|
|
@ -1412,13 +817,6 @@ void SDL_ChooseAudioConverters(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_NEON_INTRINSICS
|
||||
if (SDL_HasNEON()) {
|
||||
SET_CONVERTER_FUNCS(NEON);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NEED_SCALAR_CONVERTER_FALLBACKS
|
||||
SET_CONVERTER_FUNCS(Scalar);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -98,10 +98,8 @@ typedef struct SDL_AudioDriverImpl
|
|||
typedef struct SDL_AudioDeviceItem
|
||||
{
|
||||
void *handle;
|
||||
char *name;
|
||||
char *original_name;
|
||||
int dupenum;
|
||||
struct SDL_AudioDeviceItem *next;
|
||||
char name[SDL_VARIABLE_LENGTH_ARRAY];
|
||||
} SDL_AudioDeviceItem;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -22,10 +22,6 @@
|
|||
|
||||
#if SDL_AUDIO_DRIVER_ALSA
|
||||
|
||||
#ifndef SDL_ALSA_NON_BLOCKING
|
||||
#define SDL_ALSA_NON_BLOCKING 0
|
||||
#endif
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
|
@ -94,7 +90,6 @@ static int (*ALSA_snd_pcm_reset)(snd_pcm_t *);
|
|||
static int (*ALSA_snd_device_name_hint) (int, const char *, void ***);
|
||||
static char* (*ALSA_snd_device_name_get_hint) (const void *, const char *);
|
||||
static int (*ALSA_snd_device_name_free_hint) (void **);
|
||||
static snd_pcm_sframes_t (*ALSA_snd_pcm_avail)(snd_pcm_t *);
|
||||
#ifdef SND_CHMAP_API_VERSION
|
||||
static snd_pcm_chmap_t* (*ALSA_snd_pcm_get_chmap) (snd_pcm_t *);
|
||||
static int (*ALSA_snd_pcm_chmap_print) (const snd_pcm_chmap_t *map, size_t maxlen, char *buf);
|
||||
|
|
@ -163,7 +158,6 @@ load_alsa_syms(void)
|
|||
SDL_ALSA_SYM(snd_device_name_hint);
|
||||
SDL_ALSA_SYM(snd_device_name_get_hint);
|
||||
SDL_ALSA_SYM(snd_device_name_free_hint);
|
||||
SDL_ALSA_SYM(snd_pcm_avail);
|
||||
#ifdef SND_CHMAP_API_VERSION
|
||||
SDL_ALSA_SYM(snd_pcm_get_chmap);
|
||||
SDL_ALSA_SYM(snd_pcm_chmap_print);
|
||||
|
|
@ -249,24 +243,7 @@ get_audio_device(void *handle, const int channels)
|
|||
static void
|
||||
ALSA_WaitDevice(_THIS)
|
||||
{
|
||||
#if SDL_ALSA_NON_BLOCKING
|
||||
const snd_pcm_sframes_t needed = (snd_pcm_sframes_t) this->spec.samples;
|
||||
while (SDL_AtomicGet(&this->enabled)) {
|
||||
const snd_pcm_sframes_t rc = ALSA_snd_pcm_avail(this->hidden->pcm_handle);
|
||||
if ((rc < 0) && (rc != -EAGAIN)) {
|
||||
/* Hmm, not much we can do - abort */
|
||||
fprintf(stderr, "ALSA snd_pcm_avail failed (unrecoverable): %s\n",
|
||||
ALSA_snd_strerror(rc));
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
return;
|
||||
} else if (rc < needed) {
|
||||
const Uint32 delay = ((needed - (SDL_max(rc, 0))) * 1000) / this->spec.freq;
|
||||
SDL_Delay(SDL_max(delay, 10));
|
||||
} else {
|
||||
break; /* ready to go! */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* We're in blocking mode, so there's nothing to do here */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -445,7 +422,7 @@ static void
|
|||
ALSA_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden->pcm_handle) {
|
||||
/* Wait for the submitted audio to drain
|
||||
/* Wait for the submitted audio to drain
|
||||
ALSA_snd_pcm_drop() can hang, so don't use that.
|
||||
*/
|
||||
Uint32 delay = ((this->spec.samples * 1000) / this->spec.freq) * 2;
|
||||
|
|
@ -458,32 +435,10 @@ ALSA_CloseDevice(_THIS)
|
|||
}
|
||||
|
||||
static int
|
||||
ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params)
|
||||
ALSA_finalize_hardware(_THIS, snd_pcm_hw_params_t *hwparams, int override)
|
||||
{
|
||||
int status;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_uframes_t bufsize;
|
||||
snd_pcm_uframes_t persize;
|
||||
|
||||
/* Copy the hardware parameters for this setup */
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
ALSA_snd_pcm_hw_params_copy(hwparams, params);
|
||||
|
||||
/* Prioritize matching the period size to the requested buffer size */
|
||||
persize = this->spec.samples;
|
||||
status = ALSA_snd_pcm_hw_params_set_period_size_near(
|
||||
this->hidden->pcm_handle, hwparams, &persize, NULL);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Next try to restrict the parameters to having only two periods */
|
||||
bufsize = this->spec.samples * 2;
|
||||
status = ALSA_snd_pcm_hw_params_set_buffer_size_near(
|
||||
this->hidden->pcm_handle, hwparams, &bufsize);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* "set" the hardware with the desired parameters */
|
||||
status = ALSA_snd_pcm_hw_params(this->hidden->pcm_handle, hwparams);
|
||||
|
|
@ -491,12 +446,24 @@ ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params)
|
|||
return(-1);
|
||||
}
|
||||
|
||||
this->spec.samples = persize;
|
||||
/* Get samples for the actual buffer size */
|
||||
status = ALSA_snd_pcm_hw_params_get_buffer_size(hwparams, &bufsize);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
if ( !override && bufsize != this->spec.samples * 2 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* !!! FIXME: Is this safe to do? */
|
||||
this->spec.samples = bufsize / 2;
|
||||
|
||||
/* This is useful for debugging */
|
||||
if ( SDL_getenv("SDL_AUDIO_ALSA_DEBUG") ) {
|
||||
snd_pcm_uframes_t persize = 0;
|
||||
unsigned int periods = 0;
|
||||
|
||||
ALSA_snd_pcm_hw_params_get_period_size(hwparams, &persize, NULL);
|
||||
ALSA_snd_pcm_hw_params_get_periods(hwparams, &periods, NULL);
|
||||
|
||||
fprintf(stderr,
|
||||
|
|
@ -507,6 +474,78 @@ ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params)
|
|||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
ALSA_set_period_size(_THIS, snd_pcm_hw_params_t *params, int override)
|
||||
{
|
||||
const char *env;
|
||||
int status;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_uframes_t frames;
|
||||
unsigned int periods;
|
||||
|
||||
/* Copy the hardware parameters for this setup */
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
ALSA_snd_pcm_hw_params_copy(hwparams, params);
|
||||
|
||||
if ( !override ) {
|
||||
env = SDL_getenv("SDL_AUDIO_ALSA_SET_PERIOD_SIZE");
|
||||
if ( env ) {
|
||||
override = SDL_atoi(env);
|
||||
if ( override == 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frames = this->spec.samples;
|
||||
status = ALSA_snd_pcm_hw_params_set_period_size_near(
|
||||
this->hidden->pcm_handle, hwparams, &frames, NULL);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
periods = 2;
|
||||
status = ALSA_snd_pcm_hw_params_set_periods_near(
|
||||
this->hidden->pcm_handle, hwparams, &periods, NULL);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return ALSA_finalize_hardware(this, hwparams, override);
|
||||
}
|
||||
|
||||
static int
|
||||
ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params, int override)
|
||||
{
|
||||
const char *env;
|
||||
int status;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_uframes_t frames;
|
||||
|
||||
/* Copy the hardware parameters for this setup */
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
ALSA_snd_pcm_hw_params_copy(hwparams, params);
|
||||
|
||||
if ( !override ) {
|
||||
env = SDL_getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE");
|
||||
if ( env ) {
|
||||
override = SDL_atoi(env);
|
||||
if ( override == 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frames = this->spec.samples * 2;
|
||||
status = ALSA_snd_pcm_hw_params_set_buffer_size_near(
|
||||
this->hidden->pcm_handle, hwparams, &frames);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return ALSA_finalize_hardware(this, hwparams, override);
|
||||
}
|
||||
|
||||
static int
|
||||
ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
|
|
@ -653,11 +692,14 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
this->spec.freq = rate;
|
||||
|
||||
/* Set the buffer size, in samples */
|
||||
status = ALSA_set_buffer_size(this, hwparams);
|
||||
if (status < 0) {
|
||||
return SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
|
||||
if ( ALSA_set_period_size(this, hwparams, 0) < 0 &&
|
||||
ALSA_set_buffer_size(this, hwparams, 0) < 0 ) {
|
||||
/* Failed to set desired buffer size, do the best you can... */
|
||||
status = ALSA_set_period_size(this, hwparams, 1);
|
||||
if (status < 0) {
|
||||
return SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the software parameters */
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
|
||||
|
|
@ -695,11 +737,9 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
|
||||
}
|
||||
|
||||
#if !SDL_ALSA_NON_BLOCKING
|
||||
if (!iscapture) {
|
||||
ALSA_snd_pcm_nonblock(pcm_handle, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -57,9 +57,7 @@ ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
|
||||
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)) {
|
||||
if ((test_format == AUDIO_U8) || (test_format == AUDIO_S16LSB)) {
|
||||
this->spec.format = test_format;
|
||||
break;
|
||||
}
|
||||
|
|
@ -71,8 +69,25 @@ ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
return SDL_SetError("No compatible audio format!");
|
||||
}
|
||||
|
||||
if (Android_JNI_OpenAudioDevice(iscapture, &this->spec) < 0) {
|
||||
return -1;
|
||||
if (this->spec.channels > 1) {
|
||||
this->spec.channels = 2;
|
||||
} else {
|
||||
this->spec.channels = 1;
|
||||
}
|
||||
|
||||
if (this->spec.freq < 8000) {
|
||||
this->spec.freq = 8000;
|
||||
}
|
||||
if (this->spec.freq > 48000) {
|
||||
this->spec.freq = 48000;
|
||||
}
|
||||
|
||||
/* TODO: pass in/return a (Java) device ID */
|
||||
this->spec.samples = Android_JNI_OpenAudioDevice(iscapture, this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
|
||||
|
||||
if (this->spec.samples == 0) {
|
||||
/* Init failed? */
|
||||
return SDL_SetError("Java-side initialization failed!");
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
#include "SDL_name.h"
|
||||
#include "SDL_loadso.h"
|
||||
#else
|
||||
#define SDL_NAME(X) X
|
||||
#define SDL_NAME(X) X
|
||||
#endif
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
|
||||
|
|
|
|||
|
|
@ -45,14 +45,16 @@
|
|||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
SDL_Thread *thread;
|
||||
AudioQueueRef audioQueue;
|
||||
int numAudioBuffers;
|
||||
AudioQueueBufferRef *audioBuffer;
|
||||
void *buffer;
|
||||
UInt32 bufferOffset;
|
||||
UInt32 bufferSize;
|
||||
AudioStreamBasicDescription strdesc;
|
||||
SDL_bool refill;
|
||||
SDL_AudioStream *capturestream;
|
||||
SDL_sem *ready_semaphore;
|
||||
char *thread_error;
|
||||
SDL_atomic_t shutdown;
|
||||
#if MACOSX_COREAUDIO
|
||||
AudioDeviceID deviceID;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_coreaudio.h"
|
||||
|
|
@ -355,7 +354,7 @@ static BOOL update_audio_session(_THIS, SDL_bool open)
|
|||
return NO;
|
||||
}
|
||||
|
||||
if (open && (open_playback_devices + open_capture_devices) == 1) {
|
||||
if (open_playback_devices + open_capture_devices == 1) {
|
||||
if (![session setActive:YES error:&err]) {
|
||||
NSString *desc = err.description;
|
||||
SDL_SetError("Could not activate Audio Session: %s", desc.UTF8String);
|
||||
|
|
@ -392,10 +391,10 @@ static BOOL update_audio_session(_THIS, SDL_bool open)
|
|||
if (this->hidden->interruption_listener != NULL) {
|
||||
SDLInterruptionListener *listener = nil;
|
||||
listener = (SDLInterruptionListener *) CFBridgingRelease(this->hidden->interruption_listener);
|
||||
[center removeObserver:listener];
|
||||
@synchronized (listener) {
|
||||
listener.device = NULL;
|
||||
}
|
||||
[center removeObserver:listener];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -410,27 +409,43 @@ static void
|
|||
outputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
|
||||
{
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) inUserData;
|
||||
SDL_assert(inBuffer->mAudioDataBytesCapacity == this->hidden->bufferSize);
|
||||
SDL_memcpy(inBuffer->mAudioData, this->hidden->buffer, this->hidden->bufferSize);
|
||||
SDL_memset(this->hidden->buffer, '\0', this->hidden->bufferSize); /* zero out in case we have to fill again without new data. */
|
||||
inBuffer->mAudioDataByteSize = this->hidden->bufferSize;
|
||||
AudioQueueEnqueueBuffer(this->hidden->audioQueue, inBuffer, 0, NULL);
|
||||
this->hidden->refill = SDL_TRUE;
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
COREAUDIO_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return this->hidden->buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
COREAUDIO_WaitDevice(_THIS)
|
||||
{
|
||||
while (SDL_AtomicGet(&this->enabled) && !this->hidden->refill) {
|
||||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1);
|
||||
if (SDL_AtomicGet(&this->hidden->shutdown)) {
|
||||
return; /* don't do anything. */
|
||||
}
|
||||
this->hidden->refill = SDL_FALSE;
|
||||
|
||||
if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
|
||||
/* Supply silence if audio is not enabled or paused */
|
||||
SDL_memset(inBuffer->mAudioData, this->spec.silence, inBuffer->mAudioDataBytesCapacity);
|
||||
} else {
|
||||
UInt32 remaining = inBuffer->mAudioDataBytesCapacity;
|
||||
Uint8 *ptr = (Uint8 *) inBuffer->mAudioData;
|
||||
|
||||
while (remaining > 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
len = this->hidden->bufferSize - this->hidden->bufferOffset;
|
||||
if (len > remaining) {
|
||||
len = remaining;
|
||||
}
|
||||
SDL_memcpy(ptr, (char *)this->hidden->buffer +
|
||||
this->hidden->bufferOffset, len);
|
||||
ptr = ptr + len;
|
||||
remaining -= len;
|
||||
this->hidden->bufferOffset += len;
|
||||
}
|
||||
}
|
||||
|
||||
AudioQueueEnqueueBuffer(this->hidden->audioQueue, inBuffer, 0, NULL);
|
||||
|
||||
inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -439,46 +454,36 @@ inputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer
|
|||
const AudioStreamPacketDescription *inPacketDescs )
|
||||
{
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) inUserData;
|
||||
if (SDL_AtomicGet(&this->enabled)) {
|
||||
SDL_AudioStream *stream = this->hidden->capturestream;
|
||||
if (SDL_AudioStreamPut(stream, inBuffer->mAudioData, inBuffer->mAudioDataByteSize) == -1) {
|
||||
/* yikes, out of memory or something. I guess drop the buffer. Our WASAPI target kills the device in this case, though */
|
||||
}
|
||||
AudioQueueEnqueueBuffer(this->hidden->audioQueue, inBuffer, 0, NULL);
|
||||
this->hidden->refill = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
COREAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
|
||||
{
|
||||
SDL_AudioStream *stream = this->hidden->capturestream;
|
||||
while (SDL_AtomicGet(&this->enabled)) {
|
||||
const int avail = SDL_AudioStreamAvailable(stream);
|
||||
if (avail > 0) {
|
||||
const int cpy = SDL_min(buflen, avail);
|
||||
SDL_AudioStreamGet(stream, buffer, cpy);
|
||||
return cpy;
|
||||
}
|
||||
|
||||
/* wait for more data, try again. */
|
||||
while (SDL_AtomicGet(&this->enabled) && !this->hidden->refill) {
|
||||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1);
|
||||
}
|
||||
this->hidden->refill = SDL_FALSE;
|
||||
if (SDL_AtomicGet(&this->shutdown)) {
|
||||
return; /* don't do anything. */
|
||||
}
|
||||
|
||||
return 0; /* not enabled, giving up. */
|
||||
}
|
||||
/* ignore unless we're active. */
|
||||
if (!SDL_AtomicGet(&this->paused) && SDL_AtomicGet(&this->enabled) && !SDL_AtomicGet(&this->paused)) {
|
||||
const Uint8 *ptr = (const Uint8 *) inBuffer->mAudioData;
|
||||
UInt32 remaining = inBuffer->mAudioDataByteSize;
|
||||
while (remaining > 0) {
|
||||
UInt32 len = this->hidden->bufferSize - this->hidden->bufferOffset;
|
||||
if (len > remaining) {
|
||||
len = remaining;
|
||||
}
|
||||
|
||||
static void
|
||||
COREAUDIO_FlushCapture(_THIS)
|
||||
{
|
||||
while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 1) == kCFRunLoopRunHandledSource) {
|
||||
/* spin. */
|
||||
SDL_memcpy((char *)this->hidden->buffer + this->hidden->bufferOffset, ptr, len);
|
||||
ptr += len;
|
||||
remaining -= len;
|
||||
this->hidden->bufferOffset += len;
|
||||
|
||||
if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
this->hidden->refill = SDL_FALSE;
|
||||
SDL_AudioStreamClear(this->hidden->capturestream);
|
||||
|
||||
AudioQueueEnqueueBuffer(this->hidden->audioQueue, inBuffer, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -536,16 +541,25 @@ COREAUDIO_CloseDevice(_THIS)
|
|||
update_audio_session(this, SDL_FALSE);
|
||||
#endif
|
||||
|
||||
/* if callback fires again, feed silence; don't call into the app. */
|
||||
SDL_AtomicSet(&this->paused, 1);
|
||||
|
||||
if (this->hidden->audioQueue) {
|
||||
AudioQueueDispose(this->hidden->audioQueue, 1);
|
||||
}
|
||||
|
||||
if (this->hidden->capturestream) {
|
||||
SDL_FreeAudioStream(this->hidden->capturestream);
|
||||
if (this->hidden->thread) {
|
||||
SDL_AtomicSet(&this->hidden->shutdown, 1);
|
||||
SDL_WaitThread(this->hidden->thread, NULL);
|
||||
}
|
||||
|
||||
if (this->hidden->ready_semaphore) {
|
||||
SDL_DestroySemaphore(this->hidden->ready_semaphore);
|
||||
}
|
||||
|
||||
/* AudioQueueDispose() frees the actual buffer objects. */
|
||||
SDL_free(this->hidden->audioBuffer);
|
||||
SDL_free(this->hidden->thread_error);
|
||||
SDL_free(this->hidden->buffer);
|
||||
SDL_free(this->hidden);
|
||||
|
||||
|
|
@ -611,8 +625,6 @@ prepare_device(_THIS, void *handle, int iscapture)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* this all happens in the audio thread, since it needs a separate runloop. */
|
||||
static int
|
||||
prepare_audioqueue(_THIS)
|
||||
{
|
||||
|
|
@ -652,6 +664,19 @@ prepare_audioqueue(_THIS)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Allocate a sample buffer */
|
||||
this->hidden->bufferSize = this->spec.size;
|
||||
this->hidden->bufferOffset = iscapture ? 0 : this->hidden->bufferSize;
|
||||
|
||||
this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
|
||||
if (this->hidden->buffer == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure we can feed the device a minimum amount of time */
|
||||
double MINIMUM_AUDIO_BUFFER_TIME_MS = 15.0;
|
||||
#if defined(__IPHONEOS__)
|
||||
|
|
@ -666,7 +691,6 @@ prepare_audioqueue(_THIS)
|
|||
numAudioBuffers = ((int)SDL_ceil(MINIMUM_AUDIO_BUFFER_TIME_MS / msecs) * 2);
|
||||
}
|
||||
|
||||
this->hidden->numAudioBuffers = numAudioBuffers;
|
||||
this->hidden->audioBuffer = SDL_calloc(1, sizeof (AudioQueueBufferRef) * numAudioBuffers);
|
||||
if (this->hidden->audioBuffer == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
|
|
@ -693,23 +717,29 @@ prepare_audioqueue(_THIS)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
COREAUDIO_ThreadInit(_THIS)
|
||||
static int
|
||||
audioqueue_thread(void *arg)
|
||||
{
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) arg;
|
||||
const int rc = prepare_audioqueue(this);
|
||||
if (!rc) {
|
||||
/* !!! FIXME: do this in RunAudio, and maybe block OpenDevice until ThreadInit finishes, too, to report an opening error */
|
||||
SDL_OpenedAudioDeviceDisconnected(this); /* oh well. */
|
||||
this->hidden->thread_error = SDL_strdup(SDL_GetError());
|
||||
SDL_SemPost(this->hidden->ready_semaphore);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
COREAUDIO_PrepareToClose(_THIS)
|
||||
{
|
||||
/* run long enough to queue some silence, so we know our actual audio
|
||||
has been played */
|
||||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, (((this->spec.samples * 1000) / this->spec.freq) * 2) / 1000.0f, 0);
|
||||
AudioQueueStop(this->hidden->audioQueue, 1);
|
||||
/* init was successful, alert parent thread and start running... */
|
||||
SDL_SemPost(this->hidden->ready_semaphore);
|
||||
while (!SDL_AtomicGet(&this->hidden->shutdown)) {
|
||||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1);
|
||||
}
|
||||
|
||||
if (!this->iscapture) { /* Drain off any pending playback. */
|
||||
const CFTimeInterval secs = (((this->spec.size / (SDL_AUDIO_BITSIZE(this->spec.format) / 8)) / this->spec.channels) / ((CFTimeInterval) this->spec.freq)) * 2.0;
|
||||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, secs, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -796,23 +826,28 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
if (iscapture) {
|
||||
this->hidden->capturestream = SDL_NewAudioStream(this->spec.format, this->spec.channels, this->spec.freq, this->spec.format, this->spec.channels, this->spec.freq);
|
||||
if (!this->hidden->capturestream) {
|
||||
return -1; /* already set SDL_Error */
|
||||
}
|
||||
} else {
|
||||
this->hidden->bufferSize = this->spec.size;
|
||||
this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
|
||||
if (this->hidden->buffer == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
/* This has to init in a new thread so it can get its own CFRunLoop. :/ */
|
||||
SDL_AtomicSet(&this->hidden->shutdown, 0);
|
||||
this->hidden->ready_semaphore = SDL_CreateSemaphore(0);
|
||||
if (!this->hidden->ready_semaphore) {
|
||||
return -1; /* oh well. */
|
||||
}
|
||||
|
||||
return 0;
|
||||
this->hidden->thread = SDL_CreateThreadInternal(audioqueue_thread, "AudioQueue thread", 512 * 1024, this);
|
||||
if (!this->hidden->thread) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_SemWait(this->hidden->ready_semaphore);
|
||||
SDL_DestroySemaphore(this->hidden->ready_semaphore);
|
||||
this->hidden->ready_semaphore = NULL;
|
||||
|
||||
if ((this->hidden->thread != NULL) && (this->hidden->thread_error != NULL)) {
|
||||
SDL_SetError("%s", this->hidden->thread_error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (this->hidden->thread != NULL) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -832,12 +867,6 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl)
|
|||
impl->OpenDevice = COREAUDIO_OpenDevice;
|
||||
impl->CloseDevice = COREAUDIO_CloseDevice;
|
||||
impl->Deinitialize = COREAUDIO_Deinitialize;
|
||||
impl->ThreadInit = COREAUDIO_ThreadInit;
|
||||
impl->WaitDevice = COREAUDIO_WaitDevice;
|
||||
impl->GetDeviceBuf = COREAUDIO_GetDeviceBuf;
|
||||
impl->PrepareToClose = COREAUDIO_PrepareToClose;
|
||||
impl->CaptureFromDevice = COREAUDIO_CaptureFromDevice;
|
||||
impl->FlushCapture = COREAUDIO_FlushCapture;
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
impl->DetectDevices = COREAUDIO_DetectDevices;
|
||||
|
|
@ -847,6 +876,7 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl)
|
|||
impl->OnlyHasDefaultCaptureDevice = 1;
|
||||
#endif
|
||||
|
||||
impl->ProvidesOwnCallbackThread = 1;
|
||||
impl->HasCaptureSupport = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
|
|
|
|||
|
|
@ -477,8 +477,8 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
SDL_bool tried_format = SDL_FALSE;
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
LPGUID guid = (LPGUID) handle;
|
||||
DWORD bufsize;
|
||||
|
||||
DWORD bufsize;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
|
|
@ -526,7 +526,7 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
(int) (DSBSIZE_MAX / numchunks));
|
||||
} else {
|
||||
int rc;
|
||||
WAVEFORMATEX wfmt;
|
||||
WAVEFORMATEX wfmt;
|
||||
SDL_zero(wfmt);
|
||||
if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
|
||||
wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
|
|
|
|||
|
|
@ -44,9 +44,7 @@ static const char ** (*JACK_jack_get_ports) (jack_client_t *, const char *, cons
|
|||
static jack_nframes_t (*JACK_jack_get_sample_rate) (jack_client_t *);
|
||||
static jack_nframes_t (*JACK_jack_get_buffer_size) (jack_client_t *);
|
||||
static jack_port_t * (*JACK_jack_port_register) (jack_client_t *, const char *, const char *, unsigned long, unsigned long);
|
||||
static jack_port_t * (*JACK_jack_port_by_name) (jack_client_t *, const char *);
|
||||
static const char * (*JACK_jack_port_name) (const jack_port_t *);
|
||||
static const char * (*JACK_jack_port_type) (const jack_port_t *);
|
||||
static int (*JACK_jack_connect) (jack_client_t *, const char *, const char *);
|
||||
static int (*JACK_jack_set_process_callback) (jack_client_t *, JackProcessCallback, void *);
|
||||
|
||||
|
|
@ -137,9 +135,7 @@ load_jack_syms(void)
|
|||
SDL_JACK_SYM(jack_get_sample_rate);
|
||||
SDL_JACK_SYM(jack_get_buffer_size);
|
||||
SDL_JACK_SYM(jack_port_register);
|
||||
SDL_JACK_SYM(jack_port_by_name);
|
||||
SDL_JACK_SYM(jack_port_name);
|
||||
SDL_JACK_SYM(jack_port_type);
|
||||
SDL_JACK_SYM(jack_connect);
|
||||
SDL_JACK_SYM(jack_set_process_callback);
|
||||
return 0;
|
||||
|
|
@ -277,6 +273,10 @@ JACK_CloseDevice(_THIS)
|
|||
SDL_DestroySemaphore(this->hidden->iosem);
|
||||
}
|
||||
|
||||
if (this->hidden->devports) {
|
||||
JACK_jack_free(this->hidden->devports);
|
||||
}
|
||||
|
||||
SDL_free(this->hidden->iobuffer);
|
||||
}
|
||||
|
||||
|
|
@ -292,11 +292,9 @@ JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
const JackProcessCallback callback = iscapture ? jackProcessCaptureCallback : jackProcessPlaybackCallback;
|
||||
const char *sdlportstr = iscapture ? "input" : "output";
|
||||
const char **devports = NULL;
|
||||
int *audio_ports;
|
||||
jack_client_t *client = NULL;
|
||||
jack_status_t status;
|
||||
int channels = 0;
|
||||
int ports = 0;
|
||||
int i;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
|
|
@ -313,30 +311,15 @@ JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
}
|
||||
|
||||
devports = JACK_jack_get_ports(client, NULL, NULL, JackPortIsPhysical | sysportflags);
|
||||
this->hidden->devports = devports;
|
||||
if (!devports || !devports[0]) {
|
||||
return SDL_SetError("No physical JACK ports available");
|
||||
}
|
||||
|
||||
while (devports[++ports]) {
|
||||
while (devports[++channels]) {
|
||||
/* spin to count devports */
|
||||
}
|
||||
|
||||
/* Filter out non-audio ports */
|
||||
audio_ports = SDL_calloc(ports, sizeof *audio_ports);
|
||||
for (i = 0; i < ports; i++) {
|
||||
const jack_port_t *dport = JACK_jack_port_by_name(client, devports[i]);
|
||||
const char *type = JACK_jack_port_type(dport);
|
||||
const int len = SDL_strlen(type);
|
||||
/* See if type ends with "audio" */
|
||||
if (len >= 5 && !SDL_memcmp(type+len-5, "audio", 5)) {
|
||||
audio_ports[channels++] = i;
|
||||
}
|
||||
}
|
||||
if (channels == 0) {
|
||||
return SDL_SetError("No physical JACK ports available");
|
||||
}
|
||||
|
||||
|
||||
/* !!! FIXME: docs say about buffer size: "This size may change, clients that depend on it must register a bufsize_callback so they will be notified if it does." */
|
||||
|
||||
/* Jack pretty much demands what it wants. */
|
||||
|
|
@ -385,16 +368,16 @@ JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
/* once activated, we can connect all the ports. */
|
||||
for (i = 0; i < channels; i++) {
|
||||
const char *sdlport = JACK_jack_port_name(this->hidden->sdlports[i]);
|
||||
const char *srcport = iscapture ? devports[audio_ports[i]] : sdlport;
|
||||
const char *dstport = iscapture ? sdlport : devports[audio_ports[i]];
|
||||
const char *srcport = iscapture ? devports[i] : sdlport;
|
||||
const char *dstport = iscapture ? sdlport : devports[i];
|
||||
if (JACK_jack_connect(client, srcport, dstport) != 0) {
|
||||
return SDL_SetError("Couldn't connect JACK ports: %s => %s", srcport, dstport);
|
||||
}
|
||||
}
|
||||
|
||||
/* don't need these anymore. */
|
||||
this->hidden->devports = NULL;
|
||||
JACK_jack_free(devports);
|
||||
SDL_free(audio_ports);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ struct SDL_PrivateAudioData
|
|||
jack_client_t *client;
|
||||
SDL_sem *iosem;
|
||||
float *iobuffer;
|
||||
const char **devports;
|
||||
jack_port_t **sdlports;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ static pa_operation * (*PULSEAUDIO_pa_stream_drain) (pa_stream *,
|
|||
pa_stream_success_cb_t, void *);
|
||||
static int (*PULSEAUDIO_pa_stream_peek) (pa_stream *, const void **, size_t *);
|
||||
static int (*PULSEAUDIO_pa_stream_drop) (pa_stream *);
|
||||
static pa_operation * (*PULSEAUDIO_pa_stream_flush) (pa_stream *,
|
||||
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 *);
|
||||
|
|
|
|||
|
|
@ -725,12 +725,6 @@ WASAPI_ThreadDeinit(_THIS)
|
|||
WASAPI_PlatformThreadDeinit(this);
|
||||
}
|
||||
|
||||
void
|
||||
WASAPI_BeginLoopIteration(_THIS)
|
||||
{
|
||||
/* no-op. */
|
||||
}
|
||||
|
||||
static void
|
||||
WASAPI_Deinitialize(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -351,42 +351,10 @@ WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
|
|||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LPWSTR devid;
|
||||
char *devname;
|
||||
} EndpointItem;
|
||||
|
||||
static int sort_endpoints(const void *_a, const void *_b)
|
||||
{
|
||||
LPWSTR a = ((const EndpointItem *) _a)->devid;
|
||||
LPWSTR b = ((const EndpointItem *) _b)->devid;
|
||||
if (!a && b) {
|
||||
return -1;
|
||||
} else if (a && !b) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (SDL_TRUE) {
|
||||
if (*a < *b) {
|
||||
return -1;
|
||||
} else if (*a > *b) {
|
||||
return 1;
|
||||
} else if (*a == 0) {
|
||||
break;
|
||||
}
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
WASAPI_EnumerateEndpointsForFlow(const SDL_bool iscapture)
|
||||
{
|
||||
IMMDeviceCollection *collection = NULL;
|
||||
EndpointItem *items;
|
||||
UINT i, total;
|
||||
|
||||
/* Note that WASAPI separates "adapter devices" from "audio endpoint devices"
|
||||
|
|
@ -401,36 +369,22 @@ WASAPI_EnumerateEndpointsForFlow(const SDL_bool iscapture)
|
|||
return;
|
||||
}
|
||||
|
||||
items = (EndpointItem *) SDL_calloc(total, sizeof (EndpointItem));
|
||||
if (!items) {
|
||||
return; /* oh well. */
|
||||
}
|
||||
|
||||
for (i = 0; i < total; i++) {
|
||||
EndpointItem *item = items + i;
|
||||
IMMDevice *device = NULL;
|
||||
if (SUCCEEDED(IMMDeviceCollection_Item(collection, i, &device))) {
|
||||
if (SUCCEEDED(IMMDevice_GetId(device, &item->devid))) {
|
||||
item->devname = GetWasapiDeviceName(device);
|
||||
LPWSTR devid = NULL;
|
||||
if (SUCCEEDED(IMMDevice_GetId(device, &devid))) {
|
||||
char *devname = GetWasapiDeviceName(device);
|
||||
if (devname) {
|
||||
WASAPI_AddDevice(iscapture, devname, devid);
|
||||
SDL_free(devname);
|
||||
}
|
||||
CoTaskMemFree(devid);
|
||||
}
|
||||
IMMDevice_Release(device);
|
||||
}
|
||||
}
|
||||
|
||||
/* sort the list of devices by their guid so list is consistent between runs */
|
||||
SDL_qsort(items, total, sizeof (*items), sort_endpoints);
|
||||
|
||||
/* Send the sorted list on to the SDL's higher level. */
|
||||
for (i = 0; i < total; i++) {
|
||||
EndpointItem *item = items + i;
|
||||
if ((item->devid) && (item->devname)) {
|
||||
WASAPI_AddDevice(iscapture, item->devname, item->devid);
|
||||
}
|
||||
SDL_free(item->devname);
|
||||
CoTaskMemFree(item->devid);
|
||||
}
|
||||
|
||||
SDL_free(items);
|
||||
IMMDeviceCollection_Release(collection);
|
||||
}
|
||||
|
||||
|
|
@ -451,6 +405,12 @@ WASAPI_PlatformDeleteActivationHandler(void *handler)
|
|||
SDL_assert(!"This function should have only been called on WinRT.");
|
||||
}
|
||||
|
||||
void
|
||||
WASAPI_BeginLoopIteration(_THIS)
|
||||
{
|
||||
/* no-op. */
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_WASAPI && !defined(__WINRT__) */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -185,9 +185,20 @@ struct SDL_WasapiActivationHandler : public RuntimeClass< RuntimeClassFlags< Cla
|
|||
HRESULT
|
||||
SDL_WasapiActivationHandler::ActivateCompleted(IActivateAudioInterfaceAsyncOperation *async)
|
||||
{
|
||||
// Just set a flag, since we're probably in a different thread. We'll pick it up and init everything on our own thread to prevent races.
|
||||
SDL_AtomicSet(&device->hidden->just_activated, 1);
|
||||
HRESULT result = S_OK;
|
||||
IUnknown *iunknown = nullptr;
|
||||
const HRESULT ret = async->GetActivateResult(&result, &iunknown);
|
||||
|
||||
if (SUCCEEDED(ret) && SUCCEEDED(result)) {
|
||||
iunknown->QueryInterface(IID_PPV_ARGS(&device->hidden->client));
|
||||
if (device->hidden->client) {
|
||||
// Just set a flag, since we're probably in a different thread. We'll pick it up and init everything on our own thread to prevent races.
|
||||
SDL_AtomicSet(&device->hidden->just_activated, 1);
|
||||
}
|
||||
}
|
||||
|
||||
WASAPI_UnrefDevice(device);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
@ -225,49 +236,29 @@ WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
|
|||
IActivateAudioInterfaceAsyncOperation *async = nullptr;
|
||||
const HRESULT ret = ActivateAudioInterfaceAsync(devid, __uuidof(IAudioClient), nullptr, handler.Get(), &async);
|
||||
|
||||
if (FAILED(ret) || async == nullptr) {
|
||||
if (async != nullptr) {
|
||||
async->Release();
|
||||
}
|
||||
if (async != nullptr) {
|
||||
async->Release();
|
||||
}
|
||||
|
||||
if (FAILED(ret)) {
|
||||
handler.Get()->Release();
|
||||
WASAPI_UnrefDevice(_this);
|
||||
return WIN_SetErrorFromHRESULT("WASAPI can't activate requested audio endpoint", ret);
|
||||
}
|
||||
|
||||
/* Spin until the async operation is complete.
|
||||
* If we don't PrepDevice before leaving this function, the bug list gets LONG:
|
||||
* - device.spec is not filled with the correct information
|
||||
* - The 'obtained' spec will be wrong for ALLOW_CHANGE properties
|
||||
* - SDL_AudioStreams will/will not be allocated at the right time
|
||||
* - SDL_assert(device->callbackspec.size == device->spec.size) will fail
|
||||
* - When the assert is ignored, skipping or a buffer overflow will occur
|
||||
*/
|
||||
while (!SDL_AtomicCAS(&_this->hidden->just_activated, 1, 0)) {
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
HRESULT activateRes = S_OK;
|
||||
IUnknown *iunknown = nullptr;
|
||||
const HRESULT getActivateRes = async->GetActivateResult(&activateRes, &iunknown);
|
||||
async->Release();
|
||||
if (FAILED(getActivateRes)) {
|
||||
return WIN_SetErrorFromHRESULT("Failed to get WASAPI activate result", getActivateRes);
|
||||
} else if (FAILED(activateRes)) {
|
||||
return WIN_SetErrorFromHRESULT("Failed to activate WASAPI device", activateRes);
|
||||
}
|
||||
|
||||
iunknown->QueryInterface(IID_PPV_ARGS(&_this->hidden->client));
|
||||
if (!_this->hidden->client) {
|
||||
return SDL_SetError("Failed to query WASAPI client interface");
|
||||
}
|
||||
|
||||
if (WASAPI_PrepDevice(_this, isrecovery) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WASAPI_BeginLoopIteration(_THIS)
|
||||
{
|
||||
if (SDL_AtomicCAS(&_this->hidden->just_activated, 1, 0)) {
|
||||
if (WASAPI_PrepDevice(_this, SDL_TRUE) == -1) {
|
||||
SDL_OpenedAudioDeviceDisconnected(_this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WASAPI_PlatformThreadInit(_THIS)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ static void DetectWave##typ##Devs(void) { \
|
|||
capstyp##2W caps; \
|
||||
UINT i; \
|
||||
for (i = 0; i < devcount; i++) { \
|
||||
if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
|
||||
if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
|
||||
char *name = WIN_LookupAudioDeviceName(caps.szPname,&caps.NameGuid); \
|
||||
if (name != NULL) { \
|
||||
SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \
|
||||
|
|
@ -375,7 +375,8 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
#endif
|
||||
|
||||
/* Create the audio buffer semaphore */
|
||||
this->hidden->audio_sem = CreateSemaphore(NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
|
||||
this->hidden->audio_sem =
|
||||
CreateSemaphore(NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
|
||||
if (this->hidden->audio_sem == NULL) {
|
||||
return SDL_SetError("Couldn't create semaphore");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue