Add gain stepping to the send mixers
This commit is contained in:
parent
83038c0dab
commit
52deb557d5
@ -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;
|
||||
|
44
Alc/ALu.c
44
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();
|
||||
|
||||
{
|
||||
|
@ -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;
|
||||
ALuint Counter = maxu(params->Counter, OutPos) - OutPos;
|
||||
ALfloat WetSend, Step;
|
||||
|
||||
WetSend = params->Gain;
|
||||
if(!(WetSend > GAIN_SILENCE_THRESHOLD))
|
||||
return;
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
WetSend = params->Gain.Target;
|
||||
if(!(WetSend > GAIN_SILENCE_THRESHOLD))
|
||||
return;
|
||||
for(;pos < BufferSize;pos++)
|
||||
OutBuffer[0][OutPos+pos] += data[pos] * WetSend;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
if(OutPos == 0)
|
||||
ClickRemoval[0] -= data[0] * 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);
|
||||
}
|
||||
for(;pos < BufferSize;pos++)
|
||||
OutBuffer[0][OutPos+pos] += data[pos] * WetGain;
|
||||
ALuint pos = 0;
|
||||
|
||||
if(OutPos+pos == SamplesToDo)
|
||||
PendingClicks[0] += data[pos] * 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user