zenilib: zenilib/jni/external/openal-soft/Alc/alcReverb.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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 */
168 ALfloat ReverbBoost = 1.0f;
169
170 /* Specifies whether to use a standard reverb effect in place of EAX reverb */
171 ALboolean EmulateEAXReverb = AL_FALSE;
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.
236 static __inline ALfloat AttenuatedDelayLineOut(DelayLine *Delay, ALuint offset, ALfloat coeff)
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.
258 static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in)
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.
295 static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
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.
349 static __inline ALfloat LateAllPassInOut(ALverbState *State, ALuint index, ALfloat in)
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.
358 static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
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.
366 static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
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.
619 static ALuint CalcLineLength(ALfloat length, ALintptrEXT offset, ALuint frequency, DelayLine *Delay)
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 */
637 static ALboolean AllocLines(ALuint frequency, ALverbState *State)
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 */
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);
656
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);
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).
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);
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.
728 static ALboolean ReverbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
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.
784 static __inline ALfloat CalcDensityGain(ALfloat a)
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) *
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);
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.
920 static ALvoid UpdateDecorrelator(ALfloat density, ALuint frequency, ALverbState *State)
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 *
978 LATE_LINE_MULTIPLIER));
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
1087 if(Slot->effect.type == AL_EFFECT_EAXREVERB && !EmulateEAXReverb)
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.
1107 UpdateModulator(Slot->effect.Reverb.ModulationTime,
1108 Slot->effect.Reverb.ModulationDepth,
1109 frequency, State);
1110 }
1111
1112 // Update the initial effect delay.
1113 UpdateDelayLine(Slot->effect.Reverb.ReflectionsDelay,
1114 Slot->effect.Reverb.LateReverbDelay,
1115 frequency, State);
1116
1117 // Update the early lines.
1118 UpdateEarlyLines(Slot->effect.Reverb.Gain,
1119 Slot->effect.Reverb.ReflectionsGain,
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,
1136 Slot->effect.Reverb.AirAbsorptionGainHF,
1137 Slot->effect.Reverb.DecayTime);
1138
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);
1143
1144 if(isEAX)
1145 {
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);
1151
1152 // Update early and late 3D panning.
1153 Update3DPanning(Device, Slot->effect.Reverb.ReflectionsPan,
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.
1175 static ALvoid ReverbDestroy(ALeffectState *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.
1188 ALeffectState *ReverbCreate(void)
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 }
ALeffect::GainHF
ALfloat GainHF
Definition: alEffect.h:34
CalcDecayCoeff
static __inline ALfloat CalcDecayCoeff(ALfloat length, ALfloat decayTime)
Definition: alcReverb.c:763
AllocLines
static ALboolean AllocLines(ALuint frequency, ALverbState *State)
Definition: alcReverb.c:637
DelayLineOut
static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
Definition: alcReverb.c:225
F_PI
#define F_PI
Definition: alu.h:16
AL_EAXREVERB_MAX_REFLECTIONS_DELAY
#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY
Definition: efx.h:409
UpdateModulator
static ALvoid UpdateModulator(ALfloat modTime, ALfloat modDepth, ALuint frequency, ALverbState *State)
Definition: alcReverb.c:865
ALvoid
void ALvoid
Definition: al.h:74
ALeffect::Reverb
struct ALeffect::@52 Reverb
UpdateEchoLine
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
DelayLineIn
static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
Definition: alcReverb.c:230
Update3DPanning
static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALverbState *State)
Definition: alcReverb.c:1031
AL_TRUE
#define AL_TRUE
Definition: al.h:86
ALeffect::ModulationTime
ALfloat ModulationTime
Definition: alEffect.h:52
SPEEDOFSOUNDMETRESPERSEC
#define SPEEDOFSOUNDMETRESPERSEC
Definition: alu.h:46
g
GLboolean GLboolean g
Definition: glew.h:8736
NULL
#define NULL
Definition: ftobjs.h:61
TRACE
#define TRACE(...)
Definition: alMain.h:806
f
GLclampf f
Definition: glew.h:3390
lerp
static __inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
Definition: alu.h:90
CalcLineLength
static ALuint CalcLineLength(ALfloat length, ALintptrEXT offset, ALuint frequency, DelayLine *Delay)
Definition: alcReverb.c:619
lpCoeffCalc
ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
Definition: alFilter.c:329
n
GLclampd n
Definition: glew.h:7287
MODULATION_DEPTH_COEFF
static const ALfloat MODULATION_DEPTH_COEFF
Definition: alcReverb.c:179
EAXVerbProcess
static ALvoid EAXVerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat(*RESTRICT SamplesOut)[BUFFERSIZE])
Definition: alcReverb.c:581
ALeffect::ReflectionsGain
ALfloat ReflectionsGain
Definition: alEffect.h:37
alu.h
x
EGLSurface EGLint x
Definition: eglext.h:293
free
SDL_EventEntry * free
Definition: SDL_events.c:80
ALCdevice_struct::Frequency
ALuint Frequency
Definition: alMain.h:569
ReverbBoost
ALfloat ReverbBoost
Definition: alcReverb.c:168
t
GLdouble GLdouble t
Definition: glew.h:1384
in
GLuint in
Definition: glew.h:10672
ALCdevice_struct
Definition: alMain.h:560
ALeffectState
Definition: alAuxEffectSlot.h:11
AL_FALSE
#define AL_FALSE
Definition: al.h:83
ReverbDeviceUpdate
static ALboolean ReverbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
Definition: alcReverb.c:728
VerbPass
static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *RESTRICT out)
Definition: alcReverb.c:480
AL_EAXREVERB_MAX_LATE_REVERB_DELAY
#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY
Definition: efx.h:419
LateAllPassInOut
static __inline ALfloat LateAllPassInOut(ALverbState *State, ALuint index, ALfloat in)
Definition: alcReverb.c:349
EAXModulation
static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in)
Definition: alcReverb.c:258
a
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
ALeffect::ReflectionsPan
ALfloat ReflectionsPan[3]
Definition: alEffect.h:48
ReverbDestroy
static ALvoid ReverbDestroy(ALeffectState *effect)
Definition: alcReverb.c:1175
alError.h
alFilter.h
ALeffect::Diffusion
ALfloat Diffusion
Definition: alEffect.h:32
d
return Display return Display Bool Bool int d
Definition: SDL_x11sym.h:30
clampf
static __inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
Definition: alu.h:58
CalcI3DL2HFreq
static __inline ALfloat CalcI3DL2HFreq(ALfloat hfRef, ALuint frequency)
Definition: alcReverb.c:777
LATE_LINE_LENGTH
static const ALfloat LATE_LINE_LENGTH[4]
Definition: alcReverb.c:214
LateReverb
static __inline ALvoid LateReverb(ALverbState *State, const ALfloat *RESTRICT in, ALfloat *RESTRICT out)
Definition: alcReverb.c:375
ALfloat
float ALfloat
Definition: al.h:68
UpdateEarlyLines
static ALvoid UpdateEarlyLines(ALfloat reverbGain, ALfloat earlyGain, ALfloat lateDelay, ALverbState *State)
Definition: alcReverb.c:903
CalcDensityGain
static __inline ALfloat CalcDensityGain(ALfloat a)
Definition: alcReverb.c:784
lpFilter2P
static __inline ALfloat lpFilter2P(FILTER *iir, ALuint offset, ALfloat input)
Definition: alFilter.h:21
ALeffect::HFReference
ALfloat HFReference
Definition: alEffect.h:54
AL_EAXREVERB_MAX_MODULATION_TIME
#define AL_EAXREVERB_MAX_MODULATION_TIME
Definition: efx.h:433
ALeffect::AirAbsorptionGainHF
ALfloat AirAbsorptionGainHF
Definition: alEffect.h:41
range
GLenum GLint * range
Definition: glew.h:3391
ALeffect::ReflectionsDelay
ALfloat ReflectionsDelay
Definition: alEffect.h:38
DECO_FRACTION
static const ALfloat DECO_FRACTION
Definition: alcReverb.c:196
ALCdevice_struct::NumChan
ALuint NumChan
Definition: alMain.h:611
UpdateDelayLine
static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALuint frequency, ALverbState *State)
Definition: alcReverb.c:895
ALCdevice_struct::Speaker2Chan
enum Channel Speaker2Chan[MaxChannels]
Definition: alMain.h:609
alAuxEffectSlot.h
ALeffect::LateReverbDelay
ALfloat LateReverbDelay
Definition: alEffect.h:40
ALeffectslot::effect
ALeffect effect
Definition: alAuxEffectSlot.h:21
v
const GLdouble * v
Definition: glew.h:1377
ALeffectslot
Definition: alAuxEffectSlot.h:19
alMain.h
length
GLsizei GLsizei * length
Definition: gl2ext.h:792
ALeffect::DecayHFRatio
ALfloat DecayHFRatio
Definition: alEffect.h:36
EarlyReflection
static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *RESTRICT out)
Definition: alcReverb.c:304
FILTER
Definition: alFilter.h:12
AL_EFFECT_REVERB
#define AL_EFFECT_REVERB
Definition: efx.h:155
CalcLimitedHfRatio
static ALfloat CalcLimitedHfRatio(ALfloat hfRatio, ALfloat airAbsorptionGainHF, ALfloat decayTime)
Definition: alcReverb.c:819
VerbProcess
static ALvoid VerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat(*RESTRICT SamplesOut)[BUFFERSIZE])
Definition: alcReverb.c:558
fastf2u
static __inline ALuint fastf2u(ALfloat f)
Definition: alMain.h:379
samples
GLsizei samples
Definition: gl2ext.h:970
ALeffect::EchoDepth
ALfloat EchoDepth
Definition: alEffect.h:51
c
const GLfloat * c
Definition: glew.h:14913
AL_EAXREVERB_MAX_ECHO_TIME
#define AL_EAXREVERB_MAX_ECHO_TIME
Definition: efx.h:425
ALeffect::DecayHFLimit
ALboolean DecayHFLimit
Definition: alEffect.h:43
realloc
#define realloc
Definition: SDL_malloc.c:637
ComputeAngleGains
ALvoid ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat *gains)
Definition: panning.c:149
index
GLuint index
Definition: glew.h:1800
ALeffectslot::Gain
volatile ALfloat Gain
Definition: alAuxEffectSlot.h:23
ALuint
unsigned int ALuint
Definition: al.h:59
State
enum State_ State
ALintptrEXT
ptrdiff_t ALintptrEXT
Definition: alMain.h:45
EAXVerbPass
static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *RESTRICT early, ALfloat *RESTRICT late)
Definition: alcReverb.c:519
ReverbCreate
ALeffectState * ReverbCreate(void)
Definition: alcReverb.c:1188
MODULATION_FILTER_COEFF
static const ALfloat MODULATION_FILTER_COEFF
Definition: alcReverb.c:186
EarlyDelayLineOut
static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
Definition: alcReverb.c:295
y
EGLSurface EGLint EGLint y
Definition: eglext.h:293
CalcMatrixCoeffs
static __inline ALvoid CalcMatrixCoeffs(ALfloat diffusion, ALfloat *x, ALfloat *y)
Definition: alcReverb.c:803
malloc
#define malloc
Definition: SDL_malloc.c:635
CalcDecayLength
static __inline ALfloat CalcDecayLength(ALfloat coeff, ALfloat decayTime)
Definition: alcReverb.c:770
ReverbUpdate
static ALvoid ReverbUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot)
Definition: alcReverb.c:1080
EmulateEAXReverb
ALboolean EmulateEAXReverb
Definition: alcReverb.c:171
ALeffect::ModulationDepth
ALfloat ModulationDepth
Definition: alEffect.h:53
ALLPASS_LINE_LENGTH
static const ALfloat ALLPASS_LINE_LENGTH[4]
Definition: alcReverb.c:208
LateLowPassInOut
static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
Definition: alcReverb.c:366
LATE_LINE_MULTIPLIER
static const ALfloat LATE_LINE_MULTIPLIER
Definition: alcReverb.c:221
offset
GLintptr offset
Definition: glew.h:1668
DECO_MULTIPLIER
static const ALfloat DECO_MULTIPLIER
Definition: alcReverb.c:197
RealizeLineOffset
static __inline ALvoid RealizeLineOffset(ALfloat *sampleBuffer, DelayLine *Delay)
Definition: alcReverb.c:613
alEffect.h
LOWPASSFREQREF
#define LOWPASSFREQREF
Definition: alFilter.h:10
MODULATION_FILTER_CONST
static const ALfloat MODULATION_FILTER_CONST
Definition: alcReverb.c:187
NextPowerOf2
static size_t NextPowerOf2(size_t value)
Definition: alffmpeg.c:42
ALboolean
char ALboolean
Definition: al.h:38
EARLY_LINE_LENGTH
static const ALfloat EARLY_LINE_LENGTH[4]
Definition: alcReverb.c:202
AllpassInOut
static __inline ALfloat AllpassInOut(DelayLine *Delay, ALuint outOffset, ALuint inOffset, ALfloat in, ALfloat feedCoeff, ALfloat coeff)
Definition: alcReverb.c:242
minf
static __inline ALfloat minf(ALfloat a, ALfloat b)
Definition: alu.h:54
ALeffect::LateReverbPan
ALfloat LateReverbPan[3]
Definition: alEffect.h:49
ALeffect::Gain
ALfloat Gain
Definition: alEffect.h:33
UpdateDecorrelator
static ALvoid UpdateDecorrelator(ALfloat density, ALuint frequency, ALverbState *State)
Definition: alcReverb.c:920
ECHO_ALLPASS_LENGTH
static const ALfloat ECHO_ALLPASS_LENGTH
Definition: alcReverb.c:191
ALeffect::DecayTime
ALfloat DecayTime
Definition: alEffect.h:35
CalcDampingCoeff
static __inline ALfloat CalcDampingCoeff(ALfloat hfRatio, ALfloat length, ALfloat decayTime, ALfloat decayCoeff, ALfloat cw)
Definition: alcReverb.c:838
DelayLine
struct DelayLine DelayLine
AL_EFFECT_EAXREVERB
#define AL_EFFECT_EAXREVERB
Definition: efx.h:167
AttenuatedDelayLineOut
static __inline ALfloat AttenuatedDelayLineOut(DelayLine *Delay, ALuint offset, ALfloat coeff)
Definition: alcReverb.c:236
BUFFERSIZE
#define BUFFERSIZE
Definition: alMain.h:556
ALverbState
struct ALverbState ALverbState
Channel
Channel
Definition: alMain.h:480
maxu
static __inline ALuint maxu(ALuint a, ALuint b)
Definition: alu.h:63
LateDelayLineOut
static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
Definition: alcReverb.c:358
ALeffect::type
ALenum type
Definition: alEffect.h:27
ALeffect::LateReverbGain
ALfloat LateReverbGain
Definition: alEffect.h:39
EAXEcho
static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *RESTRICT late)
Definition: alcReverb.c:446
ALeffect::EchoTime
ALfloat EchoTime
Definition: alEffect.h:50
UpdateLateLines
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
MaxChannels
Definition: alMain.h:491
ALeffect::Density
ALfloat Density
Definition: alEffect.h:31