Get rid of the specialized MixRow_ methods
This commit is contained in:
@@ -21,14 +21,11 @@ struct ALeffectslot;
|
||||
using MixerFunc = void(*)(const al::span<const float> InSamples,
|
||||
const al::span<FloatBufferLine> OutBuffer, float *CurrentGains, const float *TargetGains,
|
||||
const size_t Counter, const size_t OutPos);
|
||||
using RowMixerFunc = void(*)(const al::span<float> OutBuffer, const al::span<const float> Gains,
|
||||
const float *InSamples, const size_t InStride);
|
||||
using HrtfDirectMixerFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut,
|
||||
const al::span<const FloatBufferLine> InSamples, float2 *AccumSamples, DirectHrtfState *State,
|
||||
const size_t BufferSize);
|
||||
|
||||
extern MixerFunc MixSamples;
|
||||
extern RowMixerFunc MixRowSamples;
|
||||
|
||||
|
||||
#define GAIN_MIX_MAX 1000.0f /* +60dB */
|
||||
|
||||
+41
-18
@@ -82,7 +82,7 @@ constexpr float MODULATION_DEPTH_COEFF{0.05f};
|
||||
* tetrahedron, but it's close enough. Should the model be extended to 8-lines
|
||||
* in the future, true opposites can be used.
|
||||
*/
|
||||
alignas(16) constexpr float B2A[NUM_LINES][MAX_AMBI_CHANNELS]{
|
||||
alignas(16) constexpr float B2A[NUM_LINES][NUM_LINES]{
|
||||
{ 0.288675134595f, 0.288675134595f, 0.288675134595f, 0.288675134595f },
|
||||
{ 0.288675134595f, -0.288675134595f, -0.288675134595f, 0.288675134595f },
|
||||
{ 0.288675134595f, 0.288675134595f, -0.288675134595f, -0.288675134595f },
|
||||
@@ -443,26 +443,43 @@ struct ReverbState final : public EffectState {
|
||||
std::array<std::array<BandSplitter,NUM_LINES>,2> mAmbiSplitter;
|
||||
|
||||
|
||||
static void DoMixRow(const al::span<float> OutBuffer, const al::span<const float> Gains,
|
||||
const float *InSamples, const size_t InStride)
|
||||
{
|
||||
std::fill(OutBuffer.begin(), OutBuffer.end(), 0.0f);
|
||||
for(const float gain : Gains)
|
||||
{
|
||||
const float *RESTRICT input{al::assume_aligned<16>(InSamples)};
|
||||
InSamples += InStride;
|
||||
|
||||
if(!(std::fabs(gain) > GAIN_SILENCE_THRESHOLD))
|
||||
continue;
|
||||
|
||||
for(float &sample : OutBuffer)
|
||||
{
|
||||
sample += *input * gain;
|
||||
++input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MixOutPlain(const al::span<FloatBufferLine> samplesOut, const size_t counter,
|
||||
const size_t offset, const size_t todo)
|
||||
{
|
||||
ASSUME(todo > 0);
|
||||
|
||||
/* Convert back to B-Format, and mix the results to output. */
|
||||
const al::span<float> tmpspan{mTempLine.data(), todo};
|
||||
const al::span<float> tmpspan{al::assume_aligned<16>(mTempLine.data()), todo};
|
||||
for(size_t c{0u};c < NUM_LINES;c++)
|
||||
{
|
||||
std::fill(tmpspan.begin(), tmpspan.end(), 0.0f);
|
||||
MixRowSamples(tmpspan, {A2B[c], NUM_LINES}, mEarlySamples[0].data(),
|
||||
mEarlySamples[0].size());
|
||||
DoMixRow(tmpspan, A2B[c], mEarlySamples[0].data(), mEarlySamples[0].size());
|
||||
MixSamples(tmpspan, samplesOut, mEarly.CurrentGain[c], mEarly.PanGain[c], counter,
|
||||
offset);
|
||||
}
|
||||
for(size_t c{0u};c < NUM_LINES;c++)
|
||||
{
|
||||
std::fill(tmpspan.begin(), tmpspan.end(), 0.0f);
|
||||
MixRowSamples(tmpspan, {A2B[c], NUM_LINES}, mLateSamples[0].data(),
|
||||
mLateSamples[0].size());
|
||||
DoMixRow(tmpspan, A2B[c], mLateSamples[0].data(), mLateSamples[0].size());
|
||||
MixSamples(tmpspan, samplesOut, mLate.CurrentGain[c], mLate.PanGain[c], counter,
|
||||
offset);
|
||||
}
|
||||
@@ -473,12 +490,10 @@ struct ReverbState final : public EffectState {
|
||||
{
|
||||
ASSUME(todo > 0);
|
||||
|
||||
const al::span<float> tmpspan{mTempLine.data(), todo};
|
||||
const al::span<float> tmpspan{al::assume_aligned<16>(mTempLine.data()), todo};
|
||||
for(size_t c{0u};c < NUM_LINES;c++)
|
||||
{
|
||||
std::fill(tmpspan.begin(), tmpspan.end(), 0.0f);
|
||||
MixRowSamples(tmpspan, {A2B[c], NUM_LINES}, mEarlySamples[0].data(),
|
||||
mEarlySamples[0].size());
|
||||
DoMixRow(tmpspan, A2B[c], mEarlySamples[0].data(), mEarlySamples[0].size());
|
||||
|
||||
/* Apply scaling to the B-Format's HF response to "upsample" it to
|
||||
* higher-order output.
|
||||
@@ -491,9 +506,7 @@ struct ReverbState final : public EffectState {
|
||||
}
|
||||
for(size_t c{0u};c < NUM_LINES;c++)
|
||||
{
|
||||
std::fill(tmpspan.begin(), tmpspan.end(), 0.0f);
|
||||
MixRowSamples(tmpspan, {A2B[c], NUM_LINES}, mLateSamples[0].data(),
|
||||
mLateSamples[0].size());
|
||||
DoMixRow(tmpspan, A2B[c], mLateSamples[0].data(), mLateSamples[0].size());
|
||||
|
||||
const float hfscale{(c==0) ? mOrderScales[0] : mOrderScales[1]};
|
||||
mAmbiSplitter[1][c].applyHfScale(tmpspan, hfscale);
|
||||
@@ -1589,12 +1602,22 @@ void ReverbState::process(const size_t samplesToDo, const al::span<const FloatBu
|
||||
ASSUME(samplesToDo > 0);
|
||||
|
||||
/* Convert B-Format to A-Format for processing. */
|
||||
const size_t numInput{samplesIn.size()};
|
||||
const al::span<float> tmpspan{mTempLine.data(), samplesToDo};
|
||||
const size_t numInput{minz(samplesIn.size(), NUM_LINES)};
|
||||
const al::span<float> tmpspan{al::assume_aligned<16>(mTempLine.data()), samplesToDo};
|
||||
for(size_t c{0u};c < NUM_LINES;c++)
|
||||
{
|
||||
std::fill(tmpspan.begin(), tmpspan.end(), 0.0f);
|
||||
MixRowSamples(tmpspan, {B2A[c], numInput}, samplesIn[0].data(), samplesIn[0].size());
|
||||
for(size_t i{0};i < numInput;++i)
|
||||
{
|
||||
const float gain{B2A[c][i]};
|
||||
const float *RESTRICT input{al::assume_aligned<16>(samplesIn[i].data())};
|
||||
|
||||
for(float &sample : tmpspan)
|
||||
{
|
||||
sample += *input * gain;
|
||||
++input;
|
||||
}
|
||||
}
|
||||
|
||||
/* Band-pass the incoming samples and feed the initial delay line. */
|
||||
mFilter[c].Lp.process(tmpspan, tmpspan.begin());
|
||||
|
||||
@@ -18,9 +18,6 @@ const float *Resample_(const InterpState *state, const float *RESTRICT src, ALui
|
||||
template<typename InstTag>
|
||||
void Mix_(const al::span<const float> InSamples, const al::span<FloatBufferLine> OutBuffer,
|
||||
float *CurrentGains, const float *TargetGains, const size_t Counter, const size_t OutPos);
|
||||
template<typename InstTag>
|
||||
void MixRow_(const al::span<float> OutBuffer, const al::span<const float> Gains,
|
||||
const float *InSamples, const size_t InStride);
|
||||
|
||||
template<typename InstTag>
|
||||
void MixHrtf_(const float *InSamples, float2 *AccumSamples, const ALuint IrSize,
|
||||
|
||||
@@ -196,27 +196,3 @@ void Mix_<CTag>(const al::span<const float> InSamples, const al::span<FloatBuffe
|
||||
*(dst++) += *(in_iter++) * gain;
|
||||
}
|
||||
}
|
||||
|
||||
/* Basically the inverse of the above. Rather than one input going to multiple
|
||||
* outputs (each with its own gain), it's multiple inputs (each with its own
|
||||
* gain) going to one output. This applies one row (vs one column) of a matrix
|
||||
* transform. And as the matrices are more or less static once set up, no
|
||||
* stepping is necessary.
|
||||
*/
|
||||
template<>
|
||||
void MixRow_<CTag>(const al::span<float> OutBuffer, const al::span<const float> Gains,
|
||||
const float *InSamples, const size_t InStride)
|
||||
{
|
||||
for(const float gain : Gains)
|
||||
{
|
||||
const float *RESTRICT input{InSamples};
|
||||
InSamples += InStride;
|
||||
|
||||
if(!(std::fabs(gain) > GAIN_SILENCE_THRESHOLD))
|
||||
continue;
|
||||
|
||||
auto do_mix = [gain](const float cur, const float src) noexcept -> float
|
||||
{ return cur + src*gain; };
|
||||
std::transform(OutBuffer.begin(), OutBuffer.end(), input, OutBuffer.begin(), do_mix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,34 +296,3 @@ void Mix_<NEONTag>(const al::span<const float> InSamples, const al::span<FloatBu
|
||||
*(dst++) += *(in_iter++) * gain;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void MixRow_<NEONTag>(const al::span<float> OutBuffer, const al::span<const float> Gains,
|
||||
const float *InSamples, const size_t InStride)
|
||||
{
|
||||
for(const float gain : Gains)
|
||||
{
|
||||
const float *RESTRICT input{InSamples};
|
||||
InSamples += InStride;
|
||||
|
||||
if(!(std::fabs(gain) > GAIN_SILENCE_THRESHOLD))
|
||||
continue;
|
||||
|
||||
auto out_iter = OutBuffer.begin();
|
||||
if(size_t todo{OutBuffer.size() >> 2})
|
||||
{
|
||||
const float32x4_t gain4{vdupq_n_f32(gain)};
|
||||
do {
|
||||
const float32x4_t val4 = vld1q_f32(input);
|
||||
float32x4_t dry4 = vld1q_f32(out_iter);
|
||||
dry4 = vmlaq_f32(dry4, val4, gain4);
|
||||
vst1q_f32(out_iter, dry4);
|
||||
out_iter += 4; input += 4;
|
||||
} while(--todo);
|
||||
}
|
||||
|
||||
auto do_mix = [gain](const float cur, const float src) noexcept -> float
|
||||
{ return cur + src*gain; };
|
||||
std::transform(out_iter, OutBuffer.end(), input, out_iter, do_mix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,34 +268,3 @@ void Mix_<SSETag>(const al::span<const float> InSamples, const al::span<FloatBuf
|
||||
*(dst++) += *(in_iter++) * gain;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void MixRow_<SSETag>(const al::span<float> OutBuffer, const al::span<const float> Gains,
|
||||
const float *InSamples, const size_t InStride)
|
||||
{
|
||||
for(const float gain : Gains)
|
||||
{
|
||||
const float *RESTRICT input{InSamples};
|
||||
InSamples += InStride;
|
||||
|
||||
if(!(std::fabs(gain) > GAIN_SILENCE_THRESHOLD))
|
||||
continue;
|
||||
|
||||
auto out_iter = OutBuffer.begin();
|
||||
if(size_t todo{OutBuffer.size() >> 2})
|
||||
{
|
||||
const __m128 gain4 = _mm_set1_ps(gain);
|
||||
do {
|
||||
const __m128 val4{_mm_load_ps(input)};
|
||||
__m128 dry4{_mm_load_ps(out_iter)};
|
||||
dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain4));
|
||||
_mm_store_ps(out_iter, dry4);
|
||||
out_iter += 4; input += 4;
|
||||
} while(--todo);
|
||||
}
|
||||
|
||||
auto do_mix = [gain](const float cur, const float src) noexcept -> float
|
||||
{ return cur + src*gain; };
|
||||
std::transform(out_iter, OutBuffer.end(), input, out_iter, do_mix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@ static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
|
||||
Resampler ResamplerDefault{Resampler::Linear};
|
||||
|
||||
MixerFunc MixSamples{Mix_<CTag>};
|
||||
RowMixerFunc MixRowSamples{MixRow_<CTag>};
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -107,19 +106,6 @@ inline MixerFunc SelectMixer()
|
||||
return Mix_<CTag>;
|
||||
}
|
||||
|
||||
inline RowMixerFunc SelectRowMixer()
|
||||
{
|
||||
#ifdef HAVE_NEON
|
||||
if((CPUCapFlags&CPU_CAP_NEON))
|
||||
return MixRow_<NEONTag>;
|
||||
#endif
|
||||
#ifdef HAVE_SSE
|
||||
if((CPUCapFlags&CPU_CAP_SSE))
|
||||
return MixRow_<SSETag>;
|
||||
#endif
|
||||
return MixRow_<CTag>;
|
||||
}
|
||||
|
||||
inline HrtfMixerFunc SelectHrtfMixer()
|
||||
{
|
||||
#ifdef HAVE_NEON
|
||||
@@ -189,7 +175,6 @@ void aluInitMixer()
|
||||
}
|
||||
|
||||
MixSamples = SelectMixer();
|
||||
MixRowSamples = SelectRowMixer();
|
||||
MixHrtfBlendSamples = SelectHrtfBlendMixer();
|
||||
MixHrtfSamples = SelectHrtfMixer();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user