// Given an input sample, this function produces modulation for the late // reverb. static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in) { ALfloat sinus, frac; ALuint offset; ALfloat out0, out1; // Calculate the sinus rythm (dependent on modulation time and the // sampling rate). The center of the sinus is moved to reduce the delay // of the effect when the time or depth are low. sinus = 1.0f - cosf(F_PI*2.0f * State->Mod.Index / State->Mod.Range); // The depth determines the range over which to read the input samples // from, so it must be filtered to reduce the distortion caused by even // small parameter changes. State->Mod.Filter = lerp(State->Mod.Filter, State->Mod.Depth, State->Mod.Coeff); // Calculate the read offset and fraction between it and the next sample. frac = (1.0f + (State->Mod.Filter * sinus)); offset = fastf2u(frac); frac -= offset; // Get the two samples crossed by the offset, and feed the delay line // with the next input sample. out0 = DelayLineOut(&State->Mod.Delay, State->Offset - offset); out1 = DelayLineOut(&State->Mod.Delay, State->Offset - offset - 1); DelayLineIn(&State->Mod.Delay, State->Offset, in); // Step the modulation index forward, keeping it bound to its range. State->Mod.Index = (State->Mod.Index + 1) % State->Mod.Range; // The output is obtained by linearly interpolating the two samples that // were acquired above. return lerp(out0, out1, frac); }
// Perform the non-EAX reverb pass on a given input sample, resulting in // four-channel output. static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late) { ALfloat feed, taps[4]; // Low-pass filter the incoming sample. in = lpFilter2P(&State->LpFilter, 0, in); // Feed the initial delay line. DelayLineIn(&State->Delay, State->Offset, in); // Calculate the early reflection from the first delay tap. in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]); EarlyReflection(State, in, early); // Feed the decorrelator from the energy-attenuated output of the second // delay tap. in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]); feed = in * State->Late.DensityGain; DelayLineIn(&State->Decorrelator, State->Offset, feed); // Calculate the late reverb from the decorrelator taps. taps[0] = feed; taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]); taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]); taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]); LateReverb(State, taps, late); // Step all delays forward one sample. State->Offset++; }
static float AllpassInOut(DelayLine *Delay, unsigned int outOffset, unsigned int inOffset, float in, float feedCoeff, float coeff) { float out, feed; out = DelayLineOut(Delay, outOffset); feed = feedCoeff * in; DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in); /* The time-based attenuation is only applied to the delay output to * keep it from affecting the feed-back path (which is already controlled * by the all-pass feed coefficient). */ return (coeff * out) - feed; }
// Basic attenuated all-pass input/output routine. static __inline ALfloat AllpassInOut(DelayLine *Delay, ALuint outOffset, ALuint inOffset, ALfloat in, ALfloat feedCoeff, ALfloat coeff) { ALfloat out, feed; out = DelayLineOut(Delay, outOffset); feed = feedCoeff * in; DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in); // The time-based attenuation is only applied to the delay output to // keep it from affecting the feed-back path (which is already controlled // by the all-pass feed coefficient). return (coeff * out) - feed; }
static void VerbPass(IDirectSoundBufferImpl* dsb, float in, float* out) { float feed, late[4], taps[4]; /* Low-pass filter the incoming sample. */ in = lpFilter2P(&dsb->eax.LpFilter, 0, in); /* Feed the initial delay line. */ DelayLineIn(&dsb->eax.Delay, dsb->eax.Offset, in); /* Calculate the early reflection from the first delay tap. */ in = DelayLineOut(&dsb->eax.Delay, dsb->eax.Offset - dsb->eax.DelayTap[0]); EarlyReflection(dsb, in, out); /* Feed the decorrelator from the energy-attenuated output of the second * delay tap. */ in = DelayLineOut(&dsb->eax.Delay, dsb->eax.Offset - dsb->eax.DelayTap[1]); feed = in * dsb->eax.Late.DensityGain; DelayLineIn(&dsb->eax.Decorrelator, dsb->eax.Offset, feed); /* Calculate the late reverb from the decorrelator taps. */ taps[0] = feed; taps[1] = DelayLineOut(&dsb->eax.Decorrelator, dsb->eax.Offset - dsb->eax.DecoTap[0]); taps[2] = DelayLineOut(&dsb->eax.Decorrelator, dsb->eax.Offset - dsb->eax.DecoTap[1]); taps[3] = DelayLineOut(&dsb->eax.Decorrelator, dsb->eax.Offset - dsb->eax.DecoTap[2]); LateReverb(dsb, taps, late); /* Mix early reflections and late reverb. */ out[0] += late[0]; out[1] += late[1]; out[2] += late[2]; out[3] += late[3]; /* Step all delays forward one sample. */ dsb->eax.Offset++; }