Skip to content

Commit

Permalink
Merge pull request #2643 from ericoporto/update-mojoAL-a9e2f30b04f1
Browse files Browse the repository at this point in the history
libsrc: update mojoAL
  • Loading branch information
ivan-mogilko authored Jan 8, 2025
2 parents c46b83c + e095216 commit 4fcd5cb
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 92 deletions.
2 changes: 1 addition & 1 deletion libsrc/mojoAL/.icculus.mojoAL.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
repo: https://github.com/icculus/mojoAL
commit: bfaf2f24034c5776c930a5575e115ee561f372b7
commit: a9e2f30b04f10df1912d06ff5a610edda4677ba5
209 changes: 118 additions & 91 deletions libsrc/mojoAL/mojoal.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,18 @@
#include "AL/alc.h"
#include "SDL.h"

#ifdef __SSE__ /* if you are on x86 or x86-64, we assume you have SSE1 by now. */
/* This is for debugging and/or pulling the fire alarm. */
#define FORCE_SCALAR_FALLBACK 0
#if FORCE_SCALAR_FALLBACK
# ifdef __SSE__
# undef __SSE__
# endif
# ifdef __ARM_NEON__
# undef __ARM_NEON__
# endif
#endif

#if defined(__SSE__) /* if you are on x86 or x86-64, we assume you have SSE1 by now. */
#define NEED_SCALAR_FALLBACK 0
#elif (defined(__ARM_ARCH) && (__ARM_ARCH >= 8)) /* ARMv8 always has NEON. */
#define NEED_SCALAR_FALLBACK 0
Expand All @@ -41,7 +52,7 @@

/* Some platforms fail to define __ARM_NEON__, others need it or arm_neon.h will fail. */
#if (defined(__ARM_ARCH) || defined(_M_ARM))
# if !NEED_SCALAR_FALLBACK && !defined(__ARM_NEON__)
# if !NEED_SCALAR_FALLBACK && !FORCE_SCALAR_FALLBACK && !defined(__ARM_NEON__)
# define __ARM_NEON__ 1
# endif
#endif
Expand Down Expand Up @@ -1739,12 +1750,13 @@ static void calculate_channel_gains(const ALCcontext *ctx, const ALsource *src,

{
#if NEED_SCALAR_FALLBACK
SDL_memcpy(position, src->position, sizeof (position));
/* if values aren't source-relative, then convert it to be so. */
if (!src->source_relative) {
position[0] -= ctx->listener.position[0];
position[1] -= ctx->listener.position[1];
position[2] -= ctx->listener.position[2];
SDL_memcpy(position, src->position, sizeof (position));
} else {
position[0] = src->position[0] - ctx->listener.position[0];
position[1] = src->position[1] - ctx->listener.position[1];
position[2] = src->position[2] - ctx->listener.position[2];
}
distance = magnitude(position);
#endif
Expand Down Expand Up @@ -1785,39 +1797,30 @@ static void calculate_channel_gains(const ALCcontext *ctx, const ALsource *src,
https://dsp.stackexchange.com/questions/21691/algorithm-to-pan-audio
Naturally, we'll need to know the angle between where our listener
is facing and where the source is to make that work...
https://www.youtube.com/watch?v=S_568VZWFJo
...but to do that, we need to rotate so we have the correct side of
the listener, which isn't just a point in space, but has a definite
direction it is facing. More or less, this is what gluLookAt deals
with...
http://www.songho.ca/opengl/gl_camera.html
...although I messed with the algorithm until it did what I wanted.
XYZZY!! https://en.wikipedia.org/wiki/Cross_product#Mnemonic
*/

#ifdef __SSE__ /* (the math is explained in the scalar version.) */
if (has_sse) {
const __m128 at_sse = _mm_load_ps(at);
const __m128 U_sse = normalize_sse(xyzzy_sse(at_sse, _mm_load_ps(up)));
const __m128 V_sse = xyzzy_sse(at_sse, U_sse);
const __m128 N_sse = normalize_sse(at_sse);
const __m128 rotated_sse = {
dotproduct_sse(position_sse, U_sse),
-dotproduct_sse(position_sse, V_sse),
-dotproduct_sse(position_sse, N_sse),
0.0f
};

const ALfloat mags = magnitude_sse(at_sse) * magnitude_sse(rotated_sse);
radians = (mags == 0.0f) ? 0.0f : SDL_acosf(dotproduct_sse(at_sse, rotated_sse) / mags);
if (_mm_comilt_ss(rotated_sse, _mm_setzero_ps())) {
const __m128 up_sse = _mm_load_ps(up);
__m128 V_sse;
__m128 R_sse;
ALfloat cosangle;
ALfloat mags;
ALfloat a;

a = dotproduct_sse(position_sse, up_sse);
V_sse = _mm_sub_ps(position_sse, _mm_mul_ps(_mm_set1_ps(a), up_sse));

mags = magnitude_sse(at_sse) * magnitude_sse(V_sse);
cosangle = (mags == 0.0f) ? 0.0f : (dotproduct_sse(at_sse, V_sse) / mags);
cosangle = SDL_clamp(cosangle, -1.0f, 1.0f);
radians = SDL_acosf(cosangle);

R_sse = xyzzy_sse(at_sse, up_sse);

if (dotproduct_sse(R_sse, V_sse) < 0.0f) {
radians = -radians;
}
} else
Expand All @@ -1826,64 +1829,55 @@ static void calculate_channel_gains(const ALCcontext *ctx, const ALsource *src,
#ifdef __ARM_NEON__ /* (the math is explained in the scalar version.) */
if (has_neon) {
const float32x4_t at_neon = vld1q_f32(at);
const float32x4_t U_neon = normalize_neon(xyzzy_neon(at_neon, vld1q_f32(up)));
const float32x4_t V_neon = xyzzy_neon(at_neon, U_neon);
const float32x4_t N_neon = normalize_neon(at_neon);
const float32x4_t rotated_neon = {
dotproduct_neon(position_neon, U_neon),
-dotproduct_neon(position_neon, V_neon),
-dotproduct_neon(position_neon, N_neon),
0.0f
};

const ALfloat mags = magnitude_neon(at_neon) * magnitude_neon(rotated_neon);
radians = (mags == 0.0f) ? 0.0f : SDL_acosf(dotproduct_neon(at_neon, rotated_neon) / mags);
if (rotated_neon[0] < 0.0f) {
const float32x4_t up_neon = vld1q_f32(up);
float32x4_t V_neon;
float32x4_t R_neon;
ALfloat cosangle;
ALfloat mags;
ALfloat a;

a = dotproduct_neon(position_neon, up_neon);
V_neon = vsubq_f32(position_neon, vmulq_f32(vdupq_n_f32(a), up_neon));

mags = magnitude_neon(at_neon) * magnitude_neon(V_neon);
cosangle = (mags == 0.0f) ? 0.0f : (dotproduct_neon(at_neon, V_neon) / mags);
cosangle = SDL_clamp(cosangle, -1.0f, 1.0f);
radians = SDL_acosf(cosangle);

R_neon = xyzzy_neon(at_neon, up_neon);

if (dotproduct_neon(R_neon, V_neon) < 0.0f) {
radians = -radians;
}

} else
#endif

{
#if NEED_SCALAR_FALLBACK
ALfloat U[3];
ALfloat V[3];
ALfloat N[3];
ALfloat rotated[3];
ALfloat R[3];
ALfloat mags;
ALfloat cosangle;
ALfloat a;

xyzzy(U, at, up);
normalize(U);
xyzzy(V, at, U);
SDL_memcpy(N, at, sizeof (N));
normalize(N);

/* we don't need the bottom row of the gluLookAt matrix, since we don't
translate. (Matrix * Vector) is just filling in each element of the
output vector with the dot product of a row of the matrix and the
vector. I made some of these negative to make it work for my purposes,
but that's not what GLU does here.
(This says gluLookAt is left-handed, so maybe that's part of it?)
https://stackoverflow.com/questions/25933581/how-u-v-n-camera-coordinate-system-explained-with-opengl
*/
rotated[0] = dotproduct(position, U);
rotated[1] = -dotproduct(position, V);
rotated[2] = -dotproduct(position, N);

/* At this point, we have rotated vector and we can calculate the angle
from 0 (directly in front of where the listener is facing) to 180
degrees (directly behind) ... */

mags = magnitude(at) * magnitude(rotated);
radians = (mags == 0.0f) ? 0.0f : SDL_acosf(dotproduct(at, rotated) / mags);
/* and we already have what we need to decide if those degrees are on the
listener's left or right...
https://gamedev.stackexchange.com/questions/43897/determining-if-something-is-on-the-right-or-left-side-of-an-object
...we already did this dot product: it's in rotated[0]. */
/* Remove upwards component so it lies completely within the horizontal plane. */
a = dotproduct(position, up);
V[0] = position[0] - (a * up[0]);
V[1] = position[1] - (a * up[1]);
V[2] = position[2] - (a * up[2]);

/* Calculate angle */
mags = magnitude(at) * magnitude(V);
cosangle = (mags == 0.0f) ? 0.0f : (dotproduct(at, V) / mags);
cosangle = SDL_clamp(cosangle, -1.0f, 1.0f);
radians = SDL_acosf(cosangle);

/* Get "right" vector */
xyzzy(R, at, up);

/* make it negative to the left, positive to the right. */
if (rotated[0] < 0.0f) {
if (dotproduct(R, V) < 0.0f) {
radians = -radians;
}
#endif
Expand Down Expand Up @@ -2770,7 +2764,7 @@ static ALsource *get_source(ALCcontext *ctx, const ALuint name, SourceBlock **_b
set_al_error(ctx, AL_INVALID_OPERATION);
if (_block) *_block = NULL;
return NULL;
} else if ((name == 0) || (blockidx >= ctx->num_source_blocks)) {
} else if ((name == 0) || (blockidx < 0) || (blockidx >= ctx->num_source_blocks)) {
set_al_error(ctx, AL_INVALID_NAME);
if (_block) *_block = NULL;
return NULL;
Expand Down Expand Up @@ -2802,7 +2796,7 @@ static ALbuffer *get_buffer(ALCcontext *ctx, const ALuint name, BufferBlock **_b
set_al_error(ctx, AL_INVALID_OPERATION);
if (_block) *_block = NULL;
return NULL;
} else if ((name == 0) || (blockidx >= ctx->device->playback.num_buffer_blocks)) {
} else if ((name == 0) || (blockidx < 0) || (blockidx >= ctx->device->playback.num_buffer_blocks)) {
set_al_error(ctx, AL_INVALID_NAME);
if (_block) *_block = NULL;
return NULL;
Expand Down Expand Up @@ -3494,9 +3488,14 @@ static void _alGenSources(const ALsizei n, ALuint *names)
ALsizei blocki;
ALsizei i;

if (!ctx) {
if (n < 0) {
set_al_error(ctx, AL_INVALID_VALUE);
return;
} else if (!ctx) {
set_al_error(ctx, AL_INVALID_OPERATION);
return;
} else if (n == 0) {
return; /* not an error, but nothing to do. */
}

if (n <= SDL_arraysize(stackobjs)) {
Expand Down Expand Up @@ -3631,7 +3630,10 @@ static void _alDeleteSources(const ALsizei n, const ALuint *names)
ALCcontext *ctx = get_current_context();
ALsizei i;

if (!ctx) {
if (n < 0) {
set_al_error(ctx, AL_INVALID_VALUE);
return;
} else if (!ctx) {
set_al_error(ctx, AL_INVALID_OPERATION);
return;
}
Expand Down Expand Up @@ -4066,7 +4068,7 @@ static void source_play(ALCcontext *ctx, const ALsizei n, const ALuint *names)
void *ptr;
ALsizei i;

if (n == 0) {
if (n <= 0) {
return;
} else if (!ctx) {
set_al_error(ctx, AL_INVALID_OPERATION);
Expand Down Expand Up @@ -4302,7 +4304,9 @@ static void source_set_offset(ALsource *src, ALenum param, ALfloat value)
void alSource##alfn(ALuint name) { source_##fn(get_current_context(), name); } \
void alSource##alfn##v(ALsizei n, const ALuint *sources) { \
ALCcontext *ctx = get_current_context(); \
if (!ctx) { \
if (n < 0) { \
set_al_error(ctx, AL_INVALID_VALUE); \
} else if (!ctx) { \
set_al_error(ctx, AL_INVALID_OPERATION); \
} else { \
ALsizei i; \
Expand Down Expand Up @@ -4346,8 +4350,11 @@ static void _alSourceQueueBuffers(const ALuint name, const ALsizei nb, const ALu
return;
}

if (nb == 0) {
return; /* nothing to do. */
if (nb < 0) {
set_al_error(ctx, AL_INVALID_VALUE);
return;
} else if (nb == 0) {
return; /* not an error, but nothing to do. */
}

for (i = nb; i > 0; i--) { /* build list in reverse */
Expand Down Expand Up @@ -4496,8 +4503,11 @@ static void _alSourceUnqueueBuffers(const ALuint name, const ALsizei nb, ALuint
return;
}

if (nb == 0) {
return; /* nothing to do. */
if (nb < 0) {
set_al_error(ctx, AL_INVALID_VALUE);
return;
} else if (nb == 0) {
return; /* not an error, but nothing to do. */
}

if (((ALsizei) SDL_AtomicGet(&src->buffer_queue_processed.num_items)) < nb) {
Expand Down Expand Up @@ -4551,9 +4561,14 @@ static void _alGenBuffers(const ALsizei n, ALuint *names)
ALsizei blocki;
ALsizei i;

if (!ctx) {
if (n < 0) {
set_al_error(ctx, AL_INVALID_VALUE);
return;
} else if (!ctx) {
set_al_error(ctx, AL_INVALID_OPERATION);
return;
} else if (n == 0) {
return; /* not an error, but nothing to do. */
}

if (n <= SDL_arraysize(stackobjs)) {
Expand Down Expand Up @@ -4665,9 +4680,14 @@ static void _alDeleteBuffers(const ALsizei n, const ALuint *names)
ALCcontext *ctx = get_current_context();
ALsizei i;

if (!ctx) {
if (n < 0) {
set_al_error(ctx, AL_INVALID_VALUE);
return;
} else if (!ctx) {
set_al_error(ctx, AL_INVALID_OPERATION);
return;
} else if (n == 0) {
return; /* not an error, but nothing to do. */
}

for (i = 0; i < n; i++) {
Expand Down Expand Up @@ -4724,6 +4744,13 @@ static void _alBufferData(const ALuint name, const ALenum alfmt, const ALvoid *d

if (!buffer) return;

if (size < 0) {
set_al_error(ctx, AL_INVALID_VALUE);
return;
} else if (freq < 0) {
return; /* not an error, but nothing to do. */
}

if (!alcfmt_to_sdlfmt(alfmt, &sdlfmt, &channels, &framesize)) {
set_al_error(ctx, AL_INVALID_VALUE);
return;
Expand Down

0 comments on commit 4fcd5cb

Please sign in to comment.