From 52deb557d5466e7dd0b78dceb16f2ad5296bbcd4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 23 Mar 2014 16:11:21 -0700 Subject: Add gain stepping to the send mixers --- Alc/ALc.c | 7 +++++ Alc/ALu.c | 44 +++++++++++++++++++++++++++-- Alc/mixer_c.c | 40 ++++++++++++++++----------- Alc/mixer_neon.c | 66 ++++++++++++++++++++++++++++---------------- Alc/mixer_sse.c | 75 ++++++++++++++++++++++++++++++++++---------------- OpenAL32/Include/alu.h | 9 +++++- OpenAL32/alSource.c | 10 ++++++- 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; } -- cgit v1.2.3