diff options
author | Chris Robinson <[email protected]> | 2020-09-08 22:56:30 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2020-09-08 23:20:06 -0700 |
commit | f4a55cc8c2e8093e1156686292a38ae10a738a08 (patch) | |
tree | 443e84925803dac41ec667491a8615a8d4ae6ec1 /alc | |
parent | 29566b995cfd80f00f8c4c7e2c3d4c798bcffdfe (diff) |
Don't leave the negative frequencies as 0 for inverse FFT
Diffstat (limited to 'alc')
-rw-r--r-- | alc/effects/convolution.cpp | 9 | ||||
-rw-r--r-- | alc/effects/pshifter.cpp | 6 | ||||
-rw-r--r-- | alc/uhjfilter.cpp | 13 |
3 files changed, 18 insertions, 10 deletions
diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index 102bed59..bbf8cb3f 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -266,8 +266,7 @@ void ConvolutionState::update(const ALCcontext *context, const ALeffectslot *slo /* The iFFT'd response is scaled up by the number of bins, so apply the * inverse to the output mixing gain. */ - constexpr size_t m{ConvolveUpdateSize/2 + 1}; - const float gain{slot->Params.Gain * (1.0f/m)}; + const float gain{slot->Params.Gain * (1.0f/float{ConvolveUpdateSize})}; auto &chans = *mChans; if(mChannels == FmtBFormat3D || mChannels == FmtBFormat2D) { @@ -386,6 +385,12 @@ void ConvolutionState::process(const size_t samplesToDo, mFftBuffer[i] += *input * *filter; } + /* Reconstruct the mirrored/negative frequencies to do a proper + * inverse FFT. + */ + for(size_t i{m};i < ConvolveUpdateSize;++i) + mFftBuffer[i] = std::conj(mFftBuffer[ConvolveUpdateSize-i]); + /* Apply iFFT to get the 1024 (really 1023) samples for output. The * 512 output samples are combined with the last output's 511 * second-half samples (and this output's second half is diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp index 18be0e38..01d24333 100644 --- a/alc/effects/pshifter.cpp +++ b/alc/effects/pshifter.cpp @@ -226,15 +226,15 @@ void PshifterState::process(const size_t samplesToDo, const al::span<const Float mFftBuffer[k] = std::polar(mSynthesisBuffer[k].Amplitude, mSumPhase[k]); } - /* Clear negative frequencies to recontruct the time-domain signal. */ - std::fill(mFftBuffer.begin()+STFT_HALF_SIZE+1, mFftBuffer.end(), complex_d{}); + for(size_t k{STFT_HALF_SIZE+1};k < STFT_SIZE;++k) + mFftBuffer[k] = std::conj(mFftBuffer[STFT_SIZE-k]); /* Apply an inverse FFT to get the time-domain siganl, and accumulate * for the output with windowing. */ complex_fft(mFftBuffer, 1.0); for(size_t k{0u};k < STFT_SIZE;k++) - mOutputAccum[k] += HannWindow[k]*mFftBuffer[k].real() * (2.0/STFT_HALF_SIZE/OVERSAMP); + mOutputAccum[k] += HannWindow[k]*mFftBuffer[k].real() * (2.0/STFT_SIZE/OVERSAMP); /* Shift FIFO and accumulator. */ fifo_iter = std::copy(mFIFO.begin()+STFT_STEP, mFIFO.end(), mFIFO.begin()); diff --git a/alc/uhjfilter.cpp b/alc/uhjfilter.cpp index 00d7dad3..9c0692c4 100644 --- a/alc/uhjfilter.cpp +++ b/alc/uhjfilter.cpp @@ -44,18 +44,21 @@ std::array<float,Uhj2Encoder::sFilterSize> GenerateFilter() */ constexpr complex_d c0{0.0, 1.0}; constexpr complex_d c1{0.0, -1.0}; - constexpr size_t half_size{32768}; + constexpr size_t fft_size{65536}; + constexpr size_t half_size{fft_size / 2}; - /* Generate a frequency domain impulse with a +90 degree phase offset. Keep - * the mirrored frequencies clear for converting to the time domain. + /* Generate a frequency domain impulse with a +90 degree phase offset. + * Reconstruct the mirrored frequencies to convert to the time domain. */ - auto fftBuffer = std::vector<complex_d>(half_size*2, complex_d{}); + auto fftBuffer = std::vector<complex_d>(fft_size, complex_d{}); for(size_t i{0};i < half_size;i += 2) { fftBuffer[i ] = c0; fftBuffer[i+1] = c1; } fftBuffer[half_size] = c0; + for(size_t i{half_size+1};i < fft_size;++i) + fftBuffer[i] = std::conj(fftBuffer[fft_size - i]); complex_fft(fftBuffer, 1.0); /* Reverse and truncate the filter to a usable size, and store only the @@ -65,7 +68,7 @@ std::array<float,Uhj2Encoder::sFilterSize> GenerateFilter() auto fftiter = fftBuffer.data() + half_size + (Uhj2Encoder::sFilterSize-1); for(float &coeff : ret) { - coeff = static_cast<float>(fftiter->real() / (half_size+1)); + coeff = static_cast<float>(fftiter->real() / double{fft_size}); fftiter -= 2; } return ret; |