diff options
Diffstat (limited to 'Alc/effects/reverb.c')
-rw-r--r-- | Alc/effects/reverb.c | 171 |
1 files changed, 50 insertions, 121 deletions
diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c index 000ba59a..60ff79b2 100644 --- a/Alc/effects/reverb.c +++ b/Alc/effects/reverb.c @@ -303,6 +303,30 @@ static ALvoid ALreverbState_Destruct(ALreverbState *State) ALeffectState_Destruct(STATIC_CAST(ALeffectState,State)); } +/* The B-Format to A-Format conversion matrix. The arrangement of rows is + * deliberately chosen to align the resulting lines to their spatial opposites + * (0:above front left <-> 3:above back right, 1:below front right <-> 2:below + * back left). It's not quite opposite, since the A-Format results in a + * tetrahedron, but it's close enough. Should the model be extended to 8-lines + * in the future, true opposites can be used. + */ +static const aluMatrixf B2A = {{ + { 0.288675134595f, 0.288675134595f, 0.288675134595f, 0.288675134595f }, + { 0.288675134595f, -0.288675134595f, -0.288675134595f, 0.288675134595f }, + { 0.288675134595f, 0.288675134595f, -0.288675134595f, -0.288675134595f }, + { 0.288675134595f, -0.288675134595f, 0.288675134595f, -0.288675134595f } +}}; + +/* Converts A-Format to B-Format (transposed). */ +static const aluMatrixf A2B = {{ + { 0.8660254038f, 0.8660254038f, 0.8660254038f, 0.8660254038f }, + { 0.8660254038f, -0.8660254038f, -0.8660254038f, 0.8660254038f }, + { 0.8660254038f, 0.8660254038f, -0.8660254038f, -0.8660254038f }, + { 0.8660254038f, -0.8660254038f, 0.8660254038f, -0.8660254038f } +}}; + +static const ALfloat FadeStep = 1.0f / FADE_SAMPLES; + /* This is a user config option for modifying the overall output of the reverb * effect. */ @@ -1275,14 +1299,6 @@ static aluMatrixf GetTransformFromVector(const ALfloat *vec) /* Update the early and late 3D panning gains. */ static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, const ALfloat gain, const ALfloat earlyGain, const ALfloat lateGain, ALreverbState *State) { - /* Converts A-Format to B-Format (transposed). */ - static const aluMatrixf A2B = {{ - { 0.8660254038f, 0.8660254038f, 0.8660254038f, 0.8660254038f }, - { 0.8660254038f, -0.8660254038f, -0.8660254038f, 0.8660254038f }, - { 0.8660254038f, 0.8660254038f, -0.8660254038f, -0.8660254038f }, - { 0.8660254038f, -0.8660254038f, 0.8660254038f, -0.8660254038f } - }}; - aluMatrixf transform, rot; ALsizei i; @@ -1633,7 +1649,7 @@ static inline void VectorReverse(ALfloat vec[4]) */ #define DECL_TEMPLATE(T) \ static ALvoid EarlyReflection_##T(ALreverbState *State, const ALsizei todo, \ - ALfloat fade, const ALfloat step, \ + ALfloat fade, \ ALfloat (*restrict out)[MAX_UPDATE_SAMPLES])\ { \ ALsizei offset = State->Offset; \ @@ -1675,7 +1691,7 @@ static ALvoid EarlyReflection_##T(ALreverbState *State, const ALsizei todo, \ f[j]); \ \ offset++; \ - fade = minf(1.0f, fade + step);/*fade += step;*/ \ + fade = minf(1.0f, fade + FadeStep); \ } \ } DECL_TEMPLATE(Unfaded) @@ -1720,7 +1736,7 @@ static inline ALfloat LateT60Filter(const ALsizei index, const ALfloat in, ALrev */ #define DECL_TEMPLATE(T) \ static ALvoid LateReverb_##T(ALreverbState *State, const ALsizei todo, \ - ALfloat fade, const ALfloat step, \ + ALfloat fade, \ ALfloat (*restrict out)[MAX_UPDATE_SAMPLES]) \ { \ const ALfloat apFeedCoeff = State->ApFeedCoeff; \ @@ -1761,18 +1777,22 @@ static ALvoid LateReverb_##T(ALreverbState *State, const ALsizei todo, \ DelayLineIn(&State->Late.Delay[j], offset, f[j]); \ \ offset++; \ - fade = minf(1.0f, fade + step);/*fade += step;*/ \ + fade = minf(1.0f, fade + FadeStep); \ } \ } DECL_TEMPLATE(Unfaded) DECL_TEMPLATE(Faded) #undef DECL_TEMPLATE +typedef ALfloat (*ProcMethodType)(ALreverbState *State, const ALsizei todo, ALfloat fade, + const ALfloat (*restrict input)[MAX_UPDATE_SAMPLES], + ALfloat (*restrict early)[MAX_UPDATE_SAMPLES], ALfloat (*restrict late)[MAX_UPDATE_SAMPLES]); + /* Perform the non-EAX reverb pass on a given input sample, resulting in * four-channel output. */ static ALfloat VerbPass(ALreverbState *State, const ALsizei todo, ALfloat fade, - const ALfloat step, ALfloat (*restrict input)[MAX_UPDATE_SAMPLES], + const ALfloat (*restrict input)[MAX_UPDATE_SAMPLES], ALfloat (*restrict early)[MAX_UPDATE_SAMPLES], ALfloat (*restrict late)[MAX_UPDATE_SAMPLES]) { @@ -1793,19 +1813,19 @@ static ALfloat VerbPass(ALreverbState *State, const ALsizei todo, ALfloat fade, if(fade < 1.0f) { /* Generate early reflections. */ - EarlyReflection_Faded(State, todo, fade, step, early); + EarlyReflection_Faded(State, todo, fade, early); /* Generate late reverb. */ - LateReverb_Faded(State, todo, fade, step, late); - fade = minf(1.0f, fade + todo*step); + LateReverb_Faded(State, todo, fade, late); + fade = minf(1.0f, fade + todo*FadeStep); } else { /* Generate early reflections. */ - EarlyReflection_Unfaded(State, todo, fade, step, early); + EarlyReflection_Unfaded(State, todo, fade, early); /* Generate late reverb. */ - LateReverb_Unfaded(State, todo, fade, step, late); + LateReverb_Unfaded(State, todo, fade, late); } /* Step all delays forward one sample. */ @@ -1817,7 +1837,10 @@ static ALfloat VerbPass(ALreverbState *State, const ALsizei todo, ALfloat fade, /* Perform the EAX reverb pass on a given input sample, resulting in four- * channel output. */ -static ALfloat EAXVerbPass(ALreverbState *State, const ALsizei todo, ALfloat fade, const ALfloat step, ALfloat (*restrict input)[MAX_UPDATE_SAMPLES], ALfloat (*restrict early)[MAX_UPDATE_SAMPLES], ALfloat (*restrict late)[MAX_UPDATE_SAMPLES]) +static ALfloat EAXVerbPass(ALreverbState *State, const ALsizei todo, ALfloat fade, + const ALfloat (*restrict input)[MAX_UPDATE_SAMPLES], + ALfloat (*restrict early)[MAX_UPDATE_SAMPLES], + ALfloat (*restrict late)[MAX_UPDATE_SAMPLES]) { ALsizei i, c; @@ -1843,19 +1866,19 @@ static ALfloat EAXVerbPass(ALreverbState *State, const ALsizei todo, ALfloat fad if(fade < 1.0f) { /* Generate early reflections. */ - EarlyReflection_Faded(State, todo, fade, step, early); + EarlyReflection_Faded(State, todo, fade, early); /* Generate late reverb. */ - LateReverb_Faded(State, todo, fade, step, late); - fade = minf(1.0f, fade + todo*step); + LateReverb_Faded(State, todo, fade, late); + fade = minf(1.0f, fade + todo*FadeStep); } else { /* Generate early reflections. */ - EarlyReflection_Unfaded(State, todo, fade, step, early); + EarlyReflection_Unfaded(State, todo, fade, early); /* Generate late reverb. */ - LateReverb_Unfaded(State, todo, fade, step, late); + LateReverb_Unfaded(State, todo, fade, late); } /* Step all delays forward. */ @@ -1864,23 +1887,9 @@ static ALfloat EAXVerbPass(ALreverbState *State, const ALsizei todo, ALfloat fad return fade; } -static ALvoid ALreverbState_processStandard(ALreverbState *State, const ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], const ALuint NumChannels) +static ALvoid ALreverbState_process(ALreverbState *State, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) { - /* The B-Format to A-Format conversion matrix. The arragement of rows - * is deliberately chosen to align the resulting lines to their spatial - * opposites (0:above front left <-> 3:above back right, 1:below front - * right <-> 2:below back left). It's not quite opposite, since the - * A-Format results in a tetrahedron, but it's close enough. Should the - * model be extended to 8-lines in the future, true opposites can be - * used. - */ - static const aluMatrixf B2A = {{ - { 0.288675134595f, 0.288675134595f, 0.288675134595f, 0.288675134595f }, - { 0.288675134595f, -0.288675134595f, -0.288675134595f, 0.288675134595f }, - { 0.288675134595f, 0.288675134595f, -0.288675134595f, -0.288675134595f }, - { 0.288675134595f, -0.288675134595f, 0.288675134595f, -0.288675134595f } - }}; - static const ALfloat FadeStep = 1.0f / FADE_SAMPLES; + ProcMethodType ReverbProc = State->IsEax ? EAXVerbPass : VerbPass; ALfloat (*restrict afmt)[MAX_UPDATE_SAMPLES] = State->AFormatSamples; ALfloat (*restrict early)[MAX_UPDATE_SAMPLES] = State->EarlySamples; ALfloat (*restrict late)[MAX_UPDATE_SAMPLES] = State->ReverbSamples; @@ -1901,78 +1910,7 @@ static ALvoid ALreverbState_processStandard(ALreverbState *State, const ALuint S ); /* Process the samples for reverb. */ - fade = VerbPass(State, todo, fade, FadeStep, afmt, early, late); - if(UNEXPECTED(fadeCount < FADE_SAMPLES) && (fadeCount += todo) >= FADE_SAMPLES) - { - /* Update the cross-fading delay line taps. */ - fadeCount = FADE_SAMPLES; - for(c = 0;c < 4;c++) - { - State->EarlyDelayTap[c][0] = State->EarlyDelayTap[c][1]; - State->Early.Ap[c].Offset[0] = State->Early.Ap[c].Offset[1]; - State->Early.Offset[c][0] = State->Early.Offset[c][1]; - State->LateDelayTap[c][0] = State->LateDelayTap[c][1]; - State->Late.Ap[c].Offset[0] = State->Late.Ap[c].Offset[1]; - State->Late.Offset[c][0] = State->Late.Offset[c][1]; - } - } - - /* Mix the A-Format results to output, implicitly converting back to - * B-Format. - */ - for(c = 0;c < 4;c++) - MixSamples(early[c], NumChannels, SamplesOut, - State->Early.CurrentGain[c], State->Early.PanGain[c], - SamplesToDo-base, base, todo - ); - for(c = 0;c < 4;c++) - MixSamples(late[c], NumChannels, SamplesOut, - State->Late.CurrentGain[c], State->Late.PanGain[c], - SamplesToDo-base, base, todo - ); - - base += todo; - } - State->FadeCount = fadeCount; -} - -static ALvoid ALreverbState_processEax(ALreverbState *State, const ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], const ALuint NumChannels) -{ - /* The B-Format to A-Format conversion matrix. The arragement of rows - * is deliberately chosen to align the resulting lines to their spatial - * opposites (0:above front left <-> 3:above back right, 1:below front - * right <-> 2:below back left). It's not quite opposite, since the - * A-Format results in a tetrahedron, but it's close enough. Should the - * model be extended to 8-lines in the future, true opposites can be - * used. - */ - static const aluMatrixf B2A = {{ - { 0.288675134595f, 0.288675134595f, 0.288675134595f, 0.288675134595f }, - { 0.288675134595f, -0.288675134595f, -0.288675134595f, 0.288675134595f }, - { 0.288675134595f, 0.288675134595f, -0.288675134595f, -0.288675134595f }, - { 0.288675134595f, -0.288675134595f, 0.288675134595f, -0.288675134595f } - }}; - static const ALfloat FadeStep = 1.0f / FADE_SAMPLES; - ALfloat (*restrict afmt)[MAX_UPDATE_SAMPLES] = State->AFormatSamples; - ALfloat (*restrict early)[MAX_UPDATE_SAMPLES] = State->EarlySamples; - ALfloat (*restrict late)[MAX_UPDATE_SAMPLES] = State->ReverbSamples; - ALsizei fadeCount = State->FadeCount; - ALfloat fade = (ALfloat)fadeCount / FADE_SAMPLES; - ALuint base, c; - - /* Process reverb for these samples. */ - for(base = 0;base < SamplesToDo;) - { - ALsizei todo = minu(SamplesToDo-base, MAX_UPDATE_SAMPLES); - - memset(afmt, 0, 4*MAX_UPDATE_SAMPLES*sizeof(float)); - for(c = 0;c < 4;c++) - MixRowSamples(afmt[c], B2A.m[c], - SamplesIn, MAX_EFFECT_CHANNELS, base, todo - ); - - /* Process the samples for EAX reverb. */ - fade = EAXVerbPass(State, todo, fade, FadeStep, afmt, early, late); + fade = ReverbProc(State, todo, fade, afmt, early, late); if(UNEXPECTED(fadeCount < FADE_SAMPLES) && (fadeCount += todo) >= FADE_SAMPLES) { /* Update the cross-fading delay line taps. */ @@ -2007,15 +1945,6 @@ static ALvoid ALreverbState_processEax(ALreverbState *State, const ALuint Sample State->FadeCount = fadeCount; } -static ALvoid ALreverbState_process(ALreverbState *State, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) -{ - /* Process the EAX or non-EAX reverb effect. */ - if(State->IsEax) - ALreverbState_processEax(State, SamplesToDo, SamplesIn, SamplesOut, NumChannels); - else - ALreverbState_processStandard(State, SamplesToDo, SamplesIn, SamplesOut, NumChannels); -} - typedef struct ALreverbStateFactory { DERIVE_FROM_TYPE(ALeffectStateFactory); |