Print an error if trying to handle a missed source property
[openal-soft.git] / Alc / alcReverb.c
blobb7dcdab91dd42f1082be5e288a5755eda5e2c46e
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;
160 /* Temporary storage used when processing, before deinterlacing. */
161 ALfloat ReverbSamples[BUFFERSIZE][4];
162 ALfloat EarlySamples[BUFFERSIZE][4];
163 } ALverbState;
165 /* This is a user config option for modifying the overall output of the reverb
166 * effect.
168 ALfloat ReverbBoost = 1.0f;
170 /* Specifies whether to use a standard reverb effect in place of EAX reverb */
171 ALboolean EmulateEAXReverb = AL_FALSE;
173 /* This coefficient is used to define the maximum frequency range controlled
174 * by the modulation depth. The current value of 0.1 will allow it to swing
175 * from 0.9x to 1.1x. This value must be below 1. At 1 it will cause the
176 * sampler to stall on the downswing, and above 1 it will cause it to sample
177 * backwards.
179 static const ALfloat MODULATION_DEPTH_COEFF = 0.1f;
181 /* A filter is used to avoid the terrible distortion caused by changing
182 * modulation time and/or depth. To be consistent across different sample
183 * rates, the coefficient must be raised to a constant divided by the sample
184 * rate: coeff^(constant / rate).
186 static const ALfloat MODULATION_FILTER_COEFF = 0.048f;
187 static const ALfloat MODULATION_FILTER_CONST = 100000.0f;
189 // When diffusion is above 0, an all-pass filter is used to take the edge off
190 // the echo effect. It uses the following line length (in seconds).
191 static const ALfloat ECHO_ALLPASS_LENGTH = 0.0133f;
193 // Input into the late reverb is decorrelated between four channels. Their
194 // timings are dependent on a fraction and multiplier. See the
195 // UpdateDecorrelator() routine for the calculations involved.
196 static const ALfloat DECO_FRACTION = 0.15f;
197 static const ALfloat DECO_MULTIPLIER = 2.0f;
199 // All delay line lengths are specified in seconds.
201 // The lengths of the early delay lines.
202 static const ALfloat EARLY_LINE_LENGTH[4] =
204 0.0015f, 0.0045f, 0.0135f, 0.0405f
207 // The lengths of the late all-pass delay lines.
208 static const ALfloat ALLPASS_LINE_LENGTH[4] =
210 0.0151f, 0.0167f, 0.0183f, 0.0200f,
213 // The lengths of the late cyclical delay lines.
214 static const ALfloat LATE_LINE_LENGTH[4] =
216 0.0211f, 0.0311f, 0.0461f, 0.0680f
219 // The late cyclical delay lines have a variable length dependent on the
220 // effect's density parameter (inverted for some reason) and this multiplier.
221 static const ALfloat LATE_LINE_MULTIPLIER = 4.0f;
224 // Basic delay line input/output routines.
225 static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
227 return Delay->Line[offset&Delay->Mask];
230 static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
232 Delay->Line[offset&Delay->Mask] = in;
235 // Attenuated delay line output routine.
236 static __inline ALfloat AttenuatedDelayLineOut(DelayLine *Delay, ALuint offset, ALfloat coeff)
238 return coeff * Delay->Line[offset&Delay->Mask];
241 // Basic attenuated all-pass input/output routine.
242 static __inline ALfloat AllpassInOut(DelayLine *Delay, ALuint outOffset, ALuint inOffset, ALfloat in, ALfloat feedCoeff, ALfloat coeff)
244 ALfloat out, feed;
246 out = DelayLineOut(Delay, outOffset);
247 feed = feedCoeff * in;
248 DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in);
250 // The time-based attenuation is only applied to the delay output to
251 // keep it from affecting the feed-back path (which is already controlled
252 // by the all-pass feed coefficient).
253 return (coeff * out) - feed;
256 // Given an input sample, this function produces modulation for the late
257 // reverb.
258 static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in)
260 ALfloat sinus, frac;
261 ALuint offset;
262 ALfloat out0, out1;
264 // Calculate the sinus rythm (dependent on modulation time and the
265 // sampling rate). The center of the sinus is moved to reduce the delay
266 // of the effect when the time or depth are low.
267 sinus = 1.0f - cosf(F_PI*2.0f * State->Mod.Index / State->Mod.Range);
269 // The depth determines the range over which to read the input samples
270 // from, so it must be filtered to reduce the distortion caused by even
271 // small parameter changes.
272 State->Mod.Filter = lerp(State->Mod.Filter, State->Mod.Depth,
273 State->Mod.Coeff);
275 // Calculate the read offset and fraction between it and the next sample.
276 frac = (1.0f + (State->Mod.Filter * sinus));
277 offset = fastf2u(frac);
278 frac -= offset;
280 // Get the two samples crossed by the offset, and feed the delay line
281 // with the next input sample.
282 out0 = DelayLineOut(&State->Mod.Delay, State->Offset - offset);
283 out1 = DelayLineOut(&State->Mod.Delay, State->Offset - offset - 1);
284 DelayLineIn(&State->Mod.Delay, State->Offset, in);
286 // Step the modulation index forward, keeping it bound to its range.
287 State->Mod.Index = (State->Mod.Index + 1) % State->Mod.Range;
289 // The output is obtained by linearly interpolating the two samples that
290 // were acquired above.
291 return lerp(out0, out1, frac);
294 // Delay line output routine for early reflections.
295 static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
297 return AttenuatedDelayLineOut(&State->Early.Delay[index],
298 State->Offset - State->Early.Offset[index],
299 State->Early.Coeff[index]);
302 // Given an input sample, this function produces four-channel output for the
303 // early reflections.
304 static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *RESTRICT out)
306 ALfloat d[4], v, f[4];
308 // Obtain the decayed results of each early delay line.
309 d[0] = EarlyDelayLineOut(State, 0);
310 d[1] = EarlyDelayLineOut(State, 1);
311 d[2] = EarlyDelayLineOut(State, 2);
312 d[3] = EarlyDelayLineOut(State, 3);
314 /* The following uses a lossless scattering junction from waveguide
315 * theory. It actually amounts to a householder mixing matrix, which
316 * will produce a maximally diffuse response, and means this can probably
317 * be considered a simple feed-back delay network (FDN).
319 * ---
321 * v = 2/N / d_i
322 * ---
323 * i=1
325 v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
326 // The junction is loaded with the input here.
327 v += in;
329 // Calculate the feed values for the delay lines.
330 f[0] = v - d[0];
331 f[1] = v - d[1];
332 f[2] = v - d[2];
333 f[3] = v - d[3];
335 // Re-feed the delay lines.
336 DelayLineIn(&State->Early.Delay[0], State->Offset, f[0]);
337 DelayLineIn(&State->Early.Delay[1], State->Offset, f[1]);
338 DelayLineIn(&State->Early.Delay[2], State->Offset, f[2]);
339 DelayLineIn(&State->Early.Delay[3], State->Offset, f[3]);
341 // Output the results of the junction for all four channels.
342 out[0] = State->Early.Gain * f[0];
343 out[1] = State->Early.Gain * f[1];
344 out[2] = State->Early.Gain * f[2];
345 out[3] = State->Early.Gain * f[3];
348 // All-pass input/output routine for late reverb.
349 static __inline ALfloat LateAllPassInOut(ALverbState *State, ALuint index, ALfloat in)
351 return AllpassInOut(&State->Late.ApDelay[index],
352 State->Offset - State->Late.ApOffset[index],
353 State->Offset, in, State->Late.ApFeedCoeff,
354 State->Late.ApCoeff[index]);
357 // Delay line output routine for late reverb.
358 static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
360 return AttenuatedDelayLineOut(&State->Late.Delay[index],
361 State->Offset - State->Late.Offset[index],
362 State->Late.Coeff[index]);
365 // Low-pass filter input/output routine for late reverb.
366 static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
368 in = lerp(in, State->Late.LpSample[index], State->Late.LpCoeff[index]);
369 State->Late.LpSample[index] = in;
370 return in;
373 // Given four decorrelated input samples, this function produces four-channel
374 // output for the late reverb.
375 static __inline ALvoid LateReverb(ALverbState *State, const ALfloat *RESTRICT in, ALfloat *RESTRICT out)
377 ALfloat d[4], f[4];
379 // Obtain the decayed results of the cyclical delay lines, and add the
380 // corresponding input channels. Then pass the results through the
381 // low-pass filters.
383 // This is where the feed-back cycles from line 0 to 1 to 3 to 2 and back
384 // to 0.
385 d[0] = LateLowPassInOut(State, 2, in[2] + LateDelayLineOut(State, 2));
386 d[1] = LateLowPassInOut(State, 0, in[0] + LateDelayLineOut(State, 0));
387 d[2] = LateLowPassInOut(State, 3, in[3] + LateDelayLineOut(State, 3));
388 d[3] = LateLowPassInOut(State, 1, in[1] + LateDelayLineOut(State, 1));
390 // To help increase diffusion, run each line through an all-pass filter.
391 // When there is no diffusion, the shortest all-pass filter will feed the
392 // shortest delay line.
393 d[0] = LateAllPassInOut(State, 0, d[0]);
394 d[1] = LateAllPassInOut(State, 1, d[1]);
395 d[2] = LateAllPassInOut(State, 2, d[2]);
396 d[3] = LateAllPassInOut(State, 3, d[3]);
398 /* Late reverb is done with a modified feed-back delay network (FDN)
399 * topology. Four input lines are each fed through their own all-pass
400 * filter and then into the mixing matrix. The four outputs of the
401 * mixing matrix are then cycled back to the inputs. Each output feeds
402 * a different input to form a circlular feed cycle.
404 * The mixing matrix used is a 4D skew-symmetric rotation matrix derived
405 * using a single unitary rotational parameter:
407 * [ d, a, b, c ] 1 = a^2 + b^2 + c^2 + d^2
408 * [ -a, d, c, -b ]
409 * [ -b, -c, d, a ]
410 * [ -c, b, -a, d ]
412 * The rotation is constructed from the effect's diffusion parameter,
413 * yielding: 1 = x^2 + 3 y^2; where a, b, and c are the coefficient y
414 * with differing signs, and d is the coefficient x. The matrix is thus:
416 * [ x, y, -y, y ] n = sqrt(matrix_order - 1)
417 * [ -y, x, y, y ] t = diffusion_parameter * atan(n)
418 * [ y, -y, x, y ] x = cos(t)
419 * [ -y, -y, -y, x ] y = sin(t) / n
421 * To reduce the number of multiplies, the x coefficient is applied with
422 * the cyclical delay line coefficients. Thus only the y coefficient is
423 * applied when mixing, and is modified to be: y / x.
425 f[0] = d[0] + (State->Late.MixCoeff * ( d[1] + -d[2] + d[3]));
426 f[1] = d[1] + (State->Late.MixCoeff * (-d[0] + d[2] + d[3]));
427 f[2] = d[2] + (State->Late.MixCoeff * ( d[0] + -d[1] + d[3]));
428 f[3] = d[3] + (State->Late.MixCoeff * (-d[0] + -d[1] + -d[2] ));
430 // Output the results of the matrix for all four channels, attenuated by
431 // the late reverb gain (which is attenuated by the 'x' mix coefficient).
432 out[0] = State->Late.Gain * f[0];
433 out[1] = State->Late.Gain * f[1];
434 out[2] = State->Late.Gain * f[2];
435 out[3] = State->Late.Gain * f[3];
437 // Re-feed the cyclical delay lines.
438 DelayLineIn(&State->Late.Delay[0], State->Offset, f[0]);
439 DelayLineIn(&State->Late.Delay[1], State->Offset, f[1]);
440 DelayLineIn(&State->Late.Delay[2], State->Offset, f[2]);
441 DelayLineIn(&State->Late.Delay[3], State->Offset, f[3]);
444 // Given an input sample, this function mixes echo into the four-channel late
445 // reverb.
446 static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *RESTRICT late)
448 ALfloat out, feed;
450 // Get the latest attenuated echo sample for output.
451 feed = AttenuatedDelayLineOut(&State->Echo.Delay,
452 State->Offset - State->Echo.Offset,
453 State->Echo.Coeff);
455 // Mix the output into the late reverb channels.
456 out = State->Echo.MixCoeff[0] * feed;
457 late[0] = (State->Echo.MixCoeff[1] * late[0]) + out;
458 late[1] = (State->Echo.MixCoeff[1] * late[1]) + out;
459 late[2] = (State->Echo.MixCoeff[1] * late[2]) + out;
460 late[3] = (State->Echo.MixCoeff[1] * late[3]) + out;
462 // Mix the energy-attenuated input with the output and pass it through
463 // the echo low-pass filter.
464 feed += State->Echo.DensityGain * in;
465 feed = lerp(feed, State->Echo.LpSample, State->Echo.LpCoeff);
466 State->Echo.LpSample = feed;
468 // Then the echo all-pass filter.
469 feed = AllpassInOut(&State->Echo.ApDelay,
470 State->Offset - State->Echo.ApOffset,
471 State->Offset, feed, State->Echo.ApFeedCoeff,
472 State->Echo.ApCoeff);
474 // Feed the delay with the mixed and filtered sample.
475 DelayLineIn(&State->Echo.Delay, State->Offset, feed);
478 // Perform the non-EAX reverb pass on a given input sample, resulting in
479 // four-channel output.
480 static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *RESTRICT out)
482 ALfloat feed, late[4], taps[4];
484 // Low-pass filter the incoming sample.
485 in = lpFilter2P(&State->LpFilter, 0, in);
487 // Feed the initial delay line.
488 DelayLineIn(&State->Delay, State->Offset, in);
490 // Calculate the early reflection from the first delay tap.
491 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
492 EarlyReflection(State, in, out);
494 // Feed the decorrelator from the energy-attenuated output of the second
495 // delay tap.
496 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
497 feed = in * State->Late.DensityGain;
498 DelayLineIn(&State->Decorrelator, State->Offset, feed);
500 // Calculate the late reverb from the decorrelator taps.
501 taps[0] = feed;
502 taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
503 taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
504 taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
505 LateReverb(State, taps, late);
507 // Mix early reflections and late reverb.
508 out[0] += late[0];
509 out[1] += late[1];
510 out[2] += late[2];
511 out[3] += late[3];
513 // Step all delays forward one sample.
514 State->Offset++;
517 // Perform the EAX reverb pass on a given input sample, resulting in four-
518 // channel output.
519 static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *RESTRICT early, ALfloat *RESTRICT late)
521 ALfloat feed, taps[4];
523 // Low-pass filter the incoming sample.
524 in = lpFilter2P(&State->LpFilter, 0, in);
526 // Perform any modulation on the input.
527 in = EAXModulation(State, in);
529 // Feed the initial delay line.
530 DelayLineIn(&State->Delay, State->Offset, in);
532 // Calculate the early reflection from the first delay tap.
533 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
534 EarlyReflection(State, in, early);
536 // Feed the decorrelator from the energy-attenuated output of the second
537 // delay tap.
538 in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
539 feed = in * State->Late.DensityGain;
540 DelayLineIn(&State->Decorrelator, State->Offset, feed);
542 // Calculate the late reverb from the decorrelator taps.
543 taps[0] = feed;
544 taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
545 taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
546 taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
547 LateReverb(State, taps, late);
549 // Calculate and mix in any echo.
550 EAXEcho(State, in, late);
552 // Step all delays forward one sample.
553 State->Offset++;
556 // This processes the reverb state, given the input samples and an output
557 // buffer.
558 static ALvoid VerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
560 ALverbState *State = (ALverbState*)effect;
561 ALfloat (*RESTRICT out)[4] = State->ReverbSamples;
562 ALuint index, c;
564 /* Process reverb for these samples. */
565 for(index = 0;index < SamplesToDo;index++)
566 VerbPass(State, SamplesIn[index], out[index]);
568 for(c = 0;c < MaxChannels;c++)
570 ALfloat gain = State->Gain[c];
571 if(gain > 0.00001f)
573 for(index = 0;index < SamplesToDo;index++)
574 SamplesOut[c][index] += gain * out[index][c&3];
579 // This processes the EAX reverb state, given the input samples and an output
580 // buffer.
581 static ALvoid EAXVerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
583 ALverbState *State = (ALverbState*)effect;
584 ALfloat (*RESTRICT early)[4] = State->EarlySamples;
585 ALfloat (*RESTRICT late)[4] = State->ReverbSamples;
586 ALuint index, c;
588 /* Process reverb for these samples. */
589 for(index = 0;index < SamplesToDo;index++)
590 EAXVerbPass(State, SamplesIn[index], early[index], late[index]);
592 for(c = 0;c < MaxChannels;c++)
594 ALfloat earlyGain = State->Early.PanGain[c];
595 ALfloat lateGain = State->Late.PanGain[c];
597 if(earlyGain > 0.00001f)
599 for(index = 0;index < SamplesToDo;index++)
600 SamplesOut[c][index] += earlyGain*early[index][c&3];
602 if(lateGain > 0.00001f)
604 for(index = 0;index < SamplesToDo;index++)
605 SamplesOut[c][index] += lateGain*late[index][c&3];
611 // Given the allocated sample buffer, this function updates each delay line
612 // offset.
613 static __inline ALvoid RealizeLineOffset(ALfloat *sampleBuffer, DelayLine *Delay)
615 Delay->Line = &sampleBuffer[(ALintptrEXT)Delay->Line];
618 // Calculate the length of a delay line and store its mask and offset.
619 static ALuint CalcLineLength(ALfloat length, ALintptrEXT offset, ALuint frequency, DelayLine *Delay)
621 ALuint samples;
623 // All line lengths are powers of 2, calculated from their lengths, with
624 // an additional sample in case of rounding errors.
625 samples = NextPowerOf2(fastf2u(length * frequency) + 1);
626 // All lines share a single sample buffer.
627 Delay->Mask = samples - 1;
628 Delay->Line = (ALfloat*)offset;
629 // Return the sample count for accumulation.
630 return samples;
633 /* Calculates the delay line metrics and allocates the shared sample buffer
634 * for all lines given the sample rate (frequency). If an allocation failure
635 * occurs, it returns AL_FALSE.
637 static ALboolean AllocLines(ALuint frequency, ALverbState *State)
639 ALuint totalSamples, index;
640 ALfloat length;
641 ALfloat *newBuffer = NULL;
643 // All delay line lengths are calculated to accomodate the full range of
644 // lengths given their respective paramters.
645 totalSamples = 0;
647 /* The modulator's line length is calculated from the maximum modulation
648 * time and depth coefficient, and halfed for the low-to-high frequency
649 * swing. An additional sample is added to keep it stable when there is no
650 * modulation.
652 length = (AL_EAXREVERB_MAX_MODULATION_TIME*MODULATION_DEPTH_COEFF/2.0f) +
653 (1.0f / frequency);
654 totalSamples += CalcLineLength(length, totalSamples, frequency,
655 &State->Mod.Delay);
657 // The initial delay is the sum of the reflections and late reverb
658 // delays.
659 length = AL_EAXREVERB_MAX_REFLECTIONS_DELAY +
660 AL_EAXREVERB_MAX_LATE_REVERB_DELAY;
661 totalSamples += CalcLineLength(length, totalSamples, frequency,
662 &State->Delay);
664 // The early reflection lines.
665 for(index = 0;index < 4;index++)
666 totalSamples += CalcLineLength(EARLY_LINE_LENGTH[index], totalSamples,
667 frequency, &State->Early.Delay[index]);
669 // The decorrelator line is calculated from the lowest reverb density (a
670 // parameter value of 1).
671 length = (DECO_FRACTION * DECO_MULTIPLIER * DECO_MULTIPLIER) *
672 LATE_LINE_LENGTH[0] * (1.0f + LATE_LINE_MULTIPLIER);
673 totalSamples += CalcLineLength(length, totalSamples, frequency,
674 &State->Decorrelator);
676 // The late all-pass lines.
677 for(index = 0;index < 4;index++)
678 totalSamples += CalcLineLength(ALLPASS_LINE_LENGTH[index], totalSamples,
679 frequency, &State->Late.ApDelay[index]);
681 // The late delay lines are calculated from the lowest reverb density.
682 for(index = 0;index < 4;index++)
684 length = LATE_LINE_LENGTH[index] * (1.0f + LATE_LINE_MULTIPLIER);
685 totalSamples += CalcLineLength(length, totalSamples, frequency,
686 &State->Late.Delay[index]);
689 // The echo all-pass and delay lines.
690 totalSamples += CalcLineLength(ECHO_ALLPASS_LENGTH, totalSamples,
691 frequency, &State->Echo.ApDelay);
692 totalSamples += CalcLineLength(AL_EAXREVERB_MAX_ECHO_TIME, totalSamples,
693 frequency, &State->Echo.Delay);
695 if(totalSamples != State->TotalSamples)
697 TRACE("New reverb buffer length: %u samples (%f sec)\n", totalSamples, totalSamples/(float)frequency);
698 newBuffer = realloc(State->SampleBuffer, sizeof(ALfloat) * totalSamples);
699 if(newBuffer == NULL)
700 return AL_FALSE;
701 State->SampleBuffer = newBuffer;
702 State->TotalSamples = totalSamples;
705 // Update all delays to reflect the new sample buffer.
706 RealizeLineOffset(State->SampleBuffer, &State->Delay);
707 RealizeLineOffset(State->SampleBuffer, &State->Decorrelator);
708 for(index = 0;index < 4;index++)
710 RealizeLineOffset(State->SampleBuffer, &State->Early.Delay[index]);
711 RealizeLineOffset(State->SampleBuffer, &State->Late.ApDelay[index]);
712 RealizeLineOffset(State->SampleBuffer, &State->Late.Delay[index]);
714 RealizeLineOffset(State->SampleBuffer, &State->Mod.Delay);
715 RealizeLineOffset(State->SampleBuffer, &State->Echo.ApDelay);
716 RealizeLineOffset(State->SampleBuffer, &State->Echo.Delay);
718 // Clear the sample buffer.
719 for(index = 0;index < State->TotalSamples;index++)
720 State->SampleBuffer[index] = 0.0f;
722 return AL_TRUE;
725 // This updates the device-dependant EAX reverb state. This is called on
726 // initialization and any time the device parameters (eg. playback frequency,
727 // format) have been changed.
728 static ALboolean ReverbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
730 ALverbState *State = (ALverbState*)effect;
731 ALuint frequency = Device->Frequency, index;
733 // Allocate the delay lines.
734 if(!AllocLines(frequency, State))
735 return AL_FALSE;
737 // Calculate the modulation filter coefficient. Notice that the exponent
738 // is calculated given the current sample rate. This ensures that the
739 // resulting filter response over time is consistent across all sample
740 // rates.
741 State->Mod.Coeff = powf(MODULATION_FILTER_COEFF,
742 MODULATION_FILTER_CONST / frequency);
744 // The early reflection and late all-pass filter line lengths are static,
745 // so their offsets only need to be calculated once.
746 for(index = 0;index < 4;index++)
748 State->Early.Offset[index] = fastf2u(EARLY_LINE_LENGTH[index] *
749 frequency);
750 State->Late.ApOffset[index] = fastf2u(ALLPASS_LINE_LENGTH[index] *
751 frequency);
754 // The echo all-pass filter line length is static, so its offset only
755 // needs to be calculated once.
756 State->Echo.ApOffset = fastf2u(ECHO_ALLPASS_LENGTH * frequency);
758 return AL_TRUE;
761 // Calculate a decay coefficient given the length of each cycle and the time
762 // until the decay reaches -60 dB.
763 static __inline ALfloat CalcDecayCoeff(ALfloat length, ALfloat decayTime)
765 return powf(0.001f/*-60 dB*/, length/decayTime);
768 // Calculate a decay length from a coefficient and the time until the decay
769 // reaches -60 dB.
770 static __inline ALfloat CalcDecayLength(ALfloat coeff, ALfloat decayTime)
772 return log10f(coeff) * decayTime / log10f(0.001f)/*-60 dB*/;
775 // Calculate the high frequency parameter for the I3DL2 coefficient
776 // calculation.
777 static __inline ALfloat CalcI3DL2HFreq(ALfloat hfRef, ALuint frequency)
779 return cosf(F_PI*2.0f * hfRef / frequency);
782 // Calculate an attenuation to be applied to the input of any echo models to
783 // compensate for modal density and decay time.
784 static __inline ALfloat CalcDensityGain(ALfloat a)
786 /* The energy of a signal can be obtained by finding the area under the
787 * squared signal. This takes the form of Sum(x_n^2), where x is the
788 * amplitude for the sample n.
790 * Decaying feedback matches exponential decay of the form Sum(a^n),
791 * where a is the attenuation coefficient, and n is the sample. The area
792 * under this decay curve can be calculated as: 1 / (1 - a).
794 * Modifying the above equation to find the squared area under the curve
795 * (for energy) yields: 1 / (1 - a^2). Input attenuation can then be
796 * calculated by inverting the square root of this approximation,
797 * yielding: 1 / sqrt(1 / (1 - a^2)), simplified to: sqrt(1 - a^2).
799 return sqrtf(1.0f - (a * a));
802 // Calculate the mixing matrix coefficients given a diffusion factor.
803 static __inline ALvoid CalcMatrixCoeffs(ALfloat diffusion, ALfloat *x, ALfloat *y)
805 ALfloat n, t;
807 // The matrix is of order 4, so n is sqrt (4 - 1).
808 n = sqrtf(3.0f);
809 t = diffusion * atanf(n);
811 // Calculate the first mixing matrix coefficient.
812 *x = cosf(t);
813 // Calculate the second mixing matrix coefficient.
814 *y = sinf(t) / n;
817 // Calculate the limited HF ratio for use with the late reverb low-pass
818 // filters.
819 static ALfloat CalcLimitedHfRatio(ALfloat hfRatio, ALfloat airAbsorptionGainHF, ALfloat decayTime)
821 ALfloat limitRatio;
823 /* Find the attenuation due to air absorption in dB (converting delay
824 * time to meters using the speed of sound). Then reversing the decay
825 * equation, solve for HF ratio. The delay length is cancelled out of
826 * the equation, so it can be calculated once for all lines.
828 limitRatio = 1.0f / (CalcDecayLength(airAbsorptionGainHF, decayTime) *
829 SPEEDOFSOUNDMETRESPERSEC);
830 /* Using the limit calculated above, apply the upper bound to the HF
831 * ratio. Also need to limit the result to a minimum of 0.1, just like the
832 * HF ratio parameter. */
833 return clampf(limitRatio, 0.1f, hfRatio);
836 // Calculate the coefficient for a HF (and eventually LF) decay damping
837 // filter.
838 static __inline ALfloat CalcDampingCoeff(ALfloat hfRatio, ALfloat length, ALfloat decayTime, ALfloat decayCoeff, ALfloat cw)
840 ALfloat coeff, g;
842 // Eventually this should boost the high frequencies when the ratio
843 // exceeds 1.
844 coeff = 0.0f;
845 if (hfRatio < 1.0f)
847 // Calculate the low-pass coefficient by dividing the HF decay
848 // coefficient by the full decay coefficient.
849 g = CalcDecayCoeff(length, decayTime * hfRatio) / decayCoeff;
851 // Damping is done with a 1-pole filter, so g needs to be squared.
852 g *= g;
853 coeff = lpCoeffCalc(g, cw);
855 // Very low decay times will produce minimal output, so apply an
856 // upper bound to the coefficient.
857 coeff = minf(coeff, 0.98f);
859 return coeff;
862 // Update the EAX modulation index, range, and depth. Keep in mind that this
863 // kind of vibrato is additive and not multiplicative as one may expect. The
864 // downswing will sound stronger than the upswing.
865 static ALvoid UpdateModulator(ALfloat modTime, ALfloat modDepth, ALuint frequency, ALverbState *State)
867 ALuint range;
869 /* Modulation is calculated in two parts.
871 * The modulation time effects the sinus applied to the change in
872 * frequency. An index out of the current time range (both in samples)
873 * is incremented each sample. The range is bound to a reasonable
874 * minimum (1 sample) and when the timing changes, the index is rescaled
875 * to the new range (to keep the sinus consistent).
877 range = maxu(fastf2u(modTime*frequency), 1);
878 State->Mod.Index = (ALuint)(State->Mod.Index * (ALuint64)range /
879 State->Mod.Range);
880 State->Mod.Range = range;
882 /* The modulation depth effects the amount of frequency change over the
883 * range of the sinus. It needs to be scaled by the modulation time so
884 * that a given depth produces a consistent change in frequency over all
885 * ranges of time. Since the depth is applied to a sinus value, it needs
886 * to be halfed once for the sinus range and again for the sinus swing
887 * in time (half of it is spent decreasing the frequency, half is spent
888 * increasing it).
890 State->Mod.Depth = modDepth * MODULATION_DEPTH_COEFF * modTime / 2.0f /
891 2.0f * frequency;
894 // Update the offsets for the initial effect delay line.
895 static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALuint frequency, ALverbState *State)
897 // Calculate the initial delay taps.
898 State->DelayTap[0] = fastf2u(earlyDelay * frequency);
899 State->DelayTap[1] = fastf2u((earlyDelay + lateDelay) * frequency);
902 // Update the early reflections gain and line coefficients.
903 static ALvoid UpdateEarlyLines(ALfloat reverbGain, ALfloat earlyGain, ALfloat lateDelay, ALverbState *State)
905 ALuint index;
907 // Calculate the early reflections gain (from the master effect gain, and
908 // reflections gain parameters) with a constant attenuation of 0.5.
909 State->Early.Gain = 0.5f * reverbGain * earlyGain;
911 // Calculate the gain (coefficient) for each early delay line using the
912 // late delay time. This expands the early reflections to the start of
913 // the late reverb.
914 for(index = 0;index < 4;index++)
915 State->Early.Coeff[index] = CalcDecayCoeff(EARLY_LINE_LENGTH[index],
916 lateDelay);
919 // Update the offsets for the decorrelator line.
920 static ALvoid UpdateDecorrelator(ALfloat density, ALuint frequency, ALverbState *State)
922 ALuint index;
923 ALfloat length;
925 /* The late reverb inputs are decorrelated to smooth the reverb tail and
926 * reduce harsh echos. The first tap occurs immediately, while the
927 * remaining taps are delayed by multiples of a fraction of the smallest
928 * cyclical delay time.
930 * offset[index] = (FRACTION (MULTIPLIER^index)) smallest_delay
932 for(index = 0;index < 3;index++)
934 length = (DECO_FRACTION * powf(DECO_MULTIPLIER, (ALfloat)index)) *
935 LATE_LINE_LENGTH[0] * (1.0f + (density * LATE_LINE_MULTIPLIER));
936 State->DecoTap[index] = fastf2u(length * frequency);
940 // Update the late reverb gains, line lengths, and line coefficients.
941 static ALvoid UpdateLateLines(ALfloat reverbGain, ALfloat lateGain, ALfloat xMix, ALfloat density, ALfloat decayTime, ALfloat diffusion, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State)
943 ALfloat length;
944 ALuint index;
946 /* Calculate the late reverb gain (from the master effect gain, and late
947 * reverb gain parameters). Since the output is tapped prior to the
948 * application of the next delay line coefficients, this gain needs to be
949 * attenuated by the 'x' mixing matrix coefficient as well.
951 State->Late.Gain = reverbGain * lateGain * xMix;
953 /* To compensate for changes in modal density and decay time of the late
954 * reverb signal, the input is attenuated based on the maximal energy of
955 * the outgoing signal. This approximation is used to keep the apparent
956 * energy of the signal equal for all ranges of density and decay time.
958 * The average length of the cyclcical delay lines is used to calculate
959 * the attenuation coefficient.
961 length = (LATE_LINE_LENGTH[0] + LATE_LINE_LENGTH[1] +
962 LATE_LINE_LENGTH[2] + LATE_LINE_LENGTH[3]) / 4.0f;
963 length *= 1.0f + (density * LATE_LINE_MULTIPLIER);
964 State->Late.DensityGain = CalcDensityGain(CalcDecayCoeff(length,
965 decayTime));
967 // Calculate the all-pass feed-back and feed-forward coefficient.
968 State->Late.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
970 for(index = 0;index < 4;index++)
972 // Calculate the gain (coefficient) for each all-pass line.
973 State->Late.ApCoeff[index] = CalcDecayCoeff(ALLPASS_LINE_LENGTH[index],
974 decayTime);
976 // Calculate the length (in seconds) of each cyclical delay line.
977 length = LATE_LINE_LENGTH[index] * (1.0f + (density *
978 LATE_LINE_MULTIPLIER));
980 // Calculate the delay offset for each cyclical delay line.
981 State->Late.Offset[index] = fastf2u(length * frequency);
983 // Calculate the gain (coefficient) for each cyclical line.
984 State->Late.Coeff[index] = CalcDecayCoeff(length, decayTime);
986 // Calculate the damping coefficient for each low-pass filter.
987 State->Late.LpCoeff[index] =
988 CalcDampingCoeff(hfRatio, length, decayTime,
989 State->Late.Coeff[index], cw);
991 // Attenuate the cyclical line coefficients by the mixing coefficient
992 // (x).
993 State->Late.Coeff[index] *= xMix;
997 // Update the echo gain, line offset, line coefficients, and mixing
998 // coefficients.
999 static ALvoid UpdateEchoLine(ALfloat reverbGain, ALfloat lateGain, ALfloat echoTime, ALfloat decayTime, ALfloat diffusion, ALfloat echoDepth, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State)
1001 // Update the offset and coefficient for the echo delay line.
1002 State->Echo.Offset = fastf2u(echoTime * frequency);
1004 // Calculate the decay coefficient for the echo line.
1005 State->Echo.Coeff = CalcDecayCoeff(echoTime, decayTime);
1007 // Calculate the energy-based attenuation coefficient for the echo delay
1008 // line.
1009 State->Echo.DensityGain = CalcDensityGain(State->Echo.Coeff);
1011 // Calculate the echo all-pass feed coefficient.
1012 State->Echo.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
1014 // Calculate the echo all-pass attenuation coefficient.
1015 State->Echo.ApCoeff = CalcDecayCoeff(ECHO_ALLPASS_LENGTH, decayTime);
1017 // Calculate the damping coefficient for each low-pass filter.
1018 State->Echo.LpCoeff = CalcDampingCoeff(hfRatio, echoTime, decayTime,
1019 State->Echo.Coeff, cw);
1021 /* Calculate the echo mixing coefficients. The first is applied to the
1022 * echo itself. The second is used to attenuate the late reverb when
1023 * echo depth is high and diffusion is low, so the echo is slightly
1024 * stronger than the decorrelated echos in the reverb tail.
1026 State->Echo.MixCoeff[0] = reverbGain * lateGain * echoDepth;
1027 State->Echo.MixCoeff[1] = 1.0f - (echoDepth * 0.5f * (1.0f - diffusion));
1030 // Update the early and late 3D panning gains.
1031 static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALverbState *State)
1033 ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1],
1034 ReflectionsPan[2] };
1035 ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
1036 LateReverbPan[2] };
1037 ALfloat ambientGain;
1038 ALfloat dirGain;
1039 ALfloat length;
1040 ALuint index;
1042 Gain *= ReverbBoost;
1044 /* Attenuate reverb according to its coverage (dirGain=0 will give
1045 * Gain*ambientGain, and dirGain=1 will give Gain). */
1046 ambientGain = minf(sqrtf(2.0f/Device->NumChan), 1.0f);
1048 length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
1049 if(length > 1.0f)
1051 length = 1.0f / sqrtf(length);
1052 earlyPan[0] *= length;
1053 earlyPan[1] *= length;
1054 earlyPan[2] *= length;
1056 length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2];
1057 if(length > 1.0f)
1059 length = 1.0f / sqrtf(length);
1060 latePan[0] *= length;
1061 latePan[1] *= length;
1062 latePan[2] *= length;
1065 dirGain = sqrtf(earlyPan[0]*earlyPan[0] + earlyPan[2]*earlyPan[2]);
1066 for(index = 0;index < MaxChannels;index++)
1067 State->Early.PanGain[index] = 0.0f;
1068 ComputeAngleGains(Device, atan2f(earlyPan[0], earlyPan[2]), (1.0f-dirGain)*F_PI,
1069 lerp(ambientGain, 1.0f, dirGain) * Gain, State->Early.PanGain);
1071 dirGain = sqrtf(latePan[0]*latePan[0] + latePan[2]*latePan[2]);
1072 for(index = 0;index < MaxChannels;index++)
1073 State->Late.PanGain[index] = 0.0f;
1074 ComputeAngleGains(Device, atan2f(latePan[0], latePan[2]), (1.0f-dirGain)*F_PI,
1075 lerp(ambientGain, 1.0f, dirGain) * Gain, State->Late.PanGain);
1078 // This updates the EAX reverb state. This is called any time the EAX reverb
1079 // effect is loaded into a slot.
1080 static ALvoid ReverbUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot)
1082 ALverbState *State = (ALverbState*)effect;
1083 ALuint frequency = Device->Frequency;
1084 ALboolean isEAX = AL_FALSE;
1085 ALfloat cw, x, y, hfRatio;
1087 if(Slot->effect.type == AL_EFFECT_EAXREVERB && !EmulateEAXReverb)
1089 State->state.Process = EAXVerbProcess;
1090 isEAX = AL_TRUE;
1092 else if(Slot->effect.type == AL_EFFECT_REVERB || EmulateEAXReverb)
1094 State->state.Process = VerbProcess;
1095 isEAX = AL_FALSE;
1098 // Calculate the master low-pass filter (from the master effect HF gain).
1099 if(isEAX) cw = CalcI3DL2HFreq(Slot->effect.Reverb.HFReference, frequency);
1100 else cw = CalcI3DL2HFreq(LOWPASSFREQREF, frequency);
1101 // This is done with 2 chained 1-pole filters, so no need to square g.
1102 State->LpFilter.coeff = lpCoeffCalc(Slot->effect.Reverb.GainHF, cw);
1104 if(isEAX)
1106 // Update the modulator line.
1107 UpdateModulator(Slot->effect.Reverb.ModulationTime,
1108 Slot->effect.Reverb.ModulationDepth,
1109 frequency, State);
1112 // Update the initial effect delay.
1113 UpdateDelayLine(Slot->effect.Reverb.ReflectionsDelay,
1114 Slot->effect.Reverb.LateReverbDelay,
1115 frequency, State);
1117 // Update the early lines.
1118 UpdateEarlyLines(Slot->effect.Reverb.Gain,
1119 Slot->effect.Reverb.ReflectionsGain,
1120 Slot->effect.Reverb.LateReverbDelay, State);
1122 // Update the decorrelator.
1123 UpdateDecorrelator(Slot->effect.Reverb.Density, frequency, State);
1125 // Get the mixing matrix coefficients (x and y).
1126 CalcMatrixCoeffs(Slot->effect.Reverb.Diffusion, &x, &y);
1127 // Then divide x into y to simplify the matrix calculation.
1128 State->Late.MixCoeff = y / x;
1130 // If the HF limit parameter is flagged, calculate an appropriate limit
1131 // based on the air absorption parameter.
1132 hfRatio = Slot->effect.Reverb.DecayHFRatio;
1133 if(Slot->effect.Reverb.DecayHFLimit &&
1134 Slot->effect.Reverb.AirAbsorptionGainHF < 1.0f)
1135 hfRatio = CalcLimitedHfRatio(hfRatio,
1136 Slot->effect.Reverb.AirAbsorptionGainHF,
1137 Slot->effect.Reverb.DecayTime);
1139 // Update the late lines.
1140 UpdateLateLines(Slot->effect.Reverb.Gain, Slot->effect.Reverb.LateReverbGain,
1141 x, Slot->effect.Reverb.Density, Slot->effect.Reverb.DecayTime,
1142 Slot->effect.Reverb.Diffusion, hfRatio, cw, frequency, State);
1144 if(isEAX)
1146 // Update the echo line.
1147 UpdateEchoLine(Slot->effect.Reverb.Gain, Slot->effect.Reverb.LateReverbGain,
1148 Slot->effect.Reverb.EchoTime, Slot->effect.Reverb.DecayTime,
1149 Slot->effect.Reverb.Diffusion, Slot->effect.Reverb.EchoDepth,
1150 hfRatio, cw, frequency, State);
1152 // Update early and late 3D panning.
1153 Update3DPanning(Device, Slot->effect.Reverb.ReflectionsPan,
1154 Slot->effect.Reverb.LateReverbPan, Slot->Gain, State);
1156 else
1158 ALfloat gain = Slot->Gain;
1159 ALuint index;
1161 /* Update channel gains */
1162 gain *= sqrtf(2.0f/Device->NumChan) * ReverbBoost;
1163 for(index = 0;index < MaxChannels;index++)
1164 State->Gain[index] = 0.0f;
1165 for(index = 0;index < Device->NumChan;index++)
1167 enum Channel chan = Device->Speaker2Chan[index];
1168 State->Gain[chan] = gain;
1173 // This destroys the reverb state. It should be called only when the effect
1174 // slot has a different (or no) effect loaded over the reverb effect.
1175 static ALvoid ReverbDestroy(ALeffectState *effect)
1177 ALverbState *State = (ALverbState*)effect;
1178 if(State)
1180 free(State->SampleBuffer);
1181 State->SampleBuffer = NULL;
1182 free(State);
1186 // This creates the reverb state. It should be called only when the reverb
1187 // effect is loaded into a slot that doesn't already have a reverb effect.
1188 ALeffectState *ReverbCreate(void)
1190 ALverbState *State = NULL;
1191 ALuint index;
1193 State = malloc(sizeof(ALverbState));
1194 if(!State)
1195 return NULL;
1197 State->state.Destroy = ReverbDestroy;
1198 State->state.DeviceUpdate = ReverbDeviceUpdate;
1199 State->state.Update = ReverbUpdate;
1200 State->state.Process = VerbProcess;
1202 State->TotalSamples = 0;
1203 State->SampleBuffer = NULL;
1205 State->LpFilter.coeff = 0.0f;
1206 State->LpFilter.history[0] = 0.0f;
1207 State->LpFilter.history[1] = 0.0f;
1209 State->Mod.Delay.Mask = 0;
1210 State->Mod.Delay.Line = NULL;
1211 State->Mod.Index = 0;
1212 State->Mod.Range = 1;
1213 State->Mod.Depth = 0.0f;
1214 State->Mod.Coeff = 0.0f;
1215 State->Mod.Filter = 0.0f;
1217 State->Delay.Mask = 0;
1218 State->Delay.Line = NULL;
1219 State->DelayTap[0] = 0;
1220 State->DelayTap[1] = 0;
1222 State->Early.Gain = 0.0f;
1223 for(index = 0;index < 4;index++)
1225 State->Early.Coeff[index] = 0.0f;
1226 State->Early.Delay[index].Mask = 0;
1227 State->Early.Delay[index].Line = NULL;
1228 State->Early.Offset[index] = 0;
1231 State->Decorrelator.Mask = 0;
1232 State->Decorrelator.Line = NULL;
1233 State->DecoTap[0] = 0;
1234 State->DecoTap[1] = 0;
1235 State->DecoTap[2] = 0;
1237 State->Late.Gain = 0.0f;
1238 State->Late.DensityGain = 0.0f;
1239 State->Late.ApFeedCoeff = 0.0f;
1240 State->Late.MixCoeff = 0.0f;
1241 for(index = 0;index < 4;index++)
1243 State->Late.ApCoeff[index] = 0.0f;
1244 State->Late.ApDelay[index].Mask = 0;
1245 State->Late.ApDelay[index].Line = NULL;
1246 State->Late.ApOffset[index] = 0;
1248 State->Late.Coeff[index] = 0.0f;
1249 State->Late.Delay[index].Mask = 0;
1250 State->Late.Delay[index].Line = NULL;
1251 State->Late.Offset[index] = 0;
1253 State->Late.LpCoeff[index] = 0.0f;
1254 State->Late.LpSample[index] = 0.0f;
1257 for(index = 0;index < MaxChannels;index++)
1259 State->Early.PanGain[index] = 0.0f;
1260 State->Late.PanGain[index] = 0.0f;
1263 State->Echo.DensityGain = 0.0f;
1264 State->Echo.Delay.Mask = 0;
1265 State->Echo.Delay.Line = NULL;
1266 State->Echo.ApDelay.Mask = 0;
1267 State->Echo.ApDelay.Line = NULL;
1268 State->Echo.Coeff = 0.0f;
1269 State->Echo.ApFeedCoeff = 0.0f;
1270 State->Echo.ApCoeff = 0.0f;
1271 State->Echo.Offset = 0;
1272 State->Echo.ApOffset = 0;
1273 State->Echo.LpCoeff = 0.0f;
1274 State->Echo.LpSample = 0.0f;
1275 State->Echo.MixCoeff[0] = 0.0f;
1276 State->Echo.MixCoeff[1] = 0.0f;
1278 State->Offset = 0;
1280 State->Gain = State->Late.PanGain;
1282 return &State->state;