From e9c7a8602530d73dd34af11172af79b7d58a3b49 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 30 Dec 2023 03:50:49 -0800 Subject: Don't apply the T60 filter on the initial late reverb input --- alc/effects/reverb.cpp | 83 ++++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index ac599e41..047dca6c 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -1587,16 +1587,51 @@ void ReverbPipeline::processLate(size_t offset, const size_t samplesToDo, /* First, calculate the modulated delays for the late feedback. */ mLate.Mod.calcDelays(todo); - /* Next, load decorrelated samples from the main and feedback delay - * lines. Filter the signal to apply its frequency-dependent decay. + /* Now load samples from the feedback delay lines. Filter the signal to + * apply its frequency-dependent decay. */ + for(size_t j{0u};j < NUM_LINES;++j) + { + size_t late_feedb_tap{offset - mLate.Offset[j]}; + const float midGain{mLate.T60[j].MidGain}; + + for(size_t i{0u};i < todo;++i) + { + /* Calculate the read offset and offset between it and the next + * sample. + */ + const float fdelay{mLate.Mod.ModDelays[i]}; + const size_t idelay{float2uint(fdelay * float{gCubicTable.sTableSteps})}; + const size_t delay{late_feedb_tap - (idelay>>gCubicTable.sTableBits)}; + const size_t delayoffset{idelay & gCubicTable.sTableMask}; + ++late_feedb_tap; + + /* Get the samples around by the delayed offset. */ + const float out0{late_delay.Line[(delay ) & late_delay.Mask][j]}; + const float out1{late_delay.Line[(delay-1) & late_delay.Mask][j]}; + const float out2{late_delay.Line[(delay-2) & late_delay.Mask][j]}; + const float out3{late_delay.Line[(delay-3) & late_delay.Mask][j]}; + + /* The output is obtained by interpolating the four samples + * that were acquired above, and combined with the main delay + * tap. + */ + const float out{out0*gCubicTable.getCoeff0(delayoffset) + + out1*gCubicTable.getCoeff1(delayoffset) + + out2*gCubicTable.getCoeff2(delayoffset) + + out3*gCubicTable.getCoeff3(delayoffset)}; + tempSamples[j][i] = out * midGain; + } + + mLate.T60[j].process({tempSamples[j].data(), todo}); + } + + /* Next load decorrelated samples from the main delay lines. */ const float fadeStep{1.0f / static_cast(todo)}; - for(size_t j{0u};j < NUM_LINES;j++) + for(size_t j{0u};j < NUM_LINES;++j) { size_t late_delay_tap0{offset - mLateDelayTap[j][0]}; size_t late_delay_tap1{offset - mLateDelayTap[j][1]}; - size_t late_feedb_tap{offset - mLate.Offset[j]}; - const float midGain{mLate.T60[j].MidGain}; const float densityGain{mLate.DensityGain}; const float densityStep{late_delay_tap0 != late_delay_tap1 ? densityGain*fadeStep : 0.0f}; @@ -1608,48 +1643,22 @@ void ReverbPipeline::processLate(size_t offset, const size_t samplesToDo, late_delay_tap1 &= in_delay.Mask; size_t td{minz(todo-i, in_delay.Mask+1 - maxz(late_delay_tap0, late_delay_tap1))}; do { - /* Calculate the read offset and offset between it and the - * next sample. - */ - const float fdelay{mLate.Mod.ModDelays[i]}; - const size_t idelay{float2uint(fdelay * float{gCubicTable.sTableSteps})}; - const size_t delay{late_feedb_tap - (idelay>>gCubicTable.sTableBits)}; - const size_t delayoffset{idelay & gCubicTable.sTableMask}; - ++late_feedb_tap; - - /* Get the samples around by the delayed offset. */ - const float out0{late_delay.Line[(delay ) & late_delay.Mask][j]}; - const float out1{late_delay.Line[(delay-1) & late_delay.Mask][j]}; - const float out2{late_delay.Line[(delay-2) & late_delay.Mask][j]}; - const float out3{late_delay.Line[(delay-3) & late_delay.Mask][j]}; - - /* The output is obtained by interpolating the four samples - * that were acquired above, and combined with the main - * delay tap. - */ - const float out{out0*gCubicTable.getCoeff0(delayoffset) - + out1*gCubicTable.getCoeff1(delayoffset) - + out2*gCubicTable.getCoeff2(delayoffset) - + out3*gCubicTable.getCoeff3(delayoffset)}; const float fade0{densityGain - densityStep*fadeCount}; const float fade1{densityStep*fadeCount}; fadeCount += 1.0f; - tempSamples[j][i] = (out + - in_delay.Line[late_delay_tap0++][j]*fade0 + - in_delay.Line[late_delay_tap1++][j]*fade1) * midGain; + tempSamples[j][i] += in_delay.Line[late_delay_tap0++][j]*fade0 + + in_delay.Line[late_delay_tap1++][j]*fade1; ++i; } while(--td); } mLateDelayTap[j][0] = mLateDelayTap[j][1]; - - mLate.T60[j].process({tempSamples[j].data(), todo}); } /* Apply a vector all-pass to improve micro-surface diffusion, and * write out the results for mixing. */ mLate.VecAp.process(tempSamples, offset, mixX, mixY, todo); - for(size_t j{0u};j < NUM_LINES;j++) + for(size_t j{0u};j < NUM_LINES;++j) std::copy_n(tempSamples[j].begin(), todo, outSamples[j].begin()+base); /* Finally, scatter and bounce the results to refeed the feedback buffer. */ @@ -1674,7 +1683,7 @@ void ReverbState::process(const size_t samplesToDo, const al::span tmpspan{al::assume_aligned<16>(mTempLine.data()), samplesToDo}; - for(size_t c{0u};c < NUM_LINES;c++) + for(size_t c{0u};c < NUM_LINES;++c) { std::fill(tmpspan.begin(), tmpspan.end(), 0.0f); for(size_t i{0};i < numInput;++i) @@ -1715,7 +1724,7 @@ void ReverbState::process(const size_t samplesToDo, const al::span tmpspan{al::assume_aligned<16>(mTempLine.data()), samplesToDo}; const float fadeStep{1.0f / static_cast(samplesToDo)}; - for(size_t c{0u};c < NUM_LINES;c++) + for(size_t c{0u};c < NUM_LINES;++c) { std::fill(tmpspan.begin(), tmpspan.end(), 0.0f); for(size_t i{0};i < numInput;++i) @@ -1739,7 +1748,7 @@ void ReverbState::process(const size_t samplesToDo, const al::span