2 * Reverb for the OpenAL cross platform audio library
3 * Copyright (C) 2008-2009 by Christopher Fitzgerald.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
29 #include "alAuxEffectSlot.h"
34 typedef struct DelayLine
36 // The delay lines use sample lengths that are powers of 2 to allow
37 // bitmasking instead of modulus wrapping.
42 typedef struct ALverbState
{
43 // Must be first in all effects!
46 // All delay lines are allocated as a single buffer to reduce memory
47 // fragmentation and management code.
48 ALfloat
*SampleBuffer
;
50 // Master effect low-pass filter (2 chained 1-pole filters).
53 // Initial effect delay and decorrelation.
55 // The tap points for the initial delay. First tap goes to early
56 // reflections, the last four decorrelate to late reverb.
59 // Total gain for early reflections.
61 // Early reflections are done with 4 delay lines.
65 // The gain for each output channel based on 3D panning.
66 ALfloat PanGain
[OUTPUTCHANNELS
];
69 // Total gain for late reverb.
71 // Attenuation to compensate for modal density and decay rate.
73 // The feed-back and feed-forward all-pass coefficient.
75 // Mixing matrix coefficient.
77 // Late reverb has 4 parallel all-pass filters.
81 // In addition to 4 cyclical delay lines.
85 // The cyclical delay lines are 1-pole low-pass filtered.
88 // The gain for each output channel based on 3D panning.
89 ALfloat PanGain
[OUTPUTCHANNELS
];
91 // The current read offset for all delay lines.
95 // All delay line lengths are specified in seconds.
97 // The lengths of the early delay lines.
98 static const ALfloat EARLY_LINE_LENGTH
[4] =
100 0.0015f
, 0.0045f
, 0.0135f
, 0.0405f
103 // The lengths of the late all-pass delay lines.
104 static const ALfloat ALLPASS_LINE_LENGTH
[4] =
106 0.0151f
, 0.0167f
, 0.0183f
, 0.0200f
,
109 // The lengths of the late cyclical delay lines.
110 static const ALfloat LATE_LINE_LENGTH
[4] =
112 0.0211f
, 0.0311f
, 0.0461f
, 0.0680f
115 // The late cyclical delay lines have a variable length dependent on the
116 // effect's density parameter (inverted for some reason) and this multiplier.
117 static const ALfloat LATE_LINE_MULTIPLIER
= 4.0f
;
119 // Input into the late reverb is decorrelated between four channels. Their
120 // timings are dependent on a fraction and multiplier. See VerbUpdate() for
121 // the calculations involved.
122 static const ALfloat DECO_FRACTION
= 1.0f
/ 32.0f
;
123 static const ALfloat DECO_MULTIPLIER
= 2.0f
;
125 // The maximum length of initial delay for the master delay line (a sum of
126 // the maximum early reflection and late reverb delays).
127 static const ALfloat MASTER_LINE_LENGTH
= 0.3f
+ 0.1f
;
129 // Find the next power of 2. Actually, this will return the input value if
130 // it is already a power of 2.
131 static ALuint
NextPowerOf2(ALuint value
)
147 static ALuint
CalcLengths(ALuint length
[13], ALuint frequency
)
149 ALuint samples
, totalLength
, index
;
151 // All line lengths are powers of 2, calculated from their lengths, with
152 // an additional sample in case of rounding errors.
154 // See VerbUpdate() for an explanation of the additional calculation
155 // added to the master line length.
157 ((MASTER_LINE_LENGTH
+
158 (LATE_LINE_LENGTH
[0] * (1.0f
+ LATE_LINE_MULTIPLIER
) *
159 (DECO_FRACTION
* ((DECO_MULTIPLIER
* DECO_MULTIPLIER
*
160 DECO_MULTIPLIER
) - 1.0f
)))) *
162 length
[0] = NextPowerOf2(samples
);
163 totalLength
= length
[0];
164 for(index
= 0;index
< 4;index
++)
166 samples
= (ALuint
)(EARLY_LINE_LENGTH
[index
] * frequency
) + 1;
167 length
[1 + index
] = NextPowerOf2(samples
);
168 totalLength
+= length
[1 + index
];
170 for(index
= 0;index
< 4;index
++)
172 samples
= (ALuint
)(ALLPASS_LINE_LENGTH
[index
] * frequency
) + 1;
173 length
[5 + index
] = NextPowerOf2(samples
);
174 totalLength
+= length
[5 + index
];
176 for(index
= 0;index
< 4;index
++)
178 samples
= (ALuint
)(LATE_LINE_LENGTH
[index
] *
179 (1.0f
+ LATE_LINE_MULTIPLIER
) * frequency
) + 1;
180 length
[9 + index
] = NextPowerOf2(samples
);
181 totalLength
+= length
[9 + index
];
187 // Basic delay line input/output routines.
188 static __inline ALfloat
DelayLineOut(DelayLine
*Delay
, ALuint offset
)
190 return Delay
->Line
[offset
&Delay
->Mask
];
193 static __inline ALvoid
DelayLineIn(DelayLine
*Delay
, ALuint offset
, ALfloat in
)
195 Delay
->Line
[offset
&Delay
->Mask
] = in
;
198 // Delay line output routine for early reflections.
199 static __inline ALfloat
EarlyDelayLineOut(ALverbState
*State
, ALuint index
)
201 return State
->Early
.Coeff
[index
] *
202 DelayLineOut(&State
->Early
.Delay
[index
],
203 State
->Offset
- State
->Early
.Offset
[index
]);
206 // Given an input sample, this function produces stereo output for early
208 static __inline ALvoid
EarlyReflection(ALverbState
*State
, ALfloat in
, ALfloat
*out
)
210 ALfloat d
[4], v
, f
[4];
212 // Obtain the decayed results of each early delay line.
213 d
[0] = EarlyDelayLineOut(State
, 0);
214 d
[1] = EarlyDelayLineOut(State
, 1);
215 d
[2] = EarlyDelayLineOut(State
, 2);
216 d
[3] = EarlyDelayLineOut(State
, 3);
218 /* The following uses a lossless scattering junction from waveguide
219 * theory. It actually amounts to a householder mixing matrix, which
220 * will produce a maximally diffuse response, and means this can probably
221 * be considered a simple feedback delay network (FDN).
229 v
= (d
[0] + d
[1] + d
[2] + d
[3]) * 0.5f
;
230 // The junction is loaded with the input here.
233 // Calculate the feed values for the delay lines.
239 // Refeed the delay lines.
240 DelayLineIn(&State
->Early
.Delay
[0], State
->Offset
, f
[0]);
241 DelayLineIn(&State
->Early
.Delay
[1], State
->Offset
, f
[1]);
242 DelayLineIn(&State
->Early
.Delay
[2], State
->Offset
, f
[2]);
243 DelayLineIn(&State
->Early
.Delay
[3], State
->Offset
, f
[3]);
245 // Output the results of the junction for all four lines.
246 out
[0] = State
->Early
.Gain
* f
[0];
247 out
[1] = State
->Early
.Gain
* f
[1];
248 out
[2] = State
->Early
.Gain
* f
[2];
249 out
[3] = State
->Early
.Gain
* f
[3];
252 // All-pass input/output routine for late reverb.
253 static __inline ALfloat
LateAllPassInOut(ALverbState
*State
, ALuint index
, ALfloat in
)
257 out
= State
->Late
.ApCoeff
[index
] *
258 DelayLineOut(&State
->Late
.ApDelay
[index
],
259 State
->Offset
- State
->Late
.ApOffset
[index
]);
260 out
-= (State
->Late
.ApFeedCoeff
* in
);
261 DelayLineIn(&State
->Late
.ApDelay
[index
], State
->Offset
,
262 (State
->Late
.ApFeedCoeff
* out
) + in
);
266 // Delay line output routine for late reverb.
267 static __inline ALfloat
LateDelayLineOut(ALverbState
*State
, ALuint index
)
269 return State
->Late
.Coeff
[index
] *
270 DelayLineOut(&State
->Late
.Delay
[index
],
271 State
->Offset
- State
->Late
.Offset
[index
]);
274 // Low-pass filter input/output routine for late reverb.
275 static __inline ALfloat
LateLowPassInOut(ALverbState
*State
, ALuint index
, ALfloat in
)
277 State
->Late
.LpSample
[index
] = in
+
278 ((State
->Late
.LpSample
[index
] - in
) * State
->Late
.LpCoeff
[index
]);
279 return State
->Late
.LpSample
[index
];
282 // Given four decorrelated input samples, this function produces stereo
283 // output for late reverb.
284 static __inline ALvoid
LateReverb(ALverbState
*State
, ALfloat
*in
, ALfloat
*out
)
288 // Obtain the decayed results of the cyclical delay lines, and add the
289 // corresponding input channels attenuated by density. Then pass the
290 // results through the low-pass filters.
291 d
[0] = LateLowPassInOut(State
, 0, (State
->Late
.DensityGain
* in
[0]) +
292 LateDelayLineOut(State
, 0));
293 d
[1] = LateLowPassInOut(State
, 1, (State
->Late
.DensityGain
* in
[1]) +
294 LateDelayLineOut(State
, 1));
295 d
[2] = LateLowPassInOut(State
, 2, (State
->Late
.DensityGain
* in
[2]) +
296 LateDelayLineOut(State
, 2));
297 d
[3] = LateLowPassInOut(State
, 3, (State
->Late
.DensityGain
* in
[3]) +
298 LateDelayLineOut(State
, 3));
300 // To help increase diffusion, run each line through an all-pass filter.
301 // The order of the all-pass filters is selected so that the shortest
302 // all-pass filter will feed the shortest delay line.
303 d
[0] = LateAllPassInOut(State
, 1, d
[0]);
304 d
[1] = LateAllPassInOut(State
, 3, d
[1]);
305 d
[2] = LateAllPassInOut(State
, 0, d
[2]);
306 d
[3] = LateAllPassInOut(State
, 2, d
[3]);
308 /* Late reverb is done with a modified feedback delay network (FDN)
309 * topology. Four input lines are each fed through their own all-pass
310 * filter and then into the mixing matrix. The four outputs of the
311 * mixing matrix are then cycled back to the inputs. Each output feeds
312 * a different input to form a circlular feed cycle.
314 * The mixing matrix used is a 4D skew-symmetric rotation matrix derived
315 * using a single unitary rotational parameter:
317 * [ d, a, b, c ] 1 = a^2 + b^2 + c^2 + d^2
322 * The rotation is constructed from the effect's diffusion parameter,
323 * yielding: 1 = x^2 + 3 y^2; where a, b, and c are the coefficient y
324 * with differing signs, and d is the coefficient x. The matrix is thus:
326 * [ x, y, -y, y ] x = 1 - (0.5 diffusion^3)
327 * [ -y, x, y, y ] y = sqrt((1 - x^2) / 3)
331 * To reduce the number of multiplies, the x coefficient is applied with
332 * the cyclical delay line coefficients. Thus only the y coefficient is
333 * applied when mixing, and is modified to be: y / x.
335 f
[0] = d
[0] + (State
->Late
.MixCoeff
* ( d
[1] - d
[2] + d
[3]));
336 f
[1] = d
[1] + (State
->Late
.MixCoeff
* (-d
[0] + d
[2] + d
[3]));
337 f
[2] = d
[2] + (State
->Late
.MixCoeff
* ( d
[0] - d
[1] + d
[3]));
338 f
[3] = d
[3] + (State
->Late
.MixCoeff
* (-d
[0] - d
[1] - d
[2]));
340 // Output the results of the matrix for all four cyclical delay lines,
341 // attenuated by the late reverb gain (which is attenuated by the 'x'
343 out
[0] = State
->Late
.Gain
* f
[0];
344 out
[1] = State
->Late
.Gain
* f
[1];
345 out
[2] = State
->Late
.Gain
* f
[2];
346 out
[3] = State
->Late
.Gain
* f
[3];
348 // The delay lines are fed circularly in the order:
349 // 0 -> 1 -> 3 -> 2 -> 0 ...
350 DelayLineIn(&State
->Late
.Delay
[0], State
->Offset
, f
[2]);
351 DelayLineIn(&State
->Late
.Delay
[1], State
->Offset
, f
[0]);
352 DelayLineIn(&State
->Late
.Delay
[2], State
->Offset
, f
[3]);
353 DelayLineIn(&State
->Late
.Delay
[3], State
->Offset
, f
[1]);
356 // Process the reverb for a given input sample, resulting in separate four-
357 // channel output for both early reflections and late reverb.
358 static __inline ALvoid
ReverbInOut(ALverbState
*State
, ALfloat in
, ALfloat
*early
, ALfloat
*late
)
362 // Low-pass filter the incoming sample.
363 in
= lpFilter2P(&State
->LpFilter
, 0, in
);
365 // Feed the initial delay line.
366 DelayLineIn(&State
->Delay
, State
->Offset
, in
);
368 // Calculate the early reflection from the first delay tap.
369 in
= DelayLineOut(&State
->Delay
, State
->Offset
- State
->Tap
[0]);
370 EarlyReflection(State
, in
, early
);
372 // Calculate the late reverb from the last four delay taps.
373 taps
[0] = DelayLineOut(&State
->Delay
, State
->Offset
- State
->Tap
[1]);
374 taps
[1] = DelayLineOut(&State
->Delay
, State
->Offset
- State
->Tap
[2]);
375 taps
[2] = DelayLineOut(&State
->Delay
, State
->Offset
- State
->Tap
[3]);
376 taps
[3] = DelayLineOut(&State
->Delay
, State
->Offset
- State
->Tap
[4]);
377 LateReverb(State
, taps
, late
);
379 // Step all delays forward one sample.
383 // This destroys the reverb state. It should be called only when the effect
384 // slot has a different (or no) effect loaded over the reverb effect.
385 ALvoid
VerbDestroy(ALeffectState
*effect
)
387 ALverbState
*State
= (ALverbState
*)effect
;
390 free(State
->SampleBuffer
);
391 State
->SampleBuffer
= NULL
;
396 // NOTE: Temp, remove later.
397 static __inline ALint
aluCart2LUTpos(ALfloat re
, ALfloat im
)
400 ALfloat denom
= aluFabs(re
) + aluFabs(im
);
402 pos
= (ALint
)(QUADRANT_NUM
*aluFabs(im
) / denom
+ 0.5);
405 pos
= 2 * QUADRANT_NUM
- pos
;
411 // This updates the device-dependant reverb state. This is called on
412 // initialization and any time the device parameters (eg. playback frequency,
413 // format) have been changed.
414 ALboolean
VerbDeviceUpdate(ALeffectState
*effect
, ALCdevice
*Device
)
416 ALverbState
*State
= (ALverbState
*)effect
;
417 ALuint length
[13], totalLength
;
420 totalLength
= CalcLengths(length
, Device
->Frequency
);
421 if(totalLength
!= State
->TotalLength
)
425 temp
= realloc(State
->SampleBuffer
, totalLength
* sizeof(ALfloat
));
428 alSetError(AL_OUT_OF_MEMORY
);
431 State
->TotalLength
= totalLength
;
432 State
->SampleBuffer
= temp
;
434 for(index
= 0; index
< totalLength
;index
++)
435 State
->SampleBuffer
[index
] = 0.0f
;
437 // All lines share a single sample buffer
438 State
->Delay
.Mask
= length
[0] - 1;
439 State
->Delay
.Line
= &State
->SampleBuffer
[0];
440 totalLength
= length
[0];
441 for(index
= 0;index
< 4;index
++)
443 State
->Early
.Delay
[index
].Mask
= length
[1 + index
] - 1;
444 State
->Early
.Delay
[index
].Line
= &State
->SampleBuffer
[totalLength
];
445 totalLength
+= length
[1 + index
];
447 for(index
= 0;index
< 4;index
++)
449 State
->Late
.ApDelay
[index
].Mask
= length
[5 + index
] - 1;
450 State
->Late
.ApDelay
[index
].Line
= &State
->SampleBuffer
[totalLength
];
451 totalLength
+= length
[5 + index
];
453 for(index
= 0;index
< 4;index
++)
455 State
->Late
.Delay
[index
].Mask
= length
[9 + index
] - 1;
456 State
->Late
.Delay
[index
].Line
= &State
->SampleBuffer
[totalLength
];
457 totalLength
+= length
[9 + index
];
461 for(index
= 0;index
< 4;index
++)
463 State
->Early
.Offset
[index
] = (ALuint
)(EARLY_LINE_LENGTH
[index
] *
465 State
->Late
.ApOffset
[index
] = (ALuint
)(ALLPASS_LINE_LENGTH
[index
] *
472 // This updates the reverb state. This is called any time the reverb effect
473 // is loaded into a slot.
474 ALvoid
VerbUpdate(ALeffectState
*effect
, ALCcontext
*Context
, const ALeffect
*Effect
)
476 ALverbState
*State
= (ALverbState
*)effect
;
478 ALfloat length
, mixCoeff
, cw
, g
, coeff
;
479 ALfloat hfRatio
= Effect
->Reverb
.DecayHFRatio
;
481 // Calculate the master low-pass filter (from the master effect HF gain).
482 cw
= cos(2.0 * M_PI
* Effect
->Reverb
.HFReference
/ Context
->Frequency
);
483 g
= __max(Effect
->Reverb
.GainHF
, 0.0001f
);
484 State
->LpFilter
.coeff
= 0.0f
;
485 if(g
< 0.9999f
) // 1-epsilon
486 State
->LpFilter
.coeff
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
488 // Calculate the initial delay taps.
489 length
= Effect
->Reverb
.ReflectionsDelay
;
490 State
->Tap
[0] = (ALuint
)(length
* Context
->Frequency
);
492 length
+= Effect
->Reverb
.LateReverbDelay
;
494 /* The four inputs to the late reverb are decorrelated to smooth the
495 * initial reverb and reduce harsh echos. The timings are calculated as
496 * multiples of a fraction of the smallest cyclical delay time. This
497 * result is then adjusted so that the first tap occurs immediately (all
498 * taps are reduced by the shortest fraction).
500 * offset[index] = ((FRACTION MULTIPLIER^index) - 1) delay
502 for(index
= 0;index
< 4;index
++)
504 length
+= LATE_LINE_LENGTH
[0] *
505 (1.0f
+ (Effect
->Reverb
.Density
* LATE_LINE_MULTIPLIER
)) *
506 (DECO_FRACTION
* (pow(DECO_MULTIPLIER
, (ALfloat
)index
) - 1.0f
));
507 State
->Tap
[1 + index
] = (ALuint
)(length
* Context
->Frequency
);
510 // Calculate the early reflections gain (from the master effect gain, and
511 // reflections gain parameters).
512 State
->Early
.Gain
= Effect
->Reverb
.Gain
* Effect
->Reverb
.ReflectionsGain
;
514 // Calculate the gain (coefficient) for each early delay line.
515 for(index
= 0;index
< 4;index
++)
516 State
->Early
.Coeff
[index
] = pow(10.0f
, EARLY_LINE_LENGTH
[index
] /
517 Effect
->Reverb
.LateReverbDelay
*
520 // Calculate the first mixing matrix coefficient (x).
521 mixCoeff
= 1.0f
- (0.5f
* pow(Effect
->Reverb
.Diffusion
, 3.0f
));
523 // Calculate the late reverb gain (from the master effect gain, and late
524 // reverb gain parameters). Since the output is tapped prior to the
525 // application of the delay line coefficients, this gain needs to be
526 // attenuated by the 'x' mix coefficient from above.
527 State
->Late
.Gain
= Effect
->Reverb
.Gain
* Effect
->Reverb
.LateReverbGain
* mixCoeff
;
529 /* To compensate for changes in modal density and decay time of the late
530 * reverb signal, the input is attenuated based on the maximal energy of
531 * the outgoing signal. This is calculated as the ratio between a
532 * reference value and the current approximation of energy for the output
535 * Reverb output matches exponential decay of the form Sum(a^n), where a
536 * is the attenuation coefficient, and n is the sample ranging from 0 to
537 * infinity. The signal energy can thus be approximated using the area
538 * under this curve, calculated as: 1 / (1 - a).
540 * The reference energy is calculated from a signal at the lowest (effect
541 * at 1.0) density with a decay time of one second.
543 * The coefficient is calculated as the average length of the cyclical
544 * delay lines. This produces a better result than calculating the gain
545 * for each line individually (most likely a side effect of diffusion).
547 * The final result is the square root of the ratio bound to a maximum
548 * value of 1 (no amplification).
550 length
= (LATE_LINE_LENGTH
[0] + LATE_LINE_LENGTH
[1] +
551 LATE_LINE_LENGTH
[2] + LATE_LINE_LENGTH
[3]);
552 g
= length
* (1.0f
+ LATE_LINE_MULTIPLIER
) * 0.25f
;
553 g
= pow(10.0f
, g
* -60.0f
/ 20.0f
);
554 g
= 1.0f
/ (1.0f
- (g
* g
));
555 length
*= 1.0f
+ (Effect
->Reverb
.Density
* LATE_LINE_MULTIPLIER
) * 0.25f
;
556 length
= pow(10.0f
, length
/ Effect
->Reverb
.DecayTime
* -60.0f
/ 20.0f
);
557 length
= 1.0f
/ (1.0f
- (length
* length
));
558 State
->Late
.DensityGain
= __min(aluSqrt(g
/ length
), 1.0f
);
560 // Calculate the all-pass feed-back and feed-forward coefficient.
561 State
->Late
.ApFeedCoeff
= 0.6f
* pow(Effect
->Reverb
.Diffusion
, 3.0f
);
563 // Calculate the mixing matrix coefficient (y / x).
564 g
= aluSqrt((1.0f
- (mixCoeff
* mixCoeff
)) / 3.0f
);
565 State
->Late
.MixCoeff
= g
/ mixCoeff
;
567 for(index
= 0;index
< 4;index
++)
569 // Calculate the gain (coefficient) for each all-pass line.
570 State
->Late
.ApCoeff
[index
] = pow(10.0f
, ALLPASS_LINE_LENGTH
[index
] /
571 Effect
->Reverb
.DecayTime
*
575 // If the HF limit parameter is flagged, calculate an appropriate limit
576 // based on the air absorption parameter.
577 if(Effect
->Reverb
.DecayHFLimit
&& Effect
->Reverb
.AirAbsorptionGainHF
< 1.0f
)
581 // For each of the cyclical delays, find the attenuation due to air
582 // absorption in dB (converting delay time to meters using the speed
583 // of sound). Then reversing the decay equation, solve for HF ratio.
584 // The delay length is cancelled out of the equation, so it can be
585 // calculated once for all lines.
586 limitRatio
= 1.0f
/ (log10(Effect
->Reverb
.AirAbsorptionGainHF
) *
587 SPEEDOFSOUNDMETRESPERSEC
*
588 Effect
->Reverb
.DecayTime
/ -60.0f
* 20.0f
);
589 // Need to limit the result to a minimum of 0.1, just like the HF
591 limitRatio
= __max(limitRatio
, 0.1f
);
593 // Using the limit calculated above, apply the upper bound to the
595 hfRatio
= __min(hfRatio
, limitRatio
);
598 // Calculate the low-pass filter frequency.
599 cw
= cos(2.0f
* M_PI
* Effect
->Reverb
.HFReference
/ Context
->Frequency
);
601 for(index
= 0;index
< 4;index
++)
603 // Calculate the length (in seconds) of each cyclical delay line.
604 length
= LATE_LINE_LENGTH
[index
] * (1.0f
+ (Effect
->Reverb
.Density
*
605 LATE_LINE_MULTIPLIER
));
606 // Calculate the delay offset for the cyclical delay lines.
607 State
->Late
.Offset
[index
] = (ALuint
)(length
* Context
->Frequency
);
609 // Calculate the gain (coefficient) for each cyclical line.
610 State
->Late
.Coeff
[index
] = pow(10.0f
, length
/ Effect
->Reverb
.DecayTime
*
613 // Eventually this should boost the high frequencies when the ratio
618 // Calculate the decay equation for each low-pass filter.
619 g
= pow(10.0f
, length
/ (Effect
->Reverb
.DecayTime
* hfRatio
) *
620 -60.0f
/ 20.0f
) / State
->Late
.Coeff
[index
];
624 // Calculate the gain (coefficient) for each low-pass filter.
625 if(g
< 0.9999f
) // 1-epsilon
626 coeff
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
628 // Very low decay times will produce minimal output, so apply an
629 // upper bound to the coefficient.
630 coeff
= __min(coeff
, 0.98f
);
632 State
->Late
.LpCoeff
[index
] = coeff
;
634 // Attenuate the cyclical line coefficients by the mixing coefficient
636 State
->Late
.Coeff
[index
] *= mixCoeff
;
639 // Calculate the 3D-panning gains for the early reflections and late
640 // reverb (for EAX mode).
642 ALfloat earlyPan
[3] = { Effect
->Reverb
.ReflectionsPan
[0], Effect
->Reverb
.ReflectionsPan
[1], Effect
->Reverb
.ReflectionsPan
[2] };
643 ALfloat latePan
[3] = { Effect
->Reverb
.LateReverbPan
[0], Effect
->Reverb
.LateReverbPan
[1], Effect
->Reverb
.LateReverbPan
[2] };
644 ALfloat
*speakerGain
, dirGain
, ambientGain
;
648 length
= earlyPan
[0]*earlyPan
[0] + earlyPan
[1]*earlyPan
[1] + earlyPan
[2]*earlyPan
[2];
651 length
= 1.0f
/ aluSqrt(length
);
652 earlyPan
[0] *= length
;
653 earlyPan
[1] *= length
;
654 earlyPan
[2] *= length
;
656 length
= latePan
[0]*latePan
[0] + latePan
[1]*latePan
[1] + latePan
[2]*latePan
[2];
659 length
= 1.0f
/ aluSqrt(length
);
660 latePan
[0] *= length
;
661 latePan
[1] *= length
;
662 latePan
[2] *= length
;
665 // This code applies directional reverb just like the mixer applies
666 // directional sources. It diffuses the sound toward all speakers
667 // as the magnitude of the panning vector drops, which is only an
668 // approximation of the expansion of sound across the speakers from
669 // the panning direction.
670 pos
= aluCart2LUTpos(earlyPan
[2], earlyPan
[0]);
671 speakerGain
= &Context
->PanningLUT
[OUTPUTCHANNELS
* pos
];
672 dirGain
= aluSqrt((earlyPan
[0] * earlyPan
[0]) + (earlyPan
[2] * earlyPan
[2]));
673 ambientGain
= (1.0 - dirGain
);
674 for(index
= 0;index
< OUTPUTCHANNELS
;index
++)
675 State
->Early
.PanGain
[index
] = dirGain
* speakerGain
[index
] + ambientGain
;
677 pos
= aluCart2LUTpos(latePan
[2], latePan
[0]);
678 speakerGain
= &Context
->PanningLUT
[OUTPUTCHANNELS
* pos
];
679 dirGain
= aluSqrt((latePan
[0] * latePan
[0]) + (latePan
[2] * latePan
[2]));
680 ambientGain
= (1.0 - dirGain
);
681 for(index
= 0;index
< OUTPUTCHANNELS
;index
++)
682 State
->Late
.PanGain
[index
] = dirGain
* speakerGain
[index
] + ambientGain
;
686 // This processes the reverb state, given the input samples and an output
688 ALvoid
VerbProcess(ALeffectState
*effect
, const ALeffectslot
*Slot
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[OUTPUTCHANNELS
])
690 ALverbState
*State
= (ALverbState
*)effect
;
692 ALfloat early
[4], late
[4], out
[4];
693 ALfloat gain
= Slot
->Gain
;
695 for(index
= 0;index
< SamplesToDo
;index
++)
697 // Process reverb for this sample.
698 ReverbInOut(State
, SamplesIn
[index
], early
, late
);
700 // Mix early reflections and late reverb.
701 out
[0] = (early
[0] + late
[0]) * gain
;
702 out
[1] = (early
[1] + late
[1]) * gain
;
703 out
[2] = (early
[2] + late
[2]) * gain
;
704 out
[3] = (early
[3] + late
[3]) * gain
;
706 // Output the results.
707 SamplesOut
[index
][FRONT_LEFT
] += out
[0];
708 SamplesOut
[index
][FRONT_RIGHT
] += out
[1];
709 SamplesOut
[index
][FRONT_CENTER
] += out
[3];
710 SamplesOut
[index
][SIDE_LEFT
] += out
[0];
711 SamplesOut
[index
][SIDE_RIGHT
] += out
[1];
712 SamplesOut
[index
][BACK_LEFT
] += out
[0];
713 SamplesOut
[index
][BACK_RIGHT
] += out
[1];
714 SamplesOut
[index
][BACK_CENTER
] += out
[2];
718 // This processes the EAX reverb state, given the input samples and an output
720 ALvoid
EAXVerbProcess(ALeffectState
*effect
, const ALeffectslot
*Slot
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[OUTPUTCHANNELS
])
722 ALverbState
*State
= (ALverbState
*)effect
;
724 ALfloat early
[4], late
[4];
725 ALfloat gain
= Slot
->Gain
;
727 for(index
= 0;index
< SamplesToDo
;index
++)
729 // Process reverb for this sample.
730 ReverbInOut(State
, SamplesIn
[index
], early
, late
);
732 // Unfortunately, while the number and configuration of gains for
733 // panning adjust according to OUTPUTCHANNELS, the output from the
734 // reverb engine is not so scalable.
735 SamplesOut
[index
][FRONT_LEFT
] +=
736 (State
->Early
.PanGain
[FRONT_LEFT
]*early
[0] +
737 State
->Late
.PanGain
[FRONT_LEFT
]*late
[0]) * gain
;
738 SamplesOut
[index
][FRONT_RIGHT
] +=
739 (State
->Early
.PanGain
[FRONT_RIGHT
]*early
[1] +
740 State
->Late
.PanGain
[FRONT_RIGHT
]*late
[1]) * gain
;
741 SamplesOut
[index
][FRONT_CENTER
] +=
742 (State
->Early
.PanGain
[FRONT_CENTER
]*early
[3] +
743 State
->Late
.PanGain
[FRONT_CENTER
]*late
[3]) * gain
;
744 SamplesOut
[index
][SIDE_LEFT
] +=
745 (State
->Early
.PanGain
[SIDE_LEFT
]*early
[0] +
746 State
->Late
.PanGain
[SIDE_LEFT
]*late
[0]) * gain
;
747 SamplesOut
[index
][SIDE_RIGHT
] +=
748 (State
->Early
.PanGain
[SIDE_RIGHT
]*early
[1] +
749 State
->Late
.PanGain
[SIDE_RIGHT
]*late
[1]) * gain
;
750 SamplesOut
[index
][BACK_LEFT
] +=
751 (State
->Early
.PanGain
[BACK_LEFT
]*early
[0] +
752 State
->Late
.PanGain
[BACK_LEFT
]*late
[0]) * gain
;
753 SamplesOut
[index
][BACK_RIGHT
] +=
754 (State
->Early
.PanGain
[BACK_RIGHT
]*early
[1] +
755 State
->Late
.PanGain
[BACK_RIGHT
]*late
[1]) * gain
;
756 SamplesOut
[index
][BACK_CENTER
] +=
757 (State
->Early
.PanGain
[BACK_CENTER
]*early
[2] +
758 State
->Late
.PanGain
[BACK_CENTER
]*late
[2]) * gain
;
762 // This creates the reverb state. It should be called only when the reverb
763 // effect is loaded into a slot that doesn't already have a reverb effect.
764 ALeffectState
*VerbCreate(void)
766 ALverbState
*State
= NULL
;
769 State
= malloc(sizeof(ALverbState
));
772 alSetError(AL_OUT_OF_MEMORY
);
776 State
->state
.Destroy
= VerbDestroy
;
777 State
->state
.DeviceUpdate
= VerbDeviceUpdate
;
778 State
->state
.Update
= VerbUpdate
;
779 State
->state
.Process
= VerbProcess
;
781 State
->TotalLength
= 0;
782 State
->SampleBuffer
= NULL
;
784 State
->LpFilter
.coeff
= 0.0f
;
785 State
->LpFilter
.history
[0] = 0.0f
;
786 State
->LpFilter
.history
[1] = 0.0f
;
787 State
->Delay
.Mask
= 0;
788 State
->Delay
.Line
= NULL
;
796 State
->Early
.Gain
= 0.0f
;
797 for(index
= 0;index
< 4;index
++)
799 State
->Early
.Coeff
[index
] = 0.0f
;
800 State
->Early
.Delay
[index
].Mask
= 0;
801 State
->Early
.Delay
[index
].Line
= NULL
;
802 State
->Early
.Offset
[index
] = 0;
805 State
->Late
.Gain
= 0.0f
;
806 State
->Late
.DensityGain
= 0.0f
;
807 State
->Late
.ApFeedCoeff
= 0.0f
;
808 State
->Late
.MixCoeff
= 0.0f
;
810 for(index
= 0;index
< 4;index
++)
812 State
->Late
.ApCoeff
[index
] = 0.0f
;
813 State
->Late
.ApDelay
[index
].Mask
= 0;
814 State
->Late
.ApDelay
[index
].Line
= NULL
;
815 State
->Late
.ApOffset
[index
] = 0;
817 State
->Late
.Coeff
[index
] = 0.0f
;
818 State
->Late
.Delay
[index
].Mask
= 0;
819 State
->Late
.Delay
[index
].Line
= NULL
;
820 State
->Late
.Offset
[index
] = 0;
822 State
->Late
.LpCoeff
[index
] = 0.0f
;
823 State
->Late
.LpSample
[index
] = 0.0f
;
826 // Panning is applied as an independent gain for each output channel.
827 for(index
= 0;index
< OUTPUTCHANNELS
;index
++)
829 State
->Early
.PanGain
[index
] = 0.0f
;
830 State
->Late
.PanGain
[index
] = 0.0f
;
834 return &State
->state
;
837 ALeffectState
*EAXVerbCreate(void)
839 ALeffectState
*State
= VerbCreate();
840 if(State
) State
->Process
= EAXVerbProcess
;