aboutsummaryrefslogtreecommitdiffstats
path: root/alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2023-12-11 15:08:12 -0800
committerChris Robinson <[email protected]>2023-12-11 15:08:12 -0800
commitec40e4fefef954544c25285bfeae4a44c1134a44 (patch)
tree72b55e01fd50bed966db533713f998cf06815172 /alc
parenta28bf538afabca45298a43e5d2acf3e6149a2c2c (diff)
Finish cleanup for effects
Diffstat (limited to 'alc')
-rw-r--r--alc/effects/autowah.cpp49
-rw-r--r--alc/effects/chorus.cpp33
-rw-r--r--alc/effects/compressor.cpp9
-rw-r--r--alc/effects/convolution.cpp115
-rw-r--r--alc/effects/dedicated.cpp4
-rw-r--r--alc/effects/distortion.cpp14
-rw-r--r--alc/effects/echo.cpp34
-rw-r--r--alc/effects/equalizer.cpp15
-rw-r--r--alc/effects/fshifter.cpp17
-rw-r--r--alc/effects/modulator.cpp5
-rw-r--r--alc/effects/pshifter.cpp12
-rw-r--r--alc/effects/reverb.cpp98
-rw-r--r--alc/effects/vmorpher.cpp104
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;
}