aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/mixer_neon.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2014-01-26 01:34:39 -0800
committerChris Robinson <[email protected]>2014-01-26 01:34:39 -0800
commita4bc0a46e9e0fe001d4c14909b47ed4ac8d81960 (patch)
treea0ba33c23b3ceeb36e44f3d0212091398da6bcf3 /Alc/mixer_neon.c
parent49baa9128dd98e986639def4f24c7522d9ec6b56 (diff)
Implement dry and wet mixers for Neon
Code provided by Philippe Simons <[email protected]>.
Diffstat (limited to 'Alc/mixer_neon.c')
-rw-r--r--Alc/mixer_neon.c80
1 files changed, 77 insertions, 3 deletions
diff --git a/Alc/mixer_neon.c b/Alc/mixer_neon.c
index 571221be..0aa450ad 100644
--- a/Alc/mixer_neon.c
+++ b/Alc/mixer_neon.c
@@ -14,11 +14,15 @@ static inline void ApplyCoeffsStep(const ALuint IrSize,
ALfloat (*restrict Coeffs)[2],
const ALfloat (*restrict CoeffStep)[2])
{
+ float32x4_t coeffs, deltas;
ALuint c;
- for(c = 0;c < IrSize;c++)
+
+ for(c = 0;c < IrSize;c += 2)
{
- Coeffs[c][0] += CoeffStep[c][0];
- Coeffs[c][1] += CoeffStep[c][1];
+ coeffs = vld1q_f32(&Coeffs[c][0]);
+ deltas = vld1q_f32(&CoeffStep[c][0]);
+ coeffs = vaddq_f32(coeffs, deltas);
+ vst1q_f32(&Coeffs[c][0], coeffs);
}
}
@@ -54,3 +58,73 @@ static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
#define SUFFIX Neon
#include "mixer_inc.c"
#undef SUFFIX
+
+
+void MixDirect_Neon(const DirectParams *params, const ALfloat *restrict data, ALuint srcchan,
+ ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
+{
+ ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer;
+ ALfloat *restrict ClickRemoval = params->ClickRemoval;
+ ALfloat *restrict PendingClicks = params->PendingClicks;
+ ALfloat DrySend;
+ float32x4_t gain;
+ ALuint pos;
+ ALuint c;
+
+ for(c = 0;c < MaxChannels;c++)
+ {
+ DrySend = params->Gains[srcchan][c];
+ if(!(DrySend > GAIN_SILENCE_THRESHOLD))
+ continue;
+
+ if(OutPos == 0)
+ ClickRemoval[c] -= data[0]*DrySend;
+
+ gain = vdupq_n_f32(DrySend);
+ for(pos = 0;BufferSize-pos > 3;pos += 4)
+ {
+ const float32x4_t val4 = vld1q_f32(&data[pos]);
+ float32x4_t dry4 = vld1q_f32(&OutBuffer[c][OutPos+pos]);
+ dry4 = vaddq_f32(dry4, vmulq_f32(val4, gain));
+ vst1q_f32(&OutBuffer[c][OutPos+pos], dry4);
+ }
+ for(;pos < BufferSize;pos++)
+ OutBuffer[c][OutPos+pos] += data[pos]*DrySend;
+
+ if(OutPos+pos == SamplesToDo)
+ PendingClicks[c] += data[pos]*DrySend;
+ }
+}
+
+
+void MixSend_Neon(const SendParams *params, const ALfloat *restrict data,
+ ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
+{
+ ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer;
+ ALfloat *restrict ClickRemoval = params->ClickRemoval;
+ ALfloat *restrict PendingClicks = params->PendingClicks;
+ ALfloat WetGain;
+ 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;
+
+ if(OutPos+pos == SamplesToDo)
+ PendingClicks[0] += data[pos] * WetGain;
+}