aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALu.c6
-rw-r--r--Alc/bformatdec.c8
-rw-r--r--Alc/inprogext.h8
-rw-r--r--Alc/mixer/mixer_neon.c12
-rw-r--r--Alc/mixer/mixer_sse.c12
-rw-r--r--OpenAL32/Include/alMain.h4
-rw-r--r--OpenAL32/alSource.c115
7 files changed, 150 insertions, 15 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 9d7fcdd5..3c36cbc6 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -1674,9 +1674,9 @@ static inline ALfloat Conv_ALfloat(ALfloat val)
{ return val; }
static inline ALint Conv_ALint(ALfloat val)
{
- /* Floats have a 23-bit mantissa. A bit of the exponent helps out along
- * with the sign bit, giving 25 bits. So [-16777216, +16777216] is the max
- * integer range normalized floats can be converted to before losing
+ /* Floats have a 23-bit mantissa. There is an implied 1 bit in the mantissa
+ * along with the sign bit, giving 25 bits total, so [-16777216, +16777216]
+ * is the max value a normalized float can be scaled to before losing
* precision.
*/
return fastf2i(clampf(val*16777216.0f, -16777216.0f, 16777215.0f))<<7;
diff --git a/Alc/bformatdec.c b/Alc/bformatdec.c
index dcde7d70..58898083 100644
--- a/Alc/bformatdec.c
+++ b/Alc/bformatdec.c
@@ -450,11 +450,11 @@ void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device, ALfloat
{
for(j = 0;j < device->Dry.NumChannels;j++)
{
- ALfloat gain=0.0f;
+ ALdouble gain = 0.0;
for(k = 0;k < COUNTOF(Ambi3DDecoder);k++)
- gain += Ambi3DDecoder[k][i] * encgains[k][j];
- ambiup->Gains[i][j][HF_BAND] = gain * Ambi3DDecoderHFScale[i];
- ambiup->Gains[i][j][LF_BAND] = gain;
+ gain += (ALdouble)Ambi3DDecoder[k][i] * encgains[k][j];
+ ambiup->Gains[i][j][HF_BAND] = (ALfloat)(gain * Ambi3DDecoderHFScale[i]);
+ ambiup->Gains[i][j][LF_BAND] = (ALfloat)gain;
}
}
}
diff --git a/Alc/inprogext.h b/Alc/inprogext.h
index 619b604f..3025abe2 100644
--- a/Alc/inprogext.h
+++ b/Alc/inprogext.h
@@ -72,6 +72,14 @@ AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values);
#endif
#endif
+#ifndef AL_SOFT_buffer_layers
+#define AL_SOFT_buffer_layers
+typedef void (AL_APIENTRY*LPALSOURCEQUEUEBUFFERLAYERSSOFT)(ALuint src, ALsizei nb, const ALuint *buffers);
+#ifdef AL_ALEXT_PROTOTYPES
+AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint src, ALsizei nb, const ALuint *buffers);
+#endif
+#endif
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/Alc/mixer/mixer_neon.c b/Alc/mixer/mixer_neon.c
index 0af977e6..9aa279a2 100644
--- a/Alc/mixer/mixer_neon.c
+++ b/Alc/mixer/mixer_neon.c
@@ -101,16 +101,20 @@ const ALfloat *Resample_bsinc_Neon(const InterpState *state,
// Apply the scale and phase interpolated filter.
r4 = vdupq_n_f32(0.0f);
{
+ const ALsizei count = m >> 2;
const float32x4_t pf4 = vdupq_n_f32(pf);
- for(j = 0;j < m;j+=4,fil++,scd++,phd++,spd++)
+
+ ASSUME(count > 0);
+
+ for(j = 0;j < count;j++)
{
/* f = ((fil + sf*scd) + pf*(phd + sf*spd)) */
const float32x4_t f4 = vmlaq_f32(
- vmlaq_f32(*fil, sf4, *scd),
- pf4, vmlaq_f32(*phd, sf4, *spd)
+ vmlaq_f32(fil[j], sf4, scd[j]),
+ pf4, vmlaq_f32(phd[j], sf4, spd[j])
);
/* r += f*src */
- r4 = vmlaq_f32(r4, f4, vld1q_f32(&src[j]));
+ r4 = vmlaq_f32(r4, f4, vld1q_f32(&src[j*4]));
}
}
r4 = vaddq_f32(r4, vcombine_f32(vrev64_f32(vget_high_f32(r4)),
diff --git a/Alc/mixer/mixer_sse.c b/Alc/mixer/mixer_sse.c
index 5b4208f9..d7d54993 100644
--- a/Alc/mixer/mixer_sse.c
+++ b/Alc/mixer/mixer_sse.c
@@ -45,17 +45,21 @@ const ALfloat *Resample_bsinc_SSE(const InterpState *state, const ALfloat *restr
// Apply the scale and phase interpolated filter.
r4 = _mm_setzero_ps();
{
+ const ALsizei count = m >> 2;
const __m128 pf4 = _mm_set1_ps(pf);
+
+ ASSUME(count > 0);
+
#define MLA4(x, y, z) _mm_add_ps(x, _mm_mul_ps(y, z))
- for(j = 0;j < m;j+=4,fil++,scd++,phd++,spd++)
+ for(j = 0;j < count;j++)
{
/* f = ((fil + sf*scd) + pf*(phd + sf*spd)) */
const __m128 f4 = MLA4(
- MLA4(*fil, sf4, *scd),
- pf4, MLA4(*phd, sf4, *spd)
+ MLA4(fil[j], sf4, scd[j]),
+ pf4, MLA4(phd[j], sf4, spd[j])
);
/* r += f*src */
- r4 = MLA4(r4, f4, _mm_loadu_ps(&src[j]));
+ r4 = MLA4(r4, f4, _mm_loadu_ps(&src[j*4]));
}
#undef MLA4
}
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 886f3ab1..093f7950 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -184,11 +184,15 @@ inline int fallback_ctz64(ALuint64 value)
#define CTZ64 fallback_ctz64
#endif
+#if defined(__BYTE_ORDER__) && defined(__LITTLE_ENDIAN__)
+#define IS_LITTLE_ENDIAN (__BYTE_ORDER__ == __LITTLE_ENDIAN__)
+#else
static const union {
ALuint u;
ALubyte b[sizeof(ALuint)];
} EndianTest = { 1 };
#define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
+#endif
#define COUNTOF(x) (sizeof(x) / sizeof(0[x]))
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index ed6bd8ee..5ce439c7 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -2826,6 +2826,121 @@ done:
ALCcontext_DecRef(context);
}
+AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint src, ALsizei nb, const ALuint *buffers)
+{
+ ALCdevice *device;
+ ALCcontext *context;
+ ALbufferlistitem *BufferListStart;
+ ALbufferlistitem *BufferList;
+ ALbuffer *BufferFmt = NULL;
+ ALsource *source;
+ ALsizei i;
+
+ if(nb == 0)
+ return;
+
+ context = GetContextRef();
+ if(!context) return;
+
+ device = context->Device;
+
+ LockSourceList(context);
+ if(!(nb >= 0 && nb < 16))
+ SETERR_GOTO(context, AL_INVALID_VALUE, done, "Queueing %d buffer layers", nb);
+ if((source=LookupSource(context, src)) == NULL)
+ SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", src);
+
+ if(source->SourceType == AL_STATIC)
+ {
+ /* Can't queue on a Static Source */
+ SETERR_GOTO(context, AL_INVALID_OPERATION, done, "Queueing onto static source %u", src);
+ }
+
+ /* Check for a valid Buffer, for its frequency and format */
+ BufferList = source->queue;
+ while(BufferList)
+ {
+ for(i = 0;i < BufferList->num_buffers;i++)
+ {
+ if((BufferFmt=BufferList->buffers[i]) != NULL)
+ break;
+ }
+ if(BufferFmt) break;
+ BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed);
+ }
+
+ LockBufferList(device);
+ BufferListStart = al_calloc(DEF_ALIGN, FAM_SIZE(ALbufferlistitem, buffers, nb));
+ BufferList = BufferListStart;
+ ATOMIC_INIT(&BufferList->next, NULL);
+ BufferList->max_samples = 0;
+ BufferList->num_buffers = 0;
+ for(i = 0;i < nb;i++)
+ {
+ ALbuffer *buffer = NULL;
+ if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
+ SETERR_GOTO(context, AL_INVALID_NAME, buffer_error, "Queueing invalid buffer ID %u",
+ buffers[i]);
+
+ BufferList->buffers[BufferList->num_buffers++] = buffer;
+ if(!buffer) continue;
+
+ IncrementRef(&buffer->ref);
+
+ BufferList->max_samples = maxi(BufferList->max_samples, buffer->SampleLen);
+
+ if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
+ SETERR_GOTO(context, AL_INVALID_OPERATION, buffer_error,
+ "Queueing non-persistently mapped buffer %u", buffer->id);
+
+ if(BufferFmt == NULL)
+ BufferFmt = buffer;
+ else if(BufferFmt->Frequency != buffer->Frequency ||
+ BufferFmt->FmtChannels != buffer->FmtChannels ||
+ BufferFmt->OriginalType != buffer->OriginalType)
+ {
+ alSetError(context, AL_INVALID_OPERATION, "Queueing buffer with mismatched format");
+
+ buffer_error:
+ /* A buffer failed (invalid ID or format), so unlock and release
+ * each buffer we had. */
+ while(BufferListStart)
+ {
+ ALbufferlistitem *next = ATOMIC_LOAD(&BufferListStart->next,
+ almemory_order_relaxed);
+ for(i = 0;i < BufferListStart->num_buffers;i++)
+ {
+ if((buffer=BufferListStart->buffers[i]) != NULL)
+ DecrementRef(&buffer->ref);
+ }
+ al_free(BufferListStart);
+ BufferListStart = next;
+ }
+ UnlockBufferList(device);
+ goto done;
+ }
+ }
+ /* All buffers good. */
+ UnlockBufferList(device);
+
+ /* Source is now streaming */
+ source->SourceType = AL_STREAMING;
+
+ if(!(BufferList=source->queue))
+ source->queue = BufferListStart;
+ else
+ {
+ ALbufferlistitem *next;
+ while((next=ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed)) != NULL)
+ BufferList = next;
+ ATOMIC_STORE(&BufferList->next, BufferListStart, almemory_order_release);
+ }
+
+done:
+ UnlockSourceList(context);
+ ALCcontext_DecRef(context);
+}
+
AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint *buffers)
{
ALCcontext *context;