Mark some parameters as const and/or RESTRICT
[openal-soft.git] / Alc / alcReverb.c
blob3181f87e13b6a7217b78936d5939ac19d625c5c9
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 <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
27 #include "alMain.h"
28 #include "alu.h"
29 #include "alAuxEffectSlot.h"
30 #include "alEffect.h"
31 #include "alFilter.h"
32 #include "alError.h"
34 typedef struct DelayLine
36 // The delay lines use sample lengths that are powers of 2 to allow the
37 // use of bit-masking instead of a modulus for 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 TotalSamples;
51 // Master effect low-pass filter (2 chained 1-pole filters).
52 FILTER LpFilter;
53 ALfloat LpHistory[2];
55 struct {
56 // Modulator delay line.
57 DelayLine Delay;
59 // The vibrato time is tracked with an index over a modulus-wrapped
60 // range (in samples).
61 ALuint Index;
62 ALuint Range;
64 // The depth of frequency change (also in samples) and its filter.
65 ALfloat Depth;
66 ALfloat Coeff;
67 ALfloat Filter;
68 } Mod;
70 // Initial effect delay.
71 DelayLine Delay;
72 // The tap points for the initial delay. First tap goes to early
73 // reflections, the last to late reverb.
74 ALuint DelayTap[2];
76 struct {
77 // Output gain for early reflections.
78 ALfloat Gain;
80 // Early reflections are done with 4 delay lines.
81 ALfloat Coeff[4];
82 DelayLine Delay[4];
83 ALuint Offset[4];
85 // The gain for each output channel based on 3D panning (only for the
86 // EAX path).
87 ALfloat PanGain[MaxChannels];
88 } Early;
90 // Decorrelator delay line.
91 DelayLine Decorrelator;
92 // There are actually 4 decorrelator taps, but the first occurs at the
93 // initial sample.
94 ALuint DecoTap[3];
96 struct {
97 // Output gain for late reverb.
98 ALfloat Gain;
100 // Attenuation to compensate for the modal density and decay rate of
101 // the late lines.
102 ALfloat DensityGain;
104 // The feed-back and feed-forward all-pass coefficient.
105 ALfloat ApFeedCoeff;
107 // Mixing matrix coefficient.
108 ALfloat MixCoeff;
110 // Late reverb has 4 parallel all-pass filters.
111 ALfloat ApCoeff[4];
112 DelayLine ApDelay[4];
113 ALuint ApOffset[4];
115 // In addition to 4 cyclical delay lines.
116 ALfloat Coeff[4];
117 DelayLine Delay[4];
118 ALuint Offset[4];
120 // The cyclical delay lines are 1-pole low-pass filtered.
121 ALfloat LpCoeff[4];
122 ALfloat LpSample[4];
124 // The gain for each output channel based on 3D panning (only for the
125 // EAX path).
126 ALfloat PanGain[MaxChannels];
127 } Late;
129 struct {
130 // Attenuation to compensate for the modal density and decay rate of
131 // the echo line.
132 ALfloat DensityGain;
134 // Echo delay and all-pass lines.
135 DelayLine Delay;
136 DelayLine ApDelay;
138 ALfloat Coeff;
139 ALfloat ApFeedCoeff;
140 ALfloat ApCoeff;
142 ALuint Offset;
143 ALuint ApOffset;
145 // The echo line is 1-pole low-pass filtered.
146 ALfloat LpCoeff;
147 ALfloat LpSample;
149 // Echo mixing coefficients.
150 ALfloat MixCoeff[2];
151 } Echo;
153 // The current read offset for all delay lines.
154 ALuint Offset;
156 // The gain for each output channel (non-EAX path only; aliased from
157 // Late.PanGain)
158 ALfloat *Gain;
159 } ALverbState;
161 /* This is a user config option for modifying the overall output of the reverb
162 * effect.
164 ALfloat ReverbBoost = 1.0f;
166 /* Specifies whether to use a standard reverb effect in place of EAX reverb */
167 ALboolean EmulateEAXReverb = AL_FALSE;
169 /* This coefficient is used to define the maximum frequency range controlled
170 * by the modulation depth. The current value of 0.1 will allow it to swing
171 * from 0.9x to 1.1x. This value must be below 1. At 1 it will cause the
172 * sampler to stall on the downswing, and above 1 it will cause it to sample
173 * backwards.
175 static const ALfloat MODULATION_DEPTH_COEFF = 0.1f;
177 /* A filter is used to avoid the terrible distortion caused by changing
178 * modulation time and/or depth. To be consistent across different sample
179 * rates, the coefficient must be raised to a constant divided by the sample
180 * rate: coeff^(constant / rate).
182 static const ALfloat MODULATION_FILTER_COEFF = 0.048f;
183 static const ALfloat MODULATION_FILTER_CONST = 100000.0f;
185 // When diffusion is above 0, an all-pass filter is used to take the edge off
186 // the echo effect. It uses the following line length (in seconds).
187 static const ALfloat ECHO_ALLPASS_LENGTH = 0.0133f;
189 // Input into the late reverb is decorrelated between four channels. Their
190 // timings are dependent on a fraction and multiplier. See the
191 // UpdateDecorrelator() routine for the calculations involved.
192 static const ALfloat DECO_FRACTION = 0.15f;
193 static const ALfloat DECO_MULTIPLIER = 2.0f;
195 // All delay line lengths are specified in seconds.
197 // The lengths of the early delay lines.
198 static const ALfloat EARLY_LINE_LENGTH[4] =
200 0.0015f, 0.0045f, 0.0135f, 0.0405f
203 // The lengths of the late all-pass delay lines.
204 static const ALfloat ALLPASS_LINE_LENGTH[4] =
206 0.0151f, 0.0167f, 0.0183f, 0.0200f,
209 // The lengths of the late cyclical delay lines.
210 static const ALfloat LATE_LINE_LENGTH[4] =
212 0.0211f, 0.0311f, 0.0461f, 0.0680f
215 // The late cyclical delay lines have a variable length dependent on the
216 // effect's density parameter (inverted for some reason) and this multiplier.
217 static const ALfloat LATE_LINE_MULTIPLIER = 4.0f;
220 // Basic delay line input/output routines.
221 static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
223 return Delay->Line[offset&Delay->Mask];
226 static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
228 Delay->Line[offset&Delay->Mask] = in;
231 // Attenuated delay line output routine.
232 static __inline ALfloat AttenuatedDelayLineOut(DelayLine *Delay, ALuint offset, ALfloat coeff)
234 return coeff * Delay->Line[offset&Delay->Mask];
237 // Basic attenuated all-pass input/output routine.
238 static __inline ALfloat AllpassInOut(DelayLine *Delay, ALuint outOffset, ALuint inOffset, ALfloat in, ALfloat feedCoeff, ALfloat coeff)
240 ALfloat out, feed;
242 out = DelayLineOut(Delay, outOffset);
243 feed = feedCoeff * in;
244 DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in);
246 // The time-based attenuation is only applied to the delay output to
247 // keep it from affecting the feed-back path (which is already controlled
248 // by the all-pass feed coefficient).
249 return (coeff * out) - feed;
252 // Given an input sample, this function produces modulation for the late
253 // reverb.
254 static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in)
256 ALfloat sinus, frac;
257 ALuint offset;
258 ALfloat out0, out1;
260 // Calculate the sinus rythm (dependent on modulation time and the
261 // sampling rate). The center of the sinus is moved to reduce the delay
262 // of the effect when the time or depth are low.
263 sinus = 1.0f - cosf(F_PI*2.0f * State->Mod.Index / State->Mod.Range);
265 // The depth determines the range over which to read the input samples
266 // from, so it must be filtered to reduce the distortion caused by even
267 // small parameter changes.
268 State->Mod.Filter = lerp(State->Mod.Filter, State->Mod.Depth,
269 State->Mod.Coeff);
271 // Calculate the read offset and fraction between it and the next sample.
272 frac = (1.0f + (State->Mod.Filter * sinus));
273 offset = fastf2u(frac);
274 frac -= offset;
276 // Get the two samples crossed by the offset, and feed the delay line
277 // with the next input sample.
278 out0 = DelayLineOut(&State->Mod.Delay, State->Offset - offset);
279 out1 = DelayLineOut(&State->Mod.Delay, State->Offset - offset - 1);
280 DelayLineIn(&State->Mod.Delay, State->Offset, in);
282 // Step the modulation index forward, keeping it bound to its range.
283 State->Mod.Index = (State->Mod.Index + 1) % State->Mod.Range;
285 // The output is obtained by linearly interpolating the two samples that
286 // were acquired above.
287 return lerp(out0, out1, frac);
290 // Delay line output routine for early reflections.
291 static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
293 return AttenuatedDelayLineOut(&State->Early.Delay[index],
294 State->Offset - State->Early.Offset[index],
295 State->Early.Coeff[index]);
298 // Given an input sample, this function produces four-channel output for the
299 // early reflections.
300 static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *RESTRICT out)
302 ALfloat d[4], v, f[4];
304 // Obtain the decayed results of each early delay line.
305 d[0] = EarlyDelayLineOut(State, 0);
306 d[1] = EarlyDelayLineOut(State, 1);
307 d[2] = EarlyDelayLineOut(State, 2);
308 d[3] = EarlyDelayLineOut(State, 3);
310 /* The following uses a lossless scattering junction from waveguide
311 * theory. It actually amounts to a householder mixing matrix, which
312 * will produce a maximally diffuse response, and means this can probably
313 * be considered a simple feed-back delay network (FDN).
315 * ---
317 * v = 2/N / d_i
318 * ---
319 * i=1
321 v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
322 // The junction is loaded with the input here.
323 v += in;
325 // Calculate the feed values for the delay lines.
326 f[0] = v - d[0];
327 f[1] = v - d[1];
328 f[2] = v - d[2];
329 f[3] = v - d[3];
331 // Re-feed the delay lines.
332 DelayLineIn(&State->Early.Delay[0], State->Offset, f[0]);
333 DelayLineIn(&State->Early.Delay[1], State->Offset, f[1]);
334 DelayLineIn(&State->Early.Delay[2], State->Offset, f[2]);
335 DelayLineIn(&State->Early.Delay[3], State->Offset, f[3]);
337 // Output the results of the junction for all four channels.
338 out[0] = State->Early.Gain * f[0];
339 out[1] = State->Early.Gain * f[1];
340 out[2] = State->Early.Gain * f[2];
341 out[3] = State->Early.Gain * f[3];
344 // All-pass input/output routine for late reverb.
345 static __inline ALfloat LateAllPassInOut(ALverbState *State, ALuint index, ALfloat in)
347 return AllpassInOut(&State->Late.ApDelay[index],
348 State->Offset - State->Late.ApOffset[index],
349 State->Offset, in, State->Late.ApFeedCoeff,
350 State->Late.ApCoeff[index]);
353 // Delay line output routine for late reverb.
354 static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
356 return AttenuatedDelayLineOut(&State->Late.Delay[index],
357 State->Offset - State->Late.Offset[index],
358 State->Late.Coeff[index]);
361 // Low-pass filter input/output routine for late reverb.
362 static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
364 in = lerp(in, State->Late.LpSample[index], State->Late.LpCoeff[index]);
365 State->Late.LpSample[index] = in;
366 return in;
369 // Given four decorrelated input samples, this function produces four-channel
370 // output for the late reverb.
371 static __inline ALvoid LateReverb(ALverbState *State, const ALfloat *RESTRICT in, ALfloat *RESTRICT out)
373 ALfloat d[4], f[4];
375 // Obtain the decayed results of the cyclical delay lines, and add the
376 // corresponding input channels. Then pass the results through the
377 // low-pass filters.
379 // This is where the feed-back cycles from line 0 to 1 to 3 to 2 and back
380 // to 0.
381 d[0] = LateLowPassInOut(State, 2, in[2] + LateDelayLineOut(State, 2));
382 d[1] = LateLowPassInOut(State, 0, in[0] + LateDelayLineOut(State, 0));
383 d[2] = LateLowPassInOut(State, 3, in[3] + LateDelayLineOut(State, 3));
384 d[3] = LateLowPassInOut(State, 1, in[1] + LateDelayLineOut(State, 1));
386 // To help increase diffusion, run each line through an all-pass filter.
387 // When there is no diffusion, the shortest all-pass filter will feed the
388 // shortest delay line.
389 d[0] = LateAllPassInOut(State, 0, d[0]);
390 d[1] = LateAllPassInOut(State, 1, d[1]);
391 d[2] = LateAllPassInOut(State, 2, d[2]);
392 d[3] = LateAllPassInOut(State, 3, d[3]);
394 /* Late reverb is done with a modified feed-back delay network (FDN)
395 * topology. Four input lines are each fed through their own all-pass
396 * filter and then into the mixing matrix. The four outputs of the
397 * mixing matrix are then cycled back to the inputs. Each output feeds
398 * a different input to form a circlular feed cycle.
400 * The mixing matrix used is a 4D skew-symmetric rotation matrix derived
401 * using a single unitary rotational parameter:
403 * [ d, a, b, c ] 1 = a^2 + b^2 + c^2 + d^2
404 * [ -a, d, c, -b ]
405 * [ -b, -c, d, a ]
406 * [ -c, b, -a, d ]
408 * The rotation is constructed from the effect's diffusion parameter,
409 * yielding: 1 = x^2 + 3 y^2; where a, b, and c are the coefficient y
410 * with differing signs, and d is the coefficient x. The matrix is thus:
412 * [ x, y, -y, y ] n = sqrt(matrix_order - 1)
413 * [ -y, x, y, y ] t = diffusion_parameter * atan(n)
414 * [ y, -y, x, y ] x = cos(t)
415 * [ -y, -y, -y, x ] y = sin(t) / n
417 * To reduce the number of multiplies, the x coefficient is applied with
418 * the cyclical delay line coefficients. Thus only the y coefficient is
419 * applied when mixing, and is modified to be: y / x.
421 f[0] = d[0] + (State->Late.MixCoeff * ( d[1] + -d[2] + d[3]));
422 f[1] = d[1] + (State->Late.MixCoeff * (-d[0] + d[2] + d[3]));
423 f[2] = d[2] + (State->Late.MixCoeff * ( d[0] + -d[1] + d[3]));
424 f[3] = d[3] + (State->Late.MixCoeff * (-d[0] + -d[1] + -d[2] ));
426 // Output the results of the matrix for all four channels, attenuated by
427 // the late reverb gain (which is attenuated by the 'x' mix coefficient).
428 out[0] = State->Late.Gain * f[0];
429 out[1] = State->Late.Gain * f[1];
430 out[2] = State->Late.Gain * f[2];
431 out[3] = State->Late.Gain * f[3];
433 // Re-feed the cyclical delay lines.
434 DelayLineIn(&State->Late.Delay[0], State->Offset, f[0]);
435 DelayLineIn(&State->Late.Delay[1], State->Offset, f[1]);
436 DelayLineIn(&State->Late.Delay[2], State->Offset, f[2]);
437 DelayLineIn(&State->Late.Delay[3], State->Offset, f[3]);
440 // Given an input sample, this function mixes echo into the four-channel late
441 // reverb.
442 static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *RESTRICT late)
444 ALfloat out, feed;
446 // Get the latest attenuated echo sample for output.
447 feed = AttenuatedDelayLineOut(&State->Echo.Delay,
448 State->Offset - State->Echo.Offset,
449 State->Echo.Coeff);
451 // Mix the output into the late reverb channels.
452 out = State->Echo.MixCoeff[0] * feed;
453 late[0] = (State->Echo.MixCoeff[1] * late[0]) + out;
454 late[1] = (State->Echo.MixCoeff[1] * late[1]) + out;
455 late[2] = (State->Echo.MixCoeff[1] * late[2]) + out;
456 late[3] = (State->Echo.MixCoeff[1] * late[3]) + out;
458 // Mix the energy-attenuated input with the output and pass it through
459 // the echo low-pass filter.
460 feed += State->Echo.DensityGain * in;
461 feed = lerp(feed, State->Echo.LpSample, State->Echo.LpCoeff);
462 State->Echo.LpSample = feed;
464 // Then the echo all-pass filter.
465 feed = AllpassInOut(&State->Echo.ApDelay,
466 State->Offset - State->Echo.ApOffset,
467 State->Offset, feed, State->Echo.ApFeedCoeff,
468 State->Echo.ApCoeff);
470 // Feed the delay with the mixed and filtered sample.
471 DelayLineIn(&State->Echo.Delay, State->Offset, feed);
474 // Perform the non-EAX reverb pass on a given input sample, resulting in
475 // four-channel output.
476 static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *RESTRICT out)
478 ALfloat feed, late[4], taps[4];
480 // Low-pass filter the incoming sample.
481 in = lpFilter2P(&State->LpFilter, 0, in);
483 // Feed the initial delay line.
484 DelayLineIn(&State->Delay, State->Offset, in);
486 // Calculate the early reflection from the first delay tap.
487 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
488 EarlyReflection(State, in, out);
490 // Feed the decorrelator from the energy-attenuated output of the second
491 // delay tap.
492 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
493 feed = in * State->Late.DensityGain;
494 DelayLineIn(&State->Decorrelator, State->Offset, feed);
496 // Calculate the late reverb from the decorrelator taps.
497 taps[0] = feed;
498 taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
499 taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
500 taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
501 LateReverb(State, taps, late);
503 // Mix early reflections and late reverb.
504 out[0] += late[0];
505 out[1] += late[1];
506 out[2] += late[2];
507 out[3] += late[3];
509 // Step all delays forward one sample.
510 State->Offset++;
513 // Perform the EAX reverb pass on a given input sample, resulting in four-
514 // channel output.
515 static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *RESTRICT early, ALfloat *RESTRICT late)
517 ALfloat feed, taps[4];
519 // Low-pass filter the incoming sample.
520 in = lpFilter2P(&State->LpFilter, 0, in);
522 // Perform any modulation on the input.
523 in = EAXModulation(State, in);
525 // Feed the initial delay line.
526 DelayLineIn(&State->Delay, State->Offset, in);
528 // Calculate the early reflection from the first delay tap.
529 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
530 EarlyReflection(State, in, early);
532 // Feed the decorrelator from the energy-attenuated output of the second
533 // delay tap.
534 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
535 feed = in * State->Late.DensityGain;
536 DelayLineIn(&State->Decorrelator, State->Offset, feed);
538 // Calculate the late reverb from the decorrelator taps.
539 taps[0] = feed;
540 taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
541 taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
542 taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
543 LateReverb(State, taps, late);
545 // Calculate and mix in any echo.
546 EAXEcho(State, in, late);
548 // Step all delays forward one sample.
549 State->Offset++;
552 // This processes the reverb state, given the input samples and an output
553 // buffer.
554 static ALvoid VerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
556 ALverbState *State = (ALverbState*)effect;
557 ALuint index, c;
558 ALfloat out[4];
559 const ALfloat *panGain = State->Gain;
561 for(index = 0;index < SamplesToDo;index++)
563 // Process reverb for this sample.
564 VerbPass(State, SamplesIn[index], out);
566 // Output the results.
567 for(c = 0;c < MaxChannels;c++)
568 SamplesOut[c][index] += panGain[c] * out[c&3];
572 // This processes the EAX reverb state, given the input samples and an output
573 // buffer.
574 static ALvoid EAXVerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
576 ALverbState *State = (ALverbState*)effect;
577 ALuint index, c;
578 ALfloat early[4], late[4];
580 for(index = 0;index < SamplesToDo;index++)
582 // Process reverb for this sample.
583 EAXVerbPass(State, SamplesIn[index], early, late);
585 for(c = 0;c < MaxChannels;c++)
586 SamplesOut[c][index] += State->Early.PanGain[c]*early[c&3] +
587 State->Late.PanGain[c]*late[c&3];
592 // Given the allocated sample buffer, this function updates each delay line
593 // offset.
594 static __inline ALvoid RealizeLineOffset(ALfloat *sampleBuffer, DelayLine *Delay)
596 Delay->Line = &sampleBuffer[(ALintptrEXT)Delay->Line];
599 // Calculate the length of a delay line and store its mask and offset.
600 static ALuint CalcLineLength(ALfloat length, ALintptrEXT offset, ALuint frequency, DelayLine *Delay)
602 ALuint samples;
604 // All line lengths are powers of 2, calculated from their lengths, with
605 // an additional sample in case of rounding errors.
606 samples = NextPowerOf2(fastf2u(length * frequency) + 1);
607 // All lines share a single sample buffer.
608 Delay->Mask = samples - 1;
609 Delay->Line = (ALfloat*)offset;
610 // Return the sample count for accumulation.
611 return samples;
614 /* Calculates the delay line metrics and allocates the shared sample buffer
615 * for all lines given the sample rate (frequency). If an allocation failure
616 * occurs, it returns AL_FALSE.
618 static ALboolean AllocLines(ALuint frequency, ALverbState *State)
620 ALuint totalSamples, index;
621 ALfloat length;
622 ALfloat *newBuffer = NULL;
624 // All delay line lengths are calculated to accomodate the full range of
625 // lengths given their respective paramters.
626 totalSamples = 0;
628 /* The modulator's line length is calculated from the maximum modulation
629 * time and depth coefficient, and halfed for the low-to-high frequency
630 * swing. An additional sample is added to keep it stable when there is no
631 * modulation.
633 length = (AL_EAXREVERB_MAX_MODULATION_TIME*MODULATION_DEPTH_COEFF/2.0f) +
634 (1.0f / frequency);
635 totalSamples += CalcLineLength(length, totalSamples, frequency,
636 &State->Mod.Delay);
638 // The initial delay is the sum of the reflections and late reverb
639 // delays.
640 length = AL_EAXREVERB_MAX_REFLECTIONS_DELAY +
641 AL_EAXREVERB_MAX_LATE_REVERB_DELAY;
642 totalSamples += CalcLineLength(length, totalSamples, frequency,
643 &State->Delay);
645 // The early reflection lines.
646 for(index = 0;index < 4;index++)
647 totalSamples += CalcLineLength(EARLY_LINE_LENGTH[index], totalSamples,
648 frequency, &State->Early.Delay[index]);
650 // The decorrelator line is calculated from the lowest reverb density (a
651 // parameter value of 1).
652 length = (DECO_FRACTION * DECO_MULTIPLIER * DECO_MULTIPLIER) *
653 LATE_LINE_LENGTH[0] * (1.0f + LATE_LINE_MULTIPLIER);
654 totalSamples += CalcLineLength(length, totalSamples, frequency,
655 &State->Decorrelator);
657 // The late all-pass lines.
658 for(index = 0;index < 4;index++)
659 totalSamples += CalcLineLength(ALLPASS_LINE_LENGTH[index], totalSamples,
660 frequency, &State->Late.ApDelay[index]);
662 // The late delay lines are calculated from the lowest reverb density.
663 for(index = 0;index < 4;index++)
665 length = LATE_LINE_LENGTH[index] * (1.0f + LATE_LINE_MULTIPLIER);
666 totalSamples += CalcLineLength(length, totalSamples, frequency,
667 &State->Late.Delay[index]);
670 // The echo all-pass and delay lines.
671 totalSamples += CalcLineLength(ECHO_ALLPASS_LENGTH, totalSamples,
672 frequency, &State->Echo.ApDelay);
673 totalSamples += CalcLineLength(AL_EAXREVERB_MAX_ECHO_TIME, totalSamples,
674 frequency, &State->Echo.Delay);
676 if(totalSamples != State->TotalSamples)
678 TRACE("New reverb buffer length: %u samples (%f sec)\n", totalSamples, totalSamples/(float)frequency);
679 newBuffer = realloc(State->SampleBuffer, sizeof(ALfloat) * totalSamples);
680 if(newBuffer == NULL)
681 return AL_FALSE;
682 State->SampleBuffer = newBuffer;
683 State->TotalSamples = totalSamples;
686 // Update all delays to reflect the new sample buffer.
687 RealizeLineOffset(State->SampleBuffer, &State->Delay);
688 RealizeLineOffset(State->SampleBuffer, &State->Decorrelator);
689 for(index = 0;index < 4;index++)
691 RealizeLineOffset(State->SampleBuffer, &State->Early.Delay[index]);
692 RealizeLineOffset(State->SampleBuffer, &State->Late.ApDelay[index]);
693 RealizeLineOffset(State->SampleBuffer, &State->Late.Delay[index]);
695 RealizeLineOffset(State->SampleBuffer, &State->Mod.Delay);
696 RealizeLineOffset(State->SampleBuffer, &State->Echo.ApDelay);
697 RealizeLineOffset(State->SampleBuffer, &State->Echo.Delay);
699 // Clear the sample buffer.
700 for(index = 0;index < State->TotalSamples;index++)
701 State->SampleBuffer[index] = 0.0f;
703 return AL_TRUE;
706 // This updates the device-dependant EAX reverb state. This is called on
707 // initialization and any time the device parameters (eg. playback frequency,
708 // format) have been changed.
709 static ALboolean ReverbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
711 ALverbState *State = (ALverbState*)effect;
712 ALuint frequency = Device->Frequency, index;
714 // Allocate the delay lines.
715 if(!AllocLines(frequency, State))
716 return AL_FALSE;
718 // Calculate the modulation filter coefficient. Notice that the exponent
719 // is calculated given the current sample rate. This ensures that the
720 // resulting filter response over time is consistent across all sample
721 // rates.
722 State->Mod.Coeff = powf(MODULATION_FILTER_COEFF,
723 MODULATION_FILTER_CONST / frequency);
725 // The early reflection and late all-pass filter line lengths are static,
726 // so their offsets only need to be calculated once.
727 for(index = 0;index < 4;index++)
729 State->Early.Offset[index] = fastf2u(EARLY_LINE_LENGTH[index] *
730 frequency);
731 State->Late.ApOffset[index] = fastf2u(ALLPASS_LINE_LENGTH[index] *
732 frequency);
735 // The echo all-pass filter line length is static, so its offset only
736 // needs to be calculated once.
737 State->Echo.ApOffset = fastf2u(ECHO_ALLPASS_LENGTH * frequency);
739 return AL_TRUE;
742 // Calculate a decay coefficient given the length of each cycle and the time
743 // until the decay reaches -60 dB.
744 static __inline ALfloat CalcDecayCoeff(ALfloat length, ALfloat decayTime)
746 return powf(0.001f/*-60 dB*/, length/decayTime);
749 // Calculate a decay length from a coefficient and the time until the decay
750 // reaches -60 dB.
751 static __inline ALfloat CalcDecayLength(ALfloat coeff, ALfloat decayTime)
753 return log10f(coeff) * decayTime / log10f(0.001f)/*-60 dB*/;
756 // Calculate the high frequency parameter for the I3DL2 coefficient
757 // calculation.
758 static __inline ALfloat CalcI3DL2HFreq(ALfloat hfRef, ALuint frequency)
760 return cosf(F_PI*2.0f * hfRef / frequency);
763 // Calculate an attenuation to be applied to the input of any echo models to
764 // compensate for modal density and decay time.
765 static __inline ALfloat CalcDensityGain(ALfloat a)
767 /* The energy of a signal can be obtained by finding the area under the
768 * squared signal. This takes the form of Sum(x_n^2), where x is the
769 * amplitude for the sample n.
771 * Decaying feedback matches exponential decay of the form Sum(a^n),
772 * where a is the attenuation coefficient, and n is the sample. The area
773 * under this decay curve can be calculated as: 1 / (1 - a).
775 * Modifying the above equation to find the squared area under the curve
776 * (for energy) yields: 1 / (1 - a^2). Input attenuation can then be
777 * calculated by inverting the square root of this approximation,
778 * yielding: 1 / sqrt(1 / (1 - a^2)), simplified to: sqrt(1 - a^2).
780 return sqrtf(1.0f - (a * a));
783 // Calculate the mixing matrix coefficients given a diffusion factor.
784 static __inline ALvoid CalcMatrixCoeffs(ALfloat diffusion, ALfloat *x, ALfloat *y)
786 ALfloat n, t;
788 // The matrix is of order 4, so n is sqrt (4 - 1).
789 n = sqrtf(3.0f);
790 t = diffusion * atanf(n);
792 // Calculate the first mixing matrix coefficient.
793 *x = cosf(t);
794 // Calculate the second mixing matrix coefficient.
795 *y = sinf(t) / n;
798 // Calculate the limited HF ratio for use with the late reverb low-pass
799 // filters.
800 static ALfloat CalcLimitedHfRatio(ALfloat hfRatio, ALfloat airAbsorptionGainHF, ALfloat decayTime)
802 ALfloat limitRatio;
804 /* Find the attenuation due to air absorption in dB (converting delay
805 * time to meters using the speed of sound). Then reversing the decay
806 * equation, solve for HF ratio. The delay length is cancelled out of
807 * the equation, so it can be calculated once for all lines.
809 limitRatio = 1.0f / (CalcDecayLength(airAbsorptionGainHF, decayTime) *
810 SPEEDOFSOUNDMETRESPERSEC);
811 /* Using the limit calculated above, apply the upper bound to the HF
812 * ratio. Also need to limit the result to a minimum of 0.1, just like the
813 * HF ratio parameter. */
814 return clampf(limitRatio, 0.1f, hfRatio);
817 // Calculate the coefficient for a HF (and eventually LF) decay damping
818 // filter.
819 static __inline ALfloat CalcDampingCoeff(ALfloat hfRatio, ALfloat length, ALfloat decayTime, ALfloat decayCoeff, ALfloat cw)
821 ALfloat coeff, g;
823 // Eventually this should boost the high frequencies when the ratio
824 // exceeds 1.
825 coeff = 0.0f;
826 if (hfRatio < 1.0f)
828 // Calculate the low-pass coefficient by dividing the HF decay
829 // coefficient by the full decay coefficient.
830 g = CalcDecayCoeff(length, decayTime * hfRatio) / decayCoeff;
832 // Damping is done with a 1-pole filter, so g needs to be squared.
833 g *= g;
834 coeff = lpCoeffCalc(g, cw);
836 // Very low decay times will produce minimal output, so apply an
837 // upper bound to the coefficient.
838 coeff = minf(coeff, 0.98f);
840 return coeff;
843 // Update the EAX modulation index, range, and depth. Keep in mind that this
844 // kind of vibrato is additive and not multiplicative as one may expect. The
845 // downswing will sound stronger than the upswing.
846 static ALvoid UpdateModulator(ALfloat modTime, ALfloat modDepth, ALuint frequency, ALverbState *State)
848 ALuint range;
850 /* Modulation is calculated in two parts.
852 * The modulation time effects the sinus applied to the change in
853 * frequency. An index out of the current time range (both in samples)
854 * is incremented each sample. The range is bound to a reasonable
855 * minimum (1 sample) and when the timing changes, the index is rescaled
856 * to the new range (to keep the sinus consistent).
858 range = maxu(fastf2u(modTime*frequency), 1);
859 State->Mod.Index = (ALuint)(State->Mod.Index * (ALuint64)range /
860 State->Mod.Range);
861 State->Mod.Range = range;
863 /* The modulation depth effects the amount of frequency change over the
864 * range of the sinus. It needs to be scaled by the modulation time so
865 * that a given depth produces a consistent change in frequency over all
866 * ranges of time. Since the depth is applied to a sinus value, it needs
867 * to be halfed once for the sinus range and again for the sinus swing
868 * in time (half of it is spent decreasing the frequency, half is spent
869 * increasing it).
871 State->Mod.Depth = modDepth * MODULATION_DEPTH_COEFF * modTime / 2.0f /
872 2.0f * frequency;
875 // Update the offsets for the initial effect delay line.
876 static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALuint frequency, ALverbState *State)
878 // Calculate the initial delay taps.
879 State->DelayTap[0] = fastf2u(earlyDelay * frequency);
880 State->DelayTap[1] = fastf2u((earlyDelay + lateDelay) * frequency);
883 // Update the early reflections gain and line coefficients.
884 static ALvoid UpdateEarlyLines(ALfloat reverbGain, ALfloat earlyGain, ALfloat lateDelay, ALverbState *State)
886 ALuint index;
888 // Calculate the early reflections gain (from the master effect gain, and
889 // reflections gain parameters) with a constant attenuation of 0.5.
890 State->Early.Gain = 0.5f * reverbGain * earlyGain;
892 // Calculate the gain (coefficient) for each early delay line using the
893 // late delay time. This expands the early reflections to the start of
894 // the late reverb.
895 for(index = 0;index < 4;index++)
896 State->Early.Coeff[index] = CalcDecayCoeff(EARLY_LINE_LENGTH[index],
897 lateDelay);
900 // Update the offsets for the decorrelator line.
901 static ALvoid UpdateDecorrelator(ALfloat density, ALuint frequency, ALverbState *State)
903 ALuint index;
904 ALfloat length;
906 /* The late reverb inputs are decorrelated to smooth the reverb tail and
907 * reduce harsh echos. The first tap occurs immediately, while the
908 * remaining taps are delayed by multiples of a fraction of the smallest
909 * cyclical delay time.
911 * offset[index] = (FRACTION (MULTIPLIER^index)) smallest_delay
913 for(index = 0;index < 3;index++)
915 length = (DECO_FRACTION * powf(DECO_MULTIPLIER, (ALfloat)index)) *
916 LATE_LINE_LENGTH[0] * (1.0f + (density * LATE_LINE_MULTIPLIER));
917 State->DecoTap[index] = fastf2u(length * frequency);
921 // Update the late reverb gains, line lengths, and line coefficients.
922 static ALvoid UpdateLateLines(ALfloat reverbGain, ALfloat lateGain, ALfloat xMix, ALfloat density, ALfloat decayTime, ALfloat diffusion, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State)
924 ALfloat length;
925 ALuint index;
927 /* Calculate the late reverb gain (from the master effect gain, and late
928 * reverb gain parameters). Since the output is tapped prior to the
929 * application of the next delay line coefficients, this gain needs to be
930 * attenuated by the 'x' mixing matrix coefficient as well.
932 State->Late.Gain = reverbGain * lateGain * xMix;
934 /* To compensate for changes in modal density and decay time of the late
935 * reverb signal, the input is attenuated based on the maximal energy of
936 * the outgoing signal. This approximation is used to keep the apparent
937 * energy of the signal equal for all ranges of density and decay time.
939 * The average length of the cyclcical delay lines is used to calculate
940 * the attenuation coefficient.
942 length = (LATE_LINE_LENGTH[0] + LATE_LINE_LENGTH[1] +
943 LATE_LINE_LENGTH[2] + LATE_LINE_LENGTH[3]) / 4.0f;
944 length *= 1.0f + (density * LATE_LINE_MULTIPLIER);
945 State->Late.DensityGain = CalcDensityGain(CalcDecayCoeff(length,
946 decayTime));
948 // Calculate the all-pass feed-back and feed-forward coefficient.
949 State->Late.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
951 for(index = 0;index < 4;index++)
953 // Calculate the gain (coefficient) for each all-pass line.
954 State->Late.ApCoeff[index] = CalcDecayCoeff(ALLPASS_LINE_LENGTH[index],
955 decayTime);
957 // Calculate the length (in seconds) of each cyclical delay line.
958 length = LATE_LINE_LENGTH[index] * (1.0f + (density *
959 LATE_LINE_MULTIPLIER));
961 // Calculate the delay offset for each cyclical delay line.
962 State->Late.Offset[index] = fastf2u(length * frequency);
964 // Calculate the gain (coefficient) for each cyclical line.
965 State->Late.Coeff[index] = CalcDecayCoeff(length, decayTime);
967 // Calculate the damping coefficient for each low-pass filter.
968 State->Late.LpCoeff[index] =
969 CalcDampingCoeff(hfRatio, length, decayTime,
970 State->Late.Coeff[index], cw);
972 // Attenuate the cyclical line coefficients by the mixing coefficient
973 // (x).
974 State->Late.Coeff[index] *= xMix;
978 // Update the echo gain, line offset, line coefficients, and mixing
979 // coefficients.
980 static ALvoid UpdateEchoLine(ALfloat reverbGain, ALfloat lateGain, ALfloat echoTime, ALfloat decayTime, ALfloat diffusion, ALfloat echoDepth, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State)
982 // Update the offset and coefficient for the echo delay line.
983 State->Echo.Offset = fastf2u(echoTime * frequency);
985 // Calculate the decay coefficient for the echo line.
986 State->Echo.Coeff = CalcDecayCoeff(echoTime, decayTime);
988 // Calculate the energy-based attenuation coefficient for the echo delay
989 // line.
990 State->Echo.DensityGain = CalcDensityGain(State->Echo.Coeff);
992 // Calculate the echo all-pass feed coefficient.
993 State->Echo.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
995 // Calculate the echo all-pass attenuation coefficient.
996 State->Echo.ApCoeff = CalcDecayCoeff(ECHO_ALLPASS_LENGTH, decayTime);
998 // Calculate the damping coefficient for each low-pass filter.
999 State->Echo.LpCoeff = CalcDampingCoeff(hfRatio, echoTime, decayTime,
1000 State->Echo.Coeff, cw);
1002 /* Calculate the echo mixing coefficients. The first is applied to the
1003 * echo itself. The second is used to attenuate the late reverb when
1004 * echo depth is high and diffusion is low, so the echo is slightly
1005 * stronger than the decorrelated echos in the reverb tail.
1007 State->Echo.MixCoeff[0] = reverbGain * lateGain * echoDepth;
1008 State->Echo.MixCoeff[1] = 1.0f - (echoDepth * 0.5f * (1.0f - diffusion));
1011 // Update the early and late 3D panning gains.
1012 static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALverbState *State)
1014 ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1],
1015 ReflectionsPan[2] };
1016 ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
1017 LateReverbPan[2] };
1018 ALfloat ambientGain;
1019 ALfloat dirGain;
1020 ALfloat length;
1021 ALuint index;
1023 Gain *= ReverbBoost;
1025 /* Attenuate reverb according to its coverage (dirGain=0 will give
1026 * Gain*ambientGain, and dirGain=1 will give Gain). */
1027 ambientGain = minf(sqrtf(2.0f/Device->NumChan), 1.0f);
1029 length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
1030 if(length > 1.0f)
1032 length = 1.0f / sqrtf(length);
1033 earlyPan[0] *= length;
1034 earlyPan[1] *= length;
1035 earlyPan[2] *= length;
1037 length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2];
1038 if(length > 1.0f)
1040 length = 1.0f / sqrtf(length);
1041 latePan[0] *= length;
1042 latePan[1] *= length;
1043 latePan[2] *= length;
1046 dirGain = sqrtf(earlyPan[0]*earlyPan[0] + earlyPan[2]*earlyPan[2]);
1047 for(index = 0;index < MaxChannels;index++)
1048 State->Early.PanGain[index] = 0.0f;
1049 ComputeAngleGains(Device, atan2f(earlyPan[0], earlyPan[2]), (1.0f-dirGain)*F_PI,
1050 lerp(ambientGain, 1.0f, dirGain) * Gain, State->Early.PanGain);
1052 dirGain = sqrtf(latePan[0]*latePan[0] + latePan[2]*latePan[2]);
1053 for(index = 0;index < MaxChannels;index++)
1054 State->Late.PanGain[index] = 0.0f;
1055 ComputeAngleGains(Device, atan2f(latePan[0], latePan[2]), (1.0f-dirGain)*F_PI,
1056 lerp(ambientGain, 1.0f, dirGain) * Gain, State->Late.PanGain);
1059 // This updates the EAX reverb state. This is called any time the EAX reverb
1060 // effect is loaded into a slot.
1061 static ALvoid ReverbUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot)
1063 ALverbState *State = (ALverbState*)effect;
1064 ALuint frequency = Device->Frequency;
1065 ALboolean isEAX = AL_FALSE;
1066 ALfloat cw, x, y, hfRatio;
1068 if(Slot->effect.type == AL_EFFECT_EAXREVERB && !EmulateEAXReverb)
1070 State->state.Process = EAXVerbProcess;
1071 isEAX = AL_TRUE;
1073 else if(Slot->effect.type == AL_EFFECT_REVERB || EmulateEAXReverb)
1075 State->state.Process = VerbProcess;
1076 isEAX = AL_FALSE;
1079 // Calculate the master low-pass filter (from the master effect HF gain).
1080 if(isEAX) cw = CalcI3DL2HFreq(Slot->effect.Reverb.HFReference, frequency);
1081 else cw = CalcI3DL2HFreq(LOWPASSFREQREF, frequency);
1082 // This is done with 2 chained 1-pole filters, so no need to square g.
1083 State->LpFilter.coeff = lpCoeffCalc(Slot->effect.Reverb.GainHF, cw);
1085 if(isEAX)
1087 // Update the modulator line.
1088 UpdateModulator(Slot->effect.Reverb.ModulationTime,
1089 Slot->effect.Reverb.ModulationDepth,
1090 frequency, State);
1093 // Update the initial effect delay.
1094 UpdateDelayLine(Slot->effect.Reverb.ReflectionsDelay,
1095 Slot->effect.Reverb.LateReverbDelay,
1096 frequency, State);
1098 // Update the early lines.
1099 UpdateEarlyLines(Slot->effect.Reverb.Gain,
1100 Slot->effect.Reverb.ReflectionsGain,
1101 Slot->effect.Reverb.LateReverbDelay, State);
1103 // Update the decorrelator.
1104 UpdateDecorrelator(Slot->effect.Reverb.Density, frequency, State);
1106 // Get the mixing matrix coefficients (x and y).
1107 CalcMatrixCoeffs(Slot->effect.Reverb.Diffusion, &x, &y);
1108 // Then divide x into y to simplify the matrix calculation.
1109 State->Late.MixCoeff = y / x;
1111 // If the HF limit parameter is flagged, calculate an appropriate limit
1112 // based on the air absorption parameter.
1113 hfRatio = Slot->effect.Reverb.DecayHFRatio;
1114 if(Slot->effect.Reverb.DecayHFLimit &&
1115 Slot->effect.Reverb.AirAbsorptionGainHF < 1.0f)
1116 hfRatio = CalcLimitedHfRatio(hfRatio,
1117 Slot->effect.Reverb.AirAbsorptionGainHF,
1118 Slot->effect.Reverb.DecayTime);
1120 // Update the late lines.
1121 UpdateLateLines(Slot->effect.Reverb.Gain, Slot->effect.Reverb.LateReverbGain,
1122 x, Slot->effect.Reverb.Density, Slot->effect.Reverb.DecayTime,
1123 Slot->effect.Reverb.Diffusion, hfRatio, cw, frequency, State);
1125 if(isEAX)
1127 // Update the echo line.
1128 UpdateEchoLine(Slot->effect.Reverb.Gain, Slot->effect.Reverb.LateReverbGain,
1129 Slot->effect.Reverb.EchoTime, Slot->effect.Reverb.DecayTime,
1130 Slot->effect.Reverb.Diffusion, Slot->effect.Reverb.EchoDepth,
1131 hfRatio, cw, frequency, State);
1133 // Update early and late 3D panning.
1134 Update3DPanning(Device, Slot->effect.Reverb.ReflectionsPan,
1135 Slot->effect.Reverb.LateReverbPan, Slot->Gain, State);
1137 else
1139 ALfloat gain = Slot->Gain;
1140 ALuint index;
1142 /* Update channel gains */
1143 gain *= sqrtf(2.0f/Device->NumChan) * ReverbBoost;
1144 for(index = 0;index < MaxChannels;index++)
1145 State->Gain[index] = 0.0f;
1146 for(index = 0;index < Device->NumChan;index++)
1148 enum Channel chan = Device->Speaker2Chan[index];
1149 State->Gain[chan] = gain;
1154 // This destroys the reverb state. It should be called only when the effect
1155 // slot has a different (or no) effect loaded over the reverb effect.
1156 static ALvoid ReverbDestroy(ALeffectState *effect)
1158 ALverbState *State = (ALverbState*)effect;
1159 if(State)
1161 free(State->SampleBuffer);
1162 State->SampleBuffer = NULL;
1163 free(State);
1167 // This creates the reverb state. It should be called only when the reverb
1168 // effect is loaded into a slot that doesn't already have a reverb effect.
1169 ALeffectState *ReverbCreate(void)
1171 ALverbState *State = NULL;
1172 ALuint index;
1174 State = malloc(sizeof(ALverbState));
1175 if(!State)
1176 return NULL;
1178 State->state.Destroy = ReverbDestroy;
1179 State->state.DeviceUpdate = ReverbDeviceUpdate;
1180 State->state.Update = ReverbUpdate;
1181 State->state.Process = VerbProcess;
1183 State->TotalSamples = 0;
1184 State->SampleBuffer = NULL;
1186 State->LpFilter.coeff = 0.0f;
1187 State->LpFilter.history[0] = 0.0f;
1188 State->LpFilter.history[1] = 0.0f;
1190 State->Mod.Delay.Mask = 0;
1191 State->Mod.Delay.Line = NULL;
1192 State->Mod.Index = 0;
1193 State->Mod.Range = 1;
1194 State->Mod.Depth = 0.0f;
1195 State->Mod.Coeff = 0.0f;
1196 State->Mod.Filter = 0.0f;
1198 State->Delay.Mask = 0;
1199 State->Delay.Line = NULL;
1200 State->DelayTap[0] = 0;
1201 State->DelayTap[1] = 0;
1203 State->Early.Gain = 0.0f;
1204 for(index = 0;index < 4;index++)
1206 State->Early.Coeff[index] = 0.0f;
1207 State->Early.Delay[index].Mask = 0;
1208 State->Early.Delay[index].Line = NULL;
1209 State->Early.Offset[index] = 0;
1212 State->Decorrelator.Mask = 0;
1213 State->Decorrelator.Line = NULL;
1214 State->DecoTap[0] = 0;
1215 State->DecoTap[1] = 0;
1216 State->DecoTap[2] = 0;
1218 State->Late.Gain = 0.0f;
1219 State->Late.DensityGain = 0.0f;
1220 State->Late.ApFeedCoeff = 0.0f;
1221 State->Late.MixCoeff = 0.0f;
1222 for(index = 0;index < 4;index++)
1224 State->Late.ApCoeff[index] = 0.0f;
1225 State->Late.ApDelay[index].Mask = 0;
1226 State->Late.ApDelay[index].Line = NULL;
1227 State->Late.ApOffset[index] = 0;
1229 State->Late.Coeff[index] = 0.0f;
1230 State->Late.Delay[index].Mask = 0;
1231 State->Late.Delay[index].Line = NULL;
1232 State->Late.Offset[index] = 0;
1234 State->Late.LpCoeff[index] = 0.0f;
1235 State->Late.LpSample[index] = 0.0f;
1238 for(index = 0;index < MaxChannels;index++)
1240 State->Early.PanGain[index] = 0.0f;
1241 State->Late.PanGain[index] = 0.0f;
1244 State->Echo.DensityGain = 0.0f;
1245 State->Echo.Delay.Mask = 0;
1246 State->Echo.Delay.Line = NULL;
1247 State->Echo.ApDelay.Mask = 0;
1248 State->Echo.ApDelay.Line = NULL;
1249 State->Echo.Coeff = 0.0f;
1250 State->Echo.ApFeedCoeff = 0.0f;
1251 State->Echo.ApCoeff = 0.0f;
1252 State->Echo.Offset = 0;
1253 State->Echo.ApOffset = 0;
1254 State->Echo.LpCoeff = 0.0f;
1255 State->Echo.LpSample = 0.0f;
1256 State->Echo.MixCoeff[0] = 0.0f;
1257 State->Echo.MixCoeff[1] = 0.0f;
1259 State->Offset = 0;
1261 State->Gain = State->Late.PanGain;
1263 return &State->state;