mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-05-10 19:13:44 +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()
|
||||
|
||||
if(AQUARIA_USE_MOJOAL)
|
||||
add_definitions(-DAL_LIBTYPE_STATIC=1)
|
||||
set(xsrc ${xsrc} mojoal.c)
|
||||
set(OPENAL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/AL" CACHE PATH "OpenAL include directory" FORCE)
|
||||
else()
|
||||
|
|
|
@ -11,7 +11,10 @@
|
|||
#include <math.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 ALC_API __declspec(dllexport)
|
||||
#endif
|
||||
|
@ -24,7 +27,18 @@
|
|||
#include "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
|
||||
|
@ -38,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
|
||||
|
@ -470,6 +484,7 @@ SIMDALIGNEDSTRUCT ALsource
|
|||
ALfloat cone_outer_gain;
|
||||
ALbuffer *buffer;
|
||||
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_processed;
|
||||
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++) {
|
||||
le <<= 1;
|
||||
le2 = le>>1;
|
||||
ur = 1.0;
|
||||
ui = 0.0;
|
||||
arg = M_PI / (le2>>1);
|
||||
wr = SDL_cos(arg);
|
||||
wi = sign*SDL_sin(arg);
|
||||
ur = 1.0f;
|
||||
ui = 0.0f;
|
||||
arg = (float) (M_PI / (le2>>1));
|
||||
wr = SDL_cosf(arg);
|
||||
wi = sign*SDL_sinf(arg);
|
||||
for (j = 0; j < le2; j += 2) {
|
||||
p1r = fftBuffer+j; p1i = p1r+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 */
|
||||
for (k = 0; k < pitch_framesize;k++) {
|
||||
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+1] = 0.;
|
||||
state->workspace[2*k] = (ALfloat) (state->infifo[k] * window);
|
||||
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 */
|
||||
tmp = phase - state->lastphase[k];
|
||||
state->lastphase[k] = phase;
|
||||
state->lastphase[k] = (ALfloat) phase;
|
||||
|
||||
/* subtract expected phase difference */
|
||||
tmp -= (double)k*expct;
|
||||
|
||||
/* map delta phase into +/- Pi interval */
|
||||
qpd = tmp/M_PI;
|
||||
qpd = (int) (tmp/M_PI);
|
||||
if (qpd >= 0) qpd += qpd&1;
|
||||
else qpd -= qpd&1;
|
||||
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;
|
||||
|
||||
/* store magnitude and true frequency in analysis arrays */
|
||||
state->workspace[2*k] = magn;
|
||||
state->workspace[2*k+1] = tmp;
|
||||
state->workspace[2*k] = (ALfloat) magn;
|
||||
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 */
|
||||
SDL_memset(state->synmagn, '\0', sizeof (state->synmagn));
|
||||
for (k = 0; k <= pitch_framesize2; k++) {
|
||||
index = k*pitchShift;
|
||||
index = (int) (k*pitchShift);
|
||||
if (index <= pitch_framesize2) {
|
||||
state->synmagn[index] += state->workspace[2*k];
|
||||
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;
|
||||
|
||||
/* accumulate delta phase to get bin phase */
|
||||
state->sumphase[k] += tmp;
|
||||
state->sumphase[k] += (ALfloat) tmp;
|
||||
phase = state->sumphase[k];
|
||||
|
||||
/* get real and imag part and re-interleave */
|
||||
state->workspace[2*k] = magn*SDL_cos(phase);
|
||||
state->workspace[2*k+1] = magn*SDL_sin(phase);
|
||||
state->workspace[2*k] = (ALfloat) (magn*SDL_cos(phase));
|
||||
state->workspace[2*k+1] = (ALfloat) (magn*SDL_sin(phase));
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
for(k=0; k < pitch_framesize; k++) {
|
||||
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];
|
||||
|
||||
|
@ -1417,12 +1432,15 @@ static ALboolean mix_source_buffer(ALCcontext *ctx, ALsource *src, BufferQueueIt
|
|||
if (src->stream) { /* resampling? */
|
||||
int mixframes, mixlen, remainingmixframes;
|
||||
while ( (((mixlen = SDL_AudioStreamAvailable(src->stream)) / bufferframesize) < framesneeded) && (src->offset < buffer->len) ) {
|
||||
const int framesput = (buffer->len - src->offset) / bufferframesize;
|
||||
const int bytesput = SDL_min(framesput, 1024) * bufferframesize;
|
||||
const int bytesleft = (buffer->len - src->offset);
|
||||
/* 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. */
|
||||
SDL_AudioStreamPut(src->stream, data, 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);
|
||||
|
@ -1733,12 +1751,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
|
||||
|
@ -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
|
||||
|
||||
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 __m128 up_sse = _mm_load_ps(up);
|
||||
__m128 V_sse;
|
||||
__m128 R_sse;
|
||||
ALfloat cosangle;
|
||||
ALfloat mags;
|
||||
ALfloat a;
|
||||
|
||||
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())) {
|
||||
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);
|
||||
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;
|
||||
}
|
||||
} 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.) */
|
||||
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 float32x4_t up_neon = vld1q_f32(up);
|
||||
float32x4_t V_neon;
|
||||
float32x4_t R_neon;
|
||||
ALfloat cosangle;
|
||||
ALfloat mags;
|
||||
ALfloat a;
|
||||
|
||||
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) {
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
} 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);
|
||||
/* 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]);
|
||||
|
||||
/* 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.
|
||||
/* Calculate angle */
|
||||
mags = magnitude(at) * magnitude(V);
|
||||
if (mags == 0.0f) {
|
||||
radians = 0.0f;
|
||||
} 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?)
|
||||
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]. */
|
||||
/* 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
|
||||
|
@ -2569,6 +2582,16 @@ static void _alcGetIntegerv(ALCdevice *device, const ALCenum param, const ALCsiz
|
|||
*values = OPENAL_VERSION_MINOR;
|
||||
return;
|
||||
|
||||
case ALC_FREQUENCY:
|
||||
if (!device) {
|
||||
*values = 0;
|
||||
set_alc_error(device, ALC_INVALID_DEVICE);
|
||||
return;
|
||||
}
|
||||
|
||||
*values = device->frequency;
|
||||
return;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -2754,7 +2777,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;
|
||||
|
@ -2786,7 +2809,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;
|
||||
|
@ -2921,7 +2944,7 @@ static const ALchar *_alGetString(const ALenum param)
|
|||
|
||||
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)
|
||||
{
|
||||
|
@ -3478,9 +3501,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)) {
|
||||
|
@ -3589,6 +3617,7 @@ static void _alGenSources(const ALsizei n, ALuint *names)
|
|||
|
||||
SDL_zerop(src);
|
||||
SDL_AtomicSet(&src->state, AL_INITIAL);
|
||||
SDL_AtomicSet(&src->total_queued_buffers, 0);
|
||||
src->name = names[i];
|
||||
src->type = AL_UNDETERMINED;
|
||||
src->recalc = AL_TRUE;
|
||||
|
@ -3614,7 +3643,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;
|
||||
}
|
||||
|
@ -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_ROLLOFF_FACTOR: *values = src->rolloff_factor; 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_OUTER_ANGLE: *values = src->cone_outer_angle; 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_TYPE: *values = (ALint) src->type; 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->buffer_queue.num_items); break;
|
||||
case AL_BUFFERS_QUEUED: *values = (ALint) SDL_AtomicGet(&src->total_queued_buffers); 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_LOOPING: *values = (ALint) src->looping; break;
|
||||
|
@ -4050,7 +4081,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);
|
||||
|
@ -4162,6 +4193,9 @@ static void source_stop(ALCcontext *ctx, const ALuint name)
|
|||
}
|
||||
SDL_AtomicSet(&src->state, AL_STOPPED);
|
||||
source_mark_all_buffers_processed(src);
|
||||
if (src->stream) {
|
||||
SDL_AudioStreamClear(src->stream);
|
||||
}
|
||||
if (must_lock) {
|
||||
SDL_UnlockMutex(ctx->source_lock);
|
||||
}
|
||||
|
@ -4228,9 +4262,10 @@ static void source_set_offset(ALsource *src, ALenum param, ALfloat value)
|
|||
if (!ctx) {
|
||||
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
if (src->type == AL_STREAMING) {
|
||||
} else if (src->type == AL_UNDETERMINED) { /* no buffer to seek in */
|
||||
set_al_error(ctx, AL_INVALID_OPERATION);
|
||||
return;
|
||||
} else if (src->type == AL_STREAMING) {
|
||||
FIXME("set_offset for streaming sources not implemented");
|
||||
return;
|
||||
}
|
||||
|
@ -4242,14 +4277,18 @@ static void source_set_offset(ALsource *src, ALenum param, ALfloat value)
|
|||
|
||||
switch (param) {
|
||||
case AL_SAMPLE_OFFSET:
|
||||
offset = value * framesize;
|
||||
offset = ((int) value) * framesize;
|
||||
break;
|
||||
case AL_SEC_OFFSET:
|
||||
offset = value * freq * framesize;
|
||||
offset = ((int) value) * freq * framesize;
|
||||
break;
|
||||
case AL_BYTE_OFFSET:
|
||||
offset = ((int)value / framesize) * framesize;
|
||||
offset = (((int) value) / framesize) * framesize;
|
||||
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)) {
|
||||
|
@ -4267,6 +4306,10 @@ static void source_set_offset(ALsource *src, ALenum param, ALfloat value)
|
|||
src->offset = offset;
|
||||
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... */
|
||||
|
@ -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##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; \
|
||||
|
@ -4318,8 +4363,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 */
|
||||
|
@ -4446,6 +4494,7 @@ static void _alSourceQueueBuffers(const ALuint name, const ALsizei nb, const ALu
|
|||
SDL_AtomicSetPtr(&queueend->next, ptr);
|
||||
} 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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -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->total_queued_buffers, -((int) nb));
|
||||
|
||||
obtain_newly_queued_buffers(&src->buffer_queue_processed);
|
||||
|
||||
|
@ -4521,9 +4574,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)) {
|
||||
|
@ -4635,9 +4693,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++) {
|
||||
|
@ -4694,6 +4757,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;
|
||||
|
|
Loading…
Add table
Reference in a new issue