diff options
author | Chris Robinson <[email protected]> | 2014-03-23 06:57:00 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2014-03-23 06:57:00 -0700 |
commit | 81e049bd47cc2423dc6983c47d9f99e70c3135ac (patch) | |
tree | 74424462f69b97dffaebdc04dc263bf5eeb6183c /Alc/mixer_sse.c | |
parent | 0ce0a88fd67ddcf7cb5248ac08d36cfa1c0013eb (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.c | 56 |
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; } } |