zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
alcReverb.c
Go to the documentation of this file.
1 
21 #include "config.h"
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26 
27 #include "alMain.h"
28 #include "alu.h"
29 #include "alAuxEffectSlot.h"
30 #include "alEffect.h"
31 #include "alFilter.h"
32 #include "alError.h"
33 
34 typedef struct DelayLine
35 {
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;
41 
42 typedef struct ALverbState {
43  // Must be first in all effects!
44  ALeffectState state;
45 
46  // All delay lines are allocated as a single buffer to reduce memory
47  // fragmentation and management code.
48  ALfloat *SampleBuffer;
49  ALuint TotalSamples;
50 
51  // Master effect low-pass filter (2 chained 1-pole filters).
52  FILTER LpFilter;
53  ALfloat LpHistory[2];
54 
55  struct {
56  // Modulator delay line.
57  DelayLine Delay;
58 
59  // The vibrato time is tracked with an index over a modulus-wrapped
60  // range (in samples).
61  ALuint Index;
62  ALuint Range;
63 
64  // The depth of frequency change (also in samples) and its filter.
65  ALfloat Depth;
66  ALfloat Coeff;
67  ALfloat Filter;
68  } Mod;
69 
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];
75 
76  struct {
77  // Output gain for early reflections.
78  ALfloat Gain;
79 
80  // Early reflections are done with 4 delay lines.
81  ALfloat Coeff[4];
82  DelayLine Delay[4];
83  ALuint Offset[4];
84 
85  // The gain for each output channel based on 3D panning (only for the
86  // EAX path).
87  ALfloat PanGain[MaxChannels];
88  } Early;
89 
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];
95 
96  struct {
97  // Output gain for late reverb.
98  ALfloat Gain;
99 
100  // Attenuation to compensate for the modal density and decay rate of
101  // the late lines.
102  ALfloat DensityGain;
103 
104  // The feed-back and feed-forward all-pass coefficient.
105  ALfloat ApFeedCoeff;
106 
107  // Mixing matrix coefficient.
108  ALfloat MixCoeff;
109 
110  // Late reverb has 4 parallel all-pass filters.
111  ALfloat ApCoeff[4];
112  DelayLine ApDelay[4];
113  ALuint ApOffset[4];
114 
115  // In addition to 4 cyclical delay lines.
116  ALfloat Coeff[4];
117  DelayLine Delay[4];
118  ALuint Offset[4];
119 
120  // The cyclical delay lines are 1-pole low-pass filtered.
121  ALfloat LpCoeff[4];
122  ALfloat LpSample[4];
123 
124  // The gain for each output channel based on 3D panning (only for the
125  // EAX path).
126  ALfloat PanGain[MaxChannels];
127  } Late;
128 
129  struct {
130  // Attenuation to compensate for the modal density and decay rate of
131  // the echo line.
132  ALfloat DensityGain;
133 
134  // Echo delay and all-pass lines.
135  DelayLine Delay;
136  DelayLine ApDelay;
137 
138  ALfloat Coeff;
139  ALfloat ApFeedCoeff;
140  ALfloat ApCoeff;
141 
142  ALuint Offset;
143  ALuint ApOffset;
144 
145  // The echo line is 1-pole low-pass filtered.
146  ALfloat LpCoeff;
147  ALfloat LpSample;
148 
149  // Echo mixing coefficients.
150  ALfloat MixCoeff[2];
151  } Echo;
152 
153  // The current read offset for all delay lines.
154  ALuint Offset;
155 
156  // The gain for each output channel (non-EAX path only; aliased from
157  // Late.PanGain)
158  ALfloat *Gain;
159 
160  /* Temporary storage used when processing, before deinterlacing. */
161  ALfloat ReverbSamples[BUFFERSIZE][4];
162  ALfloat EarlySamples[BUFFERSIZE][4];
163 } ALverbState;
164 
165 /* This is a user config option for modifying the overall output of the reverb
166  * effect.
167  */
169 
170 /* Specifies whether to use a standard reverb effect in place of EAX reverb */
172 
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.
178  */
179 static const ALfloat MODULATION_DEPTH_COEFF = 0.1f;
180 
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).
185  */
186 static const ALfloat MODULATION_FILTER_COEFF = 0.048f;
187 static const ALfloat MODULATION_FILTER_CONST = 100000.0f;
188 
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;
192 
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;
198 
199 // All delay line lengths are specified in seconds.
200 
201 // The lengths of the early delay lines.
202 static const ALfloat EARLY_LINE_LENGTH[4] =
203 {
204  0.0015f, 0.0045f, 0.0135f, 0.0405f
205 };
206 
207 // The lengths of the late all-pass delay lines.
208 static const ALfloat ALLPASS_LINE_LENGTH[4] =
209 {
210  0.0151f, 0.0167f, 0.0183f, 0.0200f,
211 };
212 
213 // The lengths of the late cyclical delay lines.
214 static const ALfloat LATE_LINE_LENGTH[4] =
215 {
216  0.0211f, 0.0311f, 0.0461f, 0.0680f
217 };
218 
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;
222 
223 
224 // Basic delay line input/output routines.
225 static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
226 {
227  return Delay->Line[offset&Delay->Mask];
228 }
229 
230 static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
231 {
232  Delay->Line[offset&Delay->Mask] = in;
233 }
234 
235 // Attenuated delay line output routine.
237 {
238  return coeff * Delay->Line[offset&Delay->Mask];
239 }
240 
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)
243 {
244  ALfloat out, feed;
245 
246  out = DelayLineOut(Delay, outOffset);
247  feed = feedCoeff * in;
248  DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in);
249 
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;
254 }
255 
256 // Given an input sample, this function produces modulation for the late
257 // reverb.
259 {
260  ALfloat sinus, frac;
261  ALuint offset;
262  ALfloat out0, out1;
263 
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);
268 
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);
274 
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;
279 
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);
285 
286  // Step the modulation index forward, keeping it bound to its range.
287  State->Mod.Index = (State->Mod.Index + 1) % State->Mod.Range;
288 
289  // The output is obtained by linearly interpolating the two samples that
290  // were acquired above.
291  return lerp(out0, out1, frac);
292 }
293 
294 // Delay line output routine for early reflections.
296 {
297  return AttenuatedDelayLineOut(&State->Early.Delay[index],
298  State->Offset - State->Early.Offset[index],
299  State->Early.Coeff[index]);
300 }
301 
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)
305 {
306  ALfloat d[4], v, f[4];
307 
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);
313 
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).
318  * N
319  * ---
320  * \
321  * v = 2/N / d_i
322  * ---
323  * i=1
324  */
325  v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
326  // The junction is loaded with the input here.
327  v += in;
328 
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];
334 
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]);
340 
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];
346 }
347 
348 // All-pass input/output routine for late reverb.
350 {
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]);
355 }
356 
357 // Delay line output routine for late reverb.
359 {
360  return AttenuatedDelayLineOut(&State->Late.Delay[index],
361  State->Offset - State->Late.Offset[index],
362  State->Late.Coeff[index]);
363 }
364 
365 // Low-pass filter input/output routine for late reverb.
367 {
368  in = lerp(in, State->Late.LpSample[index], State->Late.LpCoeff[index]);
369  State->Late.LpSample[index] = in;
370  return in;
371 }
372 
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)
376 {
377  ALfloat d[4], f[4];
378 
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.
382 
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));
389 
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]);
397 
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.
403  *
404  * The mixing matrix used is a 4D skew-symmetric rotation matrix derived
405  * using a single unitary rotational parameter:
406  *
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 ]
411  *
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:
415  *
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
420  *
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.
424  */
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] ));
429 
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];
436 
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]);
442 }
443 
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)
447 {
448  ALfloat out, feed;
449 
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);
454 
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;
461 
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;
467 
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);
473 
474  // Feed the delay with the mixed and filtered sample.
475  DelayLineIn(&State->Echo.Delay, State->Offset, feed);
476 }
477 
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)
481 {
482  ALfloat feed, late[4], taps[4];
483 
484  // Low-pass filter the incoming sample.
485  in = lpFilter2P(&State->LpFilter, 0, in);
486 
487  // Feed the initial delay line.
488  DelayLineIn(&State->Delay, State->Offset, in);
489 
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);
493 
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);
499 
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);
506 
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];
512 
513  // Step all delays forward one sample.
514  State->Offset++;
515 }
516 
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)
520 {
521  ALfloat feed, taps[4];
522 
523  // Low-pass filter the incoming sample.
524  in = lpFilter2P(&State->LpFilter, 0, in);
525 
526  // Perform any modulation on the input.
527  in = EAXModulation(State, in);
528 
529  // Feed the initial delay line.
530  DelayLineIn(&State->Delay, State->Offset, in);
531 
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);
535 
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);
541 
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);
548 
549  // Calculate and mix in any echo.
550  EAXEcho(State, in, late);
551 
552  // Step all delays forward one sample.
553  State->Offset++;
554 }
555 
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])
559 {
560  ALverbState *State = (ALverbState*)effect;
561  ALfloat (*RESTRICT out)[4] = State->ReverbSamples;
562  ALuint index, c;
563 
564  /* Process reverb for these samples. */
565  for(index = 0;index < SamplesToDo;index++)
566  VerbPass(State, SamplesIn[index], out[index]);
567 
568  for(c = 0;c < MaxChannels;c++)
569  {
570  ALfloat gain = State->Gain[c];
571  if(gain > 0.00001f)
572  {
573  for(index = 0;index < SamplesToDo;index++)
574  SamplesOut[c][index] += gain * out[index][c&3];
575  }
576  }
577 }
578 
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])
582 {
583  ALverbState *State = (ALverbState*)effect;
584  ALfloat (*RESTRICT early)[4] = State->EarlySamples;
585  ALfloat (*RESTRICT late)[4] = State->ReverbSamples;
586  ALuint index, c;
587 
588  /* Process reverb for these samples. */
589  for(index = 0;index < SamplesToDo;index++)
590  EAXVerbPass(State, SamplesIn[index], early[index], late[index]);
591 
592  for(c = 0;c < MaxChannels;c++)
593  {
594  ALfloat earlyGain = State->Early.PanGain[c];
595  ALfloat lateGain = State->Late.PanGain[c];
596 
597  if(earlyGain > 0.00001f)
598  {
599  for(index = 0;index < SamplesToDo;index++)
600  SamplesOut[c][index] += earlyGain*early[index][c&3];
601  }
602  if(lateGain > 0.00001f)
603  {
604  for(index = 0;index < SamplesToDo;index++)
605  SamplesOut[c][index] += lateGain*late[index][c&3];
606  }
607  }
608 }
609 
610 
611 // Given the allocated sample buffer, this function updates each delay line
612 // offset.
613 static __inline ALvoid RealizeLineOffset(ALfloat *sampleBuffer, DelayLine *Delay)
614 {
615  Delay->Line = &sampleBuffer[(ALintptrEXT)Delay->Line];
616 }
617 
618 // Calculate the length of a delay line and store its mask and offset.
620 {
621  ALuint samples;
622 
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;
631 }
632 
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.
636  */
638 {
639  ALuint totalSamples, index;
640  ALfloat length;
641  ALfloat *newBuffer = NULL;
642 
643  // All delay line lengths are calculated to accomodate the full range of
644  // lengths given their respective paramters.
645  totalSamples = 0;
646 
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.
651  */
653  (1.0f / frequency);
654  totalSamples += CalcLineLength(length, totalSamples, frequency,
655  &State->Mod.Delay);
656 
657  // The initial delay is the sum of the reflections and late reverb
658  // delays.
661  totalSamples += CalcLineLength(length, totalSamples, frequency,
662  &State->Delay);
663 
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]);
668 
669  // The decorrelator line is calculated from the lowest reverb density (a
670  // parameter value of 1).
673  totalSamples += CalcLineLength(length, totalSamples, frequency,
674  &State->Decorrelator);
675 
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]);
680 
681  // The late delay lines are calculated from the lowest reverb density.
682  for(index = 0;index < 4;index++)
683  {
684  length = LATE_LINE_LENGTH[index] * (1.0f + LATE_LINE_MULTIPLIER);
685  totalSamples += CalcLineLength(length, totalSamples, frequency,
686  &State->Late.Delay[index]);
687  }
688 
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);
694 
695  if(totalSamples != State->TotalSamples)
696  {
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;
703  }
704 
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++)
709  {
710  RealizeLineOffset(State->SampleBuffer, &State->Early.Delay[index]);
711  RealizeLineOffset(State->SampleBuffer, &State->Late.ApDelay[index]);
712  RealizeLineOffset(State->SampleBuffer, &State->Late.Delay[index]);
713  }
714  RealizeLineOffset(State->SampleBuffer, &State->Mod.Delay);
715  RealizeLineOffset(State->SampleBuffer, &State->Echo.ApDelay);
716  RealizeLineOffset(State->SampleBuffer, &State->Echo.Delay);
717 
718  // Clear the sample buffer.
719  for(index = 0;index < State->TotalSamples;index++)
720  State->SampleBuffer[index] = 0.0f;
721 
722  return AL_TRUE;
723 }
724 
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.
729 {
730  ALverbState *State = (ALverbState*)effect;
731  ALuint frequency = Device->Frequency, index;
732 
733  // Allocate the delay lines.
734  if(!AllocLines(frequency, State))
735  return AL_FALSE;
736 
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);
743 
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++)
747  {
748  State->Early.Offset[index] = fastf2u(EARLY_LINE_LENGTH[index] *
749  frequency);
750  State->Late.ApOffset[index] = fastf2u(ALLPASS_LINE_LENGTH[index] *
751  frequency);
752  }
753 
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);
757 
758  return AL_TRUE;
759 }
760 
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)
764 {
765  return powf(0.001f/*-60 dB*/, length/decayTime);
766 }
767 
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)
771 {
772  return log10f(coeff) * decayTime / log10f(0.001f)/*-60 dB*/;
773 }
774 
775 // Calculate the high frequency parameter for the I3DL2 coefficient
776 // calculation.
777 static __inline ALfloat CalcI3DL2HFreq(ALfloat hfRef, ALuint frequency)
778 {
779  return cosf(F_PI*2.0f * hfRef / frequency);
780 }
781 
782 // Calculate an attenuation to be applied to the input of any echo models to
783 // compensate for modal density and decay time.
785 {
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.
789  *
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).
793  *
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).
798  */
799  return sqrtf(1.0f - (a * a));
800 }
801 
802 // Calculate the mixing matrix coefficients given a diffusion factor.
803 static __inline ALvoid CalcMatrixCoeffs(ALfloat diffusion, ALfloat *x, ALfloat *y)
804 {
805  ALfloat n, t;
806 
807  // The matrix is of order 4, so n is sqrt (4 - 1).
808  n = sqrtf(3.0f);
809  t = diffusion * atanf(n);
810 
811  // Calculate the first mixing matrix coefficient.
812  *x = cosf(t);
813  // Calculate the second mixing matrix coefficient.
814  *y = sinf(t) / n;
815 }
816 
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)
820 {
821  ALfloat limitRatio;
822 
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.
827  */
828  limitRatio = 1.0f / (CalcDecayLength(airAbsorptionGainHF, decayTime) *
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);
834 }
835 
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)
839 {
840  ALfloat coeff, g;
841 
842  // Eventually this should boost the high frequencies when the ratio
843  // exceeds 1.
844  coeff = 0.0f;
845  if (hfRatio < 1.0f)
846  {
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;
850 
851  // Damping is done with a 1-pole filter, so g needs to be squared.
852  g *= g;
853  coeff = lpCoeffCalc(g, cw);
854 
855  // Very low decay times will produce minimal output, so apply an
856  // upper bound to the coefficient.
857  coeff = minf(coeff, 0.98f);
858  }
859  return coeff;
860 }
861 
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)
866 {
867  ALuint range;
868 
869  /* Modulation is calculated in two parts.
870  *
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).
876  */
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;
881 
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).
889  */
890  State->Mod.Depth = modDepth * MODULATION_DEPTH_COEFF * modTime / 2.0f /
891  2.0f * frequency;
892 }
893 
894 // Update the offsets for the initial effect delay line.
895 static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALuint frequency, ALverbState *State)
896 {
897  // Calculate the initial delay taps.
898  State->DelayTap[0] = fastf2u(earlyDelay * frequency);
899  State->DelayTap[1] = fastf2u((earlyDelay + lateDelay) * frequency);
900 }
901 
902 // Update the early reflections gain and line coefficients.
903 static ALvoid UpdateEarlyLines(ALfloat reverbGain, ALfloat earlyGain, ALfloat lateDelay, ALverbState *State)
904 {
905  ALuint index;
906 
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;
910 
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);
917 }
918 
919 // Update the offsets for the decorrelator line.
921 {
922  ALuint index;
923  ALfloat length;
924 
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.
929  *
930  * offset[index] = (FRACTION (MULTIPLIER^index)) smallest_delay
931  */
932  for(index = 0;index < 3;index++)
933  {
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);
937  }
938 }
939 
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)
942 {
943  ALfloat length;
944  ALuint index;
945 
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.
950  */
951  State->Late.Gain = reverbGain * lateGain * xMix;
952 
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.
957  *
958  * The average length of the cyclcical delay lines is used to calculate
959  * the attenuation coefficient.
960  */
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));
966 
967  // Calculate the all-pass feed-back and feed-forward coefficient.
968  State->Late.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
969 
970  for(index = 0;index < 4;index++)
971  {
972  // Calculate the gain (coefficient) for each all-pass line.
973  State->Late.ApCoeff[index] = CalcDecayCoeff(ALLPASS_LINE_LENGTH[index],
974  decayTime);
975 
976  // Calculate the length (in seconds) of each cyclical delay line.
977  length = LATE_LINE_LENGTH[index] * (1.0f + (density *
979 
980  // Calculate the delay offset for each cyclical delay line.
981  State->Late.Offset[index] = fastf2u(length * frequency);
982 
983  // Calculate the gain (coefficient) for each cyclical line.
984  State->Late.Coeff[index] = CalcDecayCoeff(length, decayTime);
985 
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);
990 
991  // Attenuate the cyclical line coefficients by the mixing coefficient
992  // (x).
993  State->Late.Coeff[index] *= xMix;
994  }
995 }
996 
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)
1000 {
1001  // Update the offset and coefficient for the echo delay line.
1002  State->Echo.Offset = fastf2u(echoTime * frequency);
1003 
1004  // Calculate the decay coefficient for the echo line.
1005  State->Echo.Coeff = CalcDecayCoeff(echoTime, decayTime);
1006 
1007  // Calculate the energy-based attenuation coefficient for the echo delay
1008  // line.
1009  State->Echo.DensityGain = CalcDensityGain(State->Echo.Coeff);
1010 
1011  // Calculate the echo all-pass feed coefficient.
1012  State->Echo.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
1013 
1014  // Calculate the echo all-pass attenuation coefficient.
1015  State->Echo.ApCoeff = CalcDecayCoeff(ECHO_ALLPASS_LENGTH, decayTime);
1016 
1017  // Calculate the damping coefficient for each low-pass filter.
1018  State->Echo.LpCoeff = CalcDampingCoeff(hfRatio, echoTime, decayTime,
1019  State->Echo.Coeff, cw);
1020 
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.
1025  */
1026  State->Echo.MixCoeff[0] = reverbGain * lateGain * echoDepth;
1027  State->Echo.MixCoeff[1] = 1.0f - (echoDepth * 0.5f * (1.0f - diffusion));
1028 }
1029 
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)
1032 {
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;
1041 
1042  Gain *= ReverbBoost;
1043 
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);
1047 
1048  length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
1049  if(length > 1.0f)
1050  {
1051  length = 1.0f / sqrtf(length);
1052  earlyPan[0] *= length;
1053  earlyPan[1] *= length;
1054  earlyPan[2] *= length;
1055  }
1056  length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2];
1057  if(length > 1.0f)
1058  {
1059  length = 1.0f / sqrtf(length);
1060  latePan[0] *= length;
1061  latePan[1] *= length;
1062  latePan[2] *= length;
1063  }
1064 
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);
1070 
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);
1076 }
1077 
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)
1081 {
1082  ALverbState *State = (ALverbState*)effect;
1083  ALuint frequency = Device->Frequency;
1084  ALboolean isEAX = AL_FALSE;
1085  ALfloat cw, x, y, hfRatio;
1086 
1088  {
1089  State->state.Process = EAXVerbProcess;
1090  isEAX = AL_TRUE;
1091  }
1092  else if(Slot->effect.type == AL_EFFECT_REVERB || EmulateEAXReverb)
1093  {
1094  State->state.Process = VerbProcess;
1095  isEAX = AL_FALSE;
1096  }
1097 
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);
1103 
1104  if(isEAX)
1105  {
1106  // Update the modulator line.
1109  frequency, State);
1110  }
1111 
1112  // Update the initial effect delay.
1115  frequency, State);
1116 
1117  // Update the early lines.
1120  Slot->effect.Reverb.LateReverbDelay, State);
1121 
1122  // Update the decorrelator.
1123  UpdateDecorrelator(Slot->effect.Reverb.Density, frequency, State);
1124 
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;
1129 
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,
1137  Slot->effect.Reverb.DecayTime);
1138 
1139  // Update the late lines.
1141  x, Slot->effect.Reverb.Density, Slot->effect.Reverb.DecayTime,
1142  Slot->effect.Reverb.Diffusion, hfRatio, cw, frequency, State);
1143 
1144  if(isEAX)
1145  {
1146  // Update the echo line.
1150  hfRatio, cw, frequency, State);
1151 
1152  // Update early and late 3D panning.
1154  Slot->effect.Reverb.LateReverbPan, Slot->Gain, State);
1155  }
1156  else
1157  {
1158  ALfloat gain = Slot->Gain;
1159  ALuint index;
1160 
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++)
1166  {
1167  enum Channel chan = Device->Speaker2Chan[index];
1168  State->Gain[chan] = gain;
1169  }
1170  }
1171 }
1172 
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.
1176 {
1177  ALverbState *State = (ALverbState*)effect;
1178  if(State)
1179  {
1180  free(State->SampleBuffer);
1181  State->SampleBuffer = NULL;
1182  free(State);
1183  }
1184 }
1185 
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.
1189 {
1190  ALverbState *State = NULL;
1191  ALuint index;
1192 
1193  State = malloc(sizeof(ALverbState));
1194  if(!State)
1195  return NULL;
1196 
1197  State->state.Destroy = ReverbDestroy;
1198  State->state.DeviceUpdate = ReverbDeviceUpdate;
1199  State->state.Update = ReverbUpdate;
1200  State->state.Process = VerbProcess;
1201 
1202  State->TotalSamples = 0;
1203  State->SampleBuffer = NULL;
1204 
1205  State->LpFilter.coeff = 0.0f;
1206  State->LpFilter.history[0] = 0.0f;
1207  State->LpFilter.history[1] = 0.0f;
1208 
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;
1216 
1217  State->Delay.Mask = 0;
1218  State->Delay.Line = NULL;
1219  State->DelayTap[0] = 0;
1220  State->DelayTap[1] = 0;
1221 
1222  State->Early.Gain = 0.0f;
1223  for(index = 0;index < 4;index++)
1224  {
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;
1229  }
1230 
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;
1236 
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++)
1242  {
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;
1247 
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;
1252 
1253  State->Late.LpCoeff[index] = 0.0f;
1254  State->Late.LpSample[index] = 0.0f;
1255  }
1256 
1257  for(index = 0;index < MaxChannels;index++)
1258  {
1259  State->Early.PanGain[index] = 0.0f;
1260  State->Late.PanGain[index] = 0.0f;
1261  }
1262 
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;
1277 
1278  State->Offset = 0;
1279 
1280  State->Gain = State->Late.PanGain;
1281 
1282  return &State->state;
1283 }
ALfloat GainHF
Definition: alEffect.h:34
static __inline ALfloat CalcDecayCoeff(ALfloat length, ALfloat decayTime)
Definition: alcReverb.c:763
static ALboolean AllocLines(ALuint frequency, ALverbState *State)
Definition: alcReverb.c:637
static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
Definition: alcReverb.c:225
#define F_PI
Definition: alu.h:16
#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY
Definition: efx.h:409
static ALvoid UpdateModulator(ALfloat modTime, ALfloat modDepth, ALuint frequency, ALverbState *State)
Definition: alcReverb.c:865
void ALvoid
Definition: al.h:74
struct ALeffect::@52 Reverb
static ALvoid UpdateEchoLine(ALfloat reverbGain, ALfloat lateGain, ALfloat echoTime, ALfloat decayTime, ALfloat diffusion, ALfloat echoDepth, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State)
Definition: alcReverb.c:999
static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
Definition: alcReverb.c:230
static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALverbState *State)
Definition: alcReverb.c:1031
#define AL_TRUE
Definition: al.h:86
ALfloat ModulationTime
Definition: alEffect.h:52
#define SPEEDOFSOUNDMETRESPERSEC
Definition: alu.h:46
GLboolean GLboolean g
Definition: glew.h:8736
#define NULL
Definition: ftobjs.h:61
#define TRACE(...)
Definition: alMain.h:806
GLclampf f
Definition: glew.h:3390
static __inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
Definition: alu.h:90
static ALuint CalcLineLength(ALfloat length, ALintptrEXT offset, ALuint frequency, DelayLine *Delay)
Definition: alcReverb.c:619
ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
Definition: alFilter.c:329
GLclampd n
Definition: glew.h:7287
static const ALfloat MODULATION_DEPTH_COEFF
Definition: alcReverb.c:179
static ALvoid EAXVerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat(*RESTRICT SamplesOut)[BUFFERSIZE])
Definition: alcReverb.c:581
ALfloat ReflectionsGain
Definition: alEffect.h:37
EGLSurface EGLint x
Definition: eglext.h:293
SDL_EventEntry * free
Definition: SDL_events.c:80
ALuint Frequency
Definition: alMain.h:569
ALfloat ReverbBoost
Definition: alcReverb.c:168
GLdouble GLdouble t
Definition: glew.h:1384
GLuint in
Definition: glew.h:10672
#define AL_FALSE
Definition: al.h:83
static ALboolean ReverbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
Definition: alcReverb.c:728
static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *RESTRICT out)
Definition: alcReverb.c:480
#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY
Definition: efx.h:419
static __inline ALfloat LateAllPassInOut(ALverbState *State, ALuint index, ALfloat in)
Definition: alcReverb.c:349
static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in)
Definition: alcReverb.c:258
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
ALfloat ReflectionsPan[3]
Definition: alEffect.h:48
static ALvoid ReverbDestroy(ALeffectState *effect)
Definition: alcReverb.c:1175
ALfloat Diffusion
Definition: alEffect.h:32
return Display return Display Bool Bool int d
Definition: SDL_x11sym.h:30
static __inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
Definition: alu.h:58
static __inline ALfloat CalcI3DL2HFreq(ALfloat hfRef, ALuint frequency)
Definition: alcReverb.c:777
static const ALfloat LATE_LINE_LENGTH[4]
Definition: alcReverb.c:214
static __inline ALvoid LateReverb(ALverbState *State, const ALfloat *RESTRICT in, ALfloat *RESTRICT out)
Definition: alcReverb.c:375
float ALfloat
Definition: al.h:68
static ALvoid UpdateEarlyLines(ALfloat reverbGain, ALfloat earlyGain, ALfloat lateDelay, ALverbState *State)
Definition: alcReverb.c:903
static __inline ALfloat CalcDensityGain(ALfloat a)
Definition: alcReverb.c:784
static __inline ALfloat lpFilter2P(FILTER *iir, ALuint offset, ALfloat input)
Definition: alFilter.h:21
ALfloat HFReference
Definition: alEffect.h:54
#define AL_EAXREVERB_MAX_MODULATION_TIME
Definition: efx.h:433
ALfloat AirAbsorptionGainHF
Definition: alEffect.h:41
GLenum GLint * range
Definition: glew.h:3391
ALfloat ReflectionsDelay
Definition: alEffect.h:38
static const ALfloat DECO_FRACTION
Definition: alcReverb.c:196
ALuint NumChan
Definition: alMain.h:611
static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALuint frequency, ALverbState *State)
Definition: alcReverb.c:895
enum Channel Speaker2Chan[MaxChannels]
Definition: alMain.h:609
ALfloat LateReverbDelay
Definition: alEffect.h:40
ALeffect effect
const GLdouble * v
Definition: glew.h:1377
GLsizei GLsizei * length
Definition: gl2ext.h:792
ALfloat DecayHFRatio
Definition: alEffect.h:36
static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *RESTRICT out)
Definition: alcReverb.c:304
#define AL_EFFECT_REVERB
Definition: efx.h:155
static ALfloat CalcLimitedHfRatio(ALfloat hfRatio, ALfloat airAbsorptionGainHF, ALfloat decayTime)
Definition: alcReverb.c:819
static ALvoid VerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat(*RESTRICT SamplesOut)[BUFFERSIZE])
Definition: alcReverb.c:558
static __inline ALuint fastf2u(ALfloat f)
Definition: alMain.h:379
GLsizei samples
Definition: gl2ext.h:970
ALfloat EchoDepth
Definition: alEffect.h:51
const GLfloat * c
Definition: glew.h:14913
#define AL_EAXREVERB_MAX_ECHO_TIME
Definition: efx.h:425
ALboolean DecayHFLimit
Definition: alEffect.h:43
#define realloc
Definition: SDL_malloc.c:637
ALvoid ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat *gains)
Definition: panning.c:149
GLuint index
Definition: glew.h:1800
volatile ALfloat Gain
unsigned int ALuint
Definition: al.h:59
enum State_ State
ptrdiff_t ALintptrEXT
Definition: alMain.h:45
static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *RESTRICT early, ALfloat *RESTRICT late)
Definition: alcReverb.c:519
ALeffectState * ReverbCreate(void)
Definition: alcReverb.c:1188
static const ALfloat MODULATION_FILTER_COEFF
Definition: alcReverb.c:186
static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
Definition: alcReverb.c:295
EGLSurface EGLint EGLint y
Definition: eglext.h:293
static __inline ALvoid CalcMatrixCoeffs(ALfloat diffusion, ALfloat *x, ALfloat *y)
Definition: alcReverb.c:803
#define malloc
Definition: SDL_malloc.c:635
static __inline ALfloat CalcDecayLength(ALfloat coeff, ALfloat decayTime)
Definition: alcReverb.c:770
static ALvoid ReverbUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot)
Definition: alcReverb.c:1080
ALboolean EmulateEAXReverb
Definition: alcReverb.c:171
ALfloat ModulationDepth
Definition: alEffect.h:53
static const ALfloat ALLPASS_LINE_LENGTH[4]
Definition: alcReverb.c:208
static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
Definition: alcReverb.c:366
static const ALfloat LATE_LINE_MULTIPLIER
Definition: alcReverb.c:221
GLintptr offset
Definition: glew.h:1668
static const ALfloat DECO_MULTIPLIER
Definition: alcReverb.c:197
static __inline ALvoid RealizeLineOffset(ALfloat *sampleBuffer, DelayLine *Delay)
Definition: alcReverb.c:613
#define LOWPASSFREQREF
Definition: alFilter.h:10
static const ALfloat MODULATION_FILTER_CONST
Definition: alcReverb.c:187
static size_t NextPowerOf2(size_t value)
Definition: alffmpeg.c:42
char ALboolean
Definition: al.h:38
static const ALfloat EARLY_LINE_LENGTH[4]
Definition: alcReverb.c:202
static __inline ALfloat AllpassInOut(DelayLine *Delay, ALuint outOffset, ALuint inOffset, ALfloat in, ALfloat feedCoeff, ALfloat coeff)
Definition: alcReverb.c:242
static __inline ALfloat minf(ALfloat a, ALfloat b)
Definition: alu.h:54
ALfloat LateReverbPan[3]
Definition: alEffect.h:49
ALfloat Gain
Definition: alEffect.h:33
static ALvoid UpdateDecorrelator(ALfloat density, ALuint frequency, ALverbState *State)
Definition: alcReverb.c:920
static const ALfloat ECHO_ALLPASS_LENGTH
Definition: alcReverb.c:191
ALfloat DecayTime
Definition: alEffect.h:35
static __inline ALfloat CalcDampingCoeff(ALfloat hfRatio, ALfloat length, ALfloat decayTime, ALfloat decayCoeff, ALfloat cw)
Definition: alcReverb.c:838
struct DelayLine DelayLine
#define AL_EFFECT_EAXREVERB
Definition: efx.h:167
static __inline ALfloat AttenuatedDelayLineOut(DelayLine *Delay, ALuint offset, ALfloat coeff)
Definition: alcReverb.c:236
#define BUFFERSIZE
Definition: alMain.h:556
struct ALverbState ALverbState
Channel
Definition: alMain.h:480
static __inline ALuint maxu(ALuint a, ALuint b)
Definition: alu.h:63
static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
Definition: alcReverb.c:358
ALenum type
Definition: alEffect.h:27
ALfloat LateReverbGain
Definition: alEffect.h:39
static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *RESTRICT late)
Definition: alcReverb.c:446
ALfloat EchoTime
Definition: alEffect.h:50
static ALvoid UpdateLateLines(ALfloat reverbGain, ALfloat lateGain, ALfloat xMix, ALfloat density, ALfloat decayTime, ALfloat diffusion, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State)
Definition: alcReverb.c:941
ALfloat Density
Definition: alEffect.h:31