diff options
author | Chris Robinson <[email protected]> | 2023-12-11 15:08:12 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2023-12-11 15:08:12 -0800 |
commit | ec40e4fefef954544c25285bfeae4a44c1134a44 (patch) | |
tree | 72b55e01fd50bed966db533713f998cf06815172 /alc | |
parent | a28bf538afabca45298a43e5d2acf3e6149a2c2c (diff) |
Finish cleanup for effects
Diffstat (limited to 'alc')
-rw-r--r-- | alc/effects/autowah.cpp | 49 | ||||
-rw-r--r-- | alc/effects/chorus.cpp | 33 | ||||
-rw-r--r-- | alc/effects/compressor.cpp | 9 | ||||
-rw-r--r-- | alc/effects/convolution.cpp | 115 | ||||
-rw-r--r-- | alc/effects/dedicated.cpp | 4 | ||||
-rw-r--r-- | alc/effects/distortion.cpp | 14 | ||||
-rw-r--r-- | alc/effects/echo.cpp | 34 | ||||
-rw-r--r-- | alc/effects/equalizer.cpp | 15 | ||||
-rw-r--r-- | alc/effects/fshifter.cpp | 17 | ||||
-rw-r--r-- | alc/effects/modulator.cpp | 5 | ||||
-rw-r--r-- | alc/effects/pshifter.cpp | 12 | ||||
-rw-r--r-- | alc/effects/reverb.cpp | 98 | ||||
-rw-r--r-- | alc/effects/vmorpher.cpp | 104 |
13 files changed, 262 insertions, 247 deletions
diff --git a/alc/effects/autowah.cpp b/alc/effects/autowah.cpp index 4f874ef2..6d66f99f 100644 --- a/alc/effects/autowah.cpp +++ b/alc/effects/autowah.cpp @@ -59,12 +59,13 @@ struct AutowahState final : public EffectState { float mEnvDelay; /* Filter components derived from the envelope. */ - struct { + struct FilterParam { float cos_w0; float alpha; - } mEnv[BufferLineSize]; + }; + std::array<FilterParam,BufferLineSize> mEnv; - struct { + struct ChannelData { uint mTargetChannel{InvalidChannelIndex}; /* Effect filters' history. */ @@ -75,10 +76,11 @@ struct AutowahState final : public EffectState { /* Effect gains for each output channel */ float mCurrentGain; float mTargetGain; - } mChans[MaxAmbiChannels]; + }; + std::array<ChannelData,MaxAmbiChannels> mChans; /* Effects buffers */ - alignas(16) float mBufferOut[BufferLineSize]; + alignas(16) FloatBufferLine mBufferOut; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; @@ -155,17 +157,16 @@ void AutowahState::process(const size_t samplesToDo, float env_delay{mEnvDelay}; for(size_t i{0u};i < samplesToDo;i++) { - float w0, sample, a; - /* Envelope follower described on the book: Audio Effects, Theory, * Implementation and Application. */ - sample = peak_gain * std::fabs(samplesIn[0][i]); - a = (sample > env_delay) ? attack_rate : release_rate; + const float sample{peak_gain * std::fabs(samplesIn[0][i])}; + const float a{(sample > env_delay) ? attack_rate : release_rate}; env_delay = lerpf(sample, env_delay, a); /* Calculate the cos and alpha components for this sample's filter. */ - w0 = minf((bandwidth*env_delay + freq_min), 0.46f) * (al::numbers::pi_v<float>*2.0f); + const float w0{minf((bandwidth*env_delay + freq_min), 0.46f) * + (al::numbers::pi_v<float>*2.0f)}; mEnv[i].cos_w0 = std::cos(w0); mEnv[i].alpha = std::sin(w0)/(2.0f * QFactor); } @@ -194,18 +195,18 @@ void AutowahState::process(const size_t samplesToDo, { const float alpha{mEnv[i].alpha}; const float cos_w0{mEnv[i].cos_w0}; - float input, output; - float a[3], b[3]; - - b[0] = 1.0f + alpha*res_gain; - b[1] = -2.0f * cos_w0; - b[2] = 1.0f - alpha*res_gain; - a[0] = 1.0f + alpha/res_gain; - a[1] = -2.0f * cos_w0; - a[2] = 1.0f - alpha/res_gain; - - input = insamples[i]; - output = input*(b[0]/a[0]) + z1; + + const std::array b{ + 1.0f + alpha*res_gain, + -2.0f * cos_w0, + 1.0f - alpha*res_gain}; + const std::array a{ + 1.0f + alpha/res_gain, + -2.0f * cos_w0, + 1.0f - alpha/res_gain}; + + const float input{insamples[i]}; + const float output{input*(b[0]/a[0]) + z1}; z1 = input*(b[1]/a[0]) - output*(a[1]/a[0]) + z2; z2 = input*(b[2]/a[0]) - output*(a[2]/a[0]); mBufferOut[i] = output; @@ -214,8 +215,8 @@ void AutowahState::process(const size_t samplesToDo, chandata->mFilter.z2 = z2; /* Now, mix the processed sound data to the output. */ - MixSamples({mBufferOut, samplesToDo}, samplesOut[outidx].data(), chandata->mCurrentGain, - chandata->mTargetGain, samplesToDo); + MixSamples({mBufferOut.data(), samplesToDo}, samplesOut[outidx].data(), + chandata->mCurrentGain, chandata->mTargetGain, samplesToDo); ++chandata; } } diff --git a/alc/effects/chorus.cpp b/alc/effects/chorus.cpp index 9cbc922f..098b33a1 100644 --- a/alc/effects/chorus.cpp +++ b/alc/effects/chorus.cpp @@ -58,16 +58,17 @@ struct ChorusState final : public EffectState { uint mLfoDisp{0}; /* Calculated delays to apply to the left and right outputs. */ - uint mModDelays[2][BufferLineSize]; + std::array<std::array<uint,BufferLineSize>,2> mModDelays; /* Temp storage for the modulated left and right outputs. */ - alignas(16) float mBuffer[2][BufferLineSize]; + alignas(16) std::array<FloatBufferLine,2> mBuffer; /* Gains for left and right outputs. */ - struct { - float Current[MaxAmbiChannels]{}; - float Target[MaxAmbiChannels]{}; - } mGains[2]; + struct OutGains { + std::array<float,MaxAmbiChannels> Current{}; + std::array<float,MaxAmbiChannels> Target{}; + }; + std::array<OutGains,2> mGains; /* effect parameters */ ChorusWaveform mWaveform{}; @@ -99,8 +100,8 @@ void ChorusState::deviceUpdate(const DeviceBase *Device, const BufferStorage*) std::fill(mDelayBuffer.begin(), mDelayBuffer.end(), 0.0f); for(auto &e : mGains) { - std::fill(std::begin(e.Current), std::end(e.Current), 0.0f); - std::fill(std::begin(e.Target), std::end(e.Target), 0.0f); + e.Current.fill(0.0f); + e.Target.fill(0.0f); } } @@ -266,10 +267,10 @@ void ChorusState::process(const size_t samplesToDo, const al::span<const FloatBu else /*if(mWaveform == ChorusWaveform::Triangle)*/ calcTriangleDelays(samplesToDo); - const uint *RESTRICT ldelays{mModDelays[0]}; - const uint *RESTRICT rdelays{mModDelays[1]}; - float *RESTRICT lbuffer{al::assume_aligned<16>(mBuffer[0])}; - float *RESTRICT rbuffer{al::assume_aligned<16>(mBuffer[1])}; + const uint *RESTRICT ldelays{mModDelays[0].data()}; + const uint *RESTRICT rdelays{mModDelays[1].data()}; + float *RESTRICT lbuffer{al::assume_aligned<16>(mBuffer[0].data())}; + float *RESTRICT rbuffer{al::assume_aligned<16>(mBuffer[1].data())}; for(size_t i{0u};i < samplesToDo;++i) { // Feed the buffer's input first (necessary for delays < 1). @@ -292,10 +293,10 @@ void ChorusState::process(const size_t samplesToDo, const al::span<const FloatBu ++offset; } - MixSamples({lbuffer, samplesToDo}, samplesOut, mGains[0].Current, mGains[0].Target, - samplesToDo, 0); - MixSamples({rbuffer, samplesToDo}, samplesOut, mGains[1].Current, mGains[1].Target, - samplesToDo, 0); + MixSamples({lbuffer, samplesToDo}, samplesOut, mGains[0].Current.data(), + mGains[0].Target.data(), samplesToDo, 0); + MixSamples({rbuffer, samplesToDo}, samplesOut, mGains[1].Current.data(), + mGains[1].Target.data(), samplesToDo, 0); mOffset = offset; } diff --git a/alc/effects/compressor.cpp b/alc/effects/compressor.cpp index 0a7ed67a..47ef64e9 100644 --- a/alc/effects/compressor.cpp +++ b/alc/effects/compressor.cpp @@ -64,10 +64,11 @@ namespace { struct CompressorState final : public EffectState { /* Effect gains for each channel */ - struct { + struct TargetGain { uint mTarget{InvalidChannelIndex}; float mGain{1.0f}; - } mChans[MaxAmbiChannels]; + }; + std::array<TargetGain,MaxAmbiChannels> mChans; /* Effect parameters */ bool mEnabled{true}; @@ -119,8 +120,8 @@ void CompressorState::process(const size_t samplesToDo, { for(size_t base{0u};base < samplesToDo;) { - float gains[256]; - const size_t td{minz(256, samplesToDo-base)}; + std::array<float,256> gains; + const size_t td{minz(gains.size(), samplesToDo-base)}; /* Generate the per-sample gains from the signal envelope. */ float env{mEnvFollower}; diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index c877456d..1fcb419c 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -10,6 +10,7 @@ #include <iterator> #include <memory> #include <utility> +#include <vector> #ifdef HAVE_SSE_INTRINSICS #include <xmmintrin.h> @@ -325,10 +326,10 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag /* Load the samples from the buffer. */ const size_t srclinelength{RoundUp(buffer->mSampleLen+DecoderPadding, 16)}; - auto srcsamples = std::make_unique<float[]>(srclinelength * numChannels); - std::fill_n(srcsamples.get(), srclinelength * numChannels, 0.0f); + auto srcsamples = std::vector<float>(srclinelength * numChannels); + std::fill(srcsamples.begin(), srcsamples.end(), 0.0f); for(size_t c{0};c < numChannels && c < realChannels;++c) - LoadSamples(srcsamples.get() + srclinelength*c, buffer->mData.data() + bytesPerSample*c, + LoadSamples(srcsamples.data() + srclinelength*c, buffer->mData.data() + bytesPerSample*c, realChannels, buffer->mType, buffer->mSampleLen); if(IsUHJ(mChannels)) @@ -336,12 +337,11 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag auto decoder = std::make_unique<UhjDecoderType>(); std::array<float*,4> samples{}; for(size_t c{0};c < numChannels;++c) - samples[c] = srcsamples.get() + srclinelength*c; + samples[c] = srcsamples.data() + srclinelength*c; decoder->decode({samples.data(), numChannels}, buffer->mSampleLen, buffer->mSampleLen); } - auto ressamples = std::make_unique<double[]>(buffer->mSampleLen + - (resampler ? resampledCount : 0)); + auto ressamples = std::vector<double>(buffer->mSampleLen + (resampler ? resampledCount : 0)); auto ffttmp = al::vector<float,16>(ConvolveUpdateSize); auto fftbuffer = std::vector<std::complex<double>>(ConvolveUpdateSize); @@ -351,19 +351,20 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag /* Resample to match the device. */ if(resampler) { - std::copy_n(srcsamples.get() + srclinelength*c, buffer->mSampleLen, - ressamples.get() + resampledCount); - resampler.process(buffer->mSampleLen, ressamples.get()+resampledCount, - resampledCount, ressamples.get()); + std::copy_n(srcsamples.data() + srclinelength*c, buffer->mSampleLen, + ressamples.data() + resampledCount); + resampler.process(buffer->mSampleLen, ressamples.data()+resampledCount, + resampledCount, ressamples.data()); } else - std::copy_n(srcsamples.get() + srclinelength*c, buffer->mSampleLen, ressamples.get()); + std::copy_n(srcsamples.data() + srclinelength*c, buffer->mSampleLen, + ressamples.data()); /* Store the first segment's samples in reverse in the time-domain, to * apply as a FIR filter. */ const size_t first_size{minz(resampledCount, ConvolveUpdateSamples)}; - std::transform(ressamples.get(), ressamples.get()+first_size, mFilter[c].rbegin(), + std::transform(ressamples.data(), ressamples.data()+first_size, mFilter[c].rbegin(), [](const double d) noexcept -> float { return static_cast<float>(d); }); size_t done{first_size}; @@ -408,43 +409,49 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot * to have its own output target since the main mixing buffer won't have an * LFE channel (due to being B-Format). */ - static constexpr ChanPosMap MonoMap[1]{ - { FrontCenter, std::array{0.0f, 0.0f, -1.0f} } - }, StereoMap[2]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, - }, RearMap[2]{ - { BackLeft, std::array{-sin30, 0.0f, cos30} }, - { BackRight, std::array{ sin30, 0.0f, cos30} }, - }, QuadMap[4]{ - { FrontLeft, std::array{-sin45, 0.0f, -cos45} }, - { FrontRight, std::array{ sin45, 0.0f, -cos45} }, - { BackLeft, std::array{-sin45, 0.0f, cos45} }, - { BackRight, std::array{ sin45, 0.0f, cos45} }, - }, X51Map[6]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, - { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, - { LFE, {} }, - { SideLeft, std::array{-sin110, 0.0f, -cos110} }, - { SideRight, std::array{ sin110, 0.0f, -cos110} }, - }, X61Map[7]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, - { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, - { LFE, {} }, - { BackCenter, std::array{ 0.0f, 0.0f, 1.0f} }, - { SideLeft, std::array{-1.0f, 0.0f, 0.0f} }, - { SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, - }, X71Map[8]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, - { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, - { LFE, {} }, - { BackLeft, std::array{-sin30, 0.0f, cos30} }, - { BackRight, std::array{ sin30, 0.0f, cos30} }, - { SideLeft, std::array{ -1.0f, 0.0f, 0.0f} }, - { SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, + static constexpr std::array MonoMap{ + ChanPosMap{FrontCenter, std::array{0.0f, 0.0f, -1.0f}} + }; + static constexpr std::array StereoMap{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + }; + static constexpr std::array RearMap{ + ChanPosMap{BackLeft, std::array{-sin30, 0.0f, cos30}}, + ChanPosMap{BackRight, std::array{ sin30, 0.0f, cos30}}, + }; + static constexpr std::array QuadMap{ + ChanPosMap{FrontLeft, std::array{-sin45, 0.0f, -cos45}}, + ChanPosMap{FrontRight, std::array{ sin45, 0.0f, -cos45}}, + ChanPosMap{BackLeft, std::array{-sin45, 0.0f, cos45}}, + ChanPosMap{BackRight, std::array{ sin45, 0.0f, cos45}}, + }; + static constexpr std::array X51Map{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + ChanPosMap{FrontCenter, std::array{ 0.0f, 0.0f, -1.0f}}, + ChanPosMap{LFE, {}}, + ChanPosMap{SideLeft, std::array{-sin110, 0.0f, -cos110}}, + ChanPosMap{SideRight, std::array{ sin110, 0.0f, -cos110}}, + }; + static constexpr std::array X61Map{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + ChanPosMap{FrontCenter, std::array{ 0.0f, 0.0f, -1.0f}}, + ChanPosMap{LFE, {}}, + ChanPosMap{BackCenter, std::array{ 0.0f, 0.0f, 1.0f} }, + ChanPosMap{SideLeft, std::array{-1.0f, 0.0f, 0.0f} }, + ChanPosMap{SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, + }; + static constexpr std::array X71Map{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + ChanPosMap{FrontCenter, std::array{ 0.0f, 0.0f, -1.0f}}, + ChanPosMap{LFE, {}}, + ChanPosMap{BackLeft, std::array{-sin30, 0.0f, cos30}}, + ChanPosMap{BackRight, std::array{ sin30, 0.0f, cos30}}, + ChanPosMap{SideLeft, std::array{ -1.0f, 0.0f, 0.0f}}, + ChanPosMap{SideRight, std::array{ 1.0f, 0.0f, 0.0f}}, }; if(mNumConvolveSegs < 1) UNLIKELY @@ -493,11 +500,11 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot alu::Vector U{N.cross_product(V)}; U.normalize(); - const float mixmatrix[4][4]{ - {1.0f, 0.0f, 0.0f, 0.0f}, - {0.0f, U[0], -U[1], U[2]}, - {0.0f, -V[0], V[1], -V[2]}, - {0.0f, -N[0], N[1], -N[2]}, + const std::array mixmatrix{ + std::array{1.0f, 0.0f, 0.0f, 0.0f}, + std::array{0.0f, U[0], -U[1], U[2]}, + std::array{0.0f, -V[0], V[1], -V[2]}, + std::array{0.0f, -N[0], N[1], -N[2]}, }; const auto scales = GetAmbiScales(mAmbiScaling); diff --git a/alc/effects/dedicated.cpp b/alc/effects/dedicated.cpp index 69e70847..1b8b3977 100644 --- a/alc/effects/dedicated.cpp +++ b/alc/effects/dedicated.cpp @@ -62,13 +62,13 @@ struct DedicatedState final : public EffectState { void DedicatedState::deviceUpdate(const DeviceBase*, const BufferStorage*) { - std::fill(std::begin(mCurrentGains), std::end(mCurrentGains), 0.0f); + std::fill(mCurrentGains.begin(), mCurrentGains.end(), 0.0f); } void DedicatedState::update(const ContextBase*, const EffectSlot *slot, const EffectProps *props, const EffectTarget target) { - std::fill(std::begin(mTargetGains), std::end(mTargetGains), 0.0f); + std::fill(mTargetGains.begin(), mTargetGains.end(), 0.0f); const float Gain{slot->Gain * props->Dedicated.Gain}; diff --git a/alc/effects/distortion.cpp b/alc/effects/distortion.cpp index 3d77ff35..9ef9de25 100644 --- a/alc/effects/distortion.cpp +++ b/alc/effects/distortion.cpp @@ -45,7 +45,7 @@ namespace { struct DistortionState final : public EffectState { /* Effect gains for each channel */ - float mGain[MaxAmbiChannels]{}; + std::array<float,MaxAmbiChannels> mGain{}; /* Effect parameters */ BiquadFilter mLowpass; @@ -53,7 +53,7 @@ struct DistortionState final : public EffectState { float mAttenuation{}; float mEdgeCoeff{}; - alignas(16) float mBuffer[2][BufferLineSize]{}; + alignas(16) std::array<FloatBufferLine,2> mBuffer{}; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; @@ -124,7 +124,7 @@ void DistortionState::process(const size_t samplesToDo, const al::span<const Flo * (which is fortunately first step of distortion). So combine three * operations into the one. */ - mLowpass.process({mBuffer[0], todo}, mBuffer[1]); + mLowpass.process({mBuffer[0].data(), todo}, mBuffer[1].data()); /* Second step, do distortion using waveshaper function to emulate * signal processing during tube overdriving. Three steps of @@ -138,15 +138,15 @@ void DistortionState::process(const size_t samplesToDo, const al::span<const Flo smp = (1.0f + fc) * smp/(1.0f + fc*std::abs(smp)); return smp; }; - std::transform(std::begin(mBuffer[1]), std::begin(mBuffer[1])+todo, std::begin(mBuffer[0]), + std::transform(mBuffer[1].begin(), mBuffer[1].begin()+todo, mBuffer[0].begin(), proc_sample); /* Third step, do bandpass filtering of distorted signal. */ - mBandpass.process({mBuffer[0], todo}, mBuffer[1]); + mBandpass.process({mBuffer[0].data(), todo}, mBuffer[1].data()); todo >>= 2; - const float *outgains{mGain}; - for(FloatBufferLine &output : samplesOut) + const float *outgains{mGain.data()}; + for(FloatBufferLine &RESTRICT output : samplesOut) { /* Fourth step, final, do attenuation and perform decimation, * storing only one sample out of four. diff --git a/alc/effects/echo.cpp b/alc/effects/echo.cpp index 714649c9..fe6d8258 100644 --- a/alc/effects/echo.cpp +++ b/alc/effects/echo.cpp @@ -53,21 +53,20 @@ struct EchoState final : public EffectState { // The echo is two tap. The delay is the number of samples from before the // current offset - struct { - size_t delay{0u}; - } mTap[2]; + std::array<size_t,2> mDelayTap{}; size_t mOffset{0u}; /* The panning gains for the two taps */ - struct { - float Current[MaxAmbiChannels]{}; - float Target[MaxAmbiChannels]{}; - } mGains[2]; + struct OutGains { + std::array<float,MaxAmbiChannels> Current{}; + std::array<float,MaxAmbiChannels> Target{}; + }; + std::array<OutGains,2> mGains; BiquadFilter mFilter; float mFeedGain{0.0f}; - alignas(16) float mTempBuffer[2][BufferLineSize]; + alignas(16) std::array<FloatBufferLine,2> mTempBuffer; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; void update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props, @@ -92,8 +91,8 @@ void EchoState::deviceUpdate(const DeviceBase *Device, const BufferStorage*) std::fill(mSampleBuffer.begin(), mSampleBuffer.end(), 0.0f); for(auto &e : mGains) { - std::fill(std::begin(e.Current), std::end(e.Current), 0.0f); - std::fill(std::begin(e.Target), std::end(e.Target), 0.0f); + std::fill(e.Current.begin(), e.Current.end(), 0.0f); + std::fill(e.Target.begin(), e.Target.end(), 0.0f); } } @@ -103,8 +102,8 @@ void EchoState::update(const ContextBase *context, const EffectSlot *slot, const DeviceBase *device{context->mDevice}; const auto frequency = static_cast<float>(device->Frequency); - mTap[0].delay = maxu(float2uint(props->Echo.Delay*frequency + 0.5f), 1); - mTap[1].delay = float2uint(props->Echo.LRDelay*frequency + 0.5f) + mTap[0].delay; + mDelayTap[0] = maxu(float2uint(props->Echo.Delay*frequency + 0.5f), 1); + mDelayTap[1] = float2uint(props->Echo.LRDelay*frequency + 0.5f) + mDelayTap[0]; const float gainhf{maxf(1.0f - props->Echo.Damping, 0.0625f)}; /* Limit -24dB */ mFilter.setParamsFromSlope(BiquadType::HighShelf, LowpassFreqRef/frequency, gainhf, 1.0f); @@ -127,14 +126,13 @@ void EchoState::process(const size_t samplesToDo, const al::span<const FloatBuff const size_t mask{mSampleBuffer.size()-1}; float *RESTRICT delaybuf{mSampleBuffer.data()}; size_t offset{mOffset}; - size_t tap1{offset - mTap[0].delay}; - size_t tap2{offset - mTap[1].delay}; - float z1, z2; + size_t tap1{offset - mDelayTap[0]}; + size_t tap2{offset - mDelayTap[1]}; ASSUME(samplesToDo > 0); const BiquadFilter filter{mFilter}; - std::tie(z1, z2) = mFilter.getComponents(); + auto [z1, z2] = mFilter.getComponents(); for(size_t i{0u};i < samplesToDo;) { offset &= mask; @@ -161,8 +159,8 @@ void EchoState::process(const size_t samplesToDo, const al::span<const FloatBuff mOffset = offset; for(size_t c{0};c < 2;c++) - MixSamples({mTempBuffer[c], samplesToDo}, samplesOut, mGains[c].Current, mGains[c].Target, - samplesToDo, 0); + MixSamples({mTempBuffer[c].data(), samplesToDo}, samplesOut, mGains[c].Current.data(), + mGains[c].Target.data(), samplesToDo, 0); } diff --git a/alc/effects/equalizer.cpp b/alc/effects/equalizer.cpp index 50bec4ad..a4a1777a 100644 --- a/alc/effects/equalizer.cpp +++ b/alc/effects/equalizer.cpp @@ -86,16 +86,17 @@ namespace { struct EqualizerState final : public EffectState { - struct { + struct OutParams { uint mTargetChannel{InvalidChannelIndex}; /* Effect parameters */ - BiquadFilter mFilter[4]; + std::array<BiquadFilter,4> mFilter; /* Effect gains for each channel */ float mCurrentGain{}; float mTargetGain{}; - } mChans[MaxAmbiChannels]; + }; + std::array<OutParams,MaxAmbiChannels> mChans; alignas(16) FloatBufferLine mSampleBuffer{}; @@ -114,8 +115,7 @@ void EqualizerState::deviceUpdate(const DeviceBase*, const BufferStorage*) for(auto &e : mChans) { e.mTargetChannel = InvalidChannelIndex; - std::for_each(std::begin(e.mFilter), std::end(e.mFilter), - std::mem_fn(&BiquadFilter::clear)); + std::for_each(e.mFilter.begin(), e.mFilter.end(), std::mem_fn(&BiquadFilter::clear)); e.mCurrentGain = 0.0f; } } @@ -125,7 +125,6 @@ void EqualizerState::update(const ContextBase *context, const EffectSlot *slot, { const DeviceBase *device{context->mDevice}; auto frequency = static_cast<float>(device->Frequency); - float gain, f0norm; /* Calculate coefficients for the each type of filter. Note that the shelf * and peaking filters' gain is for the centerpoint of the transition band, @@ -133,8 +132,8 @@ void EqualizerState::update(const ContextBase *context, const EffectSlot *slot, * property gains need their dB halved (sqrt of linear gain) for the * shelf/peak to reach the provided gain. */ - gain = std::sqrt(props->Equalizer.LowGain); - f0norm = props->Equalizer.LowCutoff / frequency; + float gain{std::sqrt(props->Equalizer.LowGain)}; + float f0norm{props->Equalizer.LowCutoff / frequency}; mChans[0].mFilter[0].setParamsFromSlope(BiquadType::LowShelf, f0norm, gain, 0.75f); gain = std::sqrt(props->Equalizer.Mid1Gain); diff --git a/alc/effects/fshifter.cpp b/alc/effects/fshifter.cpp index d3989e84..d121885b 100644 --- a/alc/effects/fshifter.cpp +++ b/alc/effects/fshifter.cpp @@ -91,10 +91,11 @@ struct FshifterState final : public EffectState { alignas(16) FloatBufferLine mBufferOut{}; /* Effect gains for each output channel */ - struct { - float Current[MaxAmbiChannels]{}; - float Target[MaxAmbiChannels]{}; - } mGains[2]; + struct OutGains { + std::array<float,MaxAmbiChannels> Current{}; + std::array<float,MaxAmbiChannels> Target{}; + }; + std::array<OutGains,2> mGains; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; @@ -122,8 +123,8 @@ void FshifterState::deviceUpdate(const DeviceBase*, const BufferStorage*) for(auto &gain : mGains) { - std::fill(std::begin(gain.Current), std::end(gain.Current), 0.0f); - std::fill(std::begin(gain.Target), std::end(gain.Target), 0.0f); + gain.Current.fill(0.0f); + gain.Target.fill(0.0f); } } @@ -235,8 +236,8 @@ void FshifterState::process(const size_t samplesToDo, const al::span<const Float mPhase[c] = phase_idx; /* Now, mix the processed sound data to the output. */ - MixSamples({BufferOut, samplesToDo}, samplesOut, mGains[c].Current, mGains[c].Target, - maxz(samplesToDo, 512), 0); + MixSamples({BufferOut, samplesToDo}, samplesOut, mGains[c].Current.data(), + mGains[c].Target.data(), maxz(samplesToDo, 512), 0); } } diff --git a/alc/effects/modulator.cpp b/alc/effects/modulator.cpp index f99ba19c..3c612a6e 100644 --- a/alc/effects/modulator.cpp +++ b/alc/effects/modulator.cpp @@ -89,14 +89,15 @@ struct ModulatorState final : public EffectState { alignas(16) FloatBufferLine mModSamples{}; alignas(16) FloatBufferLine mBuffer{}; - struct { + struct OutParams { uint mTargetChannel{InvalidChannelIndex}; BiquadFilter mFilter; float mCurrentGain{}; float mTargetGain{}; - } mChans[MaxAmbiChannels]; + }; + std::array<OutParams,MaxAmbiChannels> mChans; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp index 871e866a..c7d662c7 100644 --- a/alc/effects/pshifter.cpp +++ b/alc/effects/pshifter.cpp @@ -103,8 +103,8 @@ struct PshifterState final : public EffectState { alignas(16) FloatBufferLine mBufferOut; /* Effect gains for each output channel */ - float mCurrentGains[MaxAmbiChannels]; - float mTargetGains[MaxAmbiChannels]; + std::array<float,MaxAmbiChannels> mCurrentGains; + std::array<float,MaxAmbiChannels> mTargetGains; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; @@ -132,8 +132,8 @@ void PshifterState::deviceUpdate(const DeviceBase*, const BufferStorage*) mAnalysisBuffer.fill(FrequencyBin{}); mSynthesisBuffer.fill(FrequencyBin{}); - std::fill(std::begin(mCurrentGains), std::end(mCurrentGains), 0.0f); - std::fill(std::begin(mTargetGains), std::end(mTargetGains), 0.0f); + mCurrentGains.fill(0.0f); + mTargetGains.fill(0.0f); if(!mFft) mFft = PFFFTSetup{StftSize, PFFFT_REAL}; @@ -305,8 +305,8 @@ void PshifterState::process(const size_t samplesToDo, } /* Now, mix the processed sound data to the output. */ - MixSamples({mBufferOut.data(), samplesToDo}, samplesOut, mCurrentGains, mTargetGains, - maxz(samplesToDo, 512), 0); + MixSamples({mBufferOut.data(), samplesToDo}, samplesOut, mCurrentGains.data(), + mTargetGains.data(), maxz(samplesToDo, 512), 0); } diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index 5157cf72..43451ec8 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -22,11 +22,11 @@ #include <algorithm> #include <array> +#include <cstdint> #include <cstdio> #include <functional> #include <iterator> #include <numeric> -#include <stdint.h> #include "alc/effects/base.h" #include "almalloc.h" @@ -65,7 +65,7 @@ struct CubicFilter { static constexpr size_t sTableSteps{1 << sTableBits}; static constexpr size_t sTableMask{sTableSteps - 1}; - float mFilter[sTableSteps*2 + 1]{}; + std::array<float,sTableSteps*2 + 1> mFilter{}; constexpr CubicFilter() { @@ -85,10 +85,14 @@ struct CubicFilter { } } - constexpr float getCoeff0(size_t i) const noexcept { return mFilter[sTableSteps+i]; } - constexpr float getCoeff1(size_t i) const noexcept { return mFilter[i]; } - constexpr float getCoeff2(size_t i) const noexcept { return mFilter[sTableSteps-i]; } - constexpr float getCoeff3(size_t i) const noexcept { return mFilter[sTableSteps*2-i]; } + [[nodiscard]] constexpr auto getCoeff0(size_t i) const noexcept -> float + { return mFilter[sTableSteps+i]; } + [[nodiscard]] constexpr auto getCoeff1(size_t i) const noexcept -> float + { return mFilter[i]; } + [[nodiscard]] constexpr auto getCoeff2(size_t i) const noexcept -> float + { return mFilter[sTableSteps-i]; } + [[nodiscard]] constexpr auto getCoeff3(size_t i) const noexcept -> float + { return mFilter[sTableSteps*2-i]; } }; constexpr CubicFilter gCubicTable; @@ -119,12 +123,12 @@ constexpr float MODULATION_DEPTH_COEFF{0.05f}; * tetrahedral array of discrete signals (boosted by a factor of sqrt(3), to * reduce the error introduced in the conversion). */ -alignas(16) constexpr float B2A[NUM_LINES][NUM_LINES]{ - { 0.5f, 0.5f, 0.5f, 0.5f }, - { 0.5f, -0.5f, -0.5f, 0.5f }, - { 0.5f, 0.5f, -0.5f, -0.5f }, - { 0.5f, -0.5f, 0.5f, -0.5f } -}; +alignas(16) constexpr std::array<std::array<float,NUM_LINES>,NUM_LINES> B2A{{ + {{ 0.5f, 0.5f, 0.5f, 0.5f }}, + {{ 0.5f, -0.5f, -0.5f, 0.5f }}, + {{ 0.5f, 0.5f, -0.5f, -0.5f }}, + {{ 0.5f, -0.5f, 0.5f, -0.5f }} +}}; /* Converts (W-normalized) A-Format to B-Format for early reflections (scaled * by 1/sqrt(3) to compensate for the boost in the B2A matrix). @@ -364,7 +368,7 @@ struct DelayLineI { struct VecAllpass { DelayLineI Delay; float Coeff{0.0f}; - size_t Offset[NUM_LINES]{}; + std::array<size_t,NUM_LINES> Offset{}; void process(const al::span<ReverbUpdateLine,NUM_LINES> samples, size_t offset, const float xCoeff, const float yCoeff, const size_t todo); @@ -397,12 +401,12 @@ struct EarlyReflections { * reflections. */ DelayLineI Delay; - size_t Offset[NUM_LINES]{}; - float Coeff[NUM_LINES]{}; + std::array<size_t,NUM_LINES> Offset{}; + std::array<float,NUM_LINES> Coeff{}; /* The gain for each output channel based on 3D panning. */ - float CurrentGains[NUM_LINES][MaxAmbiChannels]{}; - float TargetGains[NUM_LINES][MaxAmbiChannels]{}; + std::array<std::array<float,MaxAmbiChannels>,NUM_LINES> CurrentGains{}; + std::array<std::array<float,MaxAmbiChannels>,NUM_LINES> TargetGains{}; void updateLines(const float density_mult, const float diffusion, const float decayTime, const float frequency); @@ -418,7 +422,7 @@ struct Modulation { /* The depth of frequency change, in samples. */ float Depth; - float ModDelays[MAX_UPDATE_SAMPLES]; + std::array<float,MAX_UPDATE_SAMPLES> ModDelays; void updateModulator(float modTime, float modDepth, float frequency); @@ -428,7 +432,7 @@ struct Modulation { struct LateReverb { /* A recursive delay line is used fill in the reverb tail. */ DelayLineI Delay; - size_t Offset[NUM_LINES]{}; + std::array<size_t,NUM_LINES> Offset{}; /* Attenuation to compensate for the modal density and decay rate of the * late lines. @@ -436,7 +440,7 @@ struct LateReverb { float DensityGain{0.0f}; /* T60 decay filters are used to simulate absorption. */ - T60Filter T60[NUM_LINES]; + std::array<T60Filter,NUM_LINES> T60; Modulation Mod; @@ -444,8 +448,8 @@ struct LateReverb { VecAllpass VecAp; /* The gain for each output channel based on 3D panning. */ - float CurrentGains[NUM_LINES][MaxAmbiChannels]{}; - float TargetGains[NUM_LINES][MaxAmbiChannels]{}; + std::array<std::array<float,MaxAmbiChannels>,NUM_LINES> CurrentGains{}; + std::array<std::array<float,MaxAmbiChannels>,NUM_LINES> TargetGains{}; void updateLines(const float density_mult, const float diffusion, const float lfDecayTime, const float mfDecayTime, const float hfDecayTime, const float lf0norm, @@ -460,21 +464,22 @@ struct LateReverb { struct ReverbPipeline { /* Master effect filters */ - struct { + struct FilterPair { BiquadFilter Lp; BiquadFilter Hp; - } mFilter[NUM_LINES]; + }; + std::array<FilterPair,NUM_LINES> mFilter; /* Core delay line (early reflections and late reverb tap from this). */ DelayLineI mEarlyDelayIn; DelayLineI mLateDelayIn; /* Tap points for early reflection delay. */ - size_t mEarlyDelayTap[NUM_LINES][2]{}; - float mEarlyDelayCoeff[NUM_LINES]{}; + std::array<std::array<size_t,2>,NUM_LINES> mEarlyDelayTap{}; + std::array<float,NUM_LINES> mEarlyDelayCoeff{}; /* Tap points for late reverb feed and delay. */ - size_t mLateDelayTap[NUM_LINES][2]{}; + std::array<std::array<size_t,2>,NUM_LINES> mLateDelayTap{}; /* Coefficients for the all-pass and line scattering matrices. */ float mMixX{0.0f}; @@ -548,7 +553,7 @@ struct ReverbState final : public EffectState { PipelineState mPipelineState{DeviceClear}; uint8_t mCurrentPipeline{0}; - ReverbPipeline mPipelines[2]; + std::array<ReverbPipeline,2> mPipelines; /* The current write offset for all delay lines. */ size_t mOffset{}; @@ -577,14 +582,14 @@ struct ReverbState final : public EffectState { for(size_t c{0u};c < NUM_LINES;c++) { const al::span<float> tmpspan{mEarlySamples[c].data(), todo}; - MixSamples(tmpspan, samplesOut, pipeline.mEarly.CurrentGains[c], - pipeline.mEarly.TargetGains[c], todo, 0); + MixSamples(tmpspan, samplesOut, pipeline.mEarly.CurrentGains[c].data(), + pipeline.mEarly.TargetGains[c].data(), todo, 0); } for(size_t c{0u};c < NUM_LINES;c++) { const al::span<float> tmpspan{mLateSamples[c].data(), todo}; - MixSamples(tmpspan, samplesOut, pipeline.mLate.CurrentGains[c], - pipeline.mLate.TargetGains[c], todo, 0); + MixSamples(tmpspan, samplesOut, pipeline.mLate.CurrentGains[c].data(), + pipeline.mLate.TargetGains[c].data(), todo, 0); } } @@ -627,8 +632,8 @@ struct ReverbState final : public EffectState { const float hfscale{(c==0) ? mOrderScales[0] : mOrderScales[1]}; pipeline.mAmbiSplitter[0][c].processHfScale(tmpspan, hfscale); - MixSamples(tmpspan, samplesOut, pipeline.mEarly.CurrentGains[c], - pipeline.mEarly.TargetGains[c], todo, 0); + MixSamples(tmpspan, samplesOut, pipeline.mEarly.CurrentGains[c].data(), + pipeline.mEarly.TargetGains[c].data(), todo, 0); } for(size_t c{0u};c < NUM_LINES;c++) { @@ -637,8 +642,8 @@ struct ReverbState final : public EffectState { const float hfscale{(c==0) ? mOrderScales[0] : mOrderScales[1]}; pipeline.mAmbiSplitter[1][c].processHfScale(tmpspan, hfscale); - MixSamples(tmpspan, samplesOut, pipeline.mLate.CurrentGains[c], - pipeline.mLate.TargetGains[c], todo, 0); + MixSamples(tmpspan, samplesOut, pipeline.mLate.CurrentGains[c].data(), + pipeline.mLate.TargetGains[c].data(), todo, 0); } } @@ -756,17 +761,16 @@ void ReverbState::deviceUpdate(const DeviceBase *device, const BufferStorage*) for(auto &pipeline : mPipelines) { - /* Clear filters and gain coefficients since the delay lines were all just - * cleared (if not reallocated). - */ + /* Clear filters and gain coefficients since the delay lines were all + * just cleared (if not reallocated). + */ for(auto &filter : pipeline.mFilter) { filter.Lp.clear(); filter.Hp.clear(); } - std::fill(std::begin(pipeline.mEarlyDelayCoeff),std::end(pipeline.mEarlyDelayCoeff), 0.0f); - std::fill(std::begin(pipeline.mEarlyDelayCoeff),std::end(pipeline.mEarlyDelayCoeff), 0.0f); + pipeline.mEarlyDelayCoeff.fill(0.0f); pipeline.mLate.DensityGain = 0.0f; for(auto &t60 : pipeline.mLate.T60) @@ -781,13 +785,13 @@ void ReverbState::deviceUpdate(const DeviceBase *device, const BufferStorage*) pipeline.mLate.Mod.Depth = 0.0f; for(auto &gains : pipeline.mEarly.CurrentGains) - std::fill(std::begin(gains), std::end(gains), 0.0f); + gains.fill(0.0f); for(auto &gains : pipeline.mEarly.TargetGains) - std::fill(std::begin(gains), std::end(gains), 0.0f); + gains.fill(0.0f); for(auto &gains : pipeline.mLate.CurrentGains) - std::fill(std::begin(gains), std::end(gains), 0.0f); + gains.fill(0.0f); for(auto &gains : pipeline.mLate.TargetGains) - std::fill(std::begin(gains), std::end(gains), 0.0f); + gains.fill(0.0f); } mPipelineState = DeviceClear; @@ -1071,7 +1075,7 @@ std::array<std::array<float,4>,4> GetTransformFromVector(const al::span<const fl * rest of OpenAL which use right-handed. This is fixed by negating Z, * which cancels out with the B-Format Z negation. */ - float norm[3]; + std::array<float,3> norm; float mag{std::sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2])}; if(mag > 1.0f) { @@ -1408,7 +1412,7 @@ void VecAllpass::process(const al::span<ReverbUpdateLine,NUM_LINES> samples, siz ASSUME(todo > 0); - size_t vap_offset[NUM_LINES]; + std::array<size_t,NUM_LINES> vap_offset; for(size_t j{0u};j < NUM_LINES;j++) vap_offset[j] = offset - Offset[j]; for(size_t i{0u};i < todo;) diff --git a/alc/effects/vmorpher.cpp b/alc/effects/vmorpher.cpp index 872c7add..6cf862c2 100644 --- a/alc/effects/vmorpher.cpp +++ b/alc/effects/vmorpher.cpp @@ -57,29 +57,30 @@ namespace { using uint = unsigned int; -#define MAX_UPDATE_SAMPLES 256 -#define NUM_FORMANTS 4 -#define NUM_FILTERS 2 -#define Q_FACTOR 5.0f - -#define VOWEL_A_INDEX 0 -#define VOWEL_B_INDEX 1 +constexpr size_t MaxUpdateSamples{256}; +constexpr size_t NumFormants{4}; +constexpr float QFactor{5.0f}; +enum : size_t { + VowelAIndex, + VowelBIndex, + NumFilters +}; -#define WAVEFORM_FRACBITS 24 -#define WAVEFORM_FRACONE (1<<WAVEFORM_FRACBITS) -#define WAVEFORM_FRACMASK (WAVEFORM_FRACONE-1) +constexpr size_t WaveformFracBits{24}; +constexpr size_t WaveformFracOne{1<<WaveformFracBits}; +constexpr size_t WaveformFracMask{WaveformFracOne-1}; inline float Sin(uint index) { - constexpr float scale{al::numbers::pi_v<float>*2.0f / WAVEFORM_FRACONE}; + constexpr float scale{al::numbers::pi_v<float>*2.0f / float{WaveformFracOne}}; return std::sin(static_cast<float>(index) * scale)*0.5f + 0.5f; } inline float Saw(uint index) -{ return static_cast<float>(index) / float{WAVEFORM_FRACONE}; } +{ return static_cast<float>(index) / float{WaveformFracOne}; } inline float Triangle(uint index) -{ return std::fabs(static_cast<float>(index)*(2.0f/WAVEFORM_FRACONE) - 1.0f); } +{ return std::fabs(static_cast<float>(index)*(2.0f/WaveformFracOne) - 1.0f); } inline float Half(uint) { return 0.5f; } @@ -89,13 +90,12 @@ void Oscillate(float *RESTRICT dst, uint index, const uint step, size_t todo) for(size_t i{0u};i < todo;i++) { index += step; - index &= WAVEFORM_FRACMASK; + index &= WaveformFracMask; dst[i] = func(index); } } -struct FormantFilter -{ +struct FormantFilter { float mCoeff{0.0f}; float mGain{1.0f}; float mS1{0.0f}; @@ -106,20 +106,21 @@ struct FormantFilter : mCoeff{std::tan(al::numbers::pi_v<float> * f0norm)}, mGain{gain} { } - inline void process(const float *samplesIn, float *samplesOut, const size_t numInput) + void process(const float *samplesIn, float *samplesOut, const size_t numInput) noexcept { /* A state variable filter from a topology-preserving transform. * Based on a talk given by Ivan Cohen: https://www.youtube.com/watch?v=esjHXGPyrhg */ const float g{mCoeff}; const float gain{mGain}; - const float h{1.0f / (1.0f + (g/Q_FACTOR) + (g*g))}; + const float h{1.0f / (1.0f + (g/QFactor) + (g*g))}; + const float coeff{1.0f/QFactor + g}; float s1{mS1}; float s2{mS2}; for(size_t i{0u};i < numInput;i++) { - const float H{(samplesIn[i] - (1.0f/Q_FACTOR + g)*s1 - s2)*h}; + const float H{(samplesIn[i] - coeff*s1 - s2)*h}; const float B{g*H + s1}; const float L{g*B + s2}; @@ -133,7 +134,7 @@ struct FormantFilter mS2 = s2; } - inline void clear() + void clear() noexcept { mS1 = 0.0f; mS2 = 0.0f; @@ -142,16 +143,17 @@ struct FormantFilter struct VmorpherState final : public EffectState { - struct { + struct OutParams { uint mTargetChannel{InvalidChannelIndex}; /* Effect parameters */ - FormantFilter mFormants[NUM_FILTERS][NUM_FORMANTS]; + std::array<std::array<FormantFilter,NumFormants>,NumFilters> mFormants; /* Effect gains for each channel */ float mCurrentGain{}; float mTargetGain{}; - } mChans[MaxAmbiChannels]; + }; + std::array<OutParams,MaxAmbiChannels> mChans; void (*mGetSamples)(float*RESTRICT, uint, const uint, size_t){}; @@ -159,9 +161,9 @@ struct VmorpherState final : public EffectState { uint mStep{1}; /* Effects buffers */ - alignas(16) float mSampleBufferA[MAX_UPDATE_SAMPLES]{}; - alignas(16) float mSampleBufferB[MAX_UPDATE_SAMPLES]{}; - alignas(16) float mLfo[MAX_UPDATE_SAMPLES]{}; + alignas(16) std::array<float,MaxUpdateSamples> mSampleBufferA{}; + alignas(16) std::array<float,MaxUpdateSamples> mSampleBufferB{}; + alignas(16) std::array<float,MaxUpdateSamples> mLfo{}; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; void update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props, @@ -169,14 +171,14 @@ struct VmorpherState final : public EffectState { void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; - static std::array<FormantFilter,4> getFiltersByPhoneme(VMorpherPhenome phoneme, - float frequency, float pitch); + static std::array<FormantFilter,NumFormants> getFiltersByPhoneme(VMorpherPhenome phoneme, + float frequency, float pitch) noexcept; DEF_NEWDEL(VmorpherState) }; -std::array<FormantFilter,4> VmorpherState::getFiltersByPhoneme(VMorpherPhenome phoneme, - float frequency, float pitch) +std::array<FormantFilter,NumFormants> VmorpherState::getFiltersByPhoneme(VMorpherPhenome phoneme, + float frequency, float pitch) noexcept { /* Using soprano formant set of values to * better match mid-range frequency space. @@ -232,9 +234,9 @@ void VmorpherState::deviceUpdate(const DeviceBase*, const BufferStorage*) for(auto &e : mChans) { e.mTargetChannel = InvalidChannelIndex; - std::for_each(std::begin(e.mFormants[VOWEL_A_INDEX]), std::end(e.mFormants[VOWEL_A_INDEX]), + std::for_each(e.mFormants[VowelAIndex].begin(), e.mFormants[VowelAIndex].end(), std::mem_fn(&FormantFilter::clear)); - std::for_each(std::begin(e.mFormants[VOWEL_B_INDEX]), std::end(e.mFormants[VOWEL_B_INDEX]), + std::for_each(e.mFormants[VowelBIndex].begin(), e.mFormants[VowelBIndex].end(), std::mem_fn(&FormantFilter::clear)); e.mCurrentGain = 0.0f; } @@ -246,7 +248,7 @@ void VmorpherState::update(const ContextBase *context, const EffectSlot *slot, const DeviceBase *device{context->mDevice}; const float frequency{static_cast<float>(device->Frequency)}; const float step{props->Vmorpher.Rate / frequency}; - mStep = fastf2u(clampf(step*WAVEFORM_FRACONE, 0.0f, float{WAVEFORM_FRACONE-1})); + mStep = fastf2u(clampf(step*WaveformFracOne, 0.0f, float{WaveformFracOne}-1.0f)); if(mStep == 0) mGetSamples = Oscillate<Half>; @@ -268,8 +270,8 @@ void VmorpherState::update(const ContextBase *context, const EffectSlot *slot, /* Copy the filter coefficients to the input channels. */ for(size_t i{0u};i < slot->Wet.Buffer.size();++i) { - std::copy(vowelA.begin(), vowelA.end(), std::begin(mChans[i].mFormants[VOWEL_A_INDEX])); - std::copy(vowelB.begin(), vowelB.end(), std::begin(mChans[i].mFormants[VOWEL_B_INDEX])); + std::copy(vowelA.begin(), vowelA.end(), mChans[i].mFormants[VowelAIndex].begin()); + std::copy(vowelB.begin(), vowelB.end(), mChans[i].mFormants[VowelBIndex].begin()); } mOutTarget = target.Main->Buffer; @@ -288,11 +290,11 @@ void VmorpherState::process(const size_t samplesToDo, const al::span<const Float */ for(size_t base{0u};base < samplesToDo;) { - const size_t td{minz(MAX_UPDATE_SAMPLES, samplesToDo-base)}; + const size_t td{minz(MaxUpdateSamples, samplesToDo-base)}; - mGetSamples(mLfo, mIndex, mStep, td); + mGetSamples(mLfo.data(), mIndex, mStep, td); mIndex += static_cast<uint>(mStep * td); - mIndex &= WAVEFORM_FRACMASK; + mIndex &= WaveformFracMask; auto chandata = std::begin(mChans); for(const auto &input : samplesIn) @@ -304,30 +306,30 @@ void VmorpherState::process(const size_t samplesToDo, const al::span<const Float continue; } - auto& vowelA = chandata->mFormants[VOWEL_A_INDEX]; - auto& vowelB = chandata->mFormants[VOWEL_B_INDEX]; + const auto vowelA = al::span{chandata->mFormants[VowelAIndex]}; + const auto vowelB = al::span{chandata->mFormants[VowelBIndex]}; /* Process first vowel. */ std::fill_n(std::begin(mSampleBufferA), td, 0.0f); - vowelA[0].process(&input[base], mSampleBufferA, td); - vowelA[1].process(&input[base], mSampleBufferA, td); - vowelA[2].process(&input[base], mSampleBufferA, td); - vowelA[3].process(&input[base], mSampleBufferA, td); + vowelA[0].process(&input[base], mSampleBufferA.data(), td); + vowelA[1].process(&input[base], mSampleBufferA.data(), td); + vowelA[2].process(&input[base], mSampleBufferA.data(), td); + vowelA[3].process(&input[base], mSampleBufferA.data(), td); /* Process second vowel. */ std::fill_n(std::begin(mSampleBufferB), td, 0.0f); - vowelB[0].process(&input[base], mSampleBufferB, td); - vowelB[1].process(&input[base], mSampleBufferB, td); - vowelB[2].process(&input[base], mSampleBufferB, td); - vowelB[3].process(&input[base], mSampleBufferB, td); + vowelB[0].process(&input[base], mSampleBufferB.data(), td); + vowelB[1].process(&input[base], mSampleBufferB.data(), td); + vowelB[2].process(&input[base], mSampleBufferB.data(), td); + vowelB[3].process(&input[base], mSampleBufferB.data(), td); - alignas(16) float blended[MAX_UPDATE_SAMPLES]; + alignas(16) std::array<float,MaxUpdateSamples> blended; for(size_t i{0u};i < td;i++) blended[i] = lerpf(mSampleBufferA[i], mSampleBufferB[i], mLfo[i]); /* Now, mix the processed sound data to the output. */ - MixSamples({blended, td}, samplesOut[outidx].data()+base, chandata->mCurrentGain, - chandata->mTargetGain, samplesToDo-base); + MixSamples({blended.data(), td}, samplesOut[outidx].data()+base, + chandata->mCurrentGain, chandata->mTargetGain, samplesToDo-base); ++chandata; } |