aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/mixer_sse.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2014-03-23 06:57:00 -0700
committerChris Robinson <[email protected]>2014-03-23 06:57:00 -0700
commit81e049bd47cc2423dc6983c47d9f99e70c3135ac (patch)
tree74424462f69b97dffaebdc04dc263bf5eeb6183c /Alc/mixer_sse.c
parent0ce0a88fd67ddcf7cb5248ac08d36cfa1c0013eb (diff)
Step mixing gains per-sample for non-HRTF mixing
This fades the dry mixing gains using a logarithmic curve, which should produce a smoother transition than a linear one. It functions similarly to a linear fade except that step = (target - current) / numsteps; ... gain += step; becomes step = powf(target / current, 1.0f / numsteps); ... gain *= step; where 'target' and 'current' are clamped to a lower bound that is greater than 0 (which makes no sense on a logarithmic scale). Consequently, the non-HRTF direct mixers do not do not feed into the click removal and pending click buffers, as this per-sample fading would do an adequate job of stopping clicks and pops caused by extreme gain changes. These buffers should be removed shortly.
Diffstat (limited to 'Alc/mixer_sse.c')
-rw-r--r--Alc/mixer_sse.c56
1 files changed, 41 insertions, 15 deletions
diff --git a/Alc/mixer_sse.c b/Alc/mixer_sse.c
index c9296d3d..52785086 100644
--- a/Alc/mixer_sse.c
+++ b/Alc/mixer_sse.c
@@ -141,27 +141,56 @@ static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
void MixDirect_SSE(DirectParams *params, const ALfloat *restrict data, ALuint srcchan,
- 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 DrySend;
- __m128 gain;
- ALuint pos;
+ ALuint Counter = maxu(params->Counter, OutPos) - OutPos;
+ ALfloat DrySend, Step;
+ __m128 gain, step;
ALuint c;
for(c = 0;c < MaxChannels;c++)
{
- DrySend = params->Mix.Gains[srcchan][c];
+ ALuint pos = 0;
+ Step = params->Mix.Gains.Step[srcchan][c];
+ if(Step != 1.0f && Counter > 0)
+ {
+ DrySend = params->Mix.Gains.Current[srcchan][c];
+ if(BufferSize-pos > 3 && Counter-pos > 3)
+ {
+ gain = _mm_set_ps(
+ DrySend,
+ DrySend * Step,
+ DrySend * Step * Step,
+ DrySend * 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[c][OutPos+pos]);
+ dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain));
+ gain = _mm_mul_ps(gain, step);
+ _mm_store_ps(&OutBuffer[c][OutPos+pos], dry4);
+ pos += 4;
+ } while(BufferSize-pos > 3 && Counter-pos > 3);
+ DrySend = _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[c][OutPos+pos] += data[pos]*DrySend;
+ DrySend *= Step;
+ }
+ }
+ params->Mix.Gains.Current[srcchan][c] = DrySend;
+ }
+
+ DrySend = params->Mix.Gains.Target[srcchan][c];
if(!(DrySend > GAIN_SILENCE_THRESHOLD))
continue;
-
- if(OutPos == 0)
- ClickRemoval[c] -= data[0]*DrySend;
-
gain = _mm_set1_ps(DrySend);
- for(pos = 0;BufferSize-pos > 3;pos += 4)
+ for(;BufferSize-pos > 3;pos += 4)
{
const __m128 val4 = _mm_load_ps(&data[pos]);
__m128 dry4 = _mm_load_ps(&OutBuffer[c][OutPos+pos]);
@@ -170,9 +199,6 @@ void MixDirect_SSE(DirectParams *params, const ALfloat *restrict data, ALuint sr
}
for(;pos < BufferSize;pos++)
OutBuffer[c][OutPos+pos] += data[pos]*DrySend;
-
- if(OutPos+pos == SamplesToDo)
- PendingClicks[c] += data[pos]*DrySend;
}
}