diff options
-rw-r--r-- | alc/effects/fshifter.cpp | 39 | ||||
-rw-r--r-- | alc/effects/pshifter.cpp | 36 |
2 files changed, 42 insertions, 33 deletions
diff --git a/alc/effects/fshifter.cpp b/alc/effects/fshifter.cpp index 1f881f9d..4037f46b 100644 --- a/alc/effects/fshifter.cpp +++ b/alc/effects/fshifter.cpp @@ -63,6 +63,7 @@ alignas(16) const std::array<double,HIL_SIZE> HannWindow = InitHannWindow(); struct FshifterState final : public EffectState { /* Effect parameters */ size_t mCount{}; + size_t mPos{}; uint mPhaseStep[2]{}; uint mPhase[2]{}; double mSign[2]{}; @@ -95,7 +96,8 @@ struct FshifterState final : public EffectState { void FshifterState::deviceUpdate(const ALCdevice*, const Buffer&) { /* (Re-)initializing parameters and clear the buffers. */ - mCount = FIFO_LATENCY; + mCount = 0; + mPos = FIFO_LATENCY; std::fill(std::begin(mPhaseStep), std::end(mPhaseStep), 0u); std::fill(std::begin(mPhase), std::end(mPhase), 0u); @@ -160,38 +162,41 @@ void FshifterState::process(const size_t samplesToDo, const al::span<const Float { for(size_t base{0u};base < samplesToDo;) { - size_t todo{minz(HIL_SIZE-mCount, samplesToDo-base)}; + size_t todo{minz(HIL_STEP-mCount, samplesToDo-base)}; /* Fill FIFO buffer with samples data */ + const size_t pos{mPos}; size_t count{mCount}; do { - mInFIFO[count] = samplesIn[0][base]; - mOutdata[base] = mOutFIFO[count-FIFO_LATENCY]; + mInFIFO[pos+count] = samplesIn[0][base]; + mOutdata[base] = mOutFIFO[count]; ++base; ++count; } while(--todo); mCount = count; /* Check whether FIFO buffer is filled */ - if(mCount < HIL_SIZE) break; - mCount = FIFO_LATENCY; + if(mCount < HIL_STEP) break; + mCount = 0; + mPos = (mPos+HIL_STEP) & (HIL_SIZE-1); /* Real signal windowing and store in Analytic buffer */ - for(size_t k{0};k < HIL_SIZE;k++) - mAnalytic[k] = mInFIFO[k]*HannWindow[k]; + 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]; /* Processing signal by Discrete Hilbert Transform (analytical signal). */ complex_hilbert(mAnalytic); /* Windowing and add to output accumulator */ - for(size_t k{0};k < HIL_SIZE;k++) - mOutputAccum[k] += 2.0/OVERSAMP*HannWindow[k]*mAnalytic[k]; - - /* Shift accumulator, input & output FIFO */ - std::copy_n(mOutputAccum, HIL_STEP, mOutFIFO); - auto accum_iter = std::copy(std::begin(mOutputAccum)+HIL_STEP, std::end(mOutputAccum), - std::begin(mOutputAccum)); - std::fill(accum_iter, std::end(mOutputAccum), complex_d{}); - std::copy(std::begin(mInFIFO)+HIL_STEP, std::end(mInFIFO), std::begin(mInFIFO)); + 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]; + + /* 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{}); } /* Process frequency shifter using the analytic signal obtained. */ diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp index 257742ed..5087860f 100644 --- a/alc/effects/pshifter.cpp +++ b/alc/effects/pshifter.cpp @@ -71,6 +71,7 @@ struct FrequencyBin { struct PshifterState final : public EffectState { /* Effect parameters */ size_t mCount; + size_t mPos; uint mPitchShiftI; double mPitchShift; @@ -104,7 +105,8 @@ struct PshifterState final : public EffectState { void PshifterState::deviceUpdate(const ALCdevice*, const Buffer&) { /* (Re-)initializing parameters and clear the buffers. */ - mCount = FIFO_LATENCY; + mCount = 0; + mPos = FIFO_LATENCY; mPitchShiftI = MixerFracOne; mPitchShift = 1.0; @@ -147,12 +149,12 @@ void PshifterState::process(const size_t samplesToDo, const al::span<const Float for(size_t base{0u};base < samplesToDo;) { - const size_t todo{minz(STFT_SIZE-mCount, samplesToDo-base)}; + const size_t todo{minz(STFT_STEP-mCount, samplesToDo-base)}; /* Retrieve the output samples from the FIFO and fill in the new input * samples. */ - auto fifo_iter = mFIFO.begin() + mCount; + auto fifo_iter = mFIFO.begin()+mPos + mCount; std::transform(fifo_iter, fifo_iter+todo, mBufferOut.begin()+base, [](double d) noexcept -> float { return static_cast<float>(d); }); @@ -161,14 +163,17 @@ void PshifterState::process(const size_t samplesToDo, const al::span<const Float base += todo; /* Check whether FIFO buffer is filled with new samples. */ - if(mCount < STFT_SIZE) break; - mCount = FIFO_LATENCY; + if(mCount < STFT_STEP) break; + mCount = 0; + mPos = (mPos+STFT_STEP) & (mFIFO.size()-1); /* Time-domain signal windowing, store in FftBuffer, and apply a * forward FFT to get the frequency-domain signal. */ - for(size_t k{0u};k < STFT_SIZE;k++) - mFftBuffer[k] = mFIFO[k] * HannWindow[k]; + for(size_t src{mPos}, k{0u};src < STFT_SIZE;++src,++k) + mFftBuffer[k] = mFIFO[src] * HannWindow[k]; + for(size_t src{0u}, k{STFT_SIZE-mPos};src < mPos;++src,++k) + mFftBuffer[k] = mFIFO[src] * HannWindow[k]; forward_fft(mFftBuffer); /* Analyze the obtained data. Since the real FFT is symmetric, only @@ -229,15 +234,14 @@ void PshifterState::process(const size_t samplesToDo, const al::span<const Float * for the output with windowing. */ inverse_fft(mFftBuffer); - for(size_t k{0u};k < STFT_SIZE;k++) - mOutputAccum[k] += HannWindow[k]*mFftBuffer[k].real() * (4.0/OVERSAMP/STFT_SIZE); - - /* Shift FIFO and accumulator. */ - fifo_iter = std::copy(mFIFO.begin()+STFT_STEP, mFIFO.end(), mFIFO.begin()); - std::copy_n(mOutputAccum.begin(), STFT_STEP, fifo_iter); - auto accum_iter = std::copy(mOutputAccum.begin()+STFT_STEP, mOutputAccum.end(), - mOutputAccum.begin()); - std::fill(accum_iter, mOutputAccum.end(), 0.0); + for(size_t dst{mPos}, k{0u};dst < STFT_SIZE;++dst,++k) + mOutputAccum[dst] += HannWindow[k]*mFftBuffer[k].real() * (4.0/OVERSAMP/STFT_SIZE); + for(size_t dst{0u}, k{STFT_SIZE-mPos};dst < mPos;++dst,++k) + mOutputAccum[dst] += HannWindow[k]*mFftBuffer[k].real() * (4.0/OVERSAMP/STFT_SIZE); + + /* Copy out the accumulated result, then clear for the next iteration. */ + std::copy_n(mOutputAccum.begin() + mPos, STFT_STEP, mFIFO.begin() + mPos); + std::fill_n(mOutputAccum.begin() + mPos, STFT_STEP, 0.0); } /* Now, mix the processed sound data to the output. */ |