~ubuntu-branches/ubuntu/utopic/openal-soft/utopic

« back to all changes in this revision

Viewing changes to Alc/alcReverb.c

  • Committer: Package Import Robot
  • Author(s): Michael Terry
  • Date: 2012-05-22 10:14:53 UTC
  • mfrom: (7.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20120522101453-knsv1m1m8vl5ccfp
Tags: 1:1.14-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  - Add a symbols file for libopenal1
* debian/libopenal1.symbols:
  - Update for 1.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
    // fragmentation and management code.
49
49
    ALfloat  *SampleBuffer;
50
50
    ALuint    TotalSamples;
 
51
 
51
52
    // Master effect low-pass filter (2 chained 1-pole filters).
52
53
    FILTER    LpFilter;
53
54
    ALfloat   LpHistory[2];
 
55
 
54
56
    struct {
55
57
        // Modulator delay line.
56
58
        DelayLine Delay;
 
59
 
57
60
        // The vibrato time is tracked with an index over a modulus-wrapped
58
61
        // range (in samples).
59
62
        ALuint    Index;
60
63
        ALuint    Range;
 
64
 
61
65
        // The depth of frequency change (also in samples) and its filter.
62
66
        ALfloat   Depth;
63
67
        ALfloat   Coeff;
64
68
        ALfloat   Filter;
65
69
    } Mod;
 
70
 
66
71
    // Initial effect delay.
67
72
    DelayLine Delay;
68
73
    // The tap points for the initial delay.  First tap goes to early
69
74
    // reflections, the last to late reverb.
70
75
    ALuint    DelayTap[2];
 
76
 
71
77
    struct {
72
78
        // Output gain for early reflections.
73
79
        ALfloat   Gain;
 
80
 
74
81
        // Early reflections are done with 4 delay lines.
75
82
        ALfloat   Coeff[4];
76
83
        DelayLine Delay[4];
77
84
        ALuint    Offset[4];
 
85
 
78
86
        // The gain for each output channel based on 3D panning (only for the
79
87
        // EAX path).
80
88
        ALfloat   PanGain[MAXCHANNELS];
81
89
    } Early;
 
90
 
82
91
    // Decorrelator delay line.
83
92
    DelayLine Decorrelator;
84
93
    // There are actually 4 decorrelator taps, but the first occurs at the
85
94
    // initial sample.
86
95
    ALuint    DecoTap[3];
 
96
 
87
97
    struct {
88
98
        // Output gain for late reverb.
89
99
        ALfloat   Gain;
 
100
 
90
101
        // Attenuation to compensate for the modal density and decay rate of
91
102
        // the late lines.
92
103
        ALfloat   DensityGain;
 
104
 
93
105
        // The feed-back and feed-forward all-pass coefficient.
94
106
        ALfloat   ApFeedCoeff;
 
107
 
95
108
        // Mixing matrix coefficient.
96
109
        ALfloat   MixCoeff;
 
110
 
97
111
        // Late reverb has 4 parallel all-pass filters.
98
112
        ALfloat   ApCoeff[4];
99
113
        DelayLine ApDelay[4];
100
114
        ALuint    ApOffset[4];
 
115
 
101
116
        // In addition to 4 cyclical delay lines.
102
117
        ALfloat   Coeff[4];
103
118
        DelayLine Delay[4];
104
119
        ALuint    Offset[4];
 
120
 
105
121
        // The cyclical delay lines are 1-pole low-pass filtered.
106
122
        ALfloat   LpCoeff[4];
107
123
        ALfloat   LpSample[4];
 
124
 
108
125
        // The gain for each output channel based on 3D panning (only for the
109
126
        // EAX path).
110
127
        ALfloat   PanGain[MAXCHANNELS];
111
128
    } Late;
 
129
 
112
130
    struct {
113
131
        // Attenuation to compensate for the modal density and decay rate of
114
132
        // the echo line.
115
133
        ALfloat   DensityGain;
 
134
 
116
135
        // Echo delay and all-pass lines.
117
136
        DelayLine Delay;
118
137
        DelayLine ApDelay;
 
138
 
119
139
        ALfloat   Coeff;
120
140
        ALfloat   ApFeedCoeff;
121
141
        ALfloat   ApCoeff;
 
142
 
122
143
        ALuint    Offset;
123
144
        ALuint    ApOffset;
 
145
 
124
146
        // The echo line is 1-pole low-pass filtered.
125
147
        ALfloat   LpCoeff;
126
148
        ALfloat   LpSample;
 
149
 
127
150
        // Echo mixing coefficients.
128
151
        ALfloat   MixCoeff[2];
129
152
    } Echo;
 
153
 
130
154
    // The current read offset for all delay lines.
131
155
    ALuint Offset;
132
156
 
135
159
    ALfloat *Gain;
136
160
} ALverbState;
137
161
 
 
162
/* This is a user config option for modifying the overall output of the reverb
 
163
 * effect.
 
164
 */
 
165
ALfloat ReverbBoost = 1.0f;
 
166
 
 
167
/* Specifies whether to use a standard reverb effect in place of EAX reverb */
 
168
ALboolean EmulateEAXReverb = AL_FALSE;
 
169
 
138
170
/* This coefficient is used to define the maximum frequency range controlled
139
171
 * by the modulation depth.  The current value of 0.1 will allow it to swing
140
172
 * from 0.9x to 1.1x.  This value must be below 1.  At 1 it will cause the
185
217
// effect's density parameter (inverted for some reason) and this multiplier.
186
218
static const ALfloat LATE_LINE_MULTIPLIER = 4.0f;
187
219
 
 
220
 
 
221
// Basic delay line input/output routines.
 
222
static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
 
223
{
 
224
    return Delay->Line[offset&Delay->Mask];
 
225
}
 
226
 
 
227
static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
 
228
{
 
229
    Delay->Line[offset&Delay->Mask] = in;
 
230
}
 
231
 
 
232
// Attenuated delay line output routine.
 
233
static __inline ALfloat AttenuatedDelayLineOut(DelayLine *Delay, ALuint offset, ALfloat coeff)
 
234
{
 
235
    return coeff * Delay->Line[offset&Delay->Mask];
 
236
}
 
237
 
 
238
// Basic attenuated all-pass input/output routine.
 
239
static __inline ALfloat AllpassInOut(DelayLine *Delay, ALuint outOffset, ALuint inOffset, ALfloat in, ALfloat feedCoeff, ALfloat coeff)
 
240
{
 
241
    ALfloat out, feed;
 
242
 
 
243
    out = DelayLineOut(Delay, outOffset);
 
244
    feed = feedCoeff * in;
 
245
    DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in);
 
246
 
 
247
    // The time-based attenuation is only applied to the delay output to
 
248
    // keep it from affecting the feed-back path (which is already controlled
 
249
    // by the all-pass feed coefficient).
 
250
    return (coeff * out) - feed;
 
251
}
 
252
 
 
253
// Given an input sample, this function produces modulation for the late
 
254
// reverb.
 
255
static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in)
 
256
{
 
257
    ALfloat sinus, frac;
 
258
    ALuint offset;
 
259
    ALfloat out0, out1;
 
260
 
 
261
    // Calculate the sinus rythm (dependent on modulation time and the
 
262
    // sampling rate).  The center of the sinus is moved to reduce the delay
 
263
    // of the effect when the time or depth are low.
 
264
    sinus = 1.0f - aluCos(F_PI*2.0f * State->Mod.Index / State->Mod.Range);
 
265
 
 
266
    // The depth determines the range over which to read the input samples
 
267
    // from, so it must be filtered to reduce the distortion caused by even
 
268
    // small parameter changes.
 
269
    State->Mod.Filter = lerp(State->Mod.Filter, State->Mod.Depth,
 
270
                             State->Mod.Coeff);
 
271
 
 
272
    // Calculate the read offset and fraction between it and the next sample.
 
273
    frac   = (1.0f + (State->Mod.Filter * sinus));
 
274
    offset = fastf2u(frac);
 
275
    frac  -= offset;
 
276
 
 
277
    // Get the two samples crossed by the offset, and feed the delay line
 
278
    // with the next input sample.
 
279
    out0 = DelayLineOut(&State->Mod.Delay, State->Offset - offset);
 
280
    out1 = DelayLineOut(&State->Mod.Delay, State->Offset - offset - 1);
 
281
    DelayLineIn(&State->Mod.Delay, State->Offset, in);
 
282
 
 
283
    // Step the modulation index forward, keeping it bound to its range.
 
284
    State->Mod.Index = (State->Mod.Index + 1) % State->Mod.Range;
 
285
 
 
286
    // The output is obtained by linearly interpolating the two samples that
 
287
    // were acquired above.
 
288
    return lerp(out0, out1, frac);
 
289
}
 
290
 
 
291
// Delay line output routine for early reflections.
 
292
static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
 
293
{
 
294
    return AttenuatedDelayLineOut(&State->Early.Delay[index],
 
295
                                  State->Offset - State->Early.Offset[index],
 
296
                                  State->Early.Coeff[index]);
 
297
}
 
298
 
 
299
// Given an input sample, this function produces four-channel output for the
 
300
// early reflections.
 
301
static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *out)
 
302
{
 
303
    ALfloat d[4], v, f[4];
 
304
 
 
305
    // Obtain the decayed results of each early delay line.
 
306
    d[0] = EarlyDelayLineOut(State, 0);
 
307
    d[1] = EarlyDelayLineOut(State, 1);
 
308
    d[2] = EarlyDelayLineOut(State, 2);
 
309
    d[3] = EarlyDelayLineOut(State, 3);
 
310
 
 
311
    /* The following uses a lossless scattering junction from waveguide
 
312
     * theory.  It actually amounts to a householder mixing matrix, which
 
313
     * will produce a maximally diffuse response, and means this can probably
 
314
     * be considered a simple feed-back delay network (FDN).
 
315
     *          N
 
316
     *         ---
 
317
     *         \
 
318
     * v = 2/N /   d_i
 
319
     *         ---
 
320
     *         i=1
 
321
     */
 
322
    v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
 
323
    // The junction is loaded with the input here.
 
324
    v += in;
 
325
 
 
326
    // Calculate the feed values for the delay lines.
 
327
    f[0] = v - d[0];
 
328
    f[1] = v - d[1];
 
329
    f[2] = v - d[2];
 
330
    f[3] = v - d[3];
 
331
 
 
332
    // Re-feed the delay lines.
 
333
    DelayLineIn(&State->Early.Delay[0], State->Offset, f[0]);
 
334
    DelayLineIn(&State->Early.Delay[1], State->Offset, f[1]);
 
335
    DelayLineIn(&State->Early.Delay[2], State->Offset, f[2]);
 
336
    DelayLineIn(&State->Early.Delay[3], State->Offset, f[3]);
 
337
 
 
338
    // Output the results of the junction for all four channels.
 
339
    out[0] = State->Early.Gain * f[0];
 
340
    out[1] = State->Early.Gain * f[1];
 
341
    out[2] = State->Early.Gain * f[2];
 
342
    out[3] = State->Early.Gain * f[3];
 
343
}
 
344
 
 
345
// All-pass input/output routine for late reverb.
 
346
static __inline ALfloat LateAllPassInOut(ALverbState *State, ALuint index, ALfloat in)
 
347
{
 
348
    return AllpassInOut(&State->Late.ApDelay[index],
 
349
                        State->Offset - State->Late.ApOffset[index],
 
350
                        State->Offset, in, State->Late.ApFeedCoeff,
 
351
                        State->Late.ApCoeff[index]);
 
352
}
 
353
 
 
354
// Delay line output routine for late reverb.
 
355
static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
 
356
{
 
357
    return AttenuatedDelayLineOut(&State->Late.Delay[index],
 
358
                                  State->Offset - State->Late.Offset[index],
 
359
                                  State->Late.Coeff[index]);
 
360
}
 
361
 
 
362
// Low-pass filter input/output routine for late reverb.
 
363
static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
 
364
{
 
365
    in = lerp(in, State->Late.LpSample[index], State->Late.LpCoeff[index]);
 
366
    State->Late.LpSample[index] = in;
 
367
    return in;
 
368
}
 
369
 
 
370
// Given four decorrelated input samples, this function produces four-channel
 
371
// output for the late reverb.
 
372
static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out)
 
373
{
 
374
    ALfloat d[4], f[4];
 
375
 
 
376
    // Obtain the decayed results of the cyclical delay lines, and add the
 
377
    // corresponding input channels.  Then pass the results through the
 
378
    // low-pass filters.
 
379
 
 
380
    // This is where the feed-back cycles from line 0 to 1 to 3 to 2 and back
 
381
    // to 0.
 
382
    d[0] = LateLowPassInOut(State, 2, in[2] + LateDelayLineOut(State, 2));
 
383
    d[1] = LateLowPassInOut(State, 0, in[0] + LateDelayLineOut(State, 0));
 
384
    d[2] = LateLowPassInOut(State, 3, in[3] + LateDelayLineOut(State, 3));
 
385
    d[3] = LateLowPassInOut(State, 1, in[1] + LateDelayLineOut(State, 1));
 
386
 
 
387
    // To help increase diffusion, run each line through an all-pass filter.
 
388
    // When there is no diffusion, the shortest all-pass filter will feed the
 
389
    // shortest delay line.
 
390
    d[0] = LateAllPassInOut(State, 0, d[0]);
 
391
    d[1] = LateAllPassInOut(State, 1, d[1]);
 
392
    d[2] = LateAllPassInOut(State, 2, d[2]);
 
393
    d[3] = LateAllPassInOut(State, 3, d[3]);
 
394
 
 
395
    /* Late reverb is done with a modified feed-back delay network (FDN)
 
396
     * topology.  Four input lines are each fed through their own all-pass
 
397
     * filter and then into the mixing matrix.  The four outputs of the
 
398
     * mixing matrix are then cycled back to the inputs.  Each output feeds
 
399
     * a different input to form a circlular feed cycle.
 
400
     *
 
401
     * The mixing matrix used is a 4D skew-symmetric rotation matrix derived
 
402
     * using a single unitary rotational parameter:
 
403
     *
 
404
     *  [  d,  a,  b,  c ]          1 = a^2 + b^2 + c^2 + d^2
 
405
     *  [ -a,  d,  c, -b ]
 
406
     *  [ -b, -c,  d,  a ]
 
407
     *  [ -c,  b, -a,  d ]
 
408
     *
 
409
     * The rotation is constructed from the effect's diffusion parameter,
 
410
     * yielding:  1 = x^2 + 3 y^2; where a, b, and c are the coefficient y
 
411
     * with differing signs, and d is the coefficient x.  The matrix is thus:
 
412
     *
 
413
     *  [  x,  y, -y,  y ]          n = sqrt(matrix_order - 1)
 
414
     *  [ -y,  x,  y,  y ]          t = diffusion_parameter * atan(n)
 
415
     *  [  y, -y,  x,  y ]          x = cos(t)
 
416
     *  [ -y, -y, -y,  x ]          y = sin(t) / n
 
417
     *
 
418
     * To reduce the number of multiplies, the x coefficient is applied with
 
419
     * the cyclical delay line coefficients.  Thus only the y coefficient is
 
420
     * applied when mixing, and is modified to be:  y / x.
 
421
     */
 
422
    f[0] = d[0] + (State->Late.MixCoeff * (         d[1] + -d[2] + d[3]));
 
423
    f[1] = d[1] + (State->Late.MixCoeff * (-d[0]         +  d[2] + d[3]));
 
424
    f[2] = d[2] + (State->Late.MixCoeff * ( d[0] + -d[1]         + d[3]));
 
425
    f[3] = d[3] + (State->Late.MixCoeff * (-d[0] + -d[1] + -d[2]       ));
 
426
 
 
427
    // Output the results of the matrix for all four channels, attenuated by
 
428
    // the late reverb gain (which is attenuated by the 'x' mix coefficient).
 
429
    out[0] = State->Late.Gain * f[0];
 
430
    out[1] = State->Late.Gain * f[1];
 
431
    out[2] = State->Late.Gain * f[2];
 
432
    out[3] = State->Late.Gain * f[3];
 
433
 
 
434
    // Re-feed the cyclical delay lines.
 
435
    DelayLineIn(&State->Late.Delay[0], State->Offset, f[0]);
 
436
    DelayLineIn(&State->Late.Delay[1], State->Offset, f[1]);
 
437
    DelayLineIn(&State->Late.Delay[2], State->Offset, f[2]);
 
438
    DelayLineIn(&State->Late.Delay[3], State->Offset, f[3]);
 
439
}
 
440
 
 
441
// Given an input sample, this function mixes echo into the four-channel late
 
442
// reverb.
 
443
static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *late)
 
444
{
 
445
    ALfloat out, feed;
 
446
 
 
447
    // Get the latest attenuated echo sample for output.
 
448
    feed = AttenuatedDelayLineOut(&State->Echo.Delay,
 
449
                                  State->Offset - State->Echo.Offset,
 
450
                                  State->Echo.Coeff);
 
451
 
 
452
    // Mix the output into the late reverb channels.
 
453
    out = State->Echo.MixCoeff[0] * feed;
 
454
    late[0] = (State->Echo.MixCoeff[1] * late[0]) + out;
 
455
    late[1] = (State->Echo.MixCoeff[1] * late[1]) + out;
 
456
    late[2] = (State->Echo.MixCoeff[1] * late[2]) + out;
 
457
    late[3] = (State->Echo.MixCoeff[1] * late[3]) + out;
 
458
 
 
459
    // Mix the energy-attenuated input with the output and pass it through
 
460
    // the echo low-pass filter.
 
461
    feed += State->Echo.DensityGain * in;
 
462
    feed = lerp(feed, State->Echo.LpSample, State->Echo.LpCoeff);
 
463
    State->Echo.LpSample = feed;
 
464
 
 
465
    // Then the echo all-pass filter.
 
466
    feed = AllpassInOut(&State->Echo.ApDelay,
 
467
                        State->Offset - State->Echo.ApOffset,
 
468
                        State->Offset, feed, State->Echo.ApFeedCoeff,
 
469
                        State->Echo.ApCoeff);
 
470
 
 
471
    // Feed the delay with the mixed and filtered sample.
 
472
    DelayLineIn(&State->Echo.Delay, State->Offset, feed);
 
473
}
 
474
 
 
475
// Perform the non-EAX reverb pass on a given input sample, resulting in
 
476
// four-channel output.
 
477
static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late)
 
478
{
 
479
    ALfloat feed, taps[4];
 
480
 
 
481
    // Low-pass filter the incoming sample.
 
482
    in = lpFilter2P(&State->LpFilter, 0, in);
 
483
 
 
484
    // Feed the initial delay line.
 
485
    DelayLineIn(&State->Delay, State->Offset, in);
 
486
 
 
487
    // Calculate the early reflection from the first delay tap.
 
488
    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
 
489
    EarlyReflection(State, in, early);
 
490
 
 
491
    // Feed the decorrelator from the energy-attenuated output of the second
 
492
    // delay tap.
 
493
    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
 
494
    feed = in * State->Late.DensityGain;
 
495
    DelayLineIn(&State->Decorrelator, State->Offset, feed);
 
496
 
 
497
    // Calculate the late reverb from the decorrelator taps.
 
498
    taps[0] = feed;
 
499
    taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
 
500
    taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
 
501
    taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
 
502
    LateReverb(State, taps, late);
 
503
 
 
504
    // Step all delays forward one sample.
 
505
    State->Offset++;
 
506
}
 
507
 
 
508
// Perform the EAX reverb pass on a given input sample, resulting in four-
 
509
// channel output.
 
510
static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late)
 
511
{
 
512
    ALfloat feed, taps[4];
 
513
 
 
514
    // Low-pass filter the incoming sample.
 
515
    in = lpFilter2P(&State->LpFilter, 0, in);
 
516
 
 
517
    // Perform any modulation on the input.
 
518
    in = EAXModulation(State, in);
 
519
 
 
520
    // Feed the initial delay line.
 
521
    DelayLineIn(&State->Delay, State->Offset, in);
 
522
 
 
523
    // Calculate the early reflection from the first delay tap.
 
524
    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
 
525
    EarlyReflection(State, in, early);
 
526
 
 
527
    // Feed the decorrelator from the energy-attenuated output of the second
 
528
    // delay tap.
 
529
    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
 
530
    feed = in * State->Late.DensityGain;
 
531
    DelayLineIn(&State->Decorrelator, State->Offset, feed);
 
532
 
 
533
    // Calculate the late reverb from the decorrelator taps.
 
534
    taps[0] = feed;
 
535
    taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
 
536
    taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
 
537
    taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
 
538
    LateReverb(State, taps, late);
 
539
 
 
540
    // Calculate and mix in any echo.
 
541
    EAXEcho(State, in, late);
 
542
 
 
543
    // Step all delays forward one sample.
 
544
    State->Offset++;
 
545
}
 
546
 
 
547
// This processes the reverb state, given the input samples and an output
 
548
// buffer.
 
549
static ALvoid VerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
 
550
{
 
551
    ALverbState *State = (ALverbState*)effect;
 
552
    ALuint index, c;
 
553
    ALfloat early[4], late[4], out[4];
 
554
    const ALfloat *panGain = State->Gain;
 
555
 
 
556
    for(index = 0;index < SamplesToDo;index++)
 
557
    {
 
558
        // Process reverb for this sample.
 
559
        VerbPass(State, SamplesIn[index], early, late);
 
560
 
 
561
        // Mix early reflections and late reverb.
 
562
        out[0] = (early[0] + late[0]);
 
563
        out[1] = (early[1] + late[1]);
 
564
        out[2] = (early[2] + late[2]);
 
565
        out[3] = (early[3] + late[3]);
 
566
 
 
567
        // Output the results.
 
568
        for(c = 0;c < MAXCHANNELS;c++)
 
569
            SamplesOut[index][c] += panGain[c] * out[c&3];
 
570
    }
 
571
}
 
572
 
 
573
// This processes the EAX reverb state, given the input samples and an output
 
574
// buffer.
 
575
static ALvoid EAXVerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
 
576
{
 
577
    ALverbState *State = (ALverbState*)effect;
 
578
    ALuint index, c;
 
579
    ALfloat early[4], late[4];
 
580
 
 
581
    for(index = 0;index < SamplesToDo;index++)
 
582
    {
 
583
        // Process reverb for this sample.
 
584
        EAXVerbPass(State, SamplesIn[index], early, late);
 
585
 
 
586
        for(c = 0;c < MAXCHANNELS;c++)
 
587
            SamplesOut[index][c] += State->Early.PanGain[c]*early[c&3] +
 
588
                                    State->Late.PanGain[c]*late[c&3];
 
589
    }
 
590
}
 
591
 
 
592
 
 
593
// Given the allocated sample buffer, this function updates each delay line
 
594
// offset.
 
595
static __inline ALvoid RealizeLineOffset(ALfloat * sampleBuffer, DelayLine *Delay)
 
596
{
 
597
    Delay->Line = &sampleBuffer[(ALintptrEXT)Delay->Line];
 
598
}
 
599
 
188
600
// Calculate the length of a delay line and store its mask and offset.
189
601
static ALuint CalcLineLength(ALfloat length, ALintptrEXT offset, ALuint frequency, DelayLine *Delay)
190
602
{
192
604
 
193
605
    // All line lengths are powers of 2, calculated from their lengths, with
194
606
    // an additional sample in case of rounding errors.
195
 
    samples = NextPowerOf2((ALuint)(length * frequency) + 1);
 
607
    samples = NextPowerOf2(fastf2u(length * frequency) + 1);
196
608
    // All lines share a single sample buffer.
197
609
    Delay->Mask = samples - 1;
198
610
    Delay->Line = (ALfloat*)offset;
200
612
    return samples;
201
613
}
202
614
 
203
 
// Given the allocated sample buffer, this function updates each delay line
204
 
// offset.
205
 
static __inline ALvoid RealizeLineOffset(ALfloat * sampleBuffer, DelayLine *Delay)
206
 
{
207
 
    Delay->Line = &sampleBuffer[(ALintptrEXT)Delay->Line];
208
 
}
209
 
 
210
615
/* Calculates the delay line metrics and allocates the shared sample buffer
211
 
 * for all lines given a flag indicating whether or not to allocate the EAX-
212
 
 * related delays (eaxFlag) and the sample rate (frequency).  If an
213
 
 * allocation failure occurs, it returns AL_FALSE.
 
616
 * for all lines given the sample rate (frequency).  If an allocation failure
 
617
 * occurs, it returns AL_FALSE.
214
618
 */
215
 
static ALboolean AllocLines(ALboolean eaxFlag, ALuint frequency, ALverbState *State)
 
619
static ALboolean AllocLines(ALuint frequency, ALverbState *State)
216
620
{
217
621
    ALuint totalSamples, index;
218
622
    ALfloat length;
221
625
    // All delay line lengths are calculated to accomodate the full range of
222
626
    // lengths given their respective paramters.
223
627
    totalSamples = 0;
224
 
    if(eaxFlag)
225
 
    {
226
 
        /* The modulator's line length is calculated from the maximum
227
 
         * modulation time and depth coefficient, and halfed for the low-to-
228
 
         * high frequency swing.  An additional sample is added to keep it
229
 
         * stable when there is no modulation.
230
 
         */
231
 
        length = (AL_EAXREVERB_MAX_MODULATION_TIME * MODULATION_DEPTH_COEFF /
232
 
                  2.0f) + (1.0f / frequency);
233
 
        totalSamples += CalcLineLength(length, totalSamples, frequency,
234
 
                                       &State->Mod.Delay);
235
 
    }
 
628
 
 
629
    /* The modulator's line length is calculated from the maximum modulation
 
630
     * time and depth coefficient, and halfed for the low-to-high frequency
 
631
     * swing.  An additional sample is added to keep it stable when there is no
 
632
     * modulation.
 
633
     */
 
634
    length = (AL_EAXREVERB_MAX_MODULATION_TIME*MODULATION_DEPTH_COEFF/2.0f) +
 
635
             (1.0f / frequency);
 
636
    totalSamples += CalcLineLength(length, totalSamples, frequency,
 
637
                                   &State->Mod.Delay);
236
638
 
237
639
    // The initial delay is the sum of the reflections and late reverb
238
640
    // delays.
239
 
    if(eaxFlag)
240
 
        length = AL_EAXREVERB_MAX_REFLECTIONS_DELAY +
241
 
                 AL_EAXREVERB_MAX_LATE_REVERB_DELAY;
242
 
    else
243
 
        length = AL_REVERB_MAX_REFLECTIONS_DELAY +
244
 
                 AL_REVERB_MAX_LATE_REVERB_DELAY;
 
641
    length = AL_EAXREVERB_MAX_REFLECTIONS_DELAY +
 
642
             AL_EAXREVERB_MAX_LATE_REVERB_DELAY;
245
643
    totalSamples += CalcLineLength(length, totalSamples, frequency,
246
644
                                   &State->Delay);
247
645
 
270
668
                                       &State->Late.Delay[index]);
271
669
    }
272
670
 
273
 
    if(eaxFlag)
274
 
    {
275
 
        // The echo all-pass and delay lines.
276
 
        totalSamples += CalcLineLength(ECHO_ALLPASS_LENGTH, totalSamples,
277
 
                                       frequency, &State->Echo.ApDelay);
278
 
        totalSamples += CalcLineLength(AL_EAXREVERB_MAX_ECHO_TIME, totalSamples,
279
 
                                       frequency, &State->Echo.Delay);
280
 
    }
 
671
    // The echo all-pass and delay lines.
 
672
    totalSamples += CalcLineLength(ECHO_ALLPASS_LENGTH, totalSamples,
 
673
                                   frequency, &State->Echo.ApDelay);
 
674
    totalSamples += CalcLineLength(AL_EAXREVERB_MAX_ECHO_TIME, totalSamples,
 
675
                                   frequency, &State->Echo.Delay);
281
676
 
282
677
    if(totalSamples != State->TotalSamples)
283
678
    {
 
679
        TRACE("New reverb buffer length: %u samples (%f sec)\n", totalSamples, totalSamples/(float)frequency);
284
680
        newBuffer = realloc(State->SampleBuffer, sizeof(ALfloat) * totalSamples);
285
681
        if(newBuffer == NULL)
286
682
            return AL_FALSE;
297
693
        RealizeLineOffset(State->SampleBuffer, &State->Late.ApDelay[index]);
298
694
        RealizeLineOffset(State->SampleBuffer, &State->Late.Delay[index]);
299
695
    }
300
 
    if(eaxFlag)
301
 
    {
302
 
        RealizeLineOffset(State->SampleBuffer, &State->Mod.Delay);
303
 
        RealizeLineOffset(State->SampleBuffer, &State->Echo.ApDelay);
304
 
        RealizeLineOffset(State->SampleBuffer, &State->Echo.Delay);
305
 
    }
 
696
    RealizeLineOffset(State->SampleBuffer, &State->Mod.Delay);
 
697
    RealizeLineOffset(State->SampleBuffer, &State->Echo.ApDelay);
 
698
    RealizeLineOffset(State->SampleBuffer, &State->Echo.Delay);
306
699
 
307
700
    // Clear the sample buffer.
308
701
    for(index = 0;index < State->TotalSamples;index++)
311
704
    return AL_TRUE;
312
705
}
313
706
 
 
707
// This updates the device-dependant EAX reverb state.  This is called on
 
708
// initialization and any time the device parameters (eg. playback frequency,
 
709
// format) have been changed.
 
710
static ALboolean ReverbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
 
711
{
 
712
    ALverbState *State = (ALverbState*)effect;
 
713
    ALuint frequency = Device->Frequency, index;
 
714
 
 
715
    // Allocate the delay lines.
 
716
    if(!AllocLines(frequency, State))
 
717
        return AL_FALSE;
 
718
 
 
719
    // Calculate the modulation filter coefficient.  Notice that the exponent
 
720
    // is calculated given the current sample rate.  This ensures that the
 
721
    // resulting filter response over time is consistent across all sample
 
722
    // rates.
 
723
    State->Mod.Coeff = aluPow(MODULATION_FILTER_COEFF,
 
724
                              MODULATION_FILTER_CONST / frequency);
 
725
 
 
726
    // The early reflection and late all-pass filter line lengths are static,
 
727
    // so their offsets only need to be calculated once.
 
728
    for(index = 0;index < 4;index++)
 
729
    {
 
730
        State->Early.Offset[index] = fastf2u(EARLY_LINE_LENGTH[index] *
 
731
                                             frequency);
 
732
        State->Late.ApOffset[index] = fastf2u(ALLPASS_LINE_LENGTH[index] *
 
733
                                              frequency);
 
734
    }
 
735
 
 
736
    // The echo all-pass filter line length is static, so its offset only
 
737
    // needs to be calculated once.
 
738
    State->Echo.ApOffset = fastf2u(ECHO_ALLPASS_LENGTH * frequency);
 
739
 
 
740
    return AL_TRUE;
 
741
}
 
742
 
314
743
// Calculate a decay coefficient given the length of each cycle and the time
315
744
// until the decay reaches -60 dB.
316
745
static __inline ALfloat CalcDecayCoeff(ALfloat length, ALfloat decayTime)
317
746
{
318
 
    return aluPow(10.0f, length / decayTime * -60.0f / 20.0f);
 
747
    return aluPow(0.001f/*-60 dB*/, length/decayTime);
319
748
}
320
749
 
321
750
// Calculate a decay length from a coefficient and the time until the decay
322
751
// reaches -60 dB.
323
752
static __inline ALfloat CalcDecayLength(ALfloat coeff, ALfloat decayTime)
324
753
{
325
 
    return log10(coeff) / -60.0 * 20.0f * decayTime;
 
754
    return aluLog10(coeff) * decayTime / aluLog10(0.001f)/*-60 dB*/;
326
755
}
327
756
 
328
757
// Calculate the high frequency parameter for the I3DL2 coefficient
329
758
// calculation.
330
759
static __inline ALfloat CalcI3DL2HFreq(ALfloat hfRef, ALuint frequency)
331
760
{
332
 
    return cos(2.0f * M_PI * hfRef / frequency);
 
761
    return aluCos(F_PI*2.0f * hfRef / frequency);
333
762
}
334
763
 
335
764
// Calculate an attenuation to be applied to the input of any echo models to
359
788
 
360
789
    // The matrix is of order 4, so n is sqrt (4 - 1).
361
790
    n = aluSqrt(3.0f);
362
 
    t = diffusion * atan(n);
 
791
    t = diffusion * aluAtan(n);
363
792
 
364
793
    // Calculate the first mixing matrix coefficient.
365
 
    *x = cos(t);
 
794
    *x = aluCos(t);
366
795
    // Calculate the second mixing matrix coefficient.
367
 
    *y = sin(t) / n;
 
796
    *y = aluSin(t) / n;
368
797
}
369
798
 
370
799
// Calculate the limited HF ratio for use with the late reverb low-pass
380
809
     */
381
810
    limitRatio = 1.0f / (CalcDecayLength(airAbsorptionGainHF, decayTime) *
382
811
                         SPEEDOFSOUNDMETRESPERSEC);
383
 
    // Need to limit the result to a minimum of 0.1, just like the HF ratio
384
 
    // parameter.
385
 
    limitRatio = __max(limitRatio, 0.1f);
386
 
 
387
 
    // Using the limit calculated above, apply the upper bound to the HF
388
 
    // ratio.
389
 
    return __min(hfRatio, limitRatio);
 
812
    /* Using the limit calculated above, apply the upper bound to the HF
 
813
     * ratio. Also need to limit the result to a minimum of 0.1, just like the
 
814
     * HF ratio parameter. */
 
815
    return clampf(limitRatio, 0.1f, hfRatio);
390
816
}
391
817
 
392
818
// Calculate the coefficient for a HF (and eventually LF) decay damping
410
836
 
411
837
        // Very low decay times will produce minimal output, so apply an
412
838
        // upper bound to the coefficient.
413
 
        coeff = __min(coeff, 0.98f);
 
839
        coeff = minf(coeff, 0.98f);
414
840
    }
415
841
    return coeff;
416
842
}
420
846
// downswing will sound stronger than the upswing.
421
847
static ALvoid UpdateModulator(ALfloat modTime, ALfloat modDepth, ALuint frequency, ALverbState *State)
422
848
{
423
 
    ALfloat length;
 
849
    ALuint range;
424
850
 
425
851
    /* Modulation is calculated in two parts.
426
852
     *
430
856
     * minimum (1 sample) and when the timing changes, the index is rescaled
431
857
     * to the new range (to keep the sinus consistent).
432
858
     */
433
 
    length = modTime * frequency;
434
 
    if (length >= 1.0f) {
435
 
       State->Mod.Index = (ALuint)(State->Mod.Index * length /
436
 
                                   State->Mod.Range);
437
 
       State->Mod.Range = (ALuint)length;
438
 
    } else {
439
 
       State->Mod.Index = 0;
440
 
       State->Mod.Range = 1;
441
 
    }
 
859
    range = maxu(fastf2u(modTime*frequency), 1);
 
860
    State->Mod.Index = (ALuint)(State->Mod.Index * (ALuint64)range /
 
861
                                State->Mod.Range);
 
862
    State->Mod.Range = range;
442
863
 
443
864
    /* The modulation depth effects the amount of frequency change over the
444
865
     * range of the sinus.  It needs to be scaled by the modulation time so
456
877
static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALuint frequency, ALverbState *State)
457
878
{
458
879
    // Calculate the initial delay taps.
459
 
    State->DelayTap[0] = (ALuint)(earlyDelay * frequency);
460
 
    State->DelayTap[1] = (ALuint)((earlyDelay + lateDelay) * frequency);
 
880
    State->DelayTap[0] = fastf2u(earlyDelay * frequency);
 
881
    State->DelayTap[1] = fastf2u((earlyDelay + lateDelay) * frequency);
461
882
}
462
883
 
463
884
// Update the early reflections gain and line coefficients.
494
915
    {
495
916
        length = (DECO_FRACTION * aluPow(DECO_MULTIPLIER, (ALfloat)index)) *
496
917
                 LATE_LINE_LENGTH[0] * (1.0f + (density * LATE_LINE_MULTIPLIER));
497
 
        State->DecoTap[index] = (ALuint)(length * frequency);
 
918
        State->DecoTap[index] = fastf2u(length * frequency);
498
919
    }
499
920
}
500
921
 
539
960
                                                    LATE_LINE_MULTIPLIER));
540
961
 
541
962
        // Calculate the delay offset for each cyclical delay line.
542
 
        State->Late.Offset[index] = (ALuint)(length * frequency);
 
963
        State->Late.Offset[index] = fastf2u(length * frequency);
543
964
 
544
965
        // Calculate the gain (coefficient) for each cyclical line.
545
966
        State->Late.Coeff[index] = CalcDecayCoeff(length, decayTime);
560
981
static ALvoid UpdateEchoLine(ALfloat reverbGain, ALfloat lateGain, ALfloat echoTime, ALfloat decayTime, ALfloat diffusion, ALfloat echoDepth, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State)
561
982
{
562
983
    // Update the offset and coefficient for the echo delay line.
563
 
    State->Echo.Offset = (ALuint)(echoTime * frequency);
 
984
    State->Echo.Offset = fastf2u(echoTime * frequency);
564
985
 
565
986
    // Calculate the decay coefficient for the echo line.
566
987
    State->Echo.Coeff = CalcDecayCoeff(echoTime, decayTime);
589
1010
}
590
1011
 
591
1012
// Update the early and late 3D panning gains.
592
 
static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALverbState *State)
 
1013
static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALverbState *State)
593
1014
{
594
1015
    ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1],
595
1016
                            ReflectionsPan[2] };
596
1017
    ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
597
1018
                           LateReverbPan[2] };
598
 
    const ALfloat *speakerGain;
 
1019
    const ALfloat *ChannelGain;
 
1020
    ALfloat ambientGain;
599
1021
    ALfloat dirGain;
600
1022
    ALfloat length;
601
1023
    ALuint index;
602
1024
    ALint pos;
603
1025
 
 
1026
    Gain *= ReverbBoost;
 
1027
 
 
1028
    // Attenuate non-directional reverb according to the number of channels
 
1029
    ambientGain = aluSqrt(2.0f/Device->NumChan);
 
1030
 
604
1031
    // Calculate the 3D-panning gains for the early reflections and late
605
1032
    // reverb.
606
1033
    length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
627
1054
     * panning direction.
628
1055
     */
629
1056
    pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]);
630
 
    speakerGain = &Device->PanningLUT[MAXCHANNELS * pos];
 
1057
    ChannelGain = Device->PanningLUT[pos];
631
1058
    dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2]));
632
1059
 
633
1060
    for(index = 0;index < MAXCHANNELS;index++)
634
1061
        State->Early.PanGain[index] = 0.0f;
635
1062
    for(index = 0;index < Device->NumChan;index++)
636
1063
    {
637
 
        Channel chan = Device->Speaker2Chan[index];
638
 
        State->Early.PanGain[chan] = 1.0 + (speakerGain[chan]-1.0)*dirGain;
 
1064
        enum Channel chan = Device->Speaker2Chan[index];
 
1065
        State->Early.PanGain[chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * Gain;
639
1066
    }
640
1067
 
641
1068
 
642
1069
    pos = aluCart2LUTpos(latePan[2], latePan[0]);
643
 
    speakerGain = &Device->PanningLUT[MAXCHANNELS * pos];
 
1070
    ChannelGain = Device->PanningLUT[pos];
644
1071
    dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2]));
645
1072
 
646
1073
    for(index = 0;index < MAXCHANNELS;index++)
647
1074
         State->Late.PanGain[index] = 0.0f;
648
1075
    for(index = 0;index < Device->NumChan;index++)
649
1076
    {
650
 
        Channel chan = Device->Speaker2Chan[index];
651
 
        State->Late.PanGain[chan] = 1.0 + (speakerGain[chan]-1.0)*dirGain;
652
 
    }
653
 
}
654
 
 
655
 
// Basic delay line input/output routines.
656
 
static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
657
 
{
658
 
    return Delay->Line[offset&Delay->Mask];
659
 
}
660
 
 
661
 
static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
662
 
{
663
 
    Delay->Line[offset&Delay->Mask] = in;
664
 
}
665
 
 
666
 
// Attenuated delay line output routine.
667
 
static __inline ALfloat AttenuatedDelayLineOut(DelayLine *Delay, ALuint offset, ALfloat coeff)
668
 
{
669
 
    return coeff * Delay->Line[offset&Delay->Mask];
670
 
}
671
 
 
672
 
// Basic attenuated all-pass input/output routine.
673
 
static __inline ALfloat AllpassInOut(DelayLine *Delay, ALuint outOffset, ALuint inOffset, ALfloat in, ALfloat feedCoeff, ALfloat coeff)
674
 
{
675
 
    ALfloat out, feed;
676
 
 
677
 
    out = DelayLineOut(Delay, outOffset);
678
 
    feed = feedCoeff * in;
679
 
    DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in);
680
 
 
681
 
    // The time-based attenuation is only applied to the delay output to
682
 
    // keep it from affecting the feed-back path (which is already controlled
683
 
    // by the all-pass feed coefficient).
684
 
    return (coeff * out) - feed;
685
 
}
686
 
 
687
 
// Given an input sample, this function produces modulation for the late
688
 
// reverb.
689
 
static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in)
690
 
{
691
 
    ALfloat sinus, frac;
692
 
    ALuint offset;
693
 
    ALfloat out0, out1;
694
 
 
695
 
    // Calculate the sinus rythm (dependent on modulation time and the
696
 
    // sampling rate).  The center of the sinus is moved to reduce the delay
697
 
    // of the effect when the time or depth are low.
698
 
    sinus = 1.0f - cos(2.0f * M_PI * State->Mod.Index / State->Mod.Range);
699
 
 
700
 
    // The depth determines the range over which to read the input samples
701
 
    // from, so it must be filtered to reduce the distortion caused by even
702
 
    // small parameter changes.
703
 
    State->Mod.Filter = lerp(State->Mod.Filter, State->Mod.Depth,
704
 
                             State->Mod.Coeff);
705
 
 
706
 
    // Calculate the read offset and fraction between it and the next sample.
707
 
    frac   = (1.0f + (State->Mod.Filter * sinus));
708
 
    offset = (ALuint)frac;
709
 
    frac  -= offset;
710
 
 
711
 
    // Get the two samples crossed by the offset, and feed the delay line
712
 
    // with the next input sample.
713
 
    out0 = DelayLineOut(&State->Mod.Delay, State->Offset - offset);
714
 
    out1 = DelayLineOut(&State->Mod.Delay, State->Offset - offset - 1);
715
 
    DelayLineIn(&State->Mod.Delay, State->Offset, in);
716
 
 
717
 
    // Step the modulation index forward, keeping it bound to its range.
718
 
    State->Mod.Index = (State->Mod.Index + 1) % State->Mod.Range;
719
 
 
720
 
    // The output is obtained by linearly interpolating the two samples that
721
 
    // were acquired above.
722
 
    return lerp(out0, out1, frac);
723
 
}
724
 
 
725
 
// Delay line output routine for early reflections.
726
 
static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
727
 
{
728
 
    return AttenuatedDelayLineOut(&State->Early.Delay[index],
729
 
                                  State->Offset - State->Early.Offset[index],
730
 
                                  State->Early.Coeff[index]);
731
 
}
732
 
 
733
 
// Given an input sample, this function produces four-channel output for the
734
 
// early reflections.
735
 
static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *out)
736
 
{
737
 
    ALfloat d[4], v, f[4];
738
 
 
739
 
    // Obtain the decayed results of each early delay line.
740
 
    d[0] = EarlyDelayLineOut(State, 0);
741
 
    d[1] = EarlyDelayLineOut(State, 1);
742
 
    d[2] = EarlyDelayLineOut(State, 2);
743
 
    d[3] = EarlyDelayLineOut(State, 3);
744
 
 
745
 
    /* The following uses a lossless scattering junction from waveguide
746
 
     * theory.  It actually amounts to a householder mixing matrix, which
747
 
     * will produce a maximally diffuse response, and means this can probably
748
 
     * be considered a simple feed-back delay network (FDN).
749
 
     *          N
750
 
     *         ---
751
 
     *         \
752
 
     * v = 2/N /   d_i
753
 
     *         ---
754
 
     *         i=1
755
 
     */
756
 
    v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
757
 
    // The junction is loaded with the input here.
758
 
    v += in;
759
 
 
760
 
    // Calculate the feed values for the delay lines.
761
 
    f[0] = v - d[0];
762
 
    f[1] = v - d[1];
763
 
    f[2] = v - d[2];
764
 
    f[3] = v - d[3];
765
 
 
766
 
    // Re-feed the delay lines.
767
 
    DelayLineIn(&State->Early.Delay[0], State->Offset, f[0]);
768
 
    DelayLineIn(&State->Early.Delay[1], State->Offset, f[1]);
769
 
    DelayLineIn(&State->Early.Delay[2], State->Offset, f[2]);
770
 
    DelayLineIn(&State->Early.Delay[3], State->Offset, f[3]);
771
 
 
772
 
    // Output the results of the junction for all four channels.
773
 
    out[0] = State->Early.Gain * f[0];
774
 
    out[1] = State->Early.Gain * f[1];
775
 
    out[2] = State->Early.Gain * f[2];
776
 
    out[3] = State->Early.Gain * f[3];
777
 
}
778
 
 
779
 
// All-pass input/output routine for late reverb.
780
 
static __inline ALfloat LateAllPassInOut(ALverbState *State, ALuint index, ALfloat in)
781
 
{
782
 
    return AllpassInOut(&State->Late.ApDelay[index],
783
 
                        State->Offset - State->Late.ApOffset[index],
784
 
                        State->Offset, in, State->Late.ApFeedCoeff,
785
 
                        State->Late.ApCoeff[index]);
786
 
}
787
 
 
788
 
// Delay line output routine for late reverb.
789
 
static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
790
 
{
791
 
    return AttenuatedDelayLineOut(&State->Late.Delay[index],
792
 
                                  State->Offset - State->Late.Offset[index],
793
 
                                  State->Late.Coeff[index]);
794
 
}
795
 
 
796
 
// Low-pass filter input/output routine for late reverb.
797
 
static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
798
 
{
799
 
    in = lerp(in, State->Late.LpSample[index], State->Late.LpCoeff[index]);
800
 
    State->Late.LpSample[index] = in;
801
 
    return in;
802
 
}
803
 
 
804
 
// Given four decorrelated input samples, this function produces four-channel
805
 
// output for the late reverb.
806
 
static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out)
807
 
{
808
 
    ALfloat d[4], f[4];
809
 
 
810
 
    // Obtain the decayed results of the cyclical delay lines, and add the
811
 
    // corresponding input channels.  Then pass the results through the
812
 
    // low-pass filters.
813
 
 
814
 
    // This is where the feed-back cycles from line 0 to 1 to 3 to 2 and back
815
 
    // to 0.
816
 
    d[0] = LateLowPassInOut(State, 2, in[2] + LateDelayLineOut(State, 2));
817
 
    d[1] = LateLowPassInOut(State, 0, in[0] + LateDelayLineOut(State, 0));
818
 
    d[2] = LateLowPassInOut(State, 3, in[3] + LateDelayLineOut(State, 3));
819
 
    d[3] = LateLowPassInOut(State, 1, in[1] + LateDelayLineOut(State, 1));
820
 
 
821
 
    // To help increase diffusion, run each line through an all-pass filter.
822
 
    // When there is no diffusion, the shortest all-pass filter will feed the
823
 
    // shortest delay line.
824
 
    d[0] = LateAllPassInOut(State, 0, d[0]);
825
 
    d[1] = LateAllPassInOut(State, 1, d[1]);
826
 
    d[2] = LateAllPassInOut(State, 2, d[2]);
827
 
    d[3] = LateAllPassInOut(State, 3, d[3]);
828
 
 
829
 
    /* Late reverb is done with a modified feed-back delay network (FDN)
830
 
     * topology.  Four input lines are each fed through their own all-pass
831
 
     * filter and then into the mixing matrix.  The four outputs of the
832
 
     * mixing matrix are then cycled back to the inputs.  Each output feeds
833
 
     * a different input to form a circlular feed cycle.
834
 
     *
835
 
     * The mixing matrix used is a 4D skew-symmetric rotation matrix derived
836
 
     * using a single unitary rotational parameter:
837
 
     *
838
 
     *  [  d,  a,  b,  c ]          1 = a^2 + b^2 + c^2 + d^2
839
 
     *  [ -a,  d,  c, -b ]
840
 
     *  [ -b, -c,  d,  a ]
841
 
     *  [ -c,  b, -a,  d ]
842
 
     *
843
 
     * The rotation is constructed from the effect's diffusion parameter,
844
 
     * yielding:  1 = x^2 + 3 y^2; where a, b, and c are the coefficient y
845
 
     * with differing signs, and d is the coefficient x.  The matrix is thus:
846
 
     *
847
 
     *  [  x,  y, -y,  y ]          n = sqrt(matrix_order - 1)
848
 
     *  [ -y,  x,  y,  y ]          t = diffusion_parameter * atan(n)
849
 
     *  [  y, -y,  x,  y ]          x = cos(t)
850
 
     *  [ -y, -y, -y,  x ]          y = sin(t) / n
851
 
     *
852
 
     * To reduce the number of multiplies, the x coefficient is applied with
853
 
     * the cyclical delay line coefficients.  Thus only the y coefficient is
854
 
     * applied when mixing, and is modified to be:  y / x.
855
 
     */
856
 
    f[0] = d[0] + (State->Late.MixCoeff * (         d[1] + -d[2] + d[3]));
857
 
    f[1] = d[1] + (State->Late.MixCoeff * (-d[0]         +  d[2] + d[3]));
858
 
    f[2] = d[2] + (State->Late.MixCoeff * ( d[0] + -d[1]         + d[3]));
859
 
    f[3] = d[3] + (State->Late.MixCoeff * (-d[0] + -d[1] + -d[2]       ));
860
 
 
861
 
    // Output the results of the matrix for all four channels, attenuated by
862
 
    // the late reverb gain (which is attenuated by the 'x' mix coefficient).
863
 
    out[0] = State->Late.Gain * f[0];
864
 
    out[1] = State->Late.Gain * f[1];
865
 
    out[2] = State->Late.Gain * f[2];
866
 
    out[3] = State->Late.Gain * f[3];
867
 
 
868
 
    // Re-feed the cyclical delay lines.
869
 
    DelayLineIn(&State->Late.Delay[0], State->Offset, f[0]);
870
 
    DelayLineIn(&State->Late.Delay[1], State->Offset, f[1]);
871
 
    DelayLineIn(&State->Late.Delay[2], State->Offset, f[2]);
872
 
    DelayLineIn(&State->Late.Delay[3], State->Offset, f[3]);
873
 
}
874
 
 
875
 
// Given an input sample, this function mixes echo into the four-channel late
876
 
// reverb.
877
 
static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *late)
878
 
{
879
 
    ALfloat out, feed;
880
 
 
881
 
    // Get the latest attenuated echo sample for output.
882
 
    feed = AttenuatedDelayLineOut(&State->Echo.Delay,
883
 
                                  State->Offset - State->Echo.Offset,
884
 
                                  State->Echo.Coeff);
885
 
 
886
 
    // Mix the output into the late reverb channels.
887
 
    out = State->Echo.MixCoeff[0] * feed;
888
 
    late[0] = (State->Echo.MixCoeff[1] * late[0]) + out;
889
 
    late[1] = (State->Echo.MixCoeff[1] * late[1]) + out;
890
 
    late[2] = (State->Echo.MixCoeff[1] * late[2]) + out;
891
 
    late[3] = (State->Echo.MixCoeff[1] * late[3]) + out;
892
 
 
893
 
    // Mix the energy-attenuated input with the output and pass it through
894
 
    // the echo low-pass filter.
895
 
    feed += State->Echo.DensityGain * in;
896
 
    feed = lerp(feed, State->Echo.LpSample, State->Echo.LpCoeff);
897
 
    State->Echo.LpSample = feed;
898
 
 
899
 
    // Then the echo all-pass filter.
900
 
    feed = AllpassInOut(&State->Echo.ApDelay,
901
 
                        State->Offset - State->Echo.ApOffset,
902
 
                        State->Offset, feed, State->Echo.ApFeedCoeff,
903
 
                        State->Echo.ApCoeff);
904
 
 
905
 
    // Feed the delay with the mixed and filtered sample.
906
 
    DelayLineIn(&State->Echo.Delay, State->Offset, feed);
907
 
}
908
 
 
909
 
// Perform the non-EAX reverb pass on a given input sample, resulting in
910
 
// four-channel output.
911
 
static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late)
912
 
{
913
 
    ALfloat feed, taps[4];
914
 
 
915
 
    // Low-pass filter the incoming sample.
916
 
    in = lpFilter2P(&State->LpFilter, 0, in);
917
 
 
918
 
    // Feed the initial delay line.
919
 
    DelayLineIn(&State->Delay, State->Offset, in);
920
 
 
921
 
    // Calculate the early reflection from the first delay tap.
922
 
    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
923
 
    EarlyReflection(State, in, early);
924
 
 
925
 
    // Feed the decorrelator from the energy-attenuated output of the second
926
 
    // delay tap.
927
 
    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
928
 
    feed = in * State->Late.DensityGain;
929
 
    DelayLineIn(&State->Decorrelator, State->Offset, feed);
930
 
 
931
 
    // Calculate the late reverb from the decorrelator taps.
932
 
    taps[0] = feed;
933
 
    taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
934
 
    taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
935
 
    taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
936
 
    LateReverb(State, taps, late);
937
 
 
938
 
    // Step all delays forward one sample.
939
 
    State->Offset++;
940
 
}
941
 
 
942
 
// Perform the EAX reverb pass on a given input sample, resulting in four-
943
 
// channel output.
944
 
static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late)
945
 
{
946
 
    ALfloat feed, taps[4];
947
 
 
948
 
    // Low-pass filter the incoming sample.
949
 
    in = lpFilter2P(&State->LpFilter, 0, in);
950
 
 
951
 
    // Perform any modulation on the input.
952
 
    in = EAXModulation(State, in);
953
 
 
954
 
    // Feed the initial delay line.
955
 
    DelayLineIn(&State->Delay, State->Offset, in);
956
 
 
957
 
    // Calculate the early reflection from the first delay tap.
958
 
    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
959
 
    EarlyReflection(State, in, early);
960
 
 
961
 
    // Feed the decorrelator from the energy-attenuated output of the second
962
 
    // delay tap.
963
 
    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
964
 
    feed = in * State->Late.DensityGain;
965
 
    DelayLineIn(&State->Decorrelator, State->Offset, feed);
966
 
 
967
 
    // Calculate the late reverb from the decorrelator taps.
968
 
    taps[0] = feed;
969
 
    taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
970
 
    taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
971
 
    taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
972
 
    LateReverb(State, taps, late);
973
 
 
974
 
    // Calculate and mix in any echo.
975
 
    EAXEcho(State, in, late);
976
 
 
977
 
    // Step all delays forward one sample.
978
 
    State->Offset++;
 
1077
        enum Channel chan = Device->Speaker2Chan[index];
 
1078
        State->Late.PanGain[chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * Gain;
 
1079
    }
 
1080
}
 
1081
 
 
1082
// This updates the EAX reverb state.  This is called any time the EAX reverb
 
1083
// effect is loaded into a slot.
 
1084
static ALvoid ReverbUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot)
 
1085
{
 
1086
    ALverbState *State = (ALverbState*)effect;
 
1087
    ALuint frequency = Device->Frequency;
 
1088
    ALboolean isEAX = AL_FALSE;
 
1089
    ALfloat cw, x, y, hfRatio;
 
1090
 
 
1091
    if(Slot->effect.type == AL_EFFECT_EAXREVERB && !EmulateEAXReverb)
 
1092
    {
 
1093
        State->state.Process = EAXVerbProcess;
 
1094
        isEAX = AL_TRUE;
 
1095
    }
 
1096
    else if(Slot->effect.type == AL_EFFECT_REVERB || EmulateEAXReverb)
 
1097
    {
 
1098
        State->state.Process = VerbProcess;
 
1099
        isEAX = AL_FALSE;
 
1100
    }
 
1101
 
 
1102
    // Calculate the master low-pass filter (from the master effect HF gain).
 
1103
    if(isEAX) cw = CalcI3DL2HFreq(Slot->effect.Reverb.HFReference, frequency);
 
1104
    else cw = CalcI3DL2HFreq(LOWPASSFREQREF, frequency);
 
1105
    // This is done with 2 chained 1-pole filters, so no need to square g.
 
1106
    State->LpFilter.coeff = lpCoeffCalc(Slot->effect.Reverb.GainHF, cw);
 
1107
 
 
1108
    if(isEAX)
 
1109
    {
 
1110
        // Update the modulator line.
 
1111
        UpdateModulator(Slot->effect.Reverb.ModulationTime,
 
1112
                        Slot->effect.Reverb.ModulationDepth,
 
1113
                        frequency, State);
 
1114
    }
 
1115
 
 
1116
    // Update the initial effect delay.
 
1117
    UpdateDelayLine(Slot->effect.Reverb.ReflectionsDelay,
 
1118
                    Slot->effect.Reverb.LateReverbDelay,
 
1119
                    frequency, State);
 
1120
 
 
1121
    // Update the early lines.
 
1122
    UpdateEarlyLines(Slot->effect.Reverb.Gain,
 
1123
                     Slot->effect.Reverb.ReflectionsGain,
 
1124
                     Slot->effect.Reverb.LateReverbDelay, State);
 
1125
 
 
1126
    // Update the decorrelator.
 
1127
    UpdateDecorrelator(Slot->effect.Reverb.Density, frequency, State);
 
1128
 
 
1129
    // Get the mixing matrix coefficients (x and y).
 
1130
    CalcMatrixCoeffs(Slot->effect.Reverb.Diffusion, &x, &y);
 
1131
    // Then divide x into y to simplify the matrix calculation.
 
1132
    State->Late.MixCoeff = y / x;
 
1133
 
 
1134
    // If the HF limit parameter is flagged, calculate an appropriate limit
 
1135
    // based on the air absorption parameter.
 
1136
    hfRatio = Slot->effect.Reverb.DecayHFRatio;
 
1137
    if(Slot->effect.Reverb.DecayHFLimit &&
 
1138
       Slot->effect.Reverb.AirAbsorptionGainHF < 1.0f)
 
1139
        hfRatio = CalcLimitedHfRatio(hfRatio,
 
1140
                                     Slot->effect.Reverb.AirAbsorptionGainHF,
 
1141
                                     Slot->effect.Reverb.DecayTime);
 
1142
 
 
1143
    // Update the late lines.
 
1144
    UpdateLateLines(Slot->effect.Reverb.Gain, Slot->effect.Reverb.LateReverbGain,
 
1145
                    x, Slot->effect.Reverb.Density, Slot->effect.Reverb.DecayTime,
 
1146
                    Slot->effect.Reverb.Diffusion, hfRatio, cw, frequency, State);
 
1147
 
 
1148
    if(isEAX)
 
1149
    {
 
1150
        // Update the echo line.
 
1151
        UpdateEchoLine(Slot->effect.Reverb.Gain, Slot->effect.Reverb.LateReverbGain,
 
1152
                       Slot->effect.Reverb.EchoTime, Slot->effect.Reverb.DecayTime,
 
1153
                       Slot->effect.Reverb.Diffusion, Slot->effect.Reverb.EchoDepth,
 
1154
                       hfRatio, cw, frequency, State);
 
1155
 
 
1156
        // Update early and late 3D panning.
 
1157
        Update3DPanning(Device, Slot->effect.Reverb.ReflectionsPan,
 
1158
                        Slot->effect.Reverb.LateReverbPan, Slot->Gain, State);
 
1159
    }
 
1160
    else
 
1161
    {
 
1162
        ALfloat gain = Slot->Gain;
 
1163
        ALuint index;
 
1164
 
 
1165
        /* Update channel gains */
 
1166
        gain *= aluSqrt(2.0f/Device->NumChan) * ReverbBoost;
 
1167
        for(index = 0;index < MAXCHANNELS;index++)
 
1168
             State->Gain[index] = 0.0f;
 
1169
        for(index = 0;index < Device->NumChan;index++)
 
1170
        {
 
1171
            enum Channel chan = Device->Speaker2Chan[index];
 
1172
            State->Gain[chan] = gain;
 
1173
        }
 
1174
    }
979
1175
}
980
1176
 
981
1177
// This destroys the reverb state.  It should be called only when the effect
982
1178
// slot has a different (or no) effect loaded over the reverb effect.
983
 
static ALvoid VerbDestroy(ALeffectState *effect)
 
1179
static ALvoid ReverbDestroy(ALeffectState *effect)
984
1180
{
985
1181
    ALverbState *State = (ALverbState*)effect;
986
1182
    if(State)
991
1187
    }
992
1188
}
993
1189
 
994
 
// This updates the device-dependant reverb state.  This is called on
995
 
// initialization and any time the device parameters (eg. playback frequency,
996
 
// or format) have been changed.
997
 
static ALboolean VerbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
998
 
{
999
 
    ALverbState *State = (ALverbState*)effect;
1000
 
    ALuint frequency = Device->Frequency;
1001
 
    ALuint index;
1002
 
 
1003
 
    // Allocate the delay lines.
1004
 
    if(!AllocLines(AL_FALSE, frequency, State))
1005
 
        return AL_FALSE;
1006
 
 
1007
 
    // The early reflection and late all-pass filter line lengths are static,
1008
 
    // so their offsets only need to be calculated once.
1009
 
    for(index = 0;index < 4;index++)
1010
 
    {
1011
 
        State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] *
1012
 
                                              frequency);
1013
 
        State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] *
1014
 
                                               frequency);
1015
 
    }
1016
 
 
1017
 
    for(index = 0;index < MAXCHANNELS;index++)
1018
 
         State->Gain[index] = 0.0f;
1019
 
    for(index = 0;index < Device->NumChan;index++)
1020
 
    {
1021
 
        Channel chan = Device->Speaker2Chan[index];
1022
 
        State->Gain[chan] = 1.0f;
1023
 
    }
1024
 
 
1025
 
    return AL_TRUE;
1026
 
}
1027
 
 
1028
 
// This updates the device-dependant EAX reverb state.  This is called on
1029
 
// initialization and any time the device parameters (eg. playback frequency,
1030
 
// format) have been changed.
1031
 
static ALboolean EAXVerbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
1032
 
{
1033
 
    ALverbState *State = (ALverbState*)effect;
1034
 
    ALuint frequency = Device->Frequency, index;
1035
 
 
1036
 
    // Allocate the delay lines.
1037
 
    if(!AllocLines(AL_TRUE, frequency, State))
1038
 
        return AL_FALSE;
1039
 
 
1040
 
    // Calculate the modulation filter coefficient.  Notice that the exponent
1041
 
    // is calculated given the current sample rate.  This ensures that the
1042
 
    // resulting filter response over time is consistent across all sample
1043
 
    // rates.
1044
 
    State->Mod.Coeff = aluPow(MODULATION_FILTER_COEFF,
1045
 
                              MODULATION_FILTER_CONST / frequency);
1046
 
 
1047
 
    // The early reflection and late all-pass filter line lengths are static,
1048
 
    // so their offsets only need to be calculated once.
1049
 
    for(index = 0;index < 4;index++)
1050
 
    {
1051
 
        State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] *
1052
 
                                              frequency);
1053
 
        State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] *
1054
 
                                               frequency);
1055
 
    }
1056
 
 
1057
 
    // The echo all-pass filter line length is static, so its offset only
1058
 
    // needs to be calculated once.
1059
 
    State->Echo.ApOffset = (ALuint)(ECHO_ALLPASS_LENGTH * frequency);
1060
 
 
1061
 
    return AL_TRUE;
1062
 
}
1063
 
 
1064
 
// This updates the reverb state.  This is called any time the reverb effect
1065
 
// is loaded into a slot.
1066
 
static ALvoid VerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect)
1067
 
{
1068
 
    ALverbState *State = (ALverbState*)effect;
1069
 
    ALuint frequency = Context->Device->Frequency;
1070
 
    ALfloat cw, x, y, hfRatio;
1071
 
 
1072
 
    // Calculate the master low-pass filter (from the master effect HF gain).
1073
 
    cw = CalcI3DL2HFreq(Effect->Reverb.HFReference, frequency);
1074
 
    // This is done with 2 chained 1-pole filters, so no need to square g.
1075
 
    State->LpFilter.coeff = lpCoeffCalc(Effect->Reverb.GainHF, cw);
1076
 
 
1077
 
    // Update the initial effect delay.
1078
 
    UpdateDelayLine(Effect->Reverb.ReflectionsDelay,
1079
 
                    Effect->Reverb.LateReverbDelay, frequency, State);
1080
 
 
1081
 
    // Update the early lines.
1082
 
    UpdateEarlyLines(Effect->Reverb.Gain, Effect->Reverb.ReflectionsGain,
1083
 
                     Effect->Reverb.LateReverbDelay, State);
1084
 
 
1085
 
    // Update the decorrelator.
1086
 
    UpdateDecorrelator(Effect->Reverb.Density, frequency, State);
1087
 
 
1088
 
    // Get the mixing matrix coefficients (x and y).
1089
 
    CalcMatrixCoeffs(Effect->Reverb.Diffusion, &x, &y);
1090
 
    // Then divide x into y to simplify the matrix calculation.
1091
 
    State->Late.MixCoeff = y / x;
1092
 
 
1093
 
    // If the HF limit parameter is flagged, calculate an appropriate limit
1094
 
    // based on the air absorption parameter.
1095
 
    hfRatio = Effect->Reverb.DecayHFRatio;
1096
 
    if(Effect->Reverb.DecayHFLimit && Effect->Reverb.AirAbsorptionGainHF < 1.0f)
1097
 
        hfRatio = CalcLimitedHfRatio(hfRatio, Effect->Reverb.AirAbsorptionGainHF,
1098
 
                                     Effect->Reverb.DecayTime);
1099
 
 
1100
 
    // Update the late lines.
1101
 
    UpdateLateLines(Effect->Reverb.Gain, Effect->Reverb.LateReverbGain,
1102
 
                    x, Effect->Reverb.Density, Effect->Reverb.DecayTime,
1103
 
                    Effect->Reverb.Diffusion, hfRatio, cw, frequency, State);
1104
 
}
1105
 
 
1106
 
// This updates the EAX reverb state.  This is called any time the EAX reverb
1107
 
// effect is loaded into a slot.
1108
 
static ALvoid EAXVerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect)
1109
 
{
1110
 
    ALverbState *State = (ALverbState*)effect;
1111
 
    ALuint frequency = Context->Device->Frequency;
1112
 
    ALfloat cw, x, y, hfRatio;
1113
 
 
1114
 
    // Calculate the master low-pass filter (from the master effect HF gain).
1115
 
    cw = CalcI3DL2HFreq(Effect->Reverb.HFReference, frequency);
1116
 
    // This is done with 2 chained 1-pole filters, so no need to square g.
1117
 
    State->LpFilter.coeff = lpCoeffCalc(Effect->Reverb.GainHF, cw);
1118
 
 
1119
 
    // Update the modulator line.
1120
 
    UpdateModulator(Effect->Reverb.ModulationTime,
1121
 
                    Effect->Reverb.ModulationDepth, frequency, State);
1122
 
 
1123
 
    // Update the initial effect delay.
1124
 
    UpdateDelayLine(Effect->Reverb.ReflectionsDelay,
1125
 
                    Effect->Reverb.LateReverbDelay, frequency, State);
1126
 
 
1127
 
    // Update the early lines.
1128
 
    UpdateEarlyLines(Effect->Reverb.Gain, Effect->Reverb.ReflectionsGain,
1129
 
                     Effect->Reverb.LateReverbDelay, State);
1130
 
 
1131
 
    // Update the decorrelator.
1132
 
    UpdateDecorrelator(Effect->Reverb.Density, frequency, State);
1133
 
 
1134
 
    // Get the mixing matrix coefficients (x and y).
1135
 
    CalcMatrixCoeffs(Effect->Reverb.Diffusion, &x, &y);
1136
 
    // Then divide x into y to simplify the matrix calculation.
1137
 
    State->Late.MixCoeff = y / x;
1138
 
 
1139
 
    // If the HF limit parameter is flagged, calculate an appropriate limit
1140
 
    // based on the air absorption parameter.
1141
 
    hfRatio = Effect->Reverb.DecayHFRatio;
1142
 
    if(Effect->Reverb.DecayHFLimit && Effect->Reverb.AirAbsorptionGainHF < 1.0f)
1143
 
        hfRatio = CalcLimitedHfRatio(hfRatio, Effect->Reverb.AirAbsorptionGainHF,
1144
 
                                     Effect->Reverb.DecayTime);
1145
 
 
1146
 
    // Update the late lines.
1147
 
    UpdateLateLines(Effect->Reverb.Gain, Effect->Reverb.LateReverbGain,
1148
 
                    x, Effect->Reverb.Density, Effect->Reverb.DecayTime,
1149
 
                    Effect->Reverb.Diffusion, hfRatio, cw, frequency, State);
1150
 
 
1151
 
    // Update the echo line.
1152
 
    UpdateEchoLine(Effect->Reverb.Gain, Effect->Reverb.LateReverbGain,
1153
 
                   Effect->Reverb.EchoTime, Effect->Reverb.DecayTime,
1154
 
                   Effect->Reverb.Diffusion, Effect->Reverb.EchoDepth,
1155
 
                   hfRatio, cw, frequency, State);
1156
 
 
1157
 
    // Update early and late 3D panning.
1158
 
    Update3DPanning(Context->Device, Effect->Reverb.ReflectionsPan,
1159
 
                    Effect->Reverb.LateReverbPan, State);
1160
 
}
1161
 
 
1162
 
// This processes the reverb state, given the input samples and an output
1163
 
// buffer.
1164
 
static ALvoid VerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
1165
 
{
1166
 
    ALverbState *State = (ALverbState*)effect;
1167
 
    ALuint index;
1168
 
    ALfloat early[4], late[4], out[4];
1169
 
    ALfloat gain = Slot->Gain;
1170
 
    const ALfloat *panGain = State->Gain;
1171
 
 
1172
 
    for(index = 0;index < SamplesToDo;index++)
1173
 
    {
1174
 
        // Process reverb for this sample.
1175
 
        VerbPass(State, SamplesIn[index], early, late);
1176
 
 
1177
 
        // Mix early reflections and late reverb.
1178
 
        out[0] = (early[0] + late[0]) * gain;
1179
 
        out[1] = (early[1] + late[1]) * gain;
1180
 
        out[2] = (early[2] + late[2]) * gain;
1181
 
        out[3] = (early[3] + late[3]) * gain;
1182
 
 
1183
 
        // Output the results.
1184
 
        SamplesOut[index][FRONT_LEFT]   += panGain[FRONT_LEFT]   * out[0];
1185
 
        SamplesOut[index][FRONT_RIGHT]  += panGain[FRONT_RIGHT]  * out[1];
1186
 
        SamplesOut[index][FRONT_CENTER] += panGain[FRONT_CENTER] * out[3];
1187
 
        SamplesOut[index][SIDE_LEFT]    += panGain[SIDE_LEFT]    * out[0];
1188
 
        SamplesOut[index][SIDE_RIGHT]   += panGain[SIDE_RIGHT]   * out[1];
1189
 
        SamplesOut[index][BACK_LEFT]    += panGain[BACK_LEFT]    * out[0];
1190
 
        SamplesOut[index][BACK_RIGHT]   += panGain[BACK_RIGHT]   * out[1];
1191
 
        SamplesOut[index][BACK_CENTER]  += panGain[BACK_CENTER]  * out[2];
1192
 
    }
1193
 
}
1194
 
 
1195
 
// This processes the EAX reverb state, given the input samples and an output
1196
 
// buffer.
1197
 
static ALvoid EAXVerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
1198
 
{
1199
 
    ALverbState *State = (ALverbState*)effect;
1200
 
    ALuint index;
1201
 
    ALfloat early[4], late[4];
1202
 
    ALfloat gain = Slot->Gain;
1203
 
 
1204
 
    for(index = 0;index < SamplesToDo;index++)
1205
 
    {
1206
 
        // Process reverb for this sample.
1207
 
        EAXVerbPass(State, SamplesIn[index], early, late);
1208
 
 
1209
 
        // Unfortunately, while the number and configuration of gains for
1210
 
        // panning adjust according to MAXCHANNELS, the output from the
1211
 
        // reverb engine is not so scalable.
1212
 
        SamplesOut[index][FRONT_LEFT] +=
1213
 
           (State->Early.PanGain[FRONT_LEFT]*early[0] +
1214
 
            State->Late.PanGain[FRONT_LEFT]*late[0]) * gain;
1215
 
        SamplesOut[index][FRONT_RIGHT] +=
1216
 
           (State->Early.PanGain[FRONT_RIGHT]*early[1] +
1217
 
            State->Late.PanGain[FRONT_RIGHT]*late[1]) * gain;
1218
 
        SamplesOut[index][FRONT_CENTER] +=
1219
 
           (State->Early.PanGain[FRONT_CENTER]*early[3] +
1220
 
            State->Late.PanGain[FRONT_CENTER]*late[3]) * gain;
1221
 
        SamplesOut[index][SIDE_LEFT] +=
1222
 
           (State->Early.PanGain[SIDE_LEFT]*early[0] +
1223
 
            State->Late.PanGain[SIDE_LEFT]*late[0]) * gain;
1224
 
        SamplesOut[index][SIDE_RIGHT] +=
1225
 
           (State->Early.PanGain[SIDE_RIGHT]*early[1] +
1226
 
            State->Late.PanGain[SIDE_RIGHT]*late[1]) * gain;
1227
 
        SamplesOut[index][BACK_LEFT] +=
1228
 
           (State->Early.PanGain[BACK_LEFT]*early[0] +
1229
 
            State->Late.PanGain[BACK_LEFT]*late[0]) * gain;
1230
 
        SamplesOut[index][BACK_RIGHT] +=
1231
 
           (State->Early.PanGain[BACK_RIGHT]*early[1] +
1232
 
            State->Late.PanGain[BACK_RIGHT]*late[1]) * gain;
1233
 
        SamplesOut[index][BACK_CENTER] +=
1234
 
           (State->Early.PanGain[BACK_CENTER]*early[2] +
1235
 
            State->Late.PanGain[BACK_CENTER]*late[2]) * gain;
1236
 
    }
1237
 
}
1238
 
 
1239
1190
// This creates the reverb state.  It should be called only when the reverb
1240
1191
// effect is loaded into a slot that doesn't already have a reverb effect.
1241
 
ALeffectState *VerbCreate(void)
 
1192
ALeffectState *ReverbCreate(void)
1242
1193
{
1243
1194
    ALverbState *State = NULL;
1244
1195
    ALuint index;
1247
1198
    if(!State)
1248
1199
        return NULL;
1249
1200
 
1250
 
    State->state.Destroy = VerbDestroy;
1251
 
    State->state.DeviceUpdate = VerbDeviceUpdate;
1252
 
    State->state.Update = VerbUpdate;
 
1201
    State->state.Destroy = ReverbDestroy;
 
1202
    State->state.DeviceUpdate = ReverbDeviceUpdate;
 
1203
    State->state.Update = ReverbUpdate;
1253
1204
    State->state.Process = VerbProcess;
1254
1205
 
1255
1206
    State->TotalSamples = 0;
1334
1285
 
1335
1286
    return &State->state;
1336
1287
}
1337
 
 
1338
 
ALeffectState *EAXVerbCreate(void)
1339
 
{
1340
 
    ALeffectState *State = VerbCreate();
1341
 
    if(State)
1342
 
    {
1343
 
        State->DeviceUpdate = EAXVerbDeviceUpdate;
1344
 
        State->Update = EAXVerbUpdate;
1345
 
        State->Process = EAXVerbProcess;
1346
 
    }
1347
 
    return State;
1348
 
}