Pass a device to the effect update functions
[openal-soft.git] / Alc / alcReverb.c
blobf11b4ee40af59f23113f8ffbbc4d6220467787ed
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 "AL/al.h"
28 #include "AL/alc.h"
29 #include "alMain.h"
30 #include "alAuxEffectSlot.h"
31 #include "alEffect.h"
32 #include "alError.h"
33 #include "alu.h"
35 typedef struct DelayLine
37 // The delay lines use sample lengths that are powers of 2 to allow the
38 // use of bit-masking instead of a modulus for wrapping.
39 ALuint Mask;
40 ALfloat *Line;
41 } DelayLine;
43 typedef struct ALverbState {
44 // Must be first in all effects!
45 ALeffectState state;
47 // All delay lines are allocated as a single buffer to reduce memory
48 // fragmentation and management code.
49 ALfloat *SampleBuffer;
50 ALuint TotalSamples;
52 // Master effect low-pass filter (2 chained 1-pole filters).
53 FILTER LpFilter;
54 ALfloat LpHistory[2];
56 struct {
57 // Modulator delay line.
58 DelayLine Delay;
60 // The vibrato time is tracked with an index over a modulus-wrapped
61 // range (in samples).
62 ALuint Index;
63 ALuint Range;
65 // The depth of frequency change (also in samples) and its filter.
66 ALfloat Depth;
67 ALfloat Coeff;
68 ALfloat Filter;
69 } Mod;
71 // Initial effect delay.
72 DelayLine Delay;
73 // The tap points for the initial delay. First tap goes to early
74 // reflections, the last to late reverb.
75 ALuint DelayTap[2];
77 struct {
78 // Output gain for early reflections.
79 ALfloat Gain;
81 // Early reflections are done with 4 delay lines.
82 ALfloat Coeff[4];
83 DelayLine Delay[4];
84 ALuint Offset[4];
86 // The gain for each output channel based on 3D panning (only for the
87 // EAX path).
88 ALfloat PanGain[MAXCHANNELS];
89 } Early;
91 // Decorrelator delay line.
92 DelayLine Decorrelator;
93 // There are actually 4 decorrelator taps, but the first occurs at the
94 // initial sample.
95 ALuint DecoTap[3];
97 struct {
98 // Output gain for late reverb.
99 ALfloat Gain;
101 // Attenuation to compensate for the modal density and decay rate of
102 // the late lines.
103 ALfloat DensityGain;
105 // The feed-back and feed-forward all-pass coefficient.
106 ALfloat ApFeedCoeff;
108 // Mixing matrix coefficient.
109 ALfloat MixCoeff;
111 // Late reverb has 4 parallel all-pass filters.
112 ALfloat ApCoeff[4];
113 DelayLine ApDelay[4];
114 ALuint ApOffset[4];
116 // In addition to 4 cyclical delay lines.
117 ALfloat Coeff[4];
118 DelayLine Delay[4];
119 ALuint Offset[4];
121 // The cyclical delay lines are 1-pole low-pass filtered.
122 ALfloat LpCoeff[4];
123 ALfloat LpSample[4];
125 // The gain for each output channel based on 3D panning (only for the
126 // EAX path).
127 ALfloat PanGain[MAXCHANNELS];
128 } Late;
130 struct {
131 // Attenuation to compensate for the modal density and decay rate of
132 // the echo line.
133 ALfloat DensityGain;
135 // Echo delay and all-pass lines.
136 DelayLine Delay;
137 DelayLine ApDelay;
139 ALfloat Coeff;
140 ALfloat ApFeedCoeff;
141 ALfloat ApCoeff;
143 ALuint Offset;
144 ALuint ApOffset;
146 // The echo line is 1-pole low-pass filtered.
147 ALfloat LpCoeff;
148 ALfloat LpSample;
150 // Echo mixing coefficients.
151 ALfloat MixCoeff[2];
152 } Echo;
154 // The current read offset for all delay lines.
155 ALuint Offset;
157 // The gain for each output channel (non-EAX path only; aliased from
158 // Late.PanGain)
159 ALfloat *Gain;
160 } ALverbState;
162 /* This is a user config option for modifying the overall output of the reverb
163 * effect.
165 ALfloat ReverbBoost = 1.0f;
167 /* Specifies whether to use a standard reverb effect in place of EAX reverb */
168 ALboolean EmulateEAXReverb = AL_FALSE;
170 /* This coefficient is used to define the maximum frequency range controlled
171 * by the modulation depth. The current value of 0.1 will allow it to swing
172 * from 0.9x to 1.1x. This value must be below 1. At 1 it will cause the
173 * sampler to stall on the downswing, and above 1 it will cause it to sample
174 * backwards.
176 static const ALfloat MODULATION_DEPTH_COEFF = 0.1f;
178 /* A filter is used to avoid the terrible distortion caused by changing
179 * modulation time and/or depth. To be consistent across different sample
180 * rates, the coefficient must be raised to a constant divided by the sample
181 * rate: coeff^(constant / rate).
183 static const ALfloat MODULATION_FILTER_COEFF = 0.048f;
184 static const ALfloat MODULATION_FILTER_CONST = 100000.0f;
186 // When diffusion is above 0, an all-pass filter is used to take the edge off
187 // the echo effect. It uses the following line length (in seconds).
188 static const ALfloat ECHO_ALLPASS_LENGTH = 0.0133f;
190 // Input into the late reverb is decorrelated between four channels. Their
191 // timings are dependent on a fraction and multiplier. See the
192 // UpdateDecorrelator() routine for the calculations involved.
193 static const ALfloat DECO_FRACTION = 0.15f;
194 static const ALfloat DECO_MULTIPLIER = 2.0f;
196 // All delay line lengths are specified in seconds.
198 // The lengths of the early delay lines.
199 static const ALfloat EARLY_LINE_LENGTH[4] =
201 0.0015f, 0.0045f, 0.0135f, 0.0405f
204 // The lengths of the late all-pass delay lines.
205 static const ALfloat ALLPASS_LINE_LENGTH[4] =
207 0.0151f, 0.0167f, 0.0183f, 0.0200f,
210 // The lengths of the late cyclical delay lines.
211 static const ALfloat LATE_LINE_LENGTH[4] =
213 0.0211f, 0.0311f, 0.0461f, 0.0680f
216 // The late cyclical delay lines have a variable length dependent on the
217 // effect's density parameter (inverted for some reason) and this multiplier.
218 static const ALfloat LATE_LINE_MULTIPLIER = 4.0f;
221 // Basic delay line input/output routines.
222 static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
224 return Delay->Line[offset&Delay->Mask];
227 static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
229 Delay->Line[offset&Delay->Mask] = in;
232 // Attenuated delay line output routine.
233 static __inline ALfloat AttenuatedDelayLineOut(DelayLine *Delay, ALuint offset, ALfloat coeff)
235 return coeff * Delay->Line[offset&Delay->Mask];
238 // Basic attenuated all-pass input/output routine.
239 static __inline ALfloat AllpassInOut(DelayLine *Delay, ALuint outOffset, ALuint inOffset, ALfloat in, ALfloat feedCoeff, ALfloat coeff)
241 ALfloat out, feed;
243 out = DelayLineOut(Delay, outOffset);
244 feed = feedCoeff * in;
245 DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in);
247 // The time-based attenuation is only applied to the delay output to
248 // keep it from affecting the feed-back path (which is already controlled
249 // by the all-pass feed coefficient).
250 return (coeff * out) - feed;
253 // Given an input sample, this function produces modulation for the late
254 // reverb.
255 static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in)
257 ALfloat sinus, frac;
258 ALuint offset;
259 ALfloat out0, out1;
261 // Calculate the sinus rythm (dependent on modulation time and the
262 // sampling rate). The center of the sinus is moved to reduce the delay
263 // of the effect when the time or depth are low.
264 sinus = 1.0f - aluCos(F_PI*2.0f * State->Mod.Index / State->Mod.Range);
266 // The depth determines the range over which to read the input samples
267 // from, so it must be filtered to reduce the distortion caused by even
268 // small parameter changes.
269 State->Mod.Filter = lerp(State->Mod.Filter, State->Mod.Depth,
270 State->Mod.Coeff);
272 // Calculate the read offset and fraction between it and the next sample.
273 frac = (1.0f + (State->Mod.Filter * sinus));
274 offset = fastf2u(frac);
275 frac -= offset;
277 // Get the two samples crossed by the offset, and feed the delay line
278 // with the next input sample.
279 out0 = DelayLineOut(&State->Mod.Delay, State->Offset - offset);
280 out1 = DelayLineOut(&State->Mod.Delay, State->Offset - offset - 1);
281 DelayLineIn(&State->Mod.Delay, State->Offset, in);
283 // Step the modulation index forward, keeping it bound to its range.
284 State->Mod.Index = (State->Mod.Index + 1) % State->Mod.Range;
286 // The output is obtained by linearly interpolating the two samples that
287 // were acquired above.
288 return lerp(out0, out1, frac);
291 // Delay line output routine for early reflections.
292 static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
294 return AttenuatedDelayLineOut(&State->Early.Delay[index],
295 State->Offset - State->Early.Offset[index],
296 State->Early.Coeff[index]);
299 // Given an input sample, this function produces four-channel output for the
300 // early reflections.
301 static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *out)
303 ALfloat d[4], v, f[4];
305 // Obtain the decayed results of each early delay line.
306 d[0] = EarlyDelayLineOut(State, 0);
307 d[1] = EarlyDelayLineOut(State, 1);
308 d[2] = EarlyDelayLineOut(State, 2);
309 d[3] = EarlyDelayLineOut(State, 3);
311 /* The following uses a lossless scattering junction from waveguide
312 * theory. It actually amounts to a householder mixing matrix, which
313 * will produce a maximally diffuse response, and means this can probably
314 * be considered a simple feed-back delay network (FDN).
316 * ---
318 * v = 2/N / d_i
319 * ---
320 * i=1
322 v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
323 // The junction is loaded with the input here.
324 v += in;
326 // Calculate the feed values for the delay lines.
327 f[0] = v - d[0];
328 f[1] = v - d[1];
329 f[2] = v - d[2];
330 f[3] = v - d[3];
332 // Re-feed the delay lines.
333 DelayLineIn(&State->Early.Delay[0], State->Offset, f[0]);
334 DelayLineIn(&State->Early.Delay[1], State->Offset, f[1]);
335 DelayLineIn(&State->Early.Delay[2], State->Offset, f[2]);
336 DelayLineIn(&State->Early.Delay[3], State->Offset, f[3]);
338 // Output the results of the junction for all four channels.
339 out[0] = State->Early.Gain * f[0];
340 out[1] = State->Early.Gain * f[1];
341 out[2] = State->Early.Gain * f[2];
342 out[3] = State->Early.Gain * f[3];
345 // All-pass input/output routine for late reverb.
346 static __inline ALfloat LateAllPassInOut(ALverbState *State, ALuint index, ALfloat in)
348 return AllpassInOut(&State->Late.ApDelay[index],
349 State->Offset - State->Late.ApOffset[index],
350 State->Offset, in, State->Late.ApFeedCoeff,
351 State->Late.ApCoeff[index]);
354 // Delay line output routine for late reverb.
355 static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
357 return AttenuatedDelayLineOut(&State->Late.Delay[index],
358 State->Offset - State->Late.Offset[index],
359 State->Late.Coeff[index]);
362 // Low-pass filter input/output routine for late reverb.
363 static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
365 in = lerp(in, State->Late.LpSample[index], State->Late.LpCoeff[index]);
366 State->Late.LpSample[index] = in;
367 return in;
370 // Given four decorrelated input samples, this function produces four-channel
371 // output for the late reverb.
372 static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out)
374 ALfloat d[4], f[4];
376 // Obtain the decayed results of the cyclical delay lines, and add the
377 // corresponding input channels. Then pass the results through the
378 // low-pass filters.
380 // This is where the feed-back cycles from line 0 to 1 to 3 to 2 and back
381 // to 0.
382 d[0] = LateLowPassInOut(State, 2, in[2] + LateDelayLineOut(State, 2));
383 d[1] = LateLowPassInOut(State, 0, in[0] + LateDelayLineOut(State, 0));
384 d[2] = LateLowPassInOut(State, 3, in[3] + LateDelayLineOut(State, 3));
385 d[3] = LateLowPassInOut(State, 1, in[1] + LateDelayLineOut(State, 1));
387 // To help increase diffusion, run each line through an all-pass filter.
388 // When there is no diffusion, the shortest all-pass filter will feed the
389 // shortest delay line.
390 d[0] = LateAllPassInOut(State, 0, d[0]);
391 d[1] = LateAllPassInOut(State, 1, d[1]);
392 d[2] = LateAllPassInOut(State, 2, d[2]);
393 d[3] = LateAllPassInOut(State, 3, d[3]);
395 /* Late reverb is done with a modified feed-back delay network (FDN)
396 * topology. Four input lines are each fed through their own all-pass
397 * filter and then into the mixing matrix. The four outputs of the
398 * mixing matrix are then cycled back to the inputs. Each output feeds
399 * a different input to form a circlular feed cycle.
401 * The mixing matrix used is a 4D skew-symmetric rotation matrix derived
402 * using a single unitary rotational parameter:
404 * [ d, a, b, c ] 1 = a^2 + b^2 + c^2 + d^2
405 * [ -a, d, c, -b ]
406 * [ -b, -c, d, a ]
407 * [ -c, b, -a, d ]
409 * The rotation is constructed from the effect's diffusion parameter,
410 * yielding: 1 = x^2 + 3 y^2; where a, b, and c are the coefficient y
411 * with differing signs, and d is the coefficient x. The matrix is thus:
413 * [ x, y, -y, y ] n = sqrt(matrix_order - 1)
414 * [ -y, x, y, y ] t = diffusion_parameter * atan(n)
415 * [ y, -y, x, y ] x = cos(t)
416 * [ -y, -y, -y, x ] y = sin(t) / n
418 * To reduce the number of multiplies, the x coefficient is applied with
419 * the cyclical delay line coefficients. Thus only the y coefficient is
420 * applied when mixing, and is modified to be: y / x.
422 f[0] = d[0] + (State->Late.MixCoeff * ( d[1] + -d[2] + d[3]));
423 f[1] = d[1] + (State->Late.MixCoeff * (-d[0] + d[2] + d[3]));
424 f[2] = d[2] + (State->Late.MixCoeff * ( d[0] + -d[1] + d[3]));
425 f[3] = d[3] + (State->Late.MixCoeff * (-d[0] + -d[1] + -d[2] ));
427 // Output the results of the matrix for all four channels, attenuated by
428 // the late reverb gain (which is attenuated by the 'x' mix coefficient).
429 out[0] = State->Late.Gain * f[0];
430 out[1] = State->Late.Gain * f[1];
431 out[2] = State->Late.Gain * f[2];
432 out[3] = State->Late.Gain * f[3];
434 // Re-feed the cyclical delay lines.
435 DelayLineIn(&State->Late.Delay[0], State->Offset, f[0]);
436 DelayLineIn(&State->Late.Delay[1], State->Offset, f[1]);
437 DelayLineIn(&State->Late.Delay[2], State->Offset, f[2]);
438 DelayLineIn(&State->Late.Delay[3], State->Offset, f[3]);
441 // Given an input sample, this function mixes echo into the four-channel late
442 // reverb.
443 static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *late)
445 ALfloat out, feed;
447 // Get the latest attenuated echo sample for output.
448 feed = AttenuatedDelayLineOut(&State->Echo.Delay,
449 State->Offset - State->Echo.Offset,
450 State->Echo.Coeff);
452 // Mix the output into the late reverb channels.
453 out = State->Echo.MixCoeff[0] * feed;
454 late[0] = (State->Echo.MixCoeff[1] * late[0]) + out;
455 late[1] = (State->Echo.MixCoeff[1] * late[1]) + out;
456 late[2] = (State->Echo.MixCoeff[1] * late[2]) + out;
457 late[3] = (State->Echo.MixCoeff[1] * late[3]) + out;
459 // Mix the energy-attenuated input with the output and pass it through
460 // the echo low-pass filter.
461 feed += State->Echo.DensityGain * in;
462 feed = lerp(feed, State->Echo.LpSample, State->Echo.LpCoeff);
463 State->Echo.LpSample = feed;
465 // Then the echo all-pass filter.
466 feed = AllpassInOut(&State->Echo.ApDelay,
467 State->Offset - State->Echo.ApOffset,
468 State->Offset, feed, State->Echo.ApFeedCoeff,
469 State->Echo.ApCoeff);
471 // Feed the delay with the mixed and filtered sample.
472 DelayLineIn(&State->Echo.Delay, State->Offset, feed);
475 // Perform the non-EAX reverb pass on a given input sample, resulting in
476 // four-channel output.
477 static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late)
479 ALfloat feed, taps[4];
481 // Low-pass filter the incoming sample.
482 in = lpFilter2P(&State->LpFilter, 0, in);
484 // Feed the initial delay line.
485 DelayLineIn(&State->Delay, State->Offset, in);
487 // Calculate the early reflection from the first delay tap.
488 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
489 EarlyReflection(State, in, early);
491 // Feed the decorrelator from the energy-attenuated output of the second
492 // delay tap.
493 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
494 feed = in * State->Late.DensityGain;
495 DelayLineIn(&State->Decorrelator, State->Offset, feed);
497 // Calculate the late reverb from the decorrelator taps.
498 taps[0] = feed;
499 taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
500 taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
501 taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
502 LateReverb(State, taps, late);
504 // Step all delays forward one sample.
505 State->Offset++;
508 // Perform the EAX reverb pass on a given input sample, resulting in four-
509 // channel output.
510 static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late)
512 ALfloat feed, taps[4];
514 // Low-pass filter the incoming sample.
515 in = lpFilter2P(&State->LpFilter, 0, in);
517 // Perform any modulation on the input.
518 in = EAXModulation(State, in);
520 // Feed the initial delay line.
521 DelayLineIn(&State->Delay, State->Offset, in);
523 // Calculate the early reflection from the first delay tap.
524 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
525 EarlyReflection(State, in, early);
527 // Feed the decorrelator from the energy-attenuated output of the second
528 // delay tap.
529 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
530 feed = in * State->Late.DensityGain;
531 DelayLineIn(&State->Decorrelator, State->Offset, feed);
533 // Calculate the late reverb from the decorrelator taps.
534 taps[0] = feed;
535 taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
536 taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
537 taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
538 LateReverb(State, taps, late);
540 // Calculate and mix in any echo.
541 EAXEcho(State, in, late);
543 // Step all delays forward one sample.
544 State->Offset++;
547 // This processes the reverb state, given the input samples and an output
548 // buffer.
549 static ALvoid VerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
551 ALverbState *State = (ALverbState*)effect;
552 ALuint index, c;
553 ALfloat early[4], late[4], out[4];
554 const ALfloat *panGain = State->Gain;
556 for(index = 0;index < SamplesToDo;index++)
558 // Process reverb for this sample.
559 VerbPass(State, SamplesIn[index], early, late);
561 // Mix early reflections and late reverb.
562 out[0] = (early[0] + late[0]);
563 out[1] = (early[1] + late[1]);
564 out[2] = (early[2] + late[2]);
565 out[3] = (early[3] + late[3]);
567 // Output the results.
568 for(c = 0;c < MAXCHANNELS;c++)
569 SamplesOut[index][c] += panGain[c] * out[c&3];
573 // This processes the EAX reverb state, given the input samples and an output
574 // buffer.
575 static ALvoid EAXVerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
577 ALverbState *State = (ALverbState*)effect;
578 ALuint index, c;
579 ALfloat early[4], late[4];
581 for(index = 0;index < SamplesToDo;index++)
583 // Process reverb for this sample.
584 EAXVerbPass(State, SamplesIn[index], early, late);
586 for(c = 0;c < MAXCHANNELS;c++)
587 SamplesOut[index][c] += State->Early.PanGain[c]*early[c&3] +
588 State->Late.PanGain[c]*late[c&3];
593 // Given the allocated sample buffer, this function updates each delay line
594 // offset.
595 static __inline ALvoid RealizeLineOffset(ALfloat * sampleBuffer, DelayLine *Delay)
597 Delay->Line = &sampleBuffer[(ALintptrEXT)Delay->Line];
600 // Calculate the length of a delay line and store its mask and offset.
601 static ALuint CalcLineLength(ALfloat length, ALintptrEXT offset, ALuint frequency, DelayLine *Delay)
603 ALuint samples;
605 // All line lengths are powers of 2, calculated from their lengths, with
606 // an additional sample in case of rounding errors.
607 samples = NextPowerOf2(fastf2u(length * frequency) + 1);
608 // All lines share a single sample buffer.
609 Delay->Mask = samples - 1;
610 Delay->Line = (ALfloat*)offset;
611 // Return the sample count for accumulation.
612 return samples;
615 /* Calculates the delay line metrics and allocates the shared sample buffer
616 * for all lines given the sample rate (frequency). If an allocation failure
617 * occurs, it returns AL_FALSE.
619 static ALboolean AllocLines(ALuint frequency, ALverbState *State)
621 ALuint totalSamples, index;
622 ALfloat length;
623 ALfloat *newBuffer = NULL;
625 // All delay line lengths are calculated to accomodate the full range of
626 // lengths given their respective paramters.
627 totalSamples = 0;
629 /* The modulator's line length is calculated from the maximum modulation
630 * time and depth coefficient, and halfed for the low-to-high frequency
631 * swing. An additional sample is added to keep it stable when there is no
632 * modulation.
634 length = (AL_EAXREVERB_MAX_MODULATION_TIME*MODULATION_DEPTH_COEFF/2.0f) +
635 (1.0f / frequency);
636 totalSamples += CalcLineLength(length, totalSamples, frequency,
637 &State->Mod.Delay);
639 // The initial delay is the sum of the reflections and late reverb
640 // delays.
641 length = AL_EAXREVERB_MAX_REFLECTIONS_DELAY +
642 AL_EAXREVERB_MAX_LATE_REVERB_DELAY;
643 totalSamples += CalcLineLength(length, totalSamples, frequency,
644 &State->Delay);
646 // The early reflection lines.
647 for(index = 0;index < 4;index++)
648 totalSamples += CalcLineLength(EARLY_LINE_LENGTH[index], totalSamples,
649 frequency, &State->Early.Delay[index]);
651 // The decorrelator line is calculated from the lowest reverb density (a
652 // parameter value of 1).
653 length = (DECO_FRACTION * DECO_MULTIPLIER * DECO_MULTIPLIER) *
654 LATE_LINE_LENGTH[0] * (1.0f + LATE_LINE_MULTIPLIER);
655 totalSamples += CalcLineLength(length, totalSamples, frequency,
656 &State->Decorrelator);
658 // The late all-pass lines.
659 for(index = 0;index < 4;index++)
660 totalSamples += CalcLineLength(ALLPASS_LINE_LENGTH[index], totalSamples,
661 frequency, &State->Late.ApDelay[index]);
663 // The late delay lines are calculated from the lowest reverb density.
664 for(index = 0;index < 4;index++)
666 length = LATE_LINE_LENGTH[index] * (1.0f + LATE_LINE_MULTIPLIER);
667 totalSamples += CalcLineLength(length, totalSamples, frequency,
668 &State->Late.Delay[index]);
671 // The echo all-pass and delay lines.
672 totalSamples += CalcLineLength(ECHO_ALLPASS_LENGTH, totalSamples,
673 frequency, &State->Echo.ApDelay);
674 totalSamples += CalcLineLength(AL_EAXREVERB_MAX_ECHO_TIME, totalSamples,
675 frequency, &State->Echo.Delay);
677 if(totalSamples != State->TotalSamples)
679 TRACE("New reverb buffer length: %u samples (%f sec)\n", totalSamples, totalSamples/(float)frequency);
680 newBuffer = realloc(State->SampleBuffer, sizeof(ALfloat) * totalSamples);
681 if(newBuffer == NULL)
682 return AL_FALSE;
683 State->SampleBuffer = newBuffer;
684 State->TotalSamples = totalSamples;
687 // Update all delays to reflect the new sample buffer.
688 RealizeLineOffset(State->SampleBuffer, &State->Delay);
689 RealizeLineOffset(State->SampleBuffer, &State->Decorrelator);
690 for(index = 0;index < 4;index++)
692 RealizeLineOffset(State->SampleBuffer, &State->Early.Delay[index]);
693 RealizeLineOffset(State->SampleBuffer, &State->Late.ApDelay[index]);
694 RealizeLineOffset(State->SampleBuffer, &State->Late.Delay[index]);
696 RealizeLineOffset(State->SampleBuffer, &State->Mod.Delay);
697 RealizeLineOffset(State->SampleBuffer, &State->Echo.ApDelay);
698 RealizeLineOffset(State->SampleBuffer, &State->Echo.Delay);
700 // Clear the sample buffer.
701 for(index = 0;index < State->TotalSamples;index++)
702 State->SampleBuffer[index] = 0.0f;
704 return AL_TRUE;
707 // This updates the device-dependant EAX reverb state. This is called on
708 // initialization and any time the device parameters (eg. playback frequency,
709 // format) have been changed.
710 static ALboolean ReverbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
712 ALverbState *State = (ALverbState*)effect;
713 ALuint frequency = Device->Frequency, index;
715 // Allocate the delay lines.
716 if(!AllocLines(frequency, State))
717 return AL_FALSE;
719 // Calculate the modulation filter coefficient. Notice that the exponent
720 // is calculated given the current sample rate. This ensures that the
721 // resulting filter response over time is consistent across all sample
722 // rates.
723 State->Mod.Coeff = aluPow(MODULATION_FILTER_COEFF,
724 MODULATION_FILTER_CONST / frequency);
726 // The early reflection and late all-pass filter line lengths are static,
727 // so their offsets only need to be calculated once.
728 for(index = 0;index < 4;index++)
730 State->Early.Offset[index] = fastf2u(EARLY_LINE_LENGTH[index] *
731 frequency);
732 State->Late.ApOffset[index] = fastf2u(ALLPASS_LINE_LENGTH[index] *
733 frequency);
736 // The echo all-pass filter line length is static, so its offset only
737 // needs to be calculated once.
738 State->Echo.ApOffset = fastf2u(ECHO_ALLPASS_LENGTH * frequency);
740 return AL_TRUE;
743 // Calculate a decay coefficient given the length of each cycle and the time
744 // until the decay reaches -60 dB.
745 static __inline ALfloat CalcDecayCoeff(ALfloat length, ALfloat decayTime)
747 return aluPow(0.001f/*-60 dB*/, length/decayTime);
750 // Calculate a decay length from a coefficient and the time until the decay
751 // reaches -60 dB.
752 static __inline ALfloat CalcDecayLength(ALfloat coeff, ALfloat decayTime)
754 return aluLog10(coeff) * decayTime / aluLog10(0.001f)/*-60 dB*/;
757 // Calculate the high frequency parameter for the I3DL2 coefficient
758 // calculation.
759 static __inline ALfloat CalcI3DL2HFreq(ALfloat hfRef, ALuint frequency)
761 return aluCos(F_PI*2.0f * hfRef / frequency);
764 // Calculate an attenuation to be applied to the input of any echo models to
765 // compensate for modal density and decay time.
766 static __inline ALfloat CalcDensityGain(ALfloat a)
768 /* The energy of a signal can be obtained by finding the area under the
769 * squared signal. This takes the form of Sum(x_n^2), where x is the
770 * amplitude for the sample n.
772 * Decaying feedback matches exponential decay of the form Sum(a^n),
773 * where a is the attenuation coefficient, and n is the sample. The area
774 * under this decay curve can be calculated as: 1 / (1 - a).
776 * Modifying the above equation to find the squared area under the curve
777 * (for energy) yields: 1 / (1 - a^2). Input attenuation can then be
778 * calculated by inverting the square root of this approximation,
779 * yielding: 1 / sqrt(1 / (1 - a^2)), simplified to: sqrt(1 - a^2).
781 return aluSqrt(1.0f - (a * a));
784 // Calculate the mixing matrix coefficients given a diffusion factor.
785 static __inline ALvoid CalcMatrixCoeffs(ALfloat diffusion, ALfloat *x, ALfloat *y)
787 ALfloat n, t;
789 // The matrix is of order 4, so n is sqrt (4 - 1).
790 n = aluSqrt(3.0f);
791 t = diffusion * aluAtan(n);
793 // Calculate the first mixing matrix coefficient.
794 *x = aluCos(t);
795 // Calculate the second mixing matrix coefficient.
796 *y = aluSin(t) / n;
799 // Calculate the limited HF ratio for use with the late reverb low-pass
800 // filters.
801 static ALfloat CalcLimitedHfRatio(ALfloat hfRatio, ALfloat airAbsorptionGainHF, ALfloat decayTime)
803 ALfloat limitRatio;
805 /* Find the attenuation due to air absorption in dB (converting delay
806 * time to meters using the speed of sound). Then reversing the decay
807 * equation, solve for HF ratio. The delay length is cancelled out of
808 * the equation, so it can be calculated once for all lines.
810 limitRatio = 1.0f / (CalcDecayLength(airAbsorptionGainHF, decayTime) *
811 SPEEDOFSOUNDMETRESPERSEC);
812 /* Using the limit calculated above, apply the upper bound to the HF
813 * ratio. Also need to limit the result to a minimum of 0.1, just like the
814 * HF ratio parameter. */
815 return clampf(limitRatio, 0.1f, hfRatio);
818 // Calculate the coefficient for a HF (and eventually LF) decay damping
819 // filter.
820 static __inline ALfloat CalcDampingCoeff(ALfloat hfRatio, ALfloat length, ALfloat decayTime, ALfloat decayCoeff, ALfloat cw)
822 ALfloat coeff, g;
824 // Eventually this should boost the high frequencies when the ratio
825 // exceeds 1.
826 coeff = 0.0f;
827 if (hfRatio < 1.0f)
829 // Calculate the low-pass coefficient by dividing the HF decay
830 // coefficient by the full decay coefficient.
831 g = CalcDecayCoeff(length, decayTime * hfRatio) / decayCoeff;
833 // Damping is done with a 1-pole filter, so g needs to be squared.
834 g *= g;
835 coeff = lpCoeffCalc(g, cw);
837 // Very low decay times will produce minimal output, so apply an
838 // upper bound to the coefficient.
839 coeff = minf(coeff, 0.98f);
841 return coeff;
844 // Update the EAX modulation index, range, and depth. Keep in mind that this
845 // kind of vibrato is additive and not multiplicative as one may expect. The
846 // downswing will sound stronger than the upswing.
847 static ALvoid UpdateModulator(ALfloat modTime, ALfloat modDepth, ALuint frequency, ALverbState *State)
849 ALuint range;
851 /* Modulation is calculated in two parts.
853 * The modulation time effects the sinus applied to the change in
854 * frequency. An index out of the current time range (both in samples)
855 * is incremented each sample. The range is bound to a reasonable
856 * minimum (1 sample) and when the timing changes, the index is rescaled
857 * to the new range (to keep the sinus consistent).
859 range = maxu(fastf2u(modTime*frequency), 1);
860 State->Mod.Index = (ALuint)(State->Mod.Index * (ALuint64)range /
861 State->Mod.Range);
862 State->Mod.Range = range;
864 /* The modulation depth effects the amount of frequency change over the
865 * range of the sinus. It needs to be scaled by the modulation time so
866 * that a given depth produces a consistent change in frequency over all
867 * ranges of time. Since the depth is applied to a sinus value, it needs
868 * to be halfed once for the sinus range and again for the sinus swing
869 * in time (half of it is spent decreasing the frequency, half is spent
870 * increasing it).
872 State->Mod.Depth = modDepth * MODULATION_DEPTH_COEFF * modTime / 2.0f /
873 2.0f * frequency;
876 // Update the offsets for the initial effect delay line.
877 static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALuint frequency, ALverbState *State)
879 // Calculate the initial delay taps.
880 State->DelayTap[0] = fastf2u(earlyDelay * frequency);
881 State->DelayTap[1] = fastf2u((earlyDelay + lateDelay) * frequency);
884 // Update the early reflections gain and line coefficients.
885 static ALvoid UpdateEarlyLines(ALfloat reverbGain, ALfloat earlyGain, ALfloat lateDelay, ALverbState *State)
887 ALuint index;
889 // Calculate the early reflections gain (from the master effect gain, and
890 // reflections gain parameters) with a constant attenuation of 0.5.
891 State->Early.Gain = 0.5f * reverbGain * earlyGain;
893 // Calculate the gain (coefficient) for each early delay line using the
894 // late delay time. This expands the early reflections to the start of
895 // the late reverb.
896 for(index = 0;index < 4;index++)
897 State->Early.Coeff[index] = CalcDecayCoeff(EARLY_LINE_LENGTH[index],
898 lateDelay);
901 // Update the offsets for the decorrelator line.
902 static ALvoid UpdateDecorrelator(ALfloat density, ALuint frequency, ALverbState *State)
904 ALuint index;
905 ALfloat length;
907 /* The late reverb inputs are decorrelated to smooth the reverb tail and
908 * reduce harsh echos. The first tap occurs immediately, while the
909 * remaining taps are delayed by multiples of a fraction of the smallest
910 * cyclical delay time.
912 * offset[index] = (FRACTION (MULTIPLIER^index)) smallest_delay
914 for(index = 0;index < 3;index++)
916 length = (DECO_FRACTION * aluPow(DECO_MULTIPLIER, (ALfloat)index)) *
917 LATE_LINE_LENGTH[0] * (1.0f + (density * LATE_LINE_MULTIPLIER));
918 State->DecoTap[index] = fastf2u(length * frequency);
922 // Update the late reverb gains, line lengths, and line coefficients.
923 static ALvoid UpdateLateLines(ALfloat reverbGain, ALfloat lateGain, ALfloat xMix, ALfloat density, ALfloat decayTime, ALfloat diffusion, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State)
925 ALfloat length;
926 ALuint index;
928 /* Calculate the late reverb gain (from the master effect gain, and late
929 * reverb gain parameters). Since the output is tapped prior to the
930 * application of the next delay line coefficients, this gain needs to be
931 * attenuated by the 'x' mixing matrix coefficient as well.
933 State->Late.Gain = reverbGain * lateGain * xMix;
935 /* To compensate for changes in modal density and decay time of the late
936 * reverb signal, the input is attenuated based on the maximal energy of
937 * the outgoing signal. This approximation is used to keep the apparent
938 * energy of the signal equal for all ranges of density and decay time.
940 * The average length of the cyclcical delay lines is used to calculate
941 * the attenuation coefficient.
943 length = (LATE_LINE_LENGTH[0] + LATE_LINE_LENGTH[1] +
944 LATE_LINE_LENGTH[2] + LATE_LINE_LENGTH[3]) / 4.0f;
945 length *= 1.0f + (density * LATE_LINE_MULTIPLIER);
946 State->Late.DensityGain = CalcDensityGain(CalcDecayCoeff(length,
947 decayTime));
949 // Calculate the all-pass feed-back and feed-forward coefficient.
950 State->Late.ApFeedCoeff = 0.5f * aluPow(diffusion, 2.0f);
952 for(index = 0;index < 4;index++)
954 // Calculate the gain (coefficient) for each all-pass line.
955 State->Late.ApCoeff[index] = CalcDecayCoeff(ALLPASS_LINE_LENGTH[index],
956 decayTime);
958 // Calculate the length (in seconds) of each cyclical delay line.
959 length = LATE_LINE_LENGTH[index] * (1.0f + (density *
960 LATE_LINE_MULTIPLIER));
962 // Calculate the delay offset for each cyclical delay line.
963 State->Late.Offset[index] = fastf2u(length * frequency);
965 // Calculate the gain (coefficient) for each cyclical line.
966 State->Late.Coeff[index] = CalcDecayCoeff(length, decayTime);
968 // Calculate the damping coefficient for each low-pass filter.
969 State->Late.LpCoeff[index] =
970 CalcDampingCoeff(hfRatio, length, decayTime,
971 State->Late.Coeff[index], cw);
973 // Attenuate the cyclical line coefficients by the mixing coefficient
974 // (x).
975 State->Late.Coeff[index] *= xMix;
979 // Update the echo gain, line offset, line coefficients, and mixing
980 // coefficients.
981 static ALvoid UpdateEchoLine(ALfloat reverbGain, ALfloat lateGain, ALfloat echoTime, ALfloat decayTime, ALfloat diffusion, ALfloat echoDepth, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State)
983 // Update the offset and coefficient for the echo delay line.
984 State->Echo.Offset = fastf2u(echoTime * frequency);
986 // Calculate the decay coefficient for the echo line.
987 State->Echo.Coeff = CalcDecayCoeff(echoTime, decayTime);
989 // Calculate the energy-based attenuation coefficient for the echo delay
990 // line.
991 State->Echo.DensityGain = CalcDensityGain(State->Echo.Coeff);
993 // Calculate the echo all-pass feed coefficient.
994 State->Echo.ApFeedCoeff = 0.5f * aluPow(diffusion, 2.0f);
996 // Calculate the echo all-pass attenuation coefficient.
997 State->Echo.ApCoeff = CalcDecayCoeff(ECHO_ALLPASS_LENGTH, decayTime);
999 // Calculate the damping coefficient for each low-pass filter.
1000 State->Echo.LpCoeff = CalcDampingCoeff(hfRatio, echoTime, decayTime,
1001 State->Echo.Coeff, cw);
1003 /* Calculate the echo mixing coefficients. The first is applied to the
1004 * echo itself. The second is used to attenuate the late reverb when
1005 * echo depth is high and diffusion is low, so the echo is slightly
1006 * stronger than the decorrelated echos in the reverb tail.
1008 State->Echo.MixCoeff[0] = reverbGain * lateGain * echoDepth;
1009 State->Echo.MixCoeff[1] = 1.0f - (echoDepth * 0.5f * (1.0f - diffusion));
1012 // Update the early and late 3D panning gains.
1013 static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALverbState *State)
1015 ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1],
1016 ReflectionsPan[2] };
1017 ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
1018 LateReverbPan[2] };
1019 const ALfloat *ChannelGain;
1020 ALfloat ambientGain;
1021 ALfloat dirGain;
1022 ALfloat length;
1023 ALuint index;
1024 ALint pos;
1026 Gain *= ReverbBoost;
1028 // Attenuate non-directional reverb according to the number of channels
1029 ambientGain = aluSqrt(2.0f/Device->NumChan);
1031 // Calculate the 3D-panning gains for the early reflections and late
1032 // reverb.
1033 length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
1034 if(length > 1.0f)
1036 length = 1.0f / aluSqrt(length);
1037 earlyPan[0] *= length;
1038 earlyPan[1] *= length;
1039 earlyPan[2] *= length;
1041 length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2];
1042 if(length > 1.0f)
1044 length = 1.0f / aluSqrt(length);
1045 latePan[0] *= length;
1046 latePan[1] *= length;
1047 latePan[2] *= length;
1050 /* This code applies directional reverb just like the mixer applies
1051 * directional sources. It diffuses the sound toward all speakers as the
1052 * magnitude of the panning vector drops, which is only a rough
1053 * approximation of the expansion of sound across the speakers from the
1054 * panning direction.
1056 pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]);
1057 ChannelGain = Device->PanningLUT[pos];
1058 dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2]));
1060 for(index = 0;index < MAXCHANNELS;index++)
1061 State->Early.PanGain[index] = 0.0f;
1062 for(index = 0;index < Device->NumChan;index++)
1064 enum Channel chan = Device->Speaker2Chan[index];
1065 State->Early.PanGain[chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * Gain;
1069 pos = aluCart2LUTpos(latePan[2], latePan[0]);
1070 ChannelGain = Device->PanningLUT[pos];
1071 dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2]));
1073 for(index = 0;index < MAXCHANNELS;index++)
1074 State->Late.PanGain[index] = 0.0f;
1075 for(index = 0;index < Device->NumChan;index++)
1077 enum Channel chan = Device->Speaker2Chan[index];
1078 State->Late.PanGain[chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * Gain;
1082 // This updates the EAX reverb state. This is called any time the EAX reverb
1083 // effect is loaded into a slot.
1084 static ALvoid ReverbUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot)
1086 ALverbState *State = (ALverbState*)effect;
1087 ALuint frequency = Device->Frequency;
1088 ALboolean isEAX = AL_FALSE;
1089 ALfloat cw, x, y, hfRatio;
1091 if(Slot->effect.type == AL_EFFECT_EAXREVERB && !EmulateEAXReverb)
1093 State->state.Process = EAXVerbProcess;
1094 isEAX = AL_TRUE;
1096 else if(Slot->effect.type == AL_EFFECT_REVERB || EmulateEAXReverb)
1098 State->state.Process = VerbProcess;
1099 isEAX = AL_FALSE;
1102 // Calculate the master low-pass filter (from the master effect HF gain).
1103 if(isEAX) cw = CalcI3DL2HFreq(Slot->effect.Reverb.HFReference, frequency);
1104 else cw = CalcI3DL2HFreq(LOWPASSFREQREF, frequency);
1105 // This is done with 2 chained 1-pole filters, so no need to square g.
1106 State->LpFilter.coeff = lpCoeffCalc(Slot->effect.Reverb.GainHF, cw);
1108 if(isEAX)
1110 // Update the modulator line.
1111 UpdateModulator(Slot->effect.Reverb.ModulationTime,
1112 Slot->effect.Reverb.ModulationDepth,
1113 frequency, State);
1116 // Update the initial effect delay.
1117 UpdateDelayLine(Slot->effect.Reverb.ReflectionsDelay,
1118 Slot->effect.Reverb.LateReverbDelay,
1119 frequency, State);
1121 // Update the early lines.
1122 UpdateEarlyLines(Slot->effect.Reverb.Gain,
1123 Slot->effect.Reverb.ReflectionsGain,
1124 Slot->effect.Reverb.LateReverbDelay, State);
1126 // Update the decorrelator.
1127 UpdateDecorrelator(Slot->effect.Reverb.Density, frequency, State);
1129 // Get the mixing matrix coefficients (x and y).
1130 CalcMatrixCoeffs(Slot->effect.Reverb.Diffusion, &x, &y);
1131 // Then divide x into y to simplify the matrix calculation.
1132 State->Late.MixCoeff = y / x;
1134 // If the HF limit parameter is flagged, calculate an appropriate limit
1135 // based on the air absorption parameter.
1136 hfRatio = Slot->effect.Reverb.DecayHFRatio;
1137 if(Slot->effect.Reverb.DecayHFLimit &&
1138 Slot->effect.Reverb.AirAbsorptionGainHF < 1.0f)
1139 hfRatio = CalcLimitedHfRatio(hfRatio,
1140 Slot->effect.Reverb.AirAbsorptionGainHF,
1141 Slot->effect.Reverb.DecayTime);
1143 // Update the late lines.
1144 UpdateLateLines(Slot->effect.Reverb.Gain, Slot->effect.Reverb.LateReverbGain,
1145 x, Slot->effect.Reverb.Density, Slot->effect.Reverb.DecayTime,
1146 Slot->effect.Reverb.Diffusion, hfRatio, cw, frequency, State);
1148 if(isEAX)
1150 // Update the echo line.
1151 UpdateEchoLine(Slot->effect.Reverb.Gain, Slot->effect.Reverb.LateReverbGain,
1152 Slot->effect.Reverb.EchoTime, Slot->effect.Reverb.DecayTime,
1153 Slot->effect.Reverb.Diffusion, Slot->effect.Reverb.EchoDepth,
1154 hfRatio, cw, frequency, State);
1156 // Update early and late 3D panning.
1157 Update3DPanning(Device, Slot->effect.Reverb.ReflectionsPan,
1158 Slot->effect.Reverb.LateReverbPan, Slot->Gain, State);
1160 else
1162 ALfloat gain = Slot->Gain;
1163 ALuint index;
1165 /* Update channel gains */
1166 gain *= aluSqrt(2.0f/Device->NumChan) * ReverbBoost;
1167 for(index = 0;index < MAXCHANNELS;index++)
1168 State->Gain[index] = 0.0f;
1169 for(index = 0;index < Device->NumChan;index++)
1171 enum Channel chan = Device->Speaker2Chan[index];
1172 State->Gain[chan] = gain;
1177 // This destroys the reverb state. It should be called only when the effect
1178 // slot has a different (or no) effect loaded over the reverb effect.
1179 static ALvoid ReverbDestroy(ALeffectState *effect)
1181 ALverbState *State = (ALverbState*)effect;
1182 if(State)
1184 free(State->SampleBuffer);
1185 State->SampleBuffer = NULL;
1186 free(State);
1190 // This creates the reverb state. It should be called only when the reverb
1191 // effect is loaded into a slot that doesn't already have a reverb effect.
1192 ALeffectState *ReverbCreate(void)
1194 ALverbState *State = NULL;
1195 ALuint index;
1197 State = malloc(sizeof(ALverbState));
1198 if(!State)
1199 return NULL;
1201 State->state.Destroy = ReverbDestroy;
1202 State->state.DeviceUpdate = ReverbDeviceUpdate;
1203 State->state.Update = ReverbUpdate;
1204 State->state.Process = VerbProcess;
1206 State->TotalSamples = 0;
1207 State->SampleBuffer = NULL;
1209 State->LpFilter.coeff = 0.0f;
1210 State->LpFilter.history[0] = 0.0f;
1211 State->LpFilter.history[1] = 0.0f;
1213 State->Mod.Delay.Mask = 0;
1214 State->Mod.Delay.Line = NULL;
1215 State->Mod.Index = 0;
1216 State->Mod.Range = 1;
1217 State->Mod.Depth = 0.0f;
1218 State->Mod.Coeff = 0.0f;
1219 State->Mod.Filter = 0.0f;
1221 State->Delay.Mask = 0;
1222 State->Delay.Line = NULL;
1223 State->DelayTap[0] = 0;
1224 State->DelayTap[1] = 0;
1226 State->Early.Gain = 0.0f;
1227 for(index = 0;index < 4;index++)
1229 State->Early.Coeff[index] = 0.0f;
1230 State->Early.Delay[index].Mask = 0;
1231 State->Early.Delay[index].Line = NULL;
1232 State->Early.Offset[index] = 0;
1235 State->Decorrelator.Mask = 0;
1236 State->Decorrelator.Line = NULL;
1237 State->DecoTap[0] = 0;
1238 State->DecoTap[1] = 0;
1239 State->DecoTap[2] = 0;
1241 State->Late.Gain = 0.0f;
1242 State->Late.DensityGain = 0.0f;
1243 State->Late.ApFeedCoeff = 0.0f;
1244 State->Late.MixCoeff = 0.0f;
1245 for(index = 0;index < 4;index++)
1247 State->Late.ApCoeff[index] = 0.0f;
1248 State->Late.ApDelay[index].Mask = 0;
1249 State->Late.ApDelay[index].Line = NULL;
1250 State->Late.ApOffset[index] = 0;
1252 State->Late.Coeff[index] = 0.0f;
1253 State->Late.Delay[index].Mask = 0;
1254 State->Late.Delay[index].Line = NULL;
1255 State->Late.Offset[index] = 0;
1257 State->Late.LpCoeff[index] = 0.0f;
1258 State->Late.LpSample[index] = 0.0f;
1261 for(index = 0;index < MAXCHANNELS;index++)
1263 State->Early.PanGain[index] = 0.0f;
1264 State->Late.PanGain[index] = 0.0f;
1267 State->Echo.DensityGain = 0.0f;
1268 State->Echo.Delay.Mask = 0;
1269 State->Echo.Delay.Line = NULL;
1270 State->Echo.ApDelay.Mask = 0;
1271 State->Echo.ApDelay.Line = NULL;
1272 State->Echo.Coeff = 0.0f;
1273 State->Echo.ApFeedCoeff = 0.0f;
1274 State->Echo.ApCoeff = 0.0f;
1275 State->Echo.Offset = 0;
1276 State->Echo.ApOffset = 0;
1277 State->Echo.LpCoeff = 0.0f;
1278 State->Echo.LpSample = 0.0f;
1279 State->Echo.MixCoeff[0] = 0.0f;
1280 State->Echo.MixCoeff[1] = 0.0f;
1282 State->Offset = 0;
1284 State->Gain = State->Late.PanGain;
1286 return &State->state;