Small fixups
[openal-soft.git] / Alc / alcReverb.c
blob2cfe341e7ac5fe70104a231b77f05eb012f9b3af
1 /**
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
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
26 #include "AL/al.h"
27 #include "AL/alc.h"
28 #include "alMain.h"
29 #include "alAuxEffectSlot.h"
30 #include "alEffect.h"
31 #include "alError.h"
32 #include "alu.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.
38 ALuint Mask;
39 ALfloat *Line;
40 } DelayLine;
42 typedef struct ALverbState {
43 // Must be first in all effects!
44 ALeffectState state;
46 // All delay lines are allocated as a single buffer to reduce memory
47 // fragmentation and management code.
48 ALfloat *SampleBuffer;
49 ALuint TotalLength;
50 // Master effect low-pass filter (2 chained 1-pole filters).
51 FILTER LpFilter;
52 ALfloat LpHistory[2];
53 // Initial effect delay and decorrelation.
54 DelayLine Delay;
55 // The tap points for the initial delay. First tap goes to early
56 // reflections, the last four decorrelate to late reverb.
57 ALuint Tap[5];
58 struct {
59 // Total gain for early reflections.
60 ALfloat Gain;
61 // Early reflections are done with 4 delay lines.
62 ALfloat Coeff[4];
63 DelayLine Delay[4];
64 ALuint Offset[4];
65 // The gain for each output channel based on 3D panning.
66 ALfloat PanGain[OUTPUTCHANNELS];
67 } Early;
68 struct {
69 // Total gain for late reverb.
70 ALfloat Gain;
71 // Attenuation to compensate for modal density and decay rate.
72 ALfloat DensityGain;
73 // The feed-back and feed-forward all-pass coefficient.
74 ALfloat ApFeedCoeff;
75 // Mixing matrix coefficient.
76 ALfloat MixCoeff;
77 // Late reverb has 4 parallel all-pass filters.
78 ALfloat ApCoeff[4];
79 DelayLine ApDelay[4];
80 ALuint ApOffset[4];
81 // In addition to 4 cyclical delay lines.
82 ALfloat Coeff[4];
83 DelayLine Delay[4];
84 ALuint Offset[4];
85 // The cyclical delay lines are 1-pole low-pass filtered.
86 ALfloat LpCoeff[4];
87 ALfloat LpSample[4];
88 // The gain for each output channel based on 3D panning.
89 ALfloat PanGain[OUTPUTCHANNELS];
90 } Late;
91 // The current read offset for all delay lines.
92 ALuint Offset;
93 } ALverbState;
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)
133 ALuint powerOf2 = 1;
135 if(value)
137 value--;
138 while(value)
140 value >>= 1;
141 powerOf2 <<= 1;
144 return powerOf2;
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.
156 samples = (ALuint)
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)))) *
161 frequency) + 1;
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];
184 return totalLength;
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
207 // reflections.
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).
223 * ---
225 * v = 2/N / d_i
226 * ---
227 * i=1
229 v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
230 // The junction is loaded with the input here.
231 v += in;
233 // Calculate the feed values for the delay lines.
234 f[0] = v - d[0];
235 f[1] = v - d[1];
236 f[2] = v - d[2];
237 f[3] = v - d[3];
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)
255 ALfloat out;
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);
263 return out;
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)
286 ALfloat d[4], f[4];
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
318 * [ -a, d, c, -b ]
319 * [ -b, -c, d, a ]
320 * [ -c, b, -a, d ]
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)
328 * [ y, -y, x, y ]
329 * [ -y, -y, -y, x ]
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'
342 // mix coefficient).
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)
360 ALfloat taps[4];
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.
380 State->Offset++;
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;
388 if(State)
390 free(State->SampleBuffer);
391 State->SampleBuffer = NULL;
392 free(State);
396 // NOTE: Temp, remove later.
397 static __inline ALint aluCart2LUTpos(ALfloat re, ALfloat im)
399 ALint pos = 0;
400 ALfloat denom = aluFabs(re) + aluFabs(im);
401 if(denom > 0.0f)
402 pos = (ALint)(QUADRANT_NUM*aluFabs(im) / denom + 0.5);
404 if(re < 0.0)
405 pos = 2 * QUADRANT_NUM - pos;
406 if(im < 0.0)
407 pos = LUT_NUM - pos;
408 return pos%LUT_NUM;
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;
418 ALuint index;
420 totalLength = CalcLengths(length, Device->Frequency);
421 if(totalLength != State->TotalLength)
423 void *temp;
425 temp = realloc(State->SampleBuffer, totalLength * sizeof(ALfloat));
426 if(!temp)
428 alSetError(AL_OUT_OF_MEMORY);
429 return AL_FALSE;
431 State->TotalLength = totalLength;
432 State->SampleBuffer = temp;
434 // All lines share a single sample buffer
435 State->Delay.Mask = length[0] - 1;
436 State->Delay.Line = &State->SampleBuffer[0];
437 totalLength = length[0];
438 for(index = 0;index < 4;index++)
440 State->Early.Delay[index].Mask = length[1 + index] - 1;
441 State->Early.Delay[index].Line = &State->SampleBuffer[totalLength];
442 totalLength += length[1 + index];
444 for(index = 0;index < 4;index++)
446 State->Late.ApDelay[index].Mask = length[5 + index] - 1;
447 State->Late.ApDelay[index].Line = &State->SampleBuffer[totalLength];
448 totalLength += length[5 + index];
450 for(index = 0;index < 4;index++)
452 State->Late.Delay[index].Mask = length[9 + index] - 1;
453 State->Late.Delay[index].Line = &State->SampleBuffer[totalLength];
454 totalLength += length[9 + index];
458 for(index = 0;index < 4;index++)
460 State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] *
461 Device->Frequency);
462 State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] *
463 Device->Frequency);
466 for(index = 0;index < State->TotalLength;index++)
467 State->SampleBuffer[index] = 0.0f;
469 return AL_TRUE;
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;
477 ALuint frequency = Context->Device->Frequency;
478 ALuint index;
479 ALfloat length, mixCoeff, cw, g, coeff;
480 ALfloat hfRatio = Effect->Reverb.DecayHFRatio;
482 // Calculate the master low-pass filter (from the master effect HF gain).
483 cw = cos(2.0*M_PI * Effect->Reverb.HFReference / frequency);
484 g = __max(Effect->Reverb.GainHF, 0.0001f);
485 State->LpFilter.coeff = 0.0f;
486 if(g < 0.9999f) // 1-epsilon
487 State->LpFilter.coeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
489 // Calculate the initial delay taps.
490 length = Effect->Reverb.ReflectionsDelay;
491 State->Tap[0] = (ALuint)(length * frequency);
493 length += Effect->Reverb.LateReverbDelay;
495 /* The four inputs to the late reverb are decorrelated to smooth the
496 * initial reverb and reduce harsh echos. The timings are calculated as
497 * multiples of a fraction of the smallest cyclical delay time. This
498 * result is then adjusted so that the first tap occurs immediately (all
499 * taps are reduced by the shortest fraction).
501 * offset[index] = ((FRACTION MULTIPLIER^index) - 1) delay
503 for(index = 0;index < 4;index++)
505 length += LATE_LINE_LENGTH[0] *
506 (1.0f + (Effect->Reverb.Density * LATE_LINE_MULTIPLIER)) *
507 (DECO_FRACTION * (pow(DECO_MULTIPLIER, (ALfloat)index) - 1.0f));
508 State->Tap[1 + index] = (ALuint)(length * frequency);
511 // Calculate the early reflections gain (from the master effect gain, and
512 // reflections gain parameters).
513 State->Early.Gain = Effect->Reverb.Gain * Effect->Reverb.ReflectionsGain;
515 // Calculate the gain (coefficient) for each early delay line.
516 for(index = 0;index < 4;index++)
517 State->Early.Coeff[index] = pow(10.0f, EARLY_LINE_LENGTH[index] /
518 Effect->Reverb.LateReverbDelay *
519 -60.0f / 20.0f);
521 // Calculate the first mixing matrix coefficient (x).
522 mixCoeff = 1.0f - (0.5f * pow(Effect->Reverb.Diffusion, 3.0f));
524 // Calculate the late reverb gain (from the master effect gain, and late
525 // reverb gain parameters). Since the output is tapped prior to the
526 // application of the delay line coefficients, this gain needs to be
527 // attenuated by the 'x' mix coefficient from above.
528 State->Late.Gain = Effect->Reverb.Gain * Effect->Reverb.LateReverbGain * mixCoeff;
530 /* To compensate for changes in modal density and decay time of the late
531 * reverb signal, the input is attenuated based on the maximal energy of
532 * the outgoing signal. This is calculated as the ratio between a
533 * reference value and the current approximation of energy for the output
534 * signal.
536 * Reverb output matches exponential decay of the form Sum(a^n), where a
537 * is the attenuation coefficient, and n is the sample ranging from 0 to
538 * infinity. The signal energy can thus be approximated using the area
539 * under this curve, calculated as: 1 / (1 - a).
541 * The reference energy is calculated from a signal at the lowest (effect
542 * at 1.0) density with a decay time of one second.
544 * The coefficient is calculated as the average length of the cyclical
545 * delay lines. This produces a better result than calculating the gain
546 * for each line individually (most likely a side effect of diffusion).
548 * The final result is the square root of the ratio bound to a maximum
549 * value of 1 (no amplification).
551 length = (LATE_LINE_LENGTH[0] + LATE_LINE_LENGTH[1] +
552 LATE_LINE_LENGTH[2] + LATE_LINE_LENGTH[3]);
553 g = length * (1.0f + LATE_LINE_MULTIPLIER) * 0.25f;
554 g = pow(10.0f, g * -60.0f / 20.0f);
555 g = 1.0f / (1.0f - (g * g));
556 length *= 1.0f + (Effect->Reverb.Density * LATE_LINE_MULTIPLIER) * 0.25f;
557 length = pow(10.0f, length / Effect->Reverb.DecayTime * -60.0f / 20.0f);
558 length = 1.0f / (1.0f - (length * length));
559 State->Late.DensityGain = __min(aluSqrt(g / length), 1.0f);
561 // Calculate the all-pass feed-back and feed-forward coefficient.
562 State->Late.ApFeedCoeff = 0.6f * pow(Effect->Reverb.Diffusion, 3.0f);
564 // Calculate the mixing matrix coefficient (y / x).
565 g = aluSqrt((1.0f - (mixCoeff * mixCoeff)) / 3.0f);
566 State->Late.MixCoeff = g / mixCoeff;
568 for(index = 0;index < 4;index++)
570 // Calculate the gain (coefficient) for each all-pass line.
571 State->Late.ApCoeff[index] = pow(10.0f, ALLPASS_LINE_LENGTH[index] /
572 Effect->Reverb.DecayTime *
573 -60.0f / 20.0f);
576 // If the HF limit parameter is flagged, calculate an appropriate limit
577 // based on the air absorption parameter.
578 if(Effect->Reverb.DecayHFLimit && Effect->Reverb.AirAbsorptionGainHF < 1.0f)
580 ALfloat limitRatio;
582 // For each of the cyclical delays, find the attenuation due to air
583 // absorption in dB (converting delay time to meters using the speed
584 // of sound). Then reversing the decay equation, solve for HF ratio.
585 // The delay length is cancelled out of the equation, so it can be
586 // calculated once for all lines.
587 limitRatio = 1.0f / (log10(Effect->Reverb.AirAbsorptionGainHF) *
588 SPEEDOFSOUNDMETRESPERSEC *
589 Effect->Reverb.DecayTime / -60.0f * 20.0f);
590 // Need to limit the result to a minimum of 0.1, just like the HF
591 // ratio parameter.
592 limitRatio = __max(limitRatio, 0.1f);
594 // Using the limit calculated above, apply the upper bound to the
595 // HF ratio.
596 hfRatio = __min(hfRatio, limitRatio);
599 // Calculate the low-pass filter frequency.
600 cw = cos(2.0*M_PI * Effect->Reverb.HFReference / frequency);
602 for(index = 0;index < 4;index++)
604 // Calculate the length (in seconds) of each cyclical delay line.
605 length = LATE_LINE_LENGTH[index] * (1.0f + (Effect->Reverb.Density *
606 LATE_LINE_MULTIPLIER));
607 // Calculate the delay offset for the cyclical delay lines.
608 State->Late.Offset[index] = (ALuint)(length * frequency);
610 // Calculate the gain (coefficient) for each cyclical line.
611 State->Late.Coeff[index] = pow(10.0f, length / Effect->Reverb.DecayTime *
612 -60.0f / 20.0f);
614 // Eventually this should boost the high frequencies when the ratio
615 // exceeds 1.
616 coeff = 0.0f;
617 if (hfRatio < 1.0f)
619 // Calculate the decay equation for each low-pass filter.
620 g = pow(10.0f, length / (Effect->Reverb.DecayTime * hfRatio) *
621 -60.0f / 20.0f) / State->Late.Coeff[index];
622 g = __max(g, 0.1f);
623 g *= g;
625 // Calculate the gain (coefficient) for each low-pass filter.
626 if(g < 0.9999f) // 1-epsilon
627 coeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
629 // Very low decay times will produce minimal output, so apply an
630 // upper bound to the coefficient.
631 coeff = __min(coeff, 0.98f);
633 State->Late.LpCoeff[index] = coeff;
635 // Attenuate the cyclical line coefficients by the mixing coefficient
636 // (x).
637 State->Late.Coeff[index] *= mixCoeff;
640 // Calculate the 3D-panning gains for the early reflections and late
641 // reverb (for EAX mode).
643 ALfloat earlyPan[3] = { Effect->Reverb.ReflectionsPan[0], Effect->Reverb.ReflectionsPan[1], Effect->Reverb.ReflectionsPan[2] };
644 ALfloat latePan[3] = { Effect->Reverb.LateReverbPan[0], Effect->Reverb.LateReverbPan[1], Effect->Reverb.LateReverbPan[2] };
645 ALfloat *speakerGain, dirGain, ambientGain;
646 ALfloat length;
647 ALint pos;
649 length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
650 if(length > 1.0f)
652 length = 1.0f / aluSqrt(length);
653 earlyPan[0] *= length;
654 earlyPan[1] *= length;
655 earlyPan[2] *= length;
657 length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2];
658 if(length > 1.0f)
660 length = 1.0f / aluSqrt(length);
661 latePan[0] *= length;
662 latePan[1] *= length;
663 latePan[2] *= length;
666 // This code applies directional reverb just like the mixer applies
667 // directional sources. It diffuses the sound toward all speakers
668 // as the magnitude of the panning vector drops, which is only an
669 // approximation of the expansion of sound across the speakers from
670 // the panning direction.
671 pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]);
672 speakerGain = &Context->PanningLUT[OUTPUTCHANNELS * pos];
673 dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2]));
674 ambientGain = (1.0 - dirGain);
675 for(index = 0;index < OUTPUTCHANNELS;index++)
676 State->Early.PanGain[index] = dirGain * speakerGain[index] + ambientGain;
678 pos = aluCart2LUTpos(latePan[2], latePan[0]);
679 speakerGain = &Context->PanningLUT[OUTPUTCHANNELS * pos];
680 dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2]));
681 ambientGain = (1.0 - dirGain);
682 for(index = 0;index < OUTPUTCHANNELS;index++)
683 State->Late.PanGain[index] = dirGain * speakerGain[index] + ambientGain;
687 // This processes the reverb state, given the input samples and an output
688 // buffer.
689 ALvoid VerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
691 ALverbState *State = (ALverbState*)effect;
692 ALuint index;
693 ALfloat early[4], late[4], out[4];
694 ALfloat gain = Slot->Gain;
696 for(index = 0;index < SamplesToDo;index++)
698 // Process reverb for this sample.
699 ReverbInOut(State, SamplesIn[index], early, late);
701 // Mix early reflections and late reverb.
702 out[0] = (early[0] + late[0]) * gain;
703 out[1] = (early[1] + late[1]) * gain;
704 out[2] = (early[2] + late[2]) * gain;
705 out[3] = (early[3] + late[3]) * gain;
707 // Output the results.
708 SamplesOut[index][FRONT_LEFT] += out[0];
709 SamplesOut[index][FRONT_RIGHT] += out[1];
710 SamplesOut[index][FRONT_CENTER] += out[3];
711 SamplesOut[index][SIDE_LEFT] += out[0];
712 SamplesOut[index][SIDE_RIGHT] += out[1];
713 SamplesOut[index][BACK_LEFT] += out[0];
714 SamplesOut[index][BACK_RIGHT] += out[1];
715 SamplesOut[index][BACK_CENTER] += out[2];
719 // This processes the EAX reverb state, given the input samples and an output
720 // buffer.
721 ALvoid EAXVerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
723 ALverbState *State = (ALverbState*)effect;
724 ALuint index;
725 ALfloat early[4], late[4];
726 ALfloat gain = Slot->Gain;
728 for(index = 0;index < SamplesToDo;index++)
730 // Process reverb for this sample.
731 ReverbInOut(State, SamplesIn[index], early, late);
733 // Unfortunately, while the number and configuration of gains for
734 // panning adjust according to OUTPUTCHANNELS, the output from the
735 // reverb engine is not so scalable.
736 SamplesOut[index][FRONT_LEFT] +=
737 (State->Early.PanGain[FRONT_LEFT]*early[0] +
738 State->Late.PanGain[FRONT_LEFT]*late[0]) * gain;
739 SamplesOut[index][FRONT_RIGHT] +=
740 (State->Early.PanGain[FRONT_RIGHT]*early[1] +
741 State->Late.PanGain[FRONT_RIGHT]*late[1]) * gain;
742 SamplesOut[index][FRONT_CENTER] +=
743 (State->Early.PanGain[FRONT_CENTER]*early[3] +
744 State->Late.PanGain[FRONT_CENTER]*late[3]) * gain;
745 SamplesOut[index][SIDE_LEFT] +=
746 (State->Early.PanGain[SIDE_LEFT]*early[0] +
747 State->Late.PanGain[SIDE_LEFT]*late[0]) * gain;
748 SamplesOut[index][SIDE_RIGHT] +=
749 (State->Early.PanGain[SIDE_RIGHT]*early[1] +
750 State->Late.PanGain[SIDE_RIGHT]*late[1]) * gain;
751 SamplesOut[index][BACK_LEFT] +=
752 (State->Early.PanGain[BACK_LEFT]*early[0] +
753 State->Late.PanGain[BACK_LEFT]*late[0]) * gain;
754 SamplesOut[index][BACK_RIGHT] +=
755 (State->Early.PanGain[BACK_RIGHT]*early[1] +
756 State->Late.PanGain[BACK_RIGHT]*late[1]) * gain;
757 SamplesOut[index][BACK_CENTER] +=
758 (State->Early.PanGain[BACK_CENTER]*early[2] +
759 State->Late.PanGain[BACK_CENTER]*late[2]) * gain;
763 // This creates the reverb state. It should be called only when the reverb
764 // effect is loaded into a slot that doesn't already have a reverb effect.
765 ALeffectState *VerbCreate(void)
767 ALverbState *State = NULL;
768 ALuint index;
770 State = malloc(sizeof(ALverbState));
771 if(!State)
773 alSetError(AL_OUT_OF_MEMORY);
774 return NULL;
777 State->state.Destroy = VerbDestroy;
778 State->state.DeviceUpdate = VerbDeviceUpdate;
779 State->state.Update = VerbUpdate;
780 State->state.Process = VerbProcess;
782 State->TotalLength = 0;
783 State->SampleBuffer = NULL;
785 State->LpFilter.coeff = 0.0f;
786 State->LpFilter.history[0] = 0.0f;
787 State->LpFilter.history[1] = 0.0f;
788 State->Delay.Mask = 0;
789 State->Delay.Line = NULL;
791 State->Tap[0] = 0;
792 State->Tap[1] = 0;
793 State->Tap[2] = 0;
794 State->Tap[3] = 0;
795 State->Tap[4] = 0;
797 State->Early.Gain = 0.0f;
798 for(index = 0;index < 4;index++)
800 State->Early.Coeff[index] = 0.0f;
801 State->Early.Delay[index].Mask = 0;
802 State->Early.Delay[index].Line = NULL;
803 State->Early.Offset[index] = 0;
806 State->Late.Gain = 0.0f;
807 State->Late.DensityGain = 0.0f;
808 State->Late.ApFeedCoeff = 0.0f;
809 State->Late.MixCoeff = 0.0f;
811 for(index = 0;index < 4;index++)
813 State->Late.ApCoeff[index] = 0.0f;
814 State->Late.ApDelay[index].Mask = 0;
815 State->Late.ApDelay[index].Line = NULL;
816 State->Late.ApOffset[index] = 0;
818 State->Late.Coeff[index] = 0.0f;
819 State->Late.Delay[index].Mask = 0;
820 State->Late.Delay[index].Line = NULL;
821 State->Late.Offset[index] = 0;
823 State->Late.LpCoeff[index] = 0.0f;
824 State->Late.LpSample[index] = 0.0f;
827 // Panning is applied as an independent gain for each output channel.
828 for(index = 0;index < OUTPUTCHANNELS;index++)
830 State->Early.PanGain[index] = 0.0f;
831 State->Late.PanGain[index] = 0.0f;
834 State->Offset = 0;
835 return &State->state;
838 ALeffectState *EAXVerbCreate(void)
840 ALeffectState *State = VerbCreate();
841 if(State) State->Process = EAXVerbProcess;
842 return State;