diff options
author | Chris Robinson <[email protected]> | 2023-01-19 13:30:00 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2023-01-19 13:30:00 -0800 |
commit | d6e79c9023ad66986fcfe16caef15d8e8b14a20f (patch) | |
tree | fc5484966fdd317e238f673c032cfd7275e3c542 /alc/effects/fshifter.cpp | |
parent | 5069f042fa8478648214a7038d87ae976a041751 (diff) |
Minor code refactor for the frequency shifter effect
Diffstat (limited to 'alc/effects/fshifter.cpp')
-rw-r--r-- | alc/effects/fshifter.cpp | 97 |
1 files changed, 50 insertions, 47 deletions
diff --git a/alc/effects/fshifter.cpp b/alc/effects/fshifter.cpp index 5d899aed..4bdb53a7 100644 --- a/alc/effects/fshifter.cpp +++ b/alc/effects/fshifter.cpp @@ -48,44 +48,47 @@ namespace { using uint = unsigned int; using complex_d = std::complex<double>; -#define HIL_SIZE 1024 -#define OVERSAMP (1<<2) +constexpr size_t HilSize{1024}; +constexpr size_t HilHalfSize{HilSize >> 1}; +constexpr size_t OversampleFactor{4}; -#define HIL_STEP (HIL_SIZE / OVERSAMP) -#define FIFO_LATENCY (HIL_STEP * (OVERSAMP-1)) +static_assert(HilSize%OversampleFactor == 0, "Factor must be a clean divisor of the size"); +constexpr size_t HilStep{HilSize / OversampleFactor}; /* Define a Hann window, used to filter the HIL input and output. */ -std::array<double,HIL_SIZE> InitHannWindow() -{ - std::array<double,HIL_SIZE> ret; - /* Create lookup table of the Hann window for the desired size, i.e. HIL_SIZE */ - for(size_t i{0};i < HIL_SIZE>>1;i++) +struct Windower { + alignas(16) std::array<double,HilSize> mData; + + Windower() { - constexpr double scale{al::numbers::pi / double{HIL_SIZE}}; - const double val{std::sin((static_cast<double>(i)+0.5) * scale)}; - ret[i] = ret[HIL_SIZE-1-i] = val * val; + /* Create lookup table of the Hann window for the desired size. */ + for(size_t i{0};i < HilHalfSize;i++) + { + constexpr double scale{al::numbers::pi / double{HilSize}}; + const double val{std::sin((static_cast<double>(i)+0.5) * scale)}; + mData[i] = mData[HilSize-1-i] = val * val; + } } - return ret; -} -alignas(16) const std::array<double,HIL_SIZE> HannWindow = InitHannWindow(); +}; +const Windower gWindow{}; struct FshifterState final : public EffectState { /* Effect parameters */ size_t mCount{}; size_t mPos{}; - uint mPhaseStep[2]{}; - uint mPhase[2]{}; - double mSign[2]{}; + std::array<uint,2> mPhaseStep{}; + std::array<uint,2> mPhase{}; + std::array<double,2> mSign{}; /* Effects buffers */ - double mInFIFO[HIL_SIZE]{}; - complex_d mOutFIFO[HIL_STEP]{}; - complex_d mOutputAccum[HIL_SIZE]{}; - complex_d mAnalytic[HIL_SIZE]{}; - complex_d mOutdata[BufferLineSize]{}; + std::array<double,HilSize> mInFIFO{}; + std::array<complex_d,HilStep> mOutFIFO{}; + std::array<complex_d,HilSize> mOutputAccum{}; + std::array<complex_d,HilSize> mAnalytic{}; + std::array<complex_d,BufferLineSize> mOutdata{}; - alignas(16) float mBufferOut[BufferLineSize]{}; + alignas(16) FloatBufferLine mBufferOut{}; /* Effect gains for each output channel */ struct { @@ -107,15 +110,15 @@ void FshifterState::deviceUpdate(const DeviceBase*, const Buffer&) { /* (Re-)initializing parameters and clear the buffers. */ mCount = 0; - mPos = FIFO_LATENCY; + mPos = HilSize - HilStep; - std::fill(std::begin(mPhaseStep), std::end(mPhaseStep), 0u); - std::fill(std::begin(mPhase), std::end(mPhase), 0u); - std::fill(std::begin(mSign), std::end(mSign), 1.0); - std::fill(std::begin(mInFIFO), std::end(mInFIFO), 0.0); - std::fill(std::begin(mOutFIFO), std::end(mOutFIFO), complex_d{}); - std::fill(std::begin(mOutputAccum), std::end(mOutputAccum), complex_d{}); - std::fill(std::begin(mAnalytic), std::end(mAnalytic), complex_d{}); + mPhaseStep.fill(0u); + mPhase.fill(0u); + mSign.fill(1.0); + mInFIFO.fill(0.0); + mOutFIFO.fill(complex_d{}); + mOutputAccum.fill(complex_d{}); + mAnalytic.fill(complex_d{}); for(auto &gain : mGains) { @@ -172,7 +175,7 @@ void FshifterState::process(const size_t samplesToDo, const al::span<const Float { for(size_t base{0u};base < samplesToDo;) { - size_t todo{minz(HIL_STEP-mCount, samplesToDo-base)}; + size_t todo{minz(HilStep-mCount, samplesToDo-base)}; /* Fill FIFO buffer with samples data */ const size_t pos{mPos}; @@ -185,33 +188,33 @@ void FshifterState::process(const size_t samplesToDo, const al::span<const Float mCount = count; /* Check whether FIFO buffer is filled */ - if(mCount < HIL_STEP) break; + if(mCount < HilStep) break; mCount = 0; - mPos = (mPos+HIL_STEP) & (HIL_SIZE-1); + mPos = (mPos+HilStep) & (HilSize-1); /* Real signal windowing and store in Analytic buffer */ - for(size_t src{mPos}, k{0u};src < HIL_SIZE;++src,++k) - mAnalytic[k] = mInFIFO[src]*HannWindow[k]; - for(size_t src{0u}, k{HIL_SIZE-mPos};src < mPos;++src,++k) - mAnalytic[k] = mInFIFO[src]*HannWindow[k]; + for(size_t src{mPos}, k{0u};src < HilSize;++src,++k) + mAnalytic[k] = mInFIFO[src]*gWindow.mData[k]; + for(size_t src{0u}, k{HilSize-mPos};src < mPos;++src,++k) + mAnalytic[k] = mInFIFO[src]*gWindow.mData[k]; /* Processing signal by Discrete Hilbert Transform (analytical signal). */ complex_hilbert(mAnalytic); /* Windowing and add to output accumulator */ - for(size_t dst{mPos}, k{0u};dst < HIL_SIZE;++dst,++k) - mOutputAccum[dst] += 2.0/OVERSAMP*HannWindow[k]*mAnalytic[k]; - for(size_t dst{0u}, k{HIL_SIZE-mPos};dst < mPos;++dst,++k) - mOutputAccum[dst] += 2.0/OVERSAMP*HannWindow[k]*mAnalytic[k]; + for(size_t dst{mPos}, k{0u};dst < HilSize;++dst,++k) + mOutputAccum[dst] += 2.0/OversampleFactor*gWindow.mData[k]*mAnalytic[k]; + for(size_t dst{0u}, k{HilSize-mPos};dst < mPos;++dst,++k) + mOutputAccum[dst] += 2.0/OversampleFactor*gWindow.mData[k]*mAnalytic[k]; /* Copy out the accumulated result, then clear for the next iteration. */ - std::copy_n(mOutputAccum + mPos, HIL_STEP, mOutFIFO); - std::fill_n(mOutputAccum + mPos, HIL_STEP, complex_d{}); + std::copy_n(mOutputAccum.cbegin() + mPos, HilStep, mOutFIFO.begin()); + std::fill_n(mOutputAccum.begin() + mPos, HilStep, complex_d{}); } /* Process frequency shifter using the analytic signal obtained. */ - float *RESTRICT BufferOut{mBufferOut}; - for(int c{0};c < 2;++c) + float *RESTRICT BufferOut{al::assume_aligned<16>(mBufferOut.data())}; + for(size_t c{0};c < 2;++c) { const uint phase_step{mPhaseStep[c]}; uint phase_idx{mPhase[c]}; |