// 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++;
}
Exemple #3
0
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;
}
Exemple #5
0
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++;
}