diff options
author | Chris Robinson <[email protected]> | 2018-08-08 22:47:07 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2018-08-08 22:47:07 -0700 |
commit | adfbe0d6cd8f1bebf48e2b2833ba0bedb644559a (patch) | |
tree | c2baf57dff3f5d86d7289407b28c29397da6cc1d | |
parent | 125ac166d19a17bc767f1193847e0d53f6a73279 (diff) |
Crossfade the early reflections delay coefficients
-rw-r--r-- | Alc/effects/reverb.c | 80 |
1 files changed, 50 insertions, 30 deletions
diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c index 93937799..c53e67d1 100644 --- a/Alc/effects/reverb.c +++ b/Alc/effects/reverb.c @@ -251,7 +251,7 @@ typedef struct EarlyReflections { */ DelayLineI Delay; ALsizei Offset[NUM_LINES][2]; - ALfloat Coeff[NUM_LINES]; + ALfloat Coeff[NUM_LINES][2]; /* The gain for each output channel based on 3D panning. */ ALfloat CurrentGain[NUM_LINES][MAX_OUTPUT_CHANNELS]; @@ -299,7 +299,7 @@ typedef struct ALreverbState { /* Tap points for early reflection delay. */ ALsizei EarlyDelayTap[NUM_LINES][2]; - ALfloat EarlyDelayCoeff[NUM_LINES]; + ALfloat EarlyDelayCoeff[NUM_LINES][2]; /* Tap points for late reverb feed and delay. */ ALsizei LateFeedTap; @@ -355,7 +355,8 @@ static void ALreverbState_Construct(ALreverbState *state) { state->EarlyDelayTap[i][0] = 0; state->EarlyDelayTap[i][1] = 0; - state->EarlyDelayCoeff[i] = 0.0f; + state->EarlyDelayCoeff[i][0] = 0.0f; + state->EarlyDelayCoeff[i][1] = 0.0f; } state->LateFeedTap = 0; @@ -380,7 +381,8 @@ static void ALreverbState_Construct(ALreverbState *state) state->Early.VecAp.Offset[i][1] = 0; state->Early.Offset[i][0] = 0; state->Early.Offset[i][1] = 0; - state->Early.Coeff[i] = 0.0f; + state->Early.Coeff[i][0] = 0.0f; + state->Early.Coeff[i][1] = 0.0f; } state->Late.DensityGain[0] = 0.0f; @@ -950,7 +952,7 @@ static ALvoid UpdateDelayLine(const ALfloat earlyDelay, const ALfloat lateDelay, State->EarlyDelayTap[i][1] = float2int(length * frequency); length = EARLY_TAP_LENGTHS[i]*multiplier; - State->EarlyDelayCoeff[i] = CalcDecayCoeff(length, decayTime); + State->EarlyDelayCoeff[i][1] = CalcDecayCoeff(length, decayTime); length = lateDelay + (LATE_LINE_LENGTHS[i] - LATE_LINE_LENGTHS[0])*0.25f*multiplier; State->LateDelayTap[i][1] = State->LateFeedTap + float2int(length * frequency); @@ -983,7 +985,7 @@ static ALvoid UpdateEarlyLines(const ALfloat density, const ALfloat diffusion, c Early->Offset[i][1] = float2int(length * frequency); /* Calculate the gain (coefficient) for each line. */ - Early->Coeff[i] = CalcDecayCoeff(length, decayTime); + Early->Coeff[i][1] = CalcDecayCoeff(length, decayTime); } } @@ -1220,16 +1222,24 @@ static ALvoid ALreverbState_update(ALreverbState *State, const ALCcontext *Conte props->Reverb.ReflectionsGain*gain, props->Reverb.LateReverbGain*gain, State); - /* Determine if delay-line cross-fading is required. */ - for(i = 0;i < NUM_LINES;i++) + /* Determine if delay-line cross-fading is required. TODO: Add some fuzz + * for the float comparisons? The math should be stable enough that the + * result should be the same if nothing's changed, and changes in the float + * values should (though may not always) be matched by changes in delay + * offsets. + */ + if(State->Late.DensityGain[1] != State->Late.DensityGain[0]) + State->FadeCount = 0; + else for(i = 0;i < NUM_LINES;i++) { if(State->EarlyDelayTap[i][1] != State->EarlyDelayTap[i][0] || + State->EarlyDelayCoeff[i][1] != State->EarlyDelayCoeff[i][0] || State->Early.VecAp.Offset[i][1] != State->Early.VecAp.Offset[i][0] || State->Early.Offset[i][1] != State->Early.Offset[i][0] || + State->Early.Coeff[i][1] != State->Early.Coeff[i][0] || State->LateDelayTap[i][1] != State->LateDelayTap[i][0] || State->Late.VecAp.Offset[i][1] != State->Late.VecAp.Offset[i][0] || - State->Late.Offset[i][1] != State->Late.Offset[i][0] || - State->Late.DensityGain[1] != State->Late.DensityGain[0]) + State->Late.Offset[i][1] != State->Late.Offset[i][0]) { State->FadeCount = 0; break; @@ -1456,7 +1466,7 @@ static void EarlyReflection_Unfaded(ALreverbState *State, const ALsizei todo, for(j = 0;j < NUM_LINES;j++) { ALsizei early_delay_tap = offset - State->EarlyDelayTap[j][0]; - ALfloat coeff = State->EarlyDelayCoeff[j]; + ALfloat coeff = State->EarlyDelayCoeff[j][0]; for(i = 0;i < todo;i++) temps[j][i] = DelayLineOut(&main_delay, early_delay_tap++, j) * coeff; } @@ -1469,7 +1479,7 @@ static void EarlyReflection_Unfaded(ALreverbState *State, const ALsizei todo, for(j = 0;j < NUM_LINES;j++) { early_feedb_tap[j] = offset - State->Early.Offset[j][0]; - early_feedb_coeff[j] = State->Early.Coeff[j]; + early_feedb_coeff[j] = State->Early.Coeff[j][0]; } late_feed_tap = offset - State->LateFeedTap; for(i = 0;i < todo;i++) @@ -1503,8 +1513,10 @@ static void EarlyReflection_Faded(ALreverbState *State, const ALsizei todo, ALfl ALfloat (*restrict temps)[MAX_UPDATE_SAMPLES] = State->TempSamples; const DelayLineI early_delay = State->Early.Delay; const DelayLineI main_delay = State->Delay; - ALsizei early_feedb_tap[NUM_LINES][2]; - ALfloat early_feedb_coeff[NUM_LINES]; + ALsizei feedb_tap[NUM_LINES][2]; + ALfloat feedb_oldCoeff[NUM_LINES]; + ALfloat feedb_oldCoeffStep[NUM_LINES]; + ALfloat feedb_newCoeffStep[NUM_LINES]; const ALfloat mixX = State->MixX; const ALfloat mixY = State->MixY; ALsizei offset = State->Offset; @@ -1517,14 +1529,16 @@ static void EarlyReflection_Faded(ALreverbState *State, const ALsizei todo, ALfl { ALsizei early_delay_tap0 = offset - State->EarlyDelayTap[j][0]; ALsizei early_delay_tap1 = offset - State->EarlyDelayTap[j][1]; - ALfloat coeff = State->EarlyDelayCoeff[j]; - ALfloat fader = fade; + ALfloat oldCoeff = State->EarlyDelayCoeff[j][0]; + ALfloat oldCoeffStep = -oldCoeff / todo; + ALfloat newCoeffStep = State->EarlyDelayCoeff[j][1] / todo; for(i = 0;i < todo;i++) { + const ALfloat fade0 = oldCoeff + oldCoeffStep*i; + const ALfloat fade1 = newCoeffStep*i; temps[j][i] = FadedDelayLineOut(&main_delay, - early_delay_tap0++, early_delay_tap1++, j, 1.0f-fader, fader - ) * coeff; - fader += FadeStep; + early_delay_tap0++, early_delay_tap1++, j, fade0, fade1 + ); } } @@ -1532,9 +1546,11 @@ static void EarlyReflection_Faded(ALreverbState *State, const ALsizei todo, ALfl for(j = 0;j < NUM_LINES;j++) { - early_feedb_tap[j][0] = offset - State->Early.Offset[j][0]; - early_feedb_tap[j][1] = offset - State->Early.Offset[j][1]; - early_feedb_coeff[j] = State->Early.Coeff[j]; + feedb_tap[j][0] = offset - State->Early.Offset[j][0]; + feedb_tap[j][1] = offset - State->Early.Offset[j][1]; + feedb_oldCoeff[j] = State->Early.Coeff[j][0]; + feedb_oldCoeffStep[j] = -feedb_oldCoeff[j] / todo; + feedb_newCoeffStep[j] = State->Early.Coeff[j][1] / todo; } late_feed_tap = offset - State->LateFeedTap; for(i = 0;i < todo;i++) @@ -1547,9 +1563,11 @@ static void EarlyReflection_Faded(ALreverbState *State, const ALsizei todo, ALfl DelayLineIn4Rev(&early_delay, offset, f); for(j = 0;j < NUM_LINES;j++) { + const ALfloat fade0 = feedb_oldCoeff[j] + feedb_oldCoeffStep[j]*i; + const ALfloat fade1 = feedb_newCoeffStep[j]*i; f[j] += FadedDelayLineOut(&early_delay, - early_feedb_tap[j][0]++, early_feedb_tap[j][1]++, j, 1.0f-fade, fade - ) * early_feedb_coeff[j]; + feedb_tap[j][0]++, feedb_tap[j][1]++, j, fade0, fade1 + ); out[j][i] = f[j]; } fade += FadeStep; @@ -1610,7 +1628,7 @@ static void LateReverb_Unfaded(ALreverbState *State, const ALsizei todo, ALfloat (*restrict temps)[MAX_UPDATE_SAMPLES] = State->TempSamples; const DelayLineI late_delay = State->Late.Delay; const DelayLineI main_delay = State->Delay; - const ALfloat densityGain = State->Late.DensityGain[1]; + const ALfloat densityGain = State->Late.DensityGain[0]; const ALfloat mixX = State->MixX; const ALfloat mixY = State->MixY; ALsizei offset = State->Offset; @@ -1689,10 +1707,6 @@ static void LateReverb_Faded(ALreverbState *State, const ALsizei todo, ALfloat f } LateT60Filter(temps[j], todo, &State->Late.T60[j]); } - /* Update the old density gain with its now-current level (in case another - * update needs to finish the fade). - */ - State->Late.DensityGain[0] = densityStep*todo; VectorAllpass_Faded(temps, offset, mixX, mixY, fade, todo, &State->Late.VecAp); @@ -1765,6 +1779,13 @@ static ALvoid ALreverbState_process(ALreverbState *State, ALsizei SamplesToDo, c SamplesToDo-base, base, todo ); + for(c = 0;c < NUM_LINES;c++) + { + State->EarlyDelayCoeff[c][0] = State->EarlyDelayCoeff[c][1]; + State->Early.Coeff[c][0] = State->Early.Coeff[c][1]; + } + State->Late.DensityGain[0] = State->Late.DensityGain[1]; + /* Step fading forward. */ fade += todo*FadeStep; fadeCount += todo; @@ -1782,7 +1803,6 @@ static ALvoid ALreverbState_process(ALreverbState *State, ALsizei SamplesToDo, c State->Late.VecAp.Offset[c][0] = State->Late.VecAp.Offset[c][1]; State->Late.Offset[c][0] = State->Late.Offset[c][1]; } - State->Late.DensityGain[0] = State->Late.DensityGain[1]; } } else |