Set some common macros in alu.h
[openal-soft.git] / Alc / alcReverb.c
blob0516ab4f58237fb3913337a0fb7f80ca754773c5
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 "alReverb.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 struct ALverbState
44 // All delay lines are allocated as a single buffer to reduce memory
45 // fragmentation and management code.
46 ALfloat *SampleBuffer;
47 // Master effect gain.
48 ALfloat Gain;
49 // Initial effect delay and decorrelation.
50 DelayLine Delay;
51 // The tap points for the initial delay. First tap goes to early
52 // reflections, the last four decorrelate to late reverb.
53 ALuint Tap[5];
54 struct {
55 // Gain for early reflections.
56 ALfloat Gain;
57 // Early reflections are done with 4 delay lines.
58 ALfloat Coeff[4];
59 DelayLine Delay[4];
60 ALuint Offset[4];
61 } Early;
62 struct {
63 // Gain for late reverb.
64 ALfloat Gain;
65 // Attenuation to compensate for modal density and decay rate.
66 ALfloat DensityGain;
67 // The feed-back and feed-forward all-pass coefficient.
68 ALfloat ApFeedCoeff;
69 // Mixing matrix coefficient.
70 ALfloat MixCoeff;
71 // Late reverb has 4 parallel all-pass filters.
72 ALfloat ApCoeff[4];
73 DelayLine ApDelay[4];
74 ALuint ApOffset[4];
75 // In addition to 4 cyclical delay lines.
76 ALfloat Coeff[4];
77 DelayLine Delay[4];
78 ALuint Offset[4];
79 // The cyclical delay lines are low-pass filtered.
80 ALfloat LpCoeff[4][2];
81 ALfloat LpSample[4];
82 } Late;
83 // The current read offset for all delay lines.
84 ALuint Offset;
87 // All delay line lengths are specified in seconds.
89 // The lengths of the early delay lines.
90 static const ALfloat EARLY_LINE_LENGTH[4] =
92 0.0015f, 0.0045f, 0.0135f, 0.0405f
95 // The lengths of the late all-pass delay lines.
96 static const ALfloat ALLPASS_LINE_LENGTH[4] =
98 0.0151f, 0.0167f, 0.0183f, 0.0200f,
101 // The lengths of the late cyclical delay lines.
102 static const ALfloat LATE_LINE_LENGTH[4] =
104 0.0211f, 0.0311f, 0.0461f, 0.0680f
107 // The late cyclical delay lines have a variable length dependent on the
108 // effect's density parameter (inverted for some reason) and this multiplier.
109 static const ALfloat LATE_LINE_MULTIPLIER = 4.0f;
111 // Input into the late reverb is decorrelated between four channels. Their
112 // timings are dependent on a fraction and multiplier. See VerbUpdate() for
113 // the calculations involved.
114 static const ALfloat DECO_FRACTION = 1.0f / 32.0f;
115 static const ALfloat DECO_MULTIPLIER = 2.0f;
117 // The maximum length of initial delay for the master delay line (a sum of
118 // the maximum early reflection and late reverb delays).
119 static const ALfloat MASTER_LINE_LENGTH = 0.3f + 0.1f;
121 // Find the next power of 2. Actually, this will return the input value if
122 // it is already a power of 2.
123 static ALuint NextPowerOf2(ALuint value)
125 ALuint powerOf2 = 1;
127 if(value)
129 value--;
130 while(value)
132 value >>= 1;
133 powerOf2 <<= 1;
136 return powerOf2;
139 // Basic delay line input/output routines.
140 static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
142 return Delay->Line[offset&Delay->Mask];
145 static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
147 Delay->Line[offset&Delay->Mask] = in;
150 // Delay line output routine for early reflections.
151 static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
153 return State->Early.Coeff[index] *
154 DelayLineOut(&State->Early.Delay[index],
155 State->Offset - State->Early.Offset[index]);
158 // Given an input sample, this function produces stereo output for early
159 // reflections.
160 static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *out)
162 ALfloat d[4], v, f[4];
164 // Obtain the decayed results of each early delay line.
165 d[0] = EarlyDelayLineOut(State, 0);
166 d[1] = EarlyDelayLineOut(State, 1);
167 d[2] = EarlyDelayLineOut(State, 2);
168 d[3] = EarlyDelayLineOut(State, 3);
170 /* The following uses a lossless scattering junction from waveguide
171 * theory. It actually amounts to a householder mixing matrix, which
172 * will produce a maximally diffuse response, and means this can probably
173 * be considered a simple feedback delay network (FDN).
175 * ---
177 * v = 2/N / d_i
178 * ---
179 * i=1
181 v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
182 // The junction is loaded with the input here.
183 v += in;
185 // Calculate the feed values for the delay lines.
186 f[0] = v - d[0];
187 f[1] = v - d[1];
188 f[2] = v - d[2];
189 f[3] = v - d[3];
191 // Refeed the delay lines.
192 DelayLineIn(&State->Early.Delay[0], State->Offset, f[0]);
193 DelayLineIn(&State->Early.Delay[1], State->Offset, f[1]);
194 DelayLineIn(&State->Early.Delay[2], State->Offset, f[2]);
195 DelayLineIn(&State->Early.Delay[3], State->Offset, f[3]);
197 // To decorrelate the output for stereo separation, the two outputs are
198 // obtained from the inner delay lines.
199 // Output is instant by using the inputs to them instead of taking the
200 // result of the two delay lines directly (f[0] and f[3] instead of d[1]
201 // and d[2]).
202 out[0] = State->Early.Gain * f[0];
203 out[1] = State->Early.Gain * f[3];
206 // All-pass input/output routine for late reverb.
207 static __inline ALfloat LateAllPassInOut(ALverbState *State, ALuint index, ALfloat in)
209 ALfloat out;
211 out = State->Late.ApCoeff[index] *
212 DelayLineOut(&State->Late.ApDelay[index],
213 State->Offset - State->Late.ApOffset[index]);
214 out -= (State->Late.ApFeedCoeff * in);
215 DelayLineIn(&State->Late.ApDelay[index], State->Offset,
216 (State->Late.ApFeedCoeff * out) + in);
217 return out;
220 // Delay line output routine for late reverb.
221 static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
223 return State->Late.Coeff[index] *
224 DelayLineOut(&State->Late.Delay[index],
225 State->Offset - State->Late.Offset[index]);
228 // Low-pass filter input/output routine for late reverb.
229 static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
231 State->Late.LpSample[index] = (State->Late.LpCoeff[index][0] * in) +
232 (State->Late.LpCoeff[index][1] * State->Late.LpSample[index]);
233 return State->Late.LpSample[index];
236 // Given four decorrelated input samples, this function produces stereo
237 // output for late reverb.
238 static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out)
240 ALfloat d[4], f[4];
242 // Obtain the decayed results of the cyclical delay lines, and add the
243 // corresponding input channels attenuated by density. Then pass the
244 // results through the low-pass filters.
245 d[0] = LateLowPassInOut(State, 0, (State->Late.DensityGain * in[0]) +
246 LateDelayLineOut(State, 0));
247 d[1] = LateLowPassInOut(State, 1, (State->Late.DensityGain * in[1]) +
248 LateDelayLineOut(State, 1));
249 d[2] = LateLowPassInOut(State, 2, (State->Late.DensityGain * in[2]) +
250 LateDelayLineOut(State, 2));
251 d[3] = LateLowPassInOut(State, 3, (State->Late.DensityGain * in[3]) +
252 LateDelayLineOut(State, 3));
254 // To help increase diffusion, run each line through an all-pass filter.
255 // The order of the all-pass filters is selected so that the shortest
256 // all-pass filter will feed the shortest delay line.
257 d[0] = LateAllPassInOut(State, 1, d[0]);
258 d[1] = LateAllPassInOut(State, 3, d[1]);
259 d[2] = LateAllPassInOut(State, 0, d[2]);
260 d[3] = LateAllPassInOut(State, 2, d[3]);
262 /* Late reverb is done with a modified feedback delay network (FDN)
263 * topology. Four input lines are each fed through their own all-pass
264 * filter and then into the mixing matrix. The four outputs of the
265 * mixing matrix are then cycled back to the inputs. Each output feeds
266 * a different input to form a circlular feed cycle.
268 * The mixing matrix used is a 4D skew-symmetric rotation matrix derived
269 * using a single unitary rotational parameter:
271 * [ d, a, b, c ] 1 = a^2 + b^2 + c^2 + d^2
272 * [ -a, d, c, -b ]
273 * [ -b, -c, d, a ]
274 * [ -c, b, -a, d ]
276 * The rotation is constructed from the effect's diffusion parameter,
277 * yielding: 1 = x^2 + 3 y^2; where a, b, and c are the coefficient y
278 * with differing signs, and d is the coefficient x. The matrix is thus:
280 * [ x, y, -y, y ] x = 1 - (0.5 diffusion^3)
281 * [ -y, x, y, y ] y = sqrt((1 - x^2) / 3)
282 * [ y, -y, x, y ]
283 * [ -y, -y, -y, x ]
285 * To reduce the number of multiplies, the x coefficient is applied with
286 * the cyclical delay line coefficients. Thus only the y coefficient is
287 * applied when mixing, and is modified to be: y / x.
289 f[0] = d[0] + (State->Late.MixCoeff * ( d[1] - d[2] + d[3]));
290 f[1] = d[1] + (State->Late.MixCoeff * (-d[0] + d[2] + d[3]));
291 f[2] = d[2] + (State->Late.MixCoeff * ( d[0] - d[1] + d[3]));
292 f[3] = d[3] + (State->Late.MixCoeff * (-d[0] - d[1] - d[2]));
294 // Output is tapped at the input to the shortest two cyclical delay
295 // lines, attenuated by the late reverb gain (which is attenuated by the
296 // mixing coefficient x).
297 out[0] = State->Late.Gain * f[0];
298 out[1] = State->Late.Gain * f[1];
300 // The delay lines are fed circularly in the order:
301 // 0 -> 1 -> 3 -> 2 -> 0 ...
302 DelayLineIn(&State->Late.Delay[0], State->Offset, f[2]);
303 DelayLineIn(&State->Late.Delay[1], State->Offset, f[0]);
304 DelayLineIn(&State->Late.Delay[2], State->Offset, f[3]);
305 DelayLineIn(&State->Late.Delay[3], State->Offset, f[1]);
308 // This creates the reverb state. It should be called only when the reverb
309 // effect is loaded into a slot that doesn't already have a reverb effect.
310 ALverbState *VerbCreate(ALCcontext *Context)
312 ALverbState *State = NULL;
313 ALuint samples, length[13], totalLength, index;
315 State = malloc(sizeof(ALverbState));
316 if(!State)
317 return NULL;
319 // All line lengths are powers of 2, calculated from their lengths, with
320 // an additional sample in case of rounding errors.
322 // See VerbUpdate() for an explanation of the additional calculation
323 // added to the master line length.
324 samples = (ALuint)
325 ((MASTER_LINE_LENGTH +
326 (LATE_LINE_LENGTH[0] * (1.0f + LATE_LINE_MULTIPLIER) *
327 (DECO_FRACTION * ((DECO_MULTIPLIER * DECO_MULTIPLIER *
328 DECO_MULTIPLIER) - 1.0f)))) *
329 Context->Frequency) + 1;
330 length[0] = NextPowerOf2(samples);
331 totalLength = length[0];
332 for(index = 0;index < 4;index++)
334 samples = (ALuint)(EARLY_LINE_LENGTH[index] * Context->Frequency) + 1;
335 length[1 + index] = NextPowerOf2(samples);
336 totalLength += length[1 + index];
338 for(index = 0;index < 4;index++)
340 samples = (ALuint)(ALLPASS_LINE_LENGTH[index] * Context->Frequency) + 1;
341 length[5 + index] = NextPowerOf2(samples);
342 totalLength += length[5 + index];
344 for(index = 0;index < 4;index++)
346 samples = (ALuint)(LATE_LINE_LENGTH[index] *
347 (1.0f + LATE_LINE_MULTIPLIER) * Context->Frequency) + 1;
348 length[9 + index] = NextPowerOf2(samples);
349 totalLength += length[9 + index];
352 // All lines share a single sample buffer.
353 State->SampleBuffer = malloc(totalLength * sizeof(ALfloat));
354 if(!State->SampleBuffer)
356 free(State);
357 return NULL;
359 for(index = 0; index < totalLength;index++)
360 State->SampleBuffer[index] = 0.0f;
362 // Each one has its mask and start address calculated one time.
363 State->Gain = 0.0f;
364 State->Delay.Mask = length[0] - 1;
365 State->Delay.Line = &State->SampleBuffer[0];
366 totalLength = length[0];
368 State->Tap[0] = 0;
369 State->Tap[1] = 0;
370 State->Tap[2] = 0;
371 State->Tap[3] = 0;
372 State->Tap[4] = 0;
374 State->Early.Gain = 0.0f;
375 for(index = 0;index < 4;index++)
377 State->Early.Coeff[index] = 0.0f;
378 State->Early.Delay[index].Mask = length[1 + index] - 1;
379 State->Early.Delay[index].Line = &State->SampleBuffer[totalLength];
380 totalLength += length[1 + index];
382 // The early delay lines have their read offsets calculated once.
383 State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] *
384 Context->Frequency);
387 State->Late.Gain = 0.0f;
388 State->Late.DensityGain = 0.0f;
389 State->Late.ApFeedCoeff = 0.0f;
390 State->Late.MixCoeff = 0.0f;
392 for(index = 0;index < 4;index++)
394 State->Late.ApCoeff[index] = 0.0f;
395 State->Late.ApDelay[index].Mask = length[5 + index] - 1;
396 State->Late.ApDelay[index].Line = &State->SampleBuffer[totalLength];
397 totalLength += length[5 + index];
399 // The late all-pass lines have their read offsets calculated once.
400 State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] *
401 Context->Frequency);
404 for(index = 0;index < 4;index++)
406 State->Late.Coeff[index] = 0.0f;
407 State->Late.Delay[index].Mask = length[9 + index] - 1;
408 State->Late.Delay[index].Line = &State->SampleBuffer[totalLength];
409 totalLength += length[9 + index];
411 State->Late.Offset[index] = 0;
413 State->Late.LpCoeff[index][0] = 0.0f;
414 State->Late.LpCoeff[index][1] = 0.0f;
415 State->Late.LpSample[index] = 0.0f;
418 State->Offset = 0;
419 return State;
422 // This destroys the reverb state. It should be called only when the effect
423 // slot has a different (or no) effect loaded over the reverb effect.
424 ALvoid VerbDestroy(ALverbState *State)
426 if(State)
428 free(State->SampleBuffer);
429 State->SampleBuffer = NULL;
430 free(State);
434 // This updates the reverb state. This is called any time the reverb effect
435 // is loaded into a slot.
436 ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
438 ALverbState *State = Slot->ReverbState;
439 ALuint index;
440 ALfloat length, mixCoeff, cw, g, lpCoeff;
441 ALfloat hfRatio = Effect->Reverb.DecayHFRatio;
443 // Calculate the master gain (from the slot and master effect gain).
444 State->Gain = Slot->Gain * Effect->Reverb.Gain;
446 // Calculate the initial delay taps.
447 length = Effect->Reverb.ReflectionsDelay;
448 State->Tap[0] = (ALuint)(length * Context->Frequency);
450 length += Effect->Reverb.LateReverbDelay;
452 /* The four inputs to the late reverb are decorrelated to smooth the
453 * initial reverb and reduce harsh echos. The timings are calculated as
454 * multiples of a fraction of the smallest cyclical delay time. This
455 * result is then adjusted so that the first tap occurs immediately (all
456 * taps are reduced by the shortest fraction).
458 * offset[index] = ((FRACTION MULTIPLIER^index) - 1) delay
460 for(index = 0;index < 4;index++)
462 length += LATE_LINE_LENGTH[0] *
463 (1.0f + (Effect->Reverb.Density * LATE_LINE_MULTIPLIER)) *
464 (DECO_FRACTION * (pow(DECO_MULTIPLIER, (ALfloat)index) - 1.0f));
465 State->Tap[1 + index] = (ALuint)(length * Context->Frequency);
468 // Set the early reflections gain.
469 State->Early.Gain = Effect->Reverb.ReflectionsGain;
471 // Calculate the gain (coefficient) for each early delay line.
472 for(index = 0;index < 4;index++)
473 State->Early.Coeff[index] = pow(10.0f, EARLY_LINE_LENGTH[index] /
474 Effect->Reverb.LateReverbDelay *
475 -60.0f / 20.0f);
477 // Calculate the first mixing matrix coefficient (x).
478 mixCoeff = 1.0f - (0.5f * pow(Effect->Reverb.Diffusion, 3.0f));
480 // Set the late reverb gain. Since the output is tapped prior to the
481 // application of the delay line coefficients, this gain needs to be
482 // attenuated by the mix coefficient from above.
483 State->Late.Gain = Effect->Reverb.LateReverbGain * mixCoeff;
485 /* To compensate for changes in modal density and decay time of the late
486 * reverb signal, the input is attenuated based on the maximal energy of
487 * the outgoing signal. This is calculated as the ratio between a
488 * reference value and the current approximation of energy for the output
489 * signal.
491 * Reverb output matches exponential decay of the form Sum(a^n), where a
492 * is the attenuation coefficient, and n is the sample ranging from 0 to
493 * infinity. The signal energy can thus be approximated using the area
494 * under this curve, calculated as: 1 / (1 - a).
496 * The reference energy is calculated from a signal at the lowest (effect
497 * at 1.0) density with a decay time of one second.
499 * The coefficient is calculated as the average length of the cyclical
500 * delay lines. This produces a better result than calculating the gain
501 * for each line individually (most likely a side effect of diffusion).
503 * The final result is the square root of the ratio bound to a maximum
504 * value of 1 (no amplification) and attenuated by 1 / sqrt(2) to
505 * compensate for the four decorrelated inputs.
507 length = (LATE_LINE_LENGTH[0] + LATE_LINE_LENGTH[1] +
508 LATE_LINE_LENGTH[2] + LATE_LINE_LENGTH[3]);
509 g = length * (1.0f + LATE_LINE_MULTIPLIER) * 0.25f;
510 g = pow(10.0f, g * -60.0f / 20.0f);
511 g = 1.0f / (1.0f - (g*g));
512 length *= 1.0f + (Effect->Reverb.Density * LATE_LINE_MULTIPLIER) * 0.25f;
513 length = pow(10.0f, length / Effect->Reverb.DecayTime * -60.0f / 20.0f);
514 length = 1.0f / (1.0f - (length*length));
515 State->Late.DensityGain = 0.707106f * __min(aluSqrt(g / length), 1.0f);
517 // Calculate the all-pass feed-back and feed-forward coefficient.
518 State->Late.ApFeedCoeff = 0.6f * pow(Effect->Reverb.Diffusion, 3.0f);
520 // Calculate the mixing matrix coefficient (y / x).
521 g = aluSqrt((1.0f - (mixCoeff * mixCoeff)) / 3.0f);
522 State->Late.MixCoeff = g / mixCoeff;
524 for(index = 0;index < 4;index++)
526 // Calculate the gain (coefficient) for each all-pass line.
527 State->Late.ApCoeff[index] = pow(10.0f, ALLPASS_LINE_LENGTH[index] /
528 Effect->Reverb.DecayTime *
529 -60.0f / 20.0f);
532 // If the HF limit parameter is flagged, calculate an appropriate limit
533 // based on the air absorption parameter.
534 if(Effect->Reverb.DecayHFLimit && Effect->Reverb.AirAbsorptionGainHF < 1.0f)
536 ALfloat limitRatio;
538 // For each of the cyclical delays, find the attenuation due to air
539 // absorption in dB (converting delay time to meters using the speed
540 // of sound). Then reversing the decay equation, solve for HF ratio.
541 // The delay length is cancelled out of the equation, so it can be
542 // calculated once for all lines.
543 limitRatio = 1.0f / (log10(Effect->Reverb.AirAbsorptionGainHF) *
544 SPEEDOFSOUNDMETRESPERSEC *
545 Effect->Reverb.DecayTime / -60.0f * 20.0f);
546 // Need to limit the result to a minimum of 0.1, just like the HF
547 // ratio parameter.
548 limitRatio = __max(limitRatio, 0.1f);
550 // Using the limit calculated above, apply the upper bound to the
551 // HF ratio.
552 hfRatio = __min(hfRatio, limitRatio);
555 // Calculate the filter frequency for low-pass or high-pass depending on
556 // whether the HF ratio is above 1.
557 cw = 2.0f * M_PI * LOWPASSFREQCUTOFF / Context->Frequency;
558 if(hfRatio > 1.0f)
559 cw = M_PI - cw;
560 cw = cos(cw);
562 for(index = 0;index < 4;index++)
564 // Calculate the length (in seconds) of each cyclical delay line.
565 length = LATE_LINE_LENGTH[index] * (1.0f + (Effect->Reverb.Density *
566 LATE_LINE_MULTIPLIER));
567 // Calculate the delay offset for the cyclical delay lines.
568 State->Late.Offset[index] = (ALuint)(length * Context->Frequency);
570 // Calculate the gain (coefficient) for each cyclical line.
571 State->Late.Coeff[index] = pow(10.0f, length / Effect->Reverb.DecayTime *
572 -60.0f / 20.0f);
574 // Calculate the decay equation for each low-pass filter.
575 g = pow(10.0f, length / (Effect->Reverb.DecayTime * hfRatio) *
576 -60.0f / 20.0f);
577 if (hfRatio > 1.0f)
578 g = State->Late.Coeff[index] / g;
579 else
580 g = g / State->Late.Coeff[index];
581 g = __max(g, 0.1f);
582 g *= g;
584 // Calculate the gain (coefficient) for each low-pass filter.
585 lpCoeff = 0.0f;
586 if(g < 0.9999f) // 1-epsilon
587 lpCoeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
589 // Very low decay times will produce minimal output, so apply an
590 // upper bound to the coefficient.
591 lpCoeff = __min(lpCoeff, 0.98f);
593 // Calculate the filter coefficients for high-pass or low-pass
594 // dependent on HF ratio being above 1.
595 if(hfRatio > 1.0f) {
596 State->Late.LpCoeff[index][0] = 1.0f + lpCoeff;
597 State->Late.LpCoeff[index][1] = -lpCoeff;
598 } else {
599 State->Late.LpCoeff[index][0] = 1.0f - lpCoeff;
600 State->Late.LpCoeff[index][1] = lpCoeff;
603 // Attenuate the cyclical line coefficients by the mixing coefficient
604 // (x).
605 State->Late.Coeff[index] *= mixCoeff;
609 // This processes the reverb state, given the input samples and an output
610 // buffer.
611 ALvoid VerbProcess(ALverbState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
613 ALuint index;
614 ALfloat in[4], early[2], late[2], out[2];
616 for(index = 0;index < SamplesToDo;index++)
618 // Feed the initial delay line.
619 DelayLineIn(&State->Delay, State->Offset, SamplesIn[index]);
621 // Calculate the early reflection from the first delay tap.
622 in[0] = DelayLineOut(&State->Delay, State->Offset - State->Tap[0]);
623 EarlyReflection(State, in[0], early);
625 // Calculate the late reverb from the last four delay taps.
626 in[0] = DelayLineOut(&State->Delay, State->Offset - State->Tap[1]);
627 in[1] = DelayLineOut(&State->Delay, State->Offset - State->Tap[2]);
628 in[2] = DelayLineOut(&State->Delay, State->Offset - State->Tap[3]);
629 in[3] = DelayLineOut(&State->Delay, State->Offset - State->Tap[4]);
630 LateReverb(State, in, late);
632 // Mix early reflections and late reverb.
633 out[0] = State->Gain * (early[0] + late[0]);
634 out[1] = State->Gain * (early[1] + late[1]);
636 // Step all delays forward one sample.
637 State->Offset++;
639 // Output the results.
640 SamplesOut[index][FRONT_LEFT] += out[0];
641 SamplesOut[index][FRONT_RIGHT] += out[1];
642 SamplesOut[index][SIDE_LEFT] += out[0];
643 SamplesOut[index][SIDE_RIGHT] += out[1];
644 SamplesOut[index][BACK_LEFT] += out[0];
645 SamplesOut[index][BACK_RIGHT] += out[1];