mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-07-05 15:34:48 +00:00
update mojoAL to current git
This commit is contained in:
parent
689d38ff10
commit
5fab8f4d81
2 changed files with 188 additions and 117 deletions
|
@ -44,6 +44,7 @@ if(AQUARIA_USE_SDL2 AND SDL2_FOUND)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(AQUARIA_USE_MOJOAL)
|
if(AQUARIA_USE_MOJOAL)
|
||||||
|
add_definitions(-DAL_LIBTYPE_STATIC=1)
|
||||||
set(xsrc ${xsrc} mojoal.c)
|
set(xsrc ${xsrc} mojoal.c)
|
||||||
set(OPENAL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/AL" CACHE PATH "OpenAL include directory" FORCE)
|
set(OPENAL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/AL" CACHE PATH "OpenAL include directory" FORCE)
|
||||||
else()
|
else()
|
||||||
|
|
|
@ -11,7 +11,10 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
/* Unless compiling statically into another app, we want the public API
|
||||||
|
to export on Windows. Define these before including al.h, so we override
|
||||||
|
its attempt to mark these as `dllimport`. */
|
||||||
|
#if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
|
||||||
#define AL_API __declspec(dllexport)
|
#define AL_API __declspec(dllexport)
|
||||||
#define ALC_API __declspec(dllexport)
|
#define ALC_API __declspec(dllexport)
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,7 +27,18 @@
|
||||||
#include "alc.h"
|
#include "alc.h"
|
||||||
#include "SDL.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
|
#define NEED_SCALAR_FALLBACK 0
|
||||||
#elif (defined(__ARM_ARCH) && (__ARM_ARCH >= 8)) /* ARMv8 always has NEON. */
|
#elif (defined(__ARM_ARCH) && (__ARM_ARCH >= 8)) /* ARMv8 always has NEON. */
|
||||||
#define NEED_SCALAR_FALLBACK 0
|
#define NEED_SCALAR_FALLBACK 0
|
||||||
|
@ -38,7 +52,7 @@
|
||||||
|
|
||||||
/* Some platforms fail to define __ARM_NEON__, others need it or arm_neon.h will fail. */
|
/* Some platforms fail to define __ARM_NEON__, others need it or arm_neon.h will fail. */
|
||||||
#if (defined(__ARM_ARCH) || defined(_M_ARM))
|
#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
|
# define __ARM_NEON__ 1
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -470,6 +484,7 @@ SIMDALIGNEDSTRUCT ALsource
|
||||||
ALfloat cone_outer_gain;
|
ALfloat cone_outer_gain;
|
||||||
ALbuffer *buffer;
|
ALbuffer *buffer;
|
||||||
SDL_AudioStream *stream; /* for resampling. */
|
SDL_AudioStream *stream; /* for resampling. */
|
||||||
|
SDL_atomic_t total_queued_buffers; /* everything queued, playing and processed. AL_BUFFERS_QUEUED value. */
|
||||||
BufferQueue buffer_queue;
|
BufferQueue buffer_queue;
|
||||||
BufferQueue buffer_queue_processed;
|
BufferQueue buffer_queue_processed;
|
||||||
ALsizei offset; /* offset in bytes for converted stream! */
|
ALsizei offset; /* offset in bytes for converted stream! */
|
||||||
|
@ -1194,11 +1209,11 @@ static void pitch_fft(float *fftBuffer, int fftFrameSize, int sign)
|
||||||
for (k = 0, le = 2; k < endval; k++) {
|
for (k = 0, le = 2; k < endval; k++) {
|
||||||
le <<= 1;
|
le <<= 1;
|
||||||
le2 = le>>1;
|
le2 = le>>1;
|
||||||
ur = 1.0;
|
ur = 1.0f;
|
||||||
ui = 0.0;
|
ui = 0.0f;
|
||||||
arg = M_PI / (le2>>1);
|
arg = (float) (M_PI / (le2>>1));
|
||||||
wr = SDL_cos(arg);
|
wr = SDL_cosf(arg);
|
||||||
wi = sign*SDL_sin(arg);
|
wi = sign*SDL_sinf(arg);
|
||||||
for (j = 0; j < le2; j += 2) {
|
for (j = 0; j < le2; j += 2) {
|
||||||
p1r = fftBuffer+j; p1i = p1r+1;
|
p1r = fftBuffer+j; p1i = p1r+1;
|
||||||
p2r = p1r+le2; p2i = p2r+1;
|
p2r = p1r+le2; p2i = p2r+1;
|
||||||
|
@ -1250,8 +1265,8 @@ static void pitch_shift(ALsource *src, const ALbuffer *buffer, int numSampsToPro
|
||||||
/* do windowing and re,im interleave */
|
/* do windowing and re,im interleave */
|
||||||
for (k = 0; k < pitch_framesize;k++) {
|
for (k = 0; k < pitch_framesize;k++) {
|
||||||
window = -.5*SDL_cos(2.*M_PI*(double)k/(double)pitch_framesize)+.5;
|
window = -.5*SDL_cos(2.*M_PI*(double)k/(double)pitch_framesize)+.5;
|
||||||
state->workspace[2*k] = state->infifo[k] * window;
|
state->workspace[2*k] = (ALfloat) (state->infifo[k] * window);
|
||||||
state->workspace[2*k+1] = 0.;
|
state->workspace[2*k+1] = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1272,13 +1287,13 @@ static void pitch_shift(ALsource *src, const ALbuffer *buffer, int numSampsToPro
|
||||||
|
|
||||||
/* compute phase difference */
|
/* compute phase difference */
|
||||||
tmp = phase - state->lastphase[k];
|
tmp = phase - state->lastphase[k];
|
||||||
state->lastphase[k] = phase;
|
state->lastphase[k] = (ALfloat) phase;
|
||||||
|
|
||||||
/* subtract expected phase difference */
|
/* subtract expected phase difference */
|
||||||
tmp -= (double)k*expct;
|
tmp -= (double)k*expct;
|
||||||
|
|
||||||
/* map delta phase into +/- Pi interval */
|
/* map delta phase into +/- Pi interval */
|
||||||
qpd = tmp/M_PI;
|
qpd = (int) (tmp/M_PI);
|
||||||
if (qpd >= 0) qpd += qpd&1;
|
if (qpd >= 0) qpd += qpd&1;
|
||||||
else qpd -= qpd&1;
|
else qpd -= qpd&1;
|
||||||
tmp -= M_PI*(double)qpd;
|
tmp -= M_PI*(double)qpd;
|
||||||
|
@ -1290,8 +1305,8 @@ static void pitch_shift(ALsource *src, const ALbuffer *buffer, int numSampsToPro
|
||||||
tmp = (double)k*freqPerBin + tmp*freqPerBin;
|
tmp = (double)k*freqPerBin + tmp*freqPerBin;
|
||||||
|
|
||||||
/* store magnitude and true frequency in analysis arrays */
|
/* store magnitude and true frequency in analysis arrays */
|
||||||
state->workspace[2*k] = magn;
|
state->workspace[2*k] = (ALfloat) magn;
|
||||||
state->workspace[2*k+1] = tmp;
|
state->workspace[2*k+1] = (ALfloat) tmp;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1299,7 +1314,7 @@ static void pitch_shift(ALsource *src, const ALbuffer *buffer, int numSampsToPro
|
||||||
/* this does the actual pitch shifting */
|
/* this does the actual pitch shifting */
|
||||||
SDL_memset(state->synmagn, '\0', sizeof (state->synmagn));
|
SDL_memset(state->synmagn, '\0', sizeof (state->synmagn));
|
||||||
for (k = 0; k <= pitch_framesize2; k++) {
|
for (k = 0; k <= pitch_framesize2; k++) {
|
||||||
index = k*pitchShift;
|
index = (int) (k*pitchShift);
|
||||||
if (index <= pitch_framesize2) {
|
if (index <= pitch_framesize2) {
|
||||||
state->synmagn[index] += state->workspace[2*k];
|
state->synmagn[index] += state->workspace[2*k];
|
||||||
state->synfreq[index] = state->workspace[2*k+1] * pitchShift;
|
state->synfreq[index] = state->workspace[2*k+1] * pitchShift;
|
||||||
|
@ -1327,12 +1342,12 @@ static void pitch_shift(ALsource *src, const ALbuffer *buffer, int numSampsToPro
|
||||||
tmp += (double)k*expct;
|
tmp += (double)k*expct;
|
||||||
|
|
||||||
/* accumulate delta phase to get bin phase */
|
/* accumulate delta phase to get bin phase */
|
||||||
state->sumphase[k] += tmp;
|
state->sumphase[k] += (ALfloat) tmp;
|
||||||
phase = state->sumphase[k];
|
phase = state->sumphase[k];
|
||||||
|
|
||||||
/* get real and imag part and re-interleave */
|
/* get real and imag part and re-interleave */
|
||||||
state->workspace[2*k] = magn*SDL_cos(phase);
|
state->workspace[2*k] = (ALfloat) (magn*SDL_cos(phase));
|
||||||
state->workspace[2*k+1] = magn*SDL_sin(phase);
|
state->workspace[2*k+1] = (ALfloat) (magn*SDL_sin(phase));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* zero negative frequencies */
|
/* zero negative frequencies */
|
||||||
|
@ -1344,7 +1359,7 @@ static void pitch_shift(ALsource *src, const ALbuffer *buffer, int numSampsToPro
|
||||||
/* do windowing and add to output accumulator */
|
/* do windowing and add to output accumulator */
|
||||||
for(k=0; k < pitch_framesize; k++) {
|
for(k=0; k < pitch_framesize; k++) {
|
||||||
window = -.5*SDL_cos(2.*M_PI*(double)k/(double)pitch_framesize)+.5;
|
window = -.5*SDL_cos(2.*M_PI*(double)k/(double)pitch_framesize)+.5;
|
||||||
state->outputaccum[k] += 2.*window*state->workspace[2*k]/(pitch_framesize2*osamp);
|
state->outputaccum[k] += (ALfloat) (2.*window*state->workspace[2*k]/(pitch_framesize2*osamp));
|
||||||
}
|
}
|
||||||
for (k = 0; k < stepSize; k++) state->outfifo[k] = state->outputaccum[k];
|
for (k = 0; k < stepSize; k++) state->outfifo[k] = state->outputaccum[k];
|
||||||
|
|
||||||
|
@ -1417,12 +1432,15 @@ static ALboolean mix_source_buffer(ALCcontext *ctx, ALsource *src, BufferQueueIt
|
||||||
if (src->stream) { /* resampling? */
|
if (src->stream) { /* resampling? */
|
||||||
int mixframes, mixlen, remainingmixframes;
|
int mixframes, mixlen, remainingmixframes;
|
||||||
while ( (((mixlen = SDL_AudioStreamAvailable(src->stream)) / bufferframesize) < framesneeded) && (src->offset < buffer->len) ) {
|
while ( (((mixlen = SDL_AudioStreamAvailable(src->stream)) / bufferframesize) < framesneeded) && (src->offset < buffer->len) ) {
|
||||||
const int framesput = (buffer->len - src->offset) / bufferframesize;
|
const int bytesleft = (buffer->len - src->offset);
|
||||||
const int bytesput = SDL_min(framesput, 1024) * bufferframesize;
|
/* workaround in case remains are less than bufferframesize */
|
||||||
|
const int framesput = (bytesleft + (bufferframesize - 1)) / bufferframesize;
|
||||||
|
const int bytesput = SDL_min(SDL_min(framesput, 1024) * bufferframesize, bytesleft);
|
||||||
FIXME("dynamically adjust frames here?"); /* we hardcode 1024 samples when opening the audio device, too. */
|
FIXME("dynamically adjust frames here?"); /* we hardcode 1024 samples when opening the audio device, too. */
|
||||||
SDL_AudioStreamPut(src->stream, data, bytesput);
|
SDL_AudioStreamPut(src->stream, data, bytesput);
|
||||||
src->offset += bytesput;
|
src->offset += bytesput;
|
||||||
data += bytesput / sizeof (float);
|
/* workaround in case remains are not evenly divided by sizeof (float) */
|
||||||
|
data += (bytesput + (sizeof (float) - 1)) / sizeof (float);
|
||||||
}
|
}
|
||||||
|
|
||||||
mixframes = SDL_min(mixlen / bufferframesize, framesneeded);
|
mixframes = SDL_min(mixlen / bufferframesize, framesneeded);
|
||||||
|
@ -1733,12 +1751,13 @@ static void calculate_channel_gains(const ALCcontext *ctx, const ALsource *src,
|
||||||
|
|
||||||
{
|
{
|
||||||
#if NEED_SCALAR_FALLBACK
|
#if NEED_SCALAR_FALLBACK
|
||||||
SDL_memcpy(position, src->position, sizeof (position));
|
|
||||||
/* if values aren't source-relative, then convert it to be so. */
|
/* if values aren't source-relative, then convert it to be so. */
|
||||||
if (!src->source_relative) {
|
if (!src->source_relative) {
|
||||||
position[0] -= ctx->listener.position[0];
|
SDL_memcpy(position, src->position, sizeof (position));
|
||||||
position[1] -= ctx->listener.position[1];
|
} else {
|
||||||
position[2] -= ctx->listener.position[2];
|
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);
|
distance = magnitude(position);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1779,39 +1798,34 @@ static void calculate_channel_gains(const ALCcontext *ctx, const ALsource *src,
|
||||||
|
|
||||||
https://dsp.stackexchange.com/questions/21691/algorithm-to-pan-audio
|
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
|
XYZZY!! https://en.wikipedia.org/wiki/Cross_product#Mnemonic
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef __SSE__ /* (the math is explained in the scalar version.) */
|
#ifdef __SSE__ /* (the math is explained in the scalar version.) */
|
||||||
if (has_sse) {
|
if (has_sse) {
|
||||||
const __m128 at_sse = _mm_load_ps(at);
|
const __m128 at_sse = _mm_load_ps(at);
|
||||||
const __m128 U_sse = normalize_sse(xyzzy_sse(at_sse, _mm_load_ps(up)));
|
const __m128 up_sse = _mm_load_ps(up);
|
||||||
const __m128 V_sse = xyzzy_sse(at_sse, U_sse);
|
__m128 V_sse;
|
||||||
const __m128 N_sse = normalize_sse(at_sse);
|
__m128 R_sse;
|
||||||
const __m128 rotated_sse = {
|
ALfloat cosangle;
|
||||||
dotproduct_sse(position_sse, U_sse),
|
ALfloat mags;
|
||||||
-dotproduct_sse(position_sse, V_sse),
|
ALfloat a;
|
||||||
-dotproduct_sse(position_sse, N_sse),
|
|
||||||
0.0f
|
|
||||||
};
|
|
||||||
|
|
||||||
const ALfloat mags = magnitude_sse(at_sse) * magnitude_sse(rotated_sse);
|
a = dotproduct_sse(position_sse, up_sse);
|
||||||
radians = (mags == 0.0f) ? 0.0f : SDL_acosf(dotproduct_sse(at_sse, rotated_sse) / mags);
|
V_sse = _mm_sub_ps(position_sse, _mm_mul_ps(_mm_set1_ps(a), up_sse));
|
||||||
if (_mm_comilt_ss(rotated_sse, _mm_setzero_ps())) {
|
|
||||||
|
mags = magnitude_sse(at_sse) * magnitude_sse(V_sse);
|
||||||
|
if (mags == 0.0f) {
|
||||||
|
radians = 0.0f;
|
||||||
|
} else {
|
||||||
|
cosangle = 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;
|
radians = -radians;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -1820,64 +1834,63 @@ static void calculate_channel_gains(const ALCcontext *ctx, const ALsource *src,
|
||||||
#ifdef __ARM_NEON__ /* (the math is explained in the scalar version.) */
|
#ifdef __ARM_NEON__ /* (the math is explained in the scalar version.) */
|
||||||
if (has_neon) {
|
if (has_neon) {
|
||||||
const float32x4_t at_neon = vld1q_f32(at);
|
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 up_neon = vld1q_f32(up);
|
||||||
const float32x4_t V_neon = xyzzy_neon(at_neon, U_neon);
|
float32x4_t V_neon;
|
||||||
const float32x4_t N_neon = normalize_neon(at_neon);
|
float32x4_t R_neon;
|
||||||
const float32x4_t rotated_neon = {
|
ALfloat cosangle;
|
||||||
dotproduct_neon(position_neon, U_neon),
|
ALfloat mags;
|
||||||
-dotproduct_neon(position_neon, V_neon),
|
ALfloat a;
|
||||||
-dotproduct_neon(position_neon, N_neon),
|
|
||||||
0.0f
|
|
||||||
};
|
|
||||||
|
|
||||||
const ALfloat mags = magnitude_neon(at_neon) * magnitude_neon(rotated_neon);
|
a = dotproduct_neon(position_neon, up_neon);
|
||||||
radians = (mags == 0.0f) ? 0.0f : SDL_acosf(dotproduct_neon(at_neon, rotated_neon) / mags);
|
V_neon = vsubq_f32(position_neon, vmulq_f32(vdupq_n_f32(a), up_neon));
|
||||||
if (rotated_neon[0] < 0.0f) {
|
|
||||||
|
mags = magnitude_neon(at_neon) * magnitude_neon(V_neon);
|
||||||
|
if (mags == 0.0f) {
|
||||||
|
radians = 0.0f;
|
||||||
|
} else {
|
||||||
|
cosangle = 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;
|
radians = -radians;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
#if NEED_SCALAR_FALLBACK
|
#if NEED_SCALAR_FALLBACK
|
||||||
ALfloat U[3];
|
|
||||||
ALfloat V[3];
|
ALfloat V[3];
|
||||||
ALfloat N[3];
|
ALfloat R[3];
|
||||||
ALfloat rotated[3];
|
|
||||||
ALfloat mags;
|
ALfloat mags;
|
||||||
|
ALfloat cosangle;
|
||||||
|
ALfloat a;
|
||||||
|
|
||||||
xyzzy(U, at, up);
|
/* Remove upwards component so it lies completely within the horizontal plane. */
|
||||||
normalize(U);
|
a = dotproduct(position, up);
|
||||||
xyzzy(V, at, U);
|
V[0] = position[0] - (a * up[0]);
|
||||||
SDL_memcpy(N, at, sizeof (N));
|
V[1] = position[1] - (a * up[1]);
|
||||||
normalize(N);
|
V[2] = position[2] - (a * up[2]);
|
||||||
|
|
||||||
/* we don't need the bottom row of the gluLookAt matrix, since we don't
|
/* Calculate angle */
|
||||||
translate. (Matrix * Vector) is just filling in each element of the
|
mags = magnitude(at) * magnitude(V);
|
||||||
output vector with the dot product of a row of the matrix and the
|
if (mags == 0.0f) {
|
||||||
vector. I made some of these negative to make it work for my purposes,
|
radians = 0.0f;
|
||||||
but that's not what GLU does here.
|
} else {
|
||||||
|
cosangle = dotproduct(at, V) / mags;
|
||||||
|
cosangle = SDL_clamp(cosangle, -1.0f, 1.0f);
|
||||||
|
radians = SDL_acosf(cosangle);
|
||||||
|
}
|
||||||
|
|
||||||
(This says gluLookAt is left-handed, so maybe that's part of it?)
|
/* Get "right" vector */
|
||||||
https://stackoverflow.com/questions/25933581/how-u-v-n-camera-coordinate-system-explained-with-opengl
|
xyzzy(R, at, up);
|
||||||
*/
|
|
||||||
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]. */
|
|
||||||
|
|
||||||
/* make it negative to the left, positive to the right. */
|
/* make it negative to the left, positive to the right. */
|
||||||
if (rotated[0] < 0.0f) {
|
if (dotproduct(R, V) < 0.0f) {
|
||||||
radians = -radians;
|
radians = -radians;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2569,6 +2582,16 @@ static void _alcGetIntegerv(ALCdevice *device, const ALCenum param, const ALCsiz
|
||||||
*values = OPENAL_VERSION_MINOR;
|
*values = OPENAL_VERSION_MINOR;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case ALC_FREQUENCY:
|
||||||
|
if (!device) {
|
||||||
|
*values = 0;
|
||||||
|
set_alc_error(device, ALC_INVALID_DEVICE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*values = device->frequency;
|
||||||
|
return;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2754,7 +2777,7 @@ static ALsource *get_source(ALCcontext *ctx, const ALuint name, SourceBlock **_b
|
||||||
set_al_error(ctx, AL_INVALID_OPERATION);
|
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||||
if (_block) *_block = NULL;
|
if (_block) *_block = NULL;
|
||||||
return 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);
|
set_al_error(ctx, AL_INVALID_NAME);
|
||||||
if (_block) *_block = NULL;
|
if (_block) *_block = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2786,7 +2809,7 @@ static ALbuffer *get_buffer(ALCcontext *ctx, const ALuint name, BufferBlock **_b
|
||||||
set_al_error(ctx, AL_INVALID_OPERATION);
|
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||||
if (_block) *_block = NULL;
|
if (_block) *_block = NULL;
|
||||||
return 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);
|
set_al_error(ctx, AL_INVALID_NAME);
|
||||||
if (_block) *_block = NULL;
|
if (_block) *_block = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2921,7 +2944,7 @@ static const ALchar *_alGetString(const ALenum param)
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ENTRYPOINT(const ALchar *,alGetString,(const ALenum param),(param))
|
ENTRYPOINT(const ALchar *,alGetString,(ALenum param),(param))
|
||||||
|
|
||||||
static void _alGetBooleanv(const ALenum param, ALboolean *values)
|
static void _alGetBooleanv(const ALenum param, ALboolean *values)
|
||||||
{
|
{
|
||||||
|
@ -3478,9 +3501,14 @@ static void _alGenSources(const ALsizei n, ALuint *names)
|
||||||
ALsizei blocki;
|
ALsizei blocki;
|
||||||
ALsizei i;
|
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);
|
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||||
return;
|
return;
|
||||||
|
} else if (n == 0) {
|
||||||
|
return; /* not an error, but nothing to do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n <= SDL_arraysize(stackobjs)) {
|
if (n <= SDL_arraysize(stackobjs)) {
|
||||||
|
@ -3589,6 +3617,7 @@ static void _alGenSources(const ALsizei n, ALuint *names)
|
||||||
|
|
||||||
SDL_zerop(src);
|
SDL_zerop(src);
|
||||||
SDL_AtomicSet(&src->state, AL_INITIAL);
|
SDL_AtomicSet(&src->state, AL_INITIAL);
|
||||||
|
SDL_AtomicSet(&src->total_queued_buffers, 0);
|
||||||
src->name = names[i];
|
src->name = names[i];
|
||||||
src->type = AL_UNDETERMINED;
|
src->type = AL_UNDETERMINED;
|
||||||
src->recalc = AL_TRUE;
|
src->recalc = AL_TRUE;
|
||||||
|
@ -3614,7 +3643,10 @@ static void _alDeleteSources(const ALsizei n, const ALuint *names)
|
||||||
ALCcontext *ctx = get_current_context();
|
ALCcontext *ctx = get_current_context();
|
||||||
ALsizei i;
|
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);
|
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3906,7 +3938,7 @@ static void _alGetSourcefv(const ALuint name, const ALenum param, ALfloat *value
|
||||||
case AL_REFERENCE_DISTANCE: *values = src->reference_distance; break;
|
case AL_REFERENCE_DISTANCE: *values = src->reference_distance; break;
|
||||||
case AL_ROLLOFF_FACTOR: *values = src->rolloff_factor; break;
|
case AL_ROLLOFF_FACTOR: *values = src->rolloff_factor; break;
|
||||||
case AL_MAX_DISTANCE: *values = src->max_distance; break;
|
case AL_MAX_DISTANCE: *values = src->max_distance; break;
|
||||||
case AL_PITCH: source_set_pitch(ctx, src, *values); break;
|
case AL_PITCH: *values = src->pitch; break;
|
||||||
case AL_CONE_INNER_ANGLE: *values = src->cone_inner_angle; break;
|
case AL_CONE_INNER_ANGLE: *values = src->cone_inner_angle; break;
|
||||||
case AL_CONE_OUTER_ANGLE: *values = src->cone_outer_angle; break;
|
case AL_CONE_OUTER_ANGLE: *values = src->cone_outer_angle; break;
|
||||||
case AL_CONE_OUTER_GAIN: *values = src->cone_outer_gain; break;
|
case AL_CONE_OUTER_GAIN: *values = src->cone_outer_gain; break;
|
||||||
|
@ -3973,8 +4005,7 @@ static void _alGetSourceiv(const ALuint name, const ALenum param, ALint *values)
|
||||||
case AL_SOURCE_STATE: *values = (ALint) SDL_AtomicGet(&src->state); break;
|
case AL_SOURCE_STATE: *values = (ALint) SDL_AtomicGet(&src->state); break;
|
||||||
case AL_SOURCE_TYPE: *values = (ALint) src->type; break;
|
case AL_SOURCE_TYPE: *values = (ALint) src->type; break;
|
||||||
case AL_BUFFER: *values = (ALint) (src->buffer ? src->buffer->name : 0); break;
|
case AL_BUFFER: *values = (ALint) (src->buffer ? src->buffer->name : 0); break;
|
||||||
/* !!! FIXME: AL_BUFFERS_QUEUED is the total number of buffers pending, playing, and processed, so this is wrong. It might also have to be 1 if there's a static buffer, but I'm not sure. */
|
case AL_BUFFERS_QUEUED: *values = (ALint) SDL_AtomicGet(&src->total_queued_buffers); break;
|
||||||
case AL_BUFFERS_QUEUED: *values = (ALint) SDL_AtomicGet(&src->buffer_queue.num_items); break;
|
|
||||||
case AL_BUFFERS_PROCESSED: *values = (ALint) SDL_AtomicGet(&src->buffer_queue_processed.num_items); break;
|
case AL_BUFFERS_PROCESSED: *values = (ALint) SDL_AtomicGet(&src->buffer_queue_processed.num_items); break;
|
||||||
case AL_SOURCE_RELATIVE: *values = (ALint) src->source_relative; break;
|
case AL_SOURCE_RELATIVE: *values = (ALint) src->source_relative; break;
|
||||||
case AL_LOOPING: *values = (ALint) src->looping; break;
|
case AL_LOOPING: *values = (ALint) src->looping; break;
|
||||||
|
@ -4050,7 +4081,7 @@ static void source_play(ALCcontext *ctx, const ALsizei n, const ALuint *names)
|
||||||
void *ptr;
|
void *ptr;
|
||||||
ALsizei i;
|
ALsizei i;
|
||||||
|
|
||||||
if (n == 0) {
|
if (n <= 0) {
|
||||||
return;
|
return;
|
||||||
} else if (!ctx) {
|
} else if (!ctx) {
|
||||||
set_al_error(ctx, AL_INVALID_OPERATION);
|
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||||
|
@ -4162,6 +4193,9 @@ static void source_stop(ALCcontext *ctx, const ALuint name)
|
||||||
}
|
}
|
||||||
SDL_AtomicSet(&src->state, AL_STOPPED);
|
SDL_AtomicSet(&src->state, AL_STOPPED);
|
||||||
source_mark_all_buffers_processed(src);
|
source_mark_all_buffers_processed(src);
|
||||||
|
if (src->stream) {
|
||||||
|
SDL_AudioStreamClear(src->stream);
|
||||||
|
}
|
||||||
if (must_lock) {
|
if (must_lock) {
|
||||||
SDL_UnlockMutex(ctx->source_lock);
|
SDL_UnlockMutex(ctx->source_lock);
|
||||||
}
|
}
|
||||||
|
@ -4228,9 +4262,10 @@ static void source_set_offset(ALsource *src, ALenum param, ALfloat value)
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
set_al_error(ctx, AL_INVALID_OPERATION);
|
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||||
return;
|
return;
|
||||||
}
|
} else if (src->type == AL_UNDETERMINED) { /* no buffer to seek in */
|
||||||
|
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||||
if (src->type == AL_STREAMING) {
|
return;
|
||||||
|
} else if (src->type == AL_STREAMING) {
|
||||||
FIXME("set_offset for streaming sources not implemented");
|
FIXME("set_offset for streaming sources not implemented");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4242,14 +4277,18 @@ static void source_set_offset(ALsource *src, ALenum param, ALfloat value)
|
||||||
|
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case AL_SAMPLE_OFFSET:
|
case AL_SAMPLE_OFFSET:
|
||||||
offset = value * framesize;
|
offset = ((int) value) * framesize;
|
||||||
break;
|
break;
|
||||||
case AL_SEC_OFFSET:
|
case AL_SEC_OFFSET:
|
||||||
offset = value * freq * framesize;
|
offset = ((int) value) * freq * framesize;
|
||||||
break;
|
break;
|
||||||
case AL_BYTE_OFFSET:
|
case AL_BYTE_OFFSET:
|
||||||
offset = ((int)value / framesize) * framesize;
|
offset = (((int) value) / framesize) * framesize;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
SDL_assert(!"Unexpected source offset type!");
|
||||||
|
set_al_error(ctx, AL_INVALID_ENUM); /* this is a MojoAL bug, not an app bug, but we'll try to recover. */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((offset < 0) || (offset > bufflen)) {
|
if ((offset < 0) || (offset > bufflen)) {
|
||||||
|
@ -4267,6 +4306,10 @@ static void source_set_offset(ALsource *src, ALenum param, ALfloat value)
|
||||||
src->offset = offset;
|
src->offset = offset;
|
||||||
SDL_UnlockMutex(ctx->source_lock);
|
SDL_UnlockMutex(ctx->source_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SDL_AtomicGet(&src->state) != AL_PLAYING) {
|
||||||
|
src->offset_latched = SDL_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deal with alSourcePlay and alSourcePlayv (etc) boiler plate... */
|
/* deal with alSourcePlay and alSourcePlayv (etc) boiler plate... */
|
||||||
|
@ -4274,7 +4317,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(ALuint name) { source_##fn(get_current_context(), name); } \
|
||||||
void alSource##alfn##v(ALsizei n, const ALuint *sources) { \
|
void alSource##alfn##v(ALsizei n, const ALuint *sources) { \
|
||||||
ALCcontext *ctx = get_current_context(); \
|
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); \
|
set_al_error(ctx, AL_INVALID_OPERATION); \
|
||||||
} else { \
|
} else { \
|
||||||
ALsizei i; \
|
ALsizei i; \
|
||||||
|
@ -4318,8 +4363,11 @@ static void _alSourceQueueBuffers(const ALuint name, const ALsizei nb, const ALu
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nb == 0) {
|
if (nb < 0) {
|
||||||
return; /* nothing to do. */
|
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 */
|
for (i = nb; i > 0; i--) { /* build list in reverse */
|
||||||
|
@ -4446,6 +4494,7 @@ static void _alSourceQueueBuffers(const ALuint name, const ALsizei nb, const ALu
|
||||||
SDL_AtomicSetPtr(&queueend->next, ptr);
|
SDL_AtomicSetPtr(&queueend->next, ptr);
|
||||||
} while (!SDL_AtomicCASPtr(&src->buffer_queue.just_queued, ptr, queue));
|
} while (!SDL_AtomicCASPtr(&src->buffer_queue.just_queued, ptr, queue));
|
||||||
|
|
||||||
|
SDL_AtomicAdd(&src->total_queued_buffers, (int) nb);
|
||||||
SDL_AtomicAdd(&src->buffer_queue.num_items, (int) nb);
|
SDL_AtomicAdd(&src->buffer_queue.num_items, (int) nb);
|
||||||
}
|
}
|
||||||
ENTRYPOINTVOID(alSourceQueueBuffers,(ALuint name, ALsizei nb, const ALuint *bufnames),(name,nb,bufnames))
|
ENTRYPOINTVOID(alSourceQueueBuffers,(ALuint name, ALsizei nb, const ALuint *bufnames),(name,nb,bufnames))
|
||||||
|
@ -4467,8 +4516,11 @@ static void _alSourceUnqueueBuffers(const ALuint name, const ALsizei nb, ALuint
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nb == 0) {
|
if (nb < 0) {
|
||||||
return; /* nothing to do. */
|
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) {
|
if (((ALsizei) SDL_AtomicGet(&src->buffer_queue_processed.num_items)) < nb) {
|
||||||
|
@ -4477,6 +4529,7 @@ static void _alSourceUnqueueBuffers(const ALuint name, const ALsizei nb, ALuint
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_AtomicAdd(&src->buffer_queue_processed.num_items, -((int) nb));
|
SDL_AtomicAdd(&src->buffer_queue_processed.num_items, -((int) nb));
|
||||||
|
SDL_AtomicAdd(&src->total_queued_buffers, -((int) nb));
|
||||||
|
|
||||||
obtain_newly_queued_buffers(&src->buffer_queue_processed);
|
obtain_newly_queued_buffers(&src->buffer_queue_processed);
|
||||||
|
|
||||||
|
@ -4521,9 +4574,14 @@ static void _alGenBuffers(const ALsizei n, ALuint *names)
|
||||||
ALsizei blocki;
|
ALsizei blocki;
|
||||||
ALsizei i;
|
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);
|
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||||
return;
|
return;
|
||||||
|
} else if (n == 0) {
|
||||||
|
return; /* not an error, but nothing to do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n <= SDL_arraysize(stackobjs)) {
|
if (n <= SDL_arraysize(stackobjs)) {
|
||||||
|
@ -4635,9 +4693,14 @@ static void _alDeleteBuffers(const ALsizei n, const ALuint *names)
|
||||||
ALCcontext *ctx = get_current_context();
|
ALCcontext *ctx = get_current_context();
|
||||||
ALsizei i;
|
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);
|
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||||
return;
|
return;
|
||||||
|
} else if (n == 0) {
|
||||||
|
return; /* not an error, but nothing to do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
|
@ -4694,6 +4757,13 @@ static void _alBufferData(const ALuint name, const ALenum alfmt, const ALvoid *d
|
||||||
|
|
||||||
if (!buffer) return;
|
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)) {
|
if (!alcfmt_to_sdlfmt(alfmt, &sdlfmt, &channels, &framesize)) {
|
||||||
set_al_error(ctx, AL_INVALID_VALUE);
|
set_al_error(ctx, AL_INVALID_VALUE);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue