summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c7
-rw-r--r--Alc/ALu.c44
-rw-r--r--Alc/mixer_c.c40
-rw-r--r--Alc/mixer_neon.c66
-rw-r--r--Alc/mixer_sse.c75
-rw-r--r--OpenAL32/Include/alu.h9
-rw-r--r--OpenAL32/alSource.c10
7 files changed, 185 insertions, 66 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index bf296974..7399a0c7 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -1931,6 +1931,13 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
{
ALactivesource *src = context->ActiveSources[pos];
ALsource *source = src->Source;
+ ALuint s = device->NumAuxSends;
+ while(s < MAX_SENDS)
+ {
+ src->Send[s].Moving = AL_FALSE;
+ src->Send[s].Counter = 0;
+ s++;
+ }
src->Update(src, context);
source->NeedsUpdate = AL_FALSE;
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 10e2a45d..d00620eb 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -565,7 +565,27 @@ ALvoid CalcNonAttnSourceParams(ALactivesource *src, const ALCcontext *ALContext)
src->DryMix = SelectDirectMixer();
}
for(i = 0;i < NumSends;i++)
- src->Send[i].Gain = WetGain[i];
+ {
+ if(src->Send[i].Moving)
+ {
+ ALfloat cur = maxf(src->Send[i].Gain.Current, GAIN_SILENCE_THRESHOLD);
+ ALfloat trg = maxf(src->Send[i].Gain.Target, GAIN_SILENCE_THRESHOLD);
+ if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD)
+ src->Send[i].Gain.Step = powf(trg/cur, 1.0f/64.0f);
+ else
+ src->Send[i].Gain.Step = 1.0f;
+ src->Send[i].Gain.Current = cur;
+ src->Send[i].Counter = 64;
+ }
+ else
+ {
+ src->Send[i].Gain.Current = WetGain[i];
+ src->Send[i].Gain.Target = WetGain[i];
+ src->Send[i].Gain.Step = 1.0f;
+ src->Send[i].Counter = 0;
+ src->Send[i].Moving = AL_TRUE;
+ }
+ }
src->WetMix = SelectSendMixer();
{
@@ -1050,7 +1070,27 @@ ALvoid CalcSourceParams(ALactivesource *src, const ALCcontext *ALContext)
src->DryMix = SelectDirectMixer();
}
for(i = 0;i < NumSends;i++)
- src->Send[i].Gain = WetGain[i];
+ {
+ if(src->Send[i].Moving)
+ {
+ ALfloat cur = maxf(src->Send[i].Gain.Current, GAIN_SILENCE_THRESHOLD);
+ ALfloat trg = maxf(src->Send[i].Gain.Target, GAIN_SILENCE_THRESHOLD);
+ if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD)
+ src->Send[i].Gain.Step = powf(trg/cur, 1.0f/64.0f);
+ else
+ src->Send[i].Gain.Step = 1.0f;
+ src->Send[i].Gain.Current = cur;
+ src->Send[i].Counter = 64;
+ }
+ else
+ {
+ src->Send[i].Gain.Current = WetGain[i];
+ src->Send[i].Gain.Target = WetGain[i];
+ src->Send[i].Gain.Step = 1.0f;
+ src->Send[i].Counter = 0;
+ src->Send[i].Moving = AL_TRUE;
+ }
+ }
src->WetMix = SelectSendMixer();
{
diff --git a/Alc/mixer_c.c b/Alc/mixer_c.c
index a4028beb..c5091322 100644
--- a/Alc/mixer_c.c
+++ b/Alc/mixer_c.c
@@ -115,22 +115,30 @@ void MixDirect_C(DirectParams *params, const ALfloat *restrict data, ALuint srcc
void MixSend_C(SendParams *params, const ALfloat *restrict data,
- ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
+ ALuint OutPos, ALuint UNUSED(SamplesToDo), ALuint BufferSize)
{
ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer;
- ALfloat *restrict ClickRemoval = params->ClickRemoval;
- ALfloat *restrict PendingClicks = params->PendingClicks;
- ALfloat WetSend;
- ALuint pos;
-
- WetSend = params->Gain;
- if(!(WetSend > GAIN_SILENCE_THRESHOLD))
- return;
-
- if(OutPos == 0)
- ClickRemoval[0] -= data[0] * WetSend;
- for(pos = 0;pos < BufferSize;pos++)
- OutBuffer[0][OutPos+pos] += data[pos] * WetSend;
- if(OutPos+pos == SamplesToDo)
- PendingClicks[0] += data[pos] * WetSend;
+ ALuint Counter = maxu(params->Counter, OutPos) - OutPos;
+ ALfloat WetSend, Step;
+
+ {
+ ALuint pos = 0;
+ Step = params->Gain.Step;
+ if(Step != 1.0f && Counter > 0)
+ {
+ WetSend = params->Gain.Current;
+ for(;pos < BufferSize && pos < Counter;pos++)
+ {
+ OutBuffer[0][OutPos+pos] += data[pos]*WetSend;
+ WetSend *= Step;
+ }
+ params->Gain.Current = WetSend;
+ }
+
+ WetSend = params->Gain.Target;
+ if(!(WetSend > GAIN_SILENCE_THRESHOLD))
+ return;
+ for(;pos < BufferSize;pos++)
+ OutBuffer[0][OutPos+pos] += data[pos] * WetSend;
+ }
}
diff --git a/Alc/mixer_neon.c b/Alc/mixer_neon.c
index 35dfd1f1..cdc889c5 100644
--- a/Alc/mixer_neon.c
+++ b/Alc/mixer_neon.c
@@ -133,33 +133,53 @@ void MixDirect_Neon(DirectParams *params, const ALfloat *restrict data, ALuint s
void MixSend_Neon(SendParams *params, const ALfloat *restrict data,
- ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
+ ALuint OutPos, ALuint UNUSED(SamplesToDo), ALuint BufferSize)
{
ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer;
- ALfloat *restrict ClickRemoval = params->ClickRemoval;
- ALfloat *restrict PendingClicks = params->PendingClicks;
- ALfloat WetGain;
+ ALuint Counter = maxu(params->Counter, OutPos) - OutPos;
+ ALfloat WetGain, Step;
float32x4_t gain;
- ALuint pos;
-
- WetGain = params->Gain;
- if(!(WetGain > GAIN_SILENCE_THRESHOLD))
- return;
-
- if(OutPos == 0)
- ClickRemoval[0] -= data[0] * WetGain;
- gain = vdupq_n_f32(WetGain);
- for(pos = 0;BufferSize-pos > 3;pos += 4)
{
- const float32x4_t val4 = vld1q_f32(&data[pos]);
- float32x4_t wet4 = vld1q_f32(&OutBuffer[0][OutPos+pos]);
- wet4 = vaddq_f32(wet4, vmulq_f32(val4, gain));
- vst1q_f32(&OutBuffer[0][OutPos+pos], wet4);
- }
- for(;pos < BufferSize;pos++)
- OutBuffer[0][OutPos+pos] += data[pos] * WetGain;
+ ALuint pos = 0;
+ Step = params->Gain.Step;
+ if(Step != 1.0f && Counter > 0)
+ {
+ WetGain = params->Gain.Current;
+ if(BufferSize-pos > 3 && Counter-pos > 3)
+ {
+ OutBuffer[0][OutPos+pos ] += data[pos ]*WetGain;
+ WetGain *= Step;
+ OutBuffer[0][OutPos+pos+1] += data[pos+1]*WetGain;
+ WetGain *= Step;
+ OutBuffer[0][OutPos+pos+2] += data[pos+2]*WetGain;
+ WetGain *= Step;
+ OutBuffer[0][OutPos+pos+4] += data[pos+3]*WetGain;
+ WetGain *= Step;
+ }
+ if(!(BufferSize-pos > 3))
+ {
+ for(;pos < BufferSize && pos < Counter;pos++)
+ {
+ OutBuffer[0][OutPos+pos] += data[pos]*WetGain;
+ WetGain *= Step;
+ }
+ }
+ params->Gain.Current = WetGain;
+ }
- if(OutPos+pos == SamplesToDo)
- PendingClicks[0] += data[pos] * WetGain;
+ WetGain = params->Gain.Target;
+ if(!(WetGain > GAIN_SILENCE_THRESHOLD))
+ return;
+ gain = vdupq_n_f32(WetGain);
+ for(;BufferSize-pos > 3;pos += 4)
+ {
+ const float32x4_t val4 = vld1q_f32(&data[pos]);
+ float32x4_t wet4 = vld1q_f32(&OutBuffer[0][OutPos+pos]);
+ wet4 = vaddq_f32(wet4, vmulq_f32(val4, gain));
+ vst1q_f32(&OutBuffer[0][OutPos+pos], wet4);
+ }
+ for(;pos < BufferSize;pos++)
+ OutBuffer[0][OutPos+pos] += data[pos] * WetGain;
+ }
}
diff --git a/Alc/mixer_sse.c b/Alc/mixer_sse.c
index 38435dac..4ae15201 100644
--- a/Alc/mixer_sse.c
+++ b/Alc/mixer_sse.c
@@ -204,33 +204,62 @@ void MixDirect_SSE(DirectParams *params, const ALfloat *restrict data, ALuint sr
void MixSend_SSE(SendParams *params, const ALfloat *restrict data,
- ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
+ ALuint OutPos, ALuint UNUSED(SamplesToDo), ALuint BufferSize)
{
ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer;
- ALfloat *restrict ClickRemoval = params->ClickRemoval;
- ALfloat *restrict PendingClicks = params->PendingClicks;
- ALfloat WetGain;
- __m128 gain;
- ALuint pos;
+ ALuint Counter = maxu(params->Counter, OutPos) - OutPos;
+ ALfloat WetGain, Step;
+ __m128 gain, step;
- WetGain = params->Gain;
- if(!(WetGain > GAIN_SILENCE_THRESHOLD))
- return;
+ {
+ ALuint pos = 0;
- if(OutPos == 0)
- ClickRemoval[0] -= data[0] * WetGain;
+ Step = params->Gain.Step;
+ if(Step != 1.0f && Counter > 0)
+ {
+ WetGain = params->Gain.Current;
+ if(BufferSize-pos > 3 && Counter-pos > 3)
+ {
+ gain = _mm_set_ps(
+ WetGain,
+ WetGain * Step,
+ WetGain * Step * Step,
+ WetGain * Step * Step * Step
+ );
+ step = _mm_set1_ps(Step * Step * Step * Step);
+ do {
+ const __m128 val4 = _mm_load_ps(&data[pos]);
+ __m128 dry4 = _mm_load_ps(&OutBuffer[0][OutPos+pos]);
+ dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain));
+ gain = _mm_mul_ps(gain, step);
+ _mm_store_ps(&OutBuffer[0][OutPos+pos], dry4);
+ pos += 4;
+ } while(BufferSize-pos > 3 && Counter-pos > 3);
+ WetGain = _mm_cvtss_f32(_mm_shuffle_ps(gain, gain, _MM_SHUFFLE(3, 3, 3, 3)));
+ }
+ if(!(BufferSize-pos > 3))
+ {
+ for(;pos < BufferSize && pos < Counter;pos++)
+ {
+ OutBuffer[0][OutPos+pos] += data[pos]*WetGain;
+ WetGain *= Step;
+ }
+ }
+ params->Gain.Current = WetGain;
+ }
- gain = _mm_set1_ps(WetGain);
- for(pos = 0;BufferSize-pos > 3;pos += 4)
- {
- const __m128 val4 = _mm_load_ps(&data[pos]);
- __m128 wet4 = _mm_load_ps(&OutBuffer[0][OutPos+pos]);
- wet4 = _mm_add_ps(wet4, _mm_mul_ps(val4, gain));
- _mm_store_ps(&OutBuffer[0][OutPos+pos], wet4);
+ WetGain = params->Gain.Target;
+ if(!(WetGain > GAIN_SILENCE_THRESHOLD))
+ return;
+ gain = _mm_set1_ps(WetGain);
+ for(;BufferSize-pos > 3;pos += 4)
+ {
+ const __m128 val4 = _mm_load_ps(&data[pos]);
+ __m128 wet4 = _mm_load_ps(&OutBuffer[0][OutPos+pos]);
+ wet4 = _mm_add_ps(wet4, _mm_mul_ps(val4, gain));
+ _mm_store_ps(&OutBuffer[0][OutPos+pos], wet4);
+ }
+ for(;pos < BufferSize;pos++)
+ OutBuffer[0][OutPos+pos] += data[pos] * WetGain;
}
- for(;pos < BufferSize;pos++)
- OutBuffer[0][OutPos+pos] += data[pos] * WetGain;
-
- if(OutPos+pos == SamplesToDo)
- PendingClicks[0] += data[pos] * WetGain;
}
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index 3850875d..cfc54acc 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -87,7 +87,14 @@ typedef struct SendParams {
/* Gain control, which applies to all input channels to a single (mono)
* output buffer. */
- ALfloat Gain;
+ struct {
+ ALfloat Current;
+ ALfloat Step;
+ ALfloat Target;
+ } Gain;
+
+ ALboolean Moving;
+ ALuint Counter;
ALfilterState LpFilter[MAX_INPUT_CHANNELS];
} SendParams;
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index 082d8f54..acccd0be 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -2276,6 +2276,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
{
if(state == AL_PLAYING)
{
+ ALCdevice *device = Context->Device;
ALbufferlistitem *BufferList;
ALactivesource *src = NULL;
ALsizei j, k;
@@ -2306,7 +2307,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
/* If there's nothing to play, or device is disconnected, go right to
* stopped */
- if(!BufferList || !Context->Device->Connected)
+ if(!BufferList || !device->Connected)
{
SetSourceState(Source, Context, AL_STOPPED);
return;
@@ -2339,6 +2340,8 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
}
else
{
+ ALuint i;
+
src->Direct.Moving = AL_FALSE;
src->Direct.Counter = 0;
for(j = 0;j < MAX_INPUT_CHANNELS;j++)
@@ -2351,6 +2354,11 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
src->Direct.Mix.Hrtf.State.Values[j][k][1] = 0.0f;
}
}
+ for(i = 0;i < device->NumAuxSends;i++)
+ {
+ src->Send[i].Counter = 0;
+ src->Send[i].Moving = AL_FALSE;
+ }
}
Source->NeedsUpdate = AL_TRUE;
}