mirror of
https://github.com/love2d/megasource.git
synced 2026-08-21 05:02:11 +02:00
Update OpenAL Soft to 1.19.1.
This commit is contained in:
+134
-143
@@ -39,6 +39,7 @@
|
||||
#include "bformatdec.h"
|
||||
#include "static_assert.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "filters/splitter.h"
|
||||
|
||||
#include "mixer/defs.h"
|
||||
#include "fpu_modes.h"
|
||||
@@ -144,16 +145,6 @@ static inline HrtfDirectMixerFunc SelectHrtfMixer(void)
|
||||
}
|
||||
|
||||
|
||||
/* Prior to VS2013, MSVC lacks the round() family of functions. */
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
static float roundf(float val)
|
||||
{
|
||||
if(val < 0.0f)
|
||||
return ceilf(val-0.5f);
|
||||
return floorf(val+0.5f);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This RNG method was created based on the math found in opusdec. It's quick,
|
||||
* and starting with a seed value of 22222, is suitable for generating
|
||||
* whitenoise.
|
||||
@@ -220,32 +211,31 @@ void aluInit(void)
|
||||
|
||||
static void SendSourceStoppedEvent(ALCcontext *context, ALuint id)
|
||||
{
|
||||
AsyncEvent evt = ASYNC_EVENT(EventType_SourceStateChange);
|
||||
ALbitfieldSOFT enabledevt;
|
||||
AsyncEvent evt;
|
||||
size_t strpos;
|
||||
ALuint scale;
|
||||
|
||||
enabledevt = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_acquire);
|
||||
if(!(enabledevt&EventType_SourceStateChange)) return;
|
||||
|
||||
evt.EnumType = EventType_SourceStateChange;
|
||||
evt.Type = AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT;
|
||||
evt.ObjectId = id;
|
||||
evt.Param = AL_STOPPED;
|
||||
evt.u.user.type = AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT;
|
||||
evt.u.user.id = id;
|
||||
evt.u.user.param = AL_STOPPED;
|
||||
|
||||
/* Normally snprintf would be used, but this is called from the mixer and
|
||||
* that function's not real-time safe, so we have to construct it manually.
|
||||
*/
|
||||
strcpy(evt.Message, "Source ID "); strpos = 10;
|
||||
strcpy(evt.u.user.msg, "Source ID "); strpos = 10;
|
||||
scale = 1000000000;
|
||||
while(scale > 0 && scale > id)
|
||||
scale /= 10;
|
||||
while(scale > 0)
|
||||
{
|
||||
evt.Message[strpos++] = '0' + ((id/scale)%10);
|
||||
evt.u.user.msg[strpos++] = '0' + ((id/scale)%10);
|
||||
scale /= 10;
|
||||
}
|
||||
strcpy(evt.Message+strpos, " state changed to AL_STOPPED");
|
||||
strcpy(evt.u.user.msg+strpos, " state changed to AL_STOPPED");
|
||||
|
||||
if(ll_ringbuffer_write(context->AsyncEvents, (const char*)&evt, 1) == 1)
|
||||
alsem_post(&context->EventSem);
|
||||
@@ -304,26 +294,24 @@ static void ProcessUhj(ALCdevice *device, ALsizei SamplesToDo)
|
||||
{
|
||||
int lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
|
||||
int ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
|
||||
if(LIKELY(lidx != -1 && ridx != -1))
|
||||
{
|
||||
/* Encode to stereo-compatible 2-channel UHJ output. */
|
||||
EncodeUhj2(device->Uhj_Encoder,
|
||||
device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
|
||||
device->Dry.Buffer, SamplesToDo
|
||||
);
|
||||
}
|
||||
assert(lidx != -1 && ridx != -1);
|
||||
|
||||
/* Encode to stereo-compatible 2-channel UHJ output. */
|
||||
EncodeUhj2(device->Uhj_Encoder,
|
||||
device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
|
||||
device->Dry.Buffer, SamplesToDo
|
||||
);
|
||||
}
|
||||
|
||||
static void ProcessBs2b(ALCdevice *device, ALsizei SamplesToDo)
|
||||
{
|
||||
int lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
|
||||
int ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
|
||||
if(LIKELY(lidx != -1 && ridx != -1))
|
||||
{
|
||||
/* Apply binaural/crossfeed filter */
|
||||
bs2b_cross_feed(device->Bs2b, device->RealOut.Buffer[lidx],
|
||||
device->RealOut.Buffer[ridx], SamplesToDo);
|
||||
}
|
||||
assert(lidx != -1 && ridx != -1);
|
||||
|
||||
/* Apply binaural/crossfeed filter */
|
||||
bs2b_cross_feed(device->Bs2b, device->RealOut.Buffer[lidx],
|
||||
device->RealOut.Buffer[ridx], SamplesToDo);
|
||||
}
|
||||
|
||||
void aluSelectPostProcess(ALCdevice *device)
|
||||
@@ -343,9 +331,7 @@ void aluSelectPostProcess(ALCdevice *device)
|
||||
}
|
||||
|
||||
|
||||
/* Prepares the interpolator for a given rate (determined by increment). A
|
||||
* result of AL_FALSE indicates that the filter output will completely cut
|
||||
* the input signal.
|
||||
/* Prepares the interpolator for a given rate (determined by increment).
|
||||
*
|
||||
* With a bit of work, and a trade of memory for CPU cost, this could be
|
||||
* modified for use with an interpolated increment for buttery-smooth pitch
|
||||
@@ -353,29 +339,24 @@ void aluSelectPostProcess(ALCdevice *device)
|
||||
*/
|
||||
void BsincPrepare(const ALuint increment, BsincState *state, const BSincTable *table)
|
||||
{
|
||||
ALfloat sf;
|
||||
ALsizei si;
|
||||
ALfloat sf = 0.0f;
|
||||
ALsizei si = BSINC_SCALE_COUNT-1;
|
||||
|
||||
if(increment > FRACTIONONE)
|
||||
{
|
||||
sf = (ALfloat)FRACTIONONE / increment;
|
||||
sf = maxf(0.0f, (BSINC_SCALE_COUNT-1) * (sf-table->scaleBase) * table->scaleRange);
|
||||
si = fastf2i(sf);
|
||||
si = float2int(sf);
|
||||
/* The interpolation factor is fit to this diagonally-symmetric curve
|
||||
* to reduce the transition ripple caused by interpolating different
|
||||
* scales of the sinc function.
|
||||
*/
|
||||
sf = 1.0f - cosf(asinf(sf - si));
|
||||
}
|
||||
else
|
||||
{
|
||||
sf = 0.0f;
|
||||
si = BSINC_SCALE_COUNT - 1;
|
||||
}
|
||||
|
||||
state->sf = sf;
|
||||
state->m = table->m[si];
|
||||
state->l = -((state->m/2) - 1);
|
||||
state->l = (state->m/2) - 1;
|
||||
state->filter = table->Tab + table->filterOffset[si];
|
||||
}
|
||||
|
||||
@@ -481,12 +462,40 @@ static bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context, bool f
|
||||
slot->Params.AirAbsorptionGainHF = 1.0f;
|
||||
}
|
||||
|
||||
/* Swap effect states. No need to play with the ref counts since they
|
||||
* keep the same number of refs.
|
||||
*/
|
||||
state = props->State;
|
||||
props->State = slot->Params.EffectState;
|
||||
slot->Params.EffectState = state;
|
||||
|
||||
if(state == slot->Params.EffectState)
|
||||
{
|
||||
/* If the effect state is the same as current, we can decrement its
|
||||
* count safely to remove it from the update object (it can't reach
|
||||
* 0 refs since the current params also hold a reference).
|
||||
*/
|
||||
DecrementRef(&state->Ref);
|
||||
props->State = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, replace it and send off the old one with a release
|
||||
* event.
|
||||
*/
|
||||
AsyncEvent evt = ASYNC_EVENT(EventType_ReleaseEffectState);
|
||||
evt.u.EffectState = slot->Params.EffectState;
|
||||
|
||||
slot->Params.EffectState = state;
|
||||
props->State = NULL;
|
||||
|
||||
if(LIKELY(ll_ringbuffer_write(context->AsyncEvents, (const char*)&evt, 1) != 0))
|
||||
alsem_post(&context->EventSem);
|
||||
else
|
||||
{
|
||||
/* If writing the event failed, the queue was probably full.
|
||||
* Store the old state in the property object where it can
|
||||
* eventually be cleaned up sometime later (not ideal, but
|
||||
* better than blocking or leaking).
|
||||
*/
|
||||
props->State = evt.u.EffectState;
|
||||
}
|
||||
}
|
||||
|
||||
ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &context->FreeEffectslotProps, props);
|
||||
}
|
||||
@@ -662,24 +671,26 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
|
||||
NfcFilterAdjust(&voice->Direct.Params[0].NFCtrlFilter, w0);
|
||||
|
||||
for(i = 0;i < MAX_AMBI_ORDER+1;i++)
|
||||
voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
|
||||
voice->Direct.ChannelsPerOrder[i] = Device->NumChannelsPerOrder[i];
|
||||
voice->Flags |= VOICE_HAS_NFC;
|
||||
}
|
||||
|
||||
if(Device->Render_Mode == StereoPair)
|
||||
CalcAnglePairwiseCoeffs(Azi, Elev, Spread, coeffs);
|
||||
else
|
||||
CalcAngleCoeffs(Azi, Elev, Spread, coeffs);
|
||||
/* A scalar of 1.5 for plain stereo results in +/-60 degrees being
|
||||
* moved to +/-90 degrees for direct right and left speaker
|
||||
* responses.
|
||||
*/
|
||||
CalcAngleCoeffs((Device->Render_Mode==StereoPair) ? ScaleAzimuthFront(Azi, 1.5f) : Azi,
|
||||
Elev, Spread, coeffs);
|
||||
|
||||
/* NOTE: W needs to be scaled by sqrt(2) due to FuMa normalization. */
|
||||
ComputeDryPanGains(&Device->Dry, coeffs, DryGain*1.414213562f,
|
||||
ComputePanGains(&Device->Dry, coeffs, DryGain*SQRTF_2,
|
||||
voice->Direct.Params[0].Gains.Target);
|
||||
for(i = 0;i < NumSends;i++)
|
||||
{
|
||||
const ALeffectslot *Slot = SendSlots[i];
|
||||
if(Slot)
|
||||
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
|
||||
coeffs, WetGain[i]*1.414213562f, voice->Send[i].Params[0].Gains.Target
|
||||
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs,
|
||||
WetGain[i]*SQRTF_2, voice->Send[i].Params[0].Gains.Target
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -688,8 +699,6 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
|
||||
/* Local B-Format sources have their XYZ channels rotated according
|
||||
* to the orientation.
|
||||
*/
|
||||
const ALfloat sqrt_2 = sqrtf(2.0f);
|
||||
const ALfloat sqrt_3 = sqrtf(3.0f);
|
||||
ALfloat N[3], V[3], U[3];
|
||||
aluMatrixf matrix;
|
||||
|
||||
@@ -732,25 +741,25 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
|
||||
* outputs on the columns.
|
||||
*/
|
||||
aluMatrixfSet(&matrix,
|
||||
// ACN0 ACN1 ACN2 ACN3
|
||||
sqrt_2, 0.0f, 0.0f, 0.0f, // Ambi W
|
||||
0.0f, -N[0]*sqrt_3, N[1]*sqrt_3, -N[2]*sqrt_3, // Ambi X
|
||||
0.0f, U[0]*sqrt_3, -U[1]*sqrt_3, U[2]*sqrt_3, // Ambi Y
|
||||
0.0f, -V[0]*sqrt_3, V[1]*sqrt_3, -V[2]*sqrt_3 // Ambi Z
|
||||
// ACN0 ACN1 ACN2 ACN3
|
||||
SQRTF_2, 0.0f, 0.0f, 0.0f, // Ambi W
|
||||
0.0f, -N[0]*SQRTF_3, N[1]*SQRTF_3, -N[2]*SQRTF_3, // Ambi X
|
||||
0.0f, U[0]*SQRTF_3, -U[1]*SQRTF_3, U[2]*SQRTF_3, // Ambi Y
|
||||
0.0f, -V[0]*SQRTF_3, V[1]*SQRTF_3, -V[2]*SQRTF_3 // Ambi Z
|
||||
);
|
||||
|
||||
voice->Direct.Buffer = Device->FOAOut.Buffer;
|
||||
voice->Direct.Channels = Device->FOAOut.NumChannels;
|
||||
for(c = 0;c < num_channels;c++)
|
||||
ComputeFirstOrderGains(&Device->FOAOut, matrix.m[c], DryGain,
|
||||
voice->Direct.Params[c].Gains.Target);
|
||||
ComputePanGains(&Device->FOAOut, matrix.m[c], DryGain,
|
||||
voice->Direct.Params[c].Gains.Target);
|
||||
for(i = 0;i < NumSends;i++)
|
||||
{
|
||||
const ALeffectslot *Slot = SendSlots[i];
|
||||
if(Slot)
|
||||
{
|
||||
for(c = 0;c < num_channels;c++)
|
||||
ComputeFirstOrderGainsBF(Slot->ChanMap, Slot->NumChannels,
|
||||
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
|
||||
matrix.m[c], WetGain[i], voice->Send[i].Params[c].Gains.Target
|
||||
);
|
||||
}
|
||||
@@ -906,17 +915,15 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
|
||||
NfcFilterAdjust(&voice->Direct.Params[c].NFCtrlFilter, w0);
|
||||
|
||||
for(i = 0;i < MAX_AMBI_ORDER+1;i++)
|
||||
voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
|
||||
voice->Direct.ChannelsPerOrder[i] = Device->NumChannelsPerOrder[i];
|
||||
voice->Flags |= VOICE_HAS_NFC;
|
||||
}
|
||||
|
||||
/* Calculate the directional coefficients once, which apply to all
|
||||
* input channels.
|
||||
*/
|
||||
if(Device->Render_Mode == StereoPair)
|
||||
CalcAnglePairwiseCoeffs(Azi, Elev, Spread, coeffs);
|
||||
else
|
||||
CalcAngleCoeffs(Azi, Elev, Spread, coeffs);
|
||||
CalcAngleCoeffs((Device->Render_Mode==StereoPair) ? ScaleAzimuthFront(Azi, 1.5f) : Azi,
|
||||
Elev, Spread, coeffs);
|
||||
|
||||
for(c = 0;c < num_channels;c++)
|
||||
{
|
||||
@@ -931,9 +938,8 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
|
||||
continue;
|
||||
}
|
||||
|
||||
ComputeDryPanGains(&Device->Dry,
|
||||
coeffs, DryGain * downmix_gain, voice->Direct.Params[c].Gains.Target
|
||||
);
|
||||
ComputePanGains(&Device->Dry, coeffs, DryGain * downmix_gain,
|
||||
voice->Direct.Params[c].Gains.Target);
|
||||
}
|
||||
|
||||
for(i = 0;i < NumSends;i++)
|
||||
@@ -969,7 +975,7 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
|
||||
NfcFilterAdjust(&voice->Direct.Params[c].NFCtrlFilter, w0);
|
||||
|
||||
for(i = 0;i < MAX_AMBI_ORDER+1;i++)
|
||||
voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
|
||||
voice->Direct.ChannelsPerOrder[i] = Device->NumChannelsPerOrder[i];
|
||||
voice->Flags |= VOICE_HAS_NFC;
|
||||
}
|
||||
|
||||
@@ -988,14 +994,14 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
|
||||
continue;
|
||||
}
|
||||
|
||||
if(Device->Render_Mode == StereoPair)
|
||||
CalcAnglePairwiseCoeffs(chans[c].angle, chans[c].elevation, Spread, coeffs);
|
||||
else
|
||||
CalcAngleCoeffs(chans[c].angle, chans[c].elevation, Spread, coeffs);
|
||||
ComputeDryPanGains(&Device->Dry,
|
||||
coeffs, DryGain, voice->Direct.Params[c].Gains.Target
|
||||
CalcAngleCoeffs(
|
||||
(Device->Render_Mode==StereoPair) ? ScaleAzimuthFront(chans[c].angle, 3.0f)
|
||||
: chans[c].angle,
|
||||
chans[c].elevation, Spread, coeffs
|
||||
);
|
||||
|
||||
ComputePanGains(&Device->Dry, coeffs, DryGain,
|
||||
voice->Direct.Params[c].Gains.Target);
|
||||
for(i = 0;i < NumSends;i++)
|
||||
{
|
||||
const ALeffectslot *Slot = SendSlots[i];
|
||||
@@ -1017,20 +1023,20 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
|
||||
voice->Direct.FilterType = AF_None;
|
||||
if(gainHF != 1.0f) voice->Direct.FilterType |= AF_LowPass;
|
||||
if(gainLF != 1.0f) voice->Direct.FilterType |= AF_HighPass;
|
||||
BiquadState_setParams(
|
||||
BiquadFilter_setParams(
|
||||
&voice->Direct.Params[0].LowPass, BiquadType_HighShelf,
|
||||
gainHF, hfScale, calc_rcpQ_from_slope(gainHF, 1.0f)
|
||||
);
|
||||
BiquadState_setParams(
|
||||
BiquadFilter_setParams(
|
||||
&voice->Direct.Params[0].HighPass, BiquadType_LowShelf,
|
||||
gainLF, lfScale, calc_rcpQ_from_slope(gainLF, 1.0f)
|
||||
);
|
||||
for(c = 1;c < num_channels;c++)
|
||||
{
|
||||
BiquadState_copyParams(&voice->Direct.Params[c].LowPass,
|
||||
&voice->Direct.Params[0].LowPass);
|
||||
BiquadState_copyParams(&voice->Direct.Params[c].HighPass,
|
||||
&voice->Direct.Params[0].HighPass);
|
||||
BiquadFilter_copyParams(&voice->Direct.Params[c].LowPass,
|
||||
&voice->Direct.Params[0].LowPass);
|
||||
BiquadFilter_copyParams(&voice->Direct.Params[c].HighPass,
|
||||
&voice->Direct.Params[0].HighPass);
|
||||
}
|
||||
}
|
||||
for(i = 0;i < NumSends;i++)
|
||||
@@ -1043,20 +1049,20 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
|
||||
voice->Send[i].FilterType = AF_None;
|
||||
if(gainHF != 1.0f) voice->Send[i].FilterType |= AF_LowPass;
|
||||
if(gainLF != 1.0f) voice->Send[i].FilterType |= AF_HighPass;
|
||||
BiquadState_setParams(
|
||||
BiquadFilter_setParams(
|
||||
&voice->Send[i].Params[0].LowPass, BiquadType_HighShelf,
|
||||
gainHF, hfScale, calc_rcpQ_from_slope(gainHF, 1.0f)
|
||||
);
|
||||
BiquadState_setParams(
|
||||
BiquadFilter_setParams(
|
||||
&voice->Send[i].Params[0].HighPass, BiquadType_LowShelf,
|
||||
gainLF, lfScale, calc_rcpQ_from_slope(gainLF, 1.0f)
|
||||
);
|
||||
for(c = 1;c < num_channels;c++)
|
||||
{
|
||||
BiquadState_copyParams(&voice->Send[i].Params[c].LowPass,
|
||||
&voice->Send[i].Params[0].LowPass);
|
||||
BiquadState_copyParams(&voice->Send[i].Params[c].HighPass,
|
||||
&voice->Send[i].Params[0].HighPass);
|
||||
BiquadFilter_copyParams(&voice->Send[i].Params[c].LowPass,
|
||||
&voice->Send[i].Params[0].LowPass);
|
||||
BiquadFilter_copyParams(&voice->Send[i].Params[c].HighPass,
|
||||
&voice->Send[i].Params[0].HighPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1098,7 +1104,7 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *p
|
||||
if(Pitch > (ALfloat)MAX_PITCH)
|
||||
voice->Step = MAX_PITCH<<FRACTIONBITS;
|
||||
else
|
||||
voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
|
||||
voice->Step = maxi(fastf2i(Pitch * FRACTIONONE), 1);
|
||||
if(props->Resampler == BSinc24Resampler)
|
||||
BsincPrepare(voice->Step, &voice->ResampleState.bsinc, &bsinc24);
|
||||
else if(props->Resampler == BSinc12Resampler)
|
||||
@@ -1459,7 +1465,7 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *prop
|
||||
if(Pitch > (ALfloat)MAX_PITCH)
|
||||
voice->Step = MAX_PITCH<<FRACTIONBITS;
|
||||
else
|
||||
voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
|
||||
voice->Step = maxi(fastf2i(Pitch * FRACTIONONE), 1);
|
||||
if(props->Resampler == BSinc24Resampler)
|
||||
BsincPrepare(voice->Step, &voice->ResampleState.bsinc, &bsinc24);
|
||||
else if(props->Resampler == BSinc12Resampler)
|
||||
@@ -1628,7 +1634,7 @@ static void ApplyDistanceComp(ALfloat (*restrict Samples)[BUFFERSIZE], DistanceC
|
||||
continue;
|
||||
}
|
||||
|
||||
if(SamplesToDo >= base)
|
||||
if(LIKELY(SamplesToDo >= base))
|
||||
{
|
||||
for(i = 0;i < base;i++)
|
||||
Values[i] = distbuf[i];
|
||||
@@ -1656,6 +1662,9 @@ static void ApplyDither(ALfloat (*restrict Samples)[BUFFERSIZE], ALuint *dither_
|
||||
ALuint seed = *dither_seed;
|
||||
ALsizei c, i;
|
||||
|
||||
ASSUME(numchans > 0);
|
||||
ASSUME(SamplesToDo > 0);
|
||||
|
||||
/* Dithering. Step 1, generate whitenoise (uniform distribution of random
|
||||
* values between -1 and +1). Step 2 is to add the noise to the samples,
|
||||
* before rounding and after scaling up to the desired quantization depth.
|
||||
@@ -1669,7 +1678,7 @@ static void ApplyDither(ALfloat (*restrict Samples)[BUFFERSIZE], ALuint *dither_
|
||||
ALuint rng0 = dither_rng(&seed);
|
||||
ALuint rng1 = dither_rng(&seed);
|
||||
val += (ALfloat)(rng0*(1.0/UINT_MAX) - rng1*(1.0/UINT_MAX));
|
||||
samples[i] = roundf(val) * invscale;
|
||||
samples[i] = fast_roundf(val) * invscale;
|
||||
}
|
||||
}
|
||||
*dither_seed = seed;
|
||||
@@ -1680,9 +1689,10 @@ static inline ALfloat Conv_ALfloat(ALfloat val)
|
||||
{ return val; }
|
||||
static inline ALint Conv_ALint(ALfloat val)
|
||||
{
|
||||
/* Floats only have a 24-bit mantissa, so [-16777216, +16777216] is the max
|
||||
* integer range normalized floats can be safely converted to (a bit of the
|
||||
* exponent helps out, effectively giving 25 bits).
|
||||
/* 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;
|
||||
}
|
||||
@@ -1707,6 +1717,10 @@ static void Write##A(const ALfloat (*restrict InBuffer)[BUFFERSIZE], \
|
||||
ALsizei numchans) \
|
||||
{ \
|
||||
ALsizei i, j; \
|
||||
\
|
||||
ASSUME(numchans > 0); \
|
||||
ASSUME(SamplesToDo > 0); \
|
||||
\
|
||||
for(j = 0;j < numchans;j++) \
|
||||
{ \
|
||||
const ALfloat *restrict in = ASSUME_ALIGNED(InBuffer[j], 16); \
|
||||
@@ -1824,41 +1838,29 @@ void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples)
|
||||
SamplesToDo, device->RealOut.NumChannels);
|
||||
|
||||
if(device->Limiter)
|
||||
ApplyCompression(device->Limiter, device->RealOut.NumChannels, SamplesToDo,
|
||||
device->RealOut.Buffer);
|
||||
ApplyCompression(device->Limiter, SamplesToDo, device->RealOut.Buffer);
|
||||
|
||||
if(device->DitherDepth > 0.0f)
|
||||
ApplyDither(device->RealOut.Buffer, &device->DitherSeed, device->DitherDepth,
|
||||
SamplesToDo, device->RealOut.NumChannels);
|
||||
|
||||
if(OutBuffer)
|
||||
if(LIKELY(OutBuffer))
|
||||
{
|
||||
ALfloat (*Buffer)[BUFFERSIZE] = device->RealOut.Buffer;
|
||||
ALsizei Channels = device->RealOut.NumChannels;
|
||||
|
||||
switch(device->FmtType)
|
||||
{
|
||||
case DevFmtByte:
|
||||
WriteI8(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
|
||||
break;
|
||||
case DevFmtUByte:
|
||||
WriteUI8(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
|
||||
break;
|
||||
case DevFmtShort:
|
||||
WriteI16(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
|
||||
break;
|
||||
case DevFmtUShort:
|
||||
WriteUI16(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
|
||||
break;
|
||||
case DevFmtInt:
|
||||
WriteI32(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
|
||||
break;
|
||||
case DevFmtUInt:
|
||||
WriteUI32(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
|
||||
break;
|
||||
case DevFmtFloat:
|
||||
WriteF32(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
|
||||
break;
|
||||
#define HANDLE_WRITE(T, S) case T: \
|
||||
Write##S(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels); break;
|
||||
HANDLE_WRITE(DevFmtByte, I8)
|
||||
HANDLE_WRITE(DevFmtUByte, UI8)
|
||||
HANDLE_WRITE(DevFmtShort, I16)
|
||||
HANDLE_WRITE(DevFmtUShort, UI16)
|
||||
HANDLE_WRITE(DevFmtInt, I32)
|
||||
HANDLE_WRITE(DevFmtUInt, UI32)
|
||||
HANDLE_WRITE(DevFmtFloat, F32)
|
||||
#undef HANDLE_WRITE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1870,35 +1872,24 @@ void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples)
|
||||
|
||||
void aluHandleDisconnect(ALCdevice *device, const char *msg, ...)
|
||||
{
|
||||
AsyncEvent evt = ASYNC_EVENT(EventType_Disconnected);
|
||||
ALCcontext *ctx;
|
||||
AsyncEvent evt;
|
||||
va_list args;
|
||||
int msglen;
|
||||
|
||||
if(!ATOMIC_EXCHANGE(&device->Connected, AL_FALSE, almemory_order_acq_rel))
|
||||
return;
|
||||
|
||||
evt.EnumType = EventType_Disconnected;
|
||||
evt.Type = AL_EVENT_TYPE_DISCONNECTED_SOFT;
|
||||
evt.ObjectId = 0;
|
||||
evt.Param = 0;
|
||||
evt.u.user.type = AL_EVENT_TYPE_DISCONNECTED_SOFT;
|
||||
evt.u.user.id = 0;
|
||||
evt.u.user.param = 0;
|
||||
|
||||
va_start(args, msg);
|
||||
msglen = vsnprintf(evt.Message, sizeof(evt.Message), msg, args);
|
||||
msglen = vsnprintf(evt.u.user.msg, sizeof(evt.u.user.msg), msg, args);
|
||||
va_end(args);
|
||||
|
||||
if(msglen < 0 || (size_t)msglen >= sizeof(evt.Message))
|
||||
{
|
||||
evt.Message[sizeof(evt.Message)-1] = 0;
|
||||
msglen = (int)strlen(evt.Message);
|
||||
}
|
||||
if(msglen > 0)
|
||||
msg = evt.Message;
|
||||
else
|
||||
{
|
||||
msg = "<internal error constructing message>";
|
||||
msglen = (int)strlen(msg);
|
||||
}
|
||||
if(msglen < 0 || (size_t)msglen >= sizeof(evt.u.user.msg))
|
||||
evt.u.user.msg[sizeof(evt.u.user.msg)-1] = 0;
|
||||
|
||||
ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
|
||||
while(ctx)
|
||||
|
||||
Reference in New Issue
Block a user