2 * Reverb for the OpenAL cross platform audio library
3 * Copyright (C) 2008-2009 by Christopher Fitzgerald.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
29 #include "alAuxEffectSlot.h"
33 #include "mixer_defs.h"
36 static const int PrimeTable
[1024] = {
37 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
38 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,
39 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
40 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,
41 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
42 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359,
43 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433,
44 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
45 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593,
46 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
47 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743,
48 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827,
49 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
50 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
51 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
52 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163,
53 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249,
54 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321,
55 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439,
56 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
57 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601,
58 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
59 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783,
60 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
61 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
62 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069,
63 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143,
64 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
65 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347,
66 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
67 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543,
68 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657,
69 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713,
70 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801,
71 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
72 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011,
73 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119,
74 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
75 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323,
76 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
77 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527,
78 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
79 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697,
80 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797,
81 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
82 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003,
83 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093,
84 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
85 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283,
86 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
87 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513,
88 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621,
89 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721,
90 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813,
91 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
92 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
93 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113,
94 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233,
95 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351,
96 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
97 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531,
98 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653,
99 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743,
100 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849,
101 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
102 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073,
103 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173,
104 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271,
105 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359,
106 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
107 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581,
108 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701,
109 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803,
110 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907,
111 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
112 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121,
113 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229,
114 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349,
115 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487,
116 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
117 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669,
118 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757,
119 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879,
120 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
121 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111,
122 8117, 8123, 8147, 8161
125 /* This is the maximum number of samples processed for each inner loop
127 #define MAX_UPDATE_SAMPLES 256
130 static MixerFunc MixSamples
= Mix_C
;
131 static RowMixerFunc MixRowSamples
= MixRow_C
;
133 static alonce_flag mixfunc_inited
= AL_ONCE_FLAG_INIT
;
134 static void init_mixfunc(void)
136 MixSamples
= SelectMixer();
137 MixRowSamples
= SelectRowMixer();
141 typedef struct DelayLine
{
142 // The delay lines use sample lengths that are powers of 2 to allow the
143 // use of bit-masking instead of a modulus for wrapping.
148 typedef struct ALreverbState
{
149 DERIVE_FROM_TYPE(ALeffectState
);
153 // All delay lines are allocated as a single buffer to reduce memory
154 // fragmentation and management code.
155 ALfloat
*SampleBuffer
;
158 // Master effect filters
161 ALfilterState Hp
; // EAX only
165 // Modulator delay line.
168 // The vibrato time is tracked with an index over a modulus-wrapped
169 // range (in samples).
173 // The depth of frequency change (also in samples) and its filter.
179 /* Core delay line (early reflections and late reverb tap from this). */
181 /* The tap points for the initial delay. First set go to early
182 * reflections, second to late reverb.
184 ALsizei EarlyDelayTap
[4];
185 ALsizei LateDelayTap
[4];
188 // Early reflections are done with 4 delay lines.
192 // The gain for each output channel based on 3D panning.
193 ALfloat CurrentGain
[4][MAX_OUTPUT_CHANNELS
];
194 ALfloat PanGain
[4][MAX_OUTPUT_CHANNELS
];
198 // Attenuation to compensate for the modal density and decay rate of
202 // In addition to 4 delay lines.
207 // The delay lines are 1-pole low-pass filtered.
213 /* Late reverb has 3 all-pass filters in series on each of the 4 lines.
218 /* One delay line is used for all 3 all-pass filters. */
222 // The feed-back and feed-forward all-pass coefficient.
225 // Mixing matrix coefficient.
228 // Output gain for late reverb.
231 // The gain for each output channel based on 3D panning.
232 ALfloat CurrentGain
[4][MAX_OUTPUT_CHANNELS
];
233 ALfloat PanGain
[4][MAX_OUTPUT_CHANNELS
];
237 // Attenuation to compensate for the modal density and decay rate of
241 // Echo delay and all-pass lines.
253 // The echo line is 1-pole low-pass filtered.
257 // Echo mixing coefficient.
261 // The current read offset for all delay lines.
264 /* Temporary storage used when processing. */
265 alignas(16) ALfloat AFormatSamples
[4][MAX_UPDATE_SAMPLES
];
266 alignas(16) ALfloat ReverbSamples
[4][MAX_UPDATE_SAMPLES
];
267 alignas(16) ALfloat EarlySamples
[4][MAX_UPDATE_SAMPLES
];
270 static ALvoid
ALreverbState_Destruct(ALreverbState
*State
);
271 static ALboolean
ALreverbState_deviceUpdate(ALreverbState
*State
, ALCdevice
*Device
);
272 static ALvoid
ALreverbState_update(ALreverbState
*State
, const ALCdevice
*Device
, const ALeffectslot
*Slot
, const ALeffectProps
*props
);
273 static ALvoid
ALreverbState_process(ALreverbState
*State
, ALuint SamplesToDo
, const ALfloat (*restrict SamplesIn
)[BUFFERSIZE
], ALfloat (*restrict SamplesOut
)[BUFFERSIZE
], ALuint NumChannels
);
274 DECLARE_DEFAULT_ALLOCATORS(ALreverbState
)
276 DEFINE_ALEFFECTSTATE_VTABLE(ALreverbState
);
279 static void ALreverbState_Construct(ALreverbState
*state
)
283 ALeffectState_Construct(STATIC_CAST(ALeffectState
, state
));
284 SET_VTABLE2(ALreverbState
, ALeffectState
, state
);
286 state
->IsEax
= AL_FALSE
;
288 state
->TotalSamples
= 0;
289 state
->SampleBuffer
= NULL
;
291 for(index
= 0;index
< 4;index
++)
293 ALfilterState_clear(&state
->Filter
[index
].Lp
);
294 ALfilterState_clear(&state
->Filter
[index
].Hp
);
296 state
->Mod
.Delay
[index
].Mask
= 0;
297 state
->Mod
.Delay
[index
].Line
= NULL
;
300 state
->Mod
.Index
= 0;
301 state
->Mod
.Range
= 1;
302 state
->Mod
.Depth
= 0.0f
;
303 state
->Mod
.Coeff
= 0.0f
;
304 state
->Mod
.Filter
= 0.0f
;
306 state
->Delay
.Mask
= 0;
307 state
->Delay
.Line
= NULL
;
308 for(index
= 0;index
< 4;index
++)
309 state
->EarlyDelayTap
[index
] = 0;
310 for(index
= 0;index
< 4;index
++)
311 state
->LateDelayTap
[index
] = 0;
313 for(index
= 0;index
< 4;index
++)
315 state
->Early
.Delay
[index
].Mask
= 0;
316 state
->Early
.Delay
[index
].Line
= NULL
;
317 state
->Early
.Offset
[index
] = 0;
320 state
->Late
.Gain
= 0.0f
;
321 state
->Late
.DensityGain
= 0.0f
;
322 state
->Late
.ApFeedCoeff
= 0.0f
;
323 state
->Late
.MixCoeff
= 0.0f
;
324 for(index
= 0;index
< 4;index
++)
328 state
->Late
.Ap
[index
].Offsets
[k
] = 0;
329 state
->Late
.Ap
[index
].Delay
.Mask
= 0;
330 state
->Late
.Ap
[index
].Delay
.Line
= NULL
;
332 state
->Late
.Coeff
[index
] = 0.0f
;
333 state
->Late
.Delay
[index
].Mask
= 0;
334 state
->Late
.Delay
[index
].Line
= NULL
;
335 state
->Late
.Offset
[index
] = 0;
337 state
->Late
.Lp
[index
].Sample
= 0.0f
;
338 state
->Late
.Lp
[index
].Coeff
= 0.0f
;
343 for(index
= 0;index
< MAX_OUTPUT_CHANNELS
;index
++)
345 state
->Early
.CurrentGain
[l
][index
] = 0.0f
;
346 state
->Early
.PanGain
[l
][index
] = 0.0f
;
347 state
->Late
.CurrentGain
[l
][index
] = 0.0f
;
348 state
->Late
.PanGain
[l
][index
] = 0.0f
;
352 state
->Echo
.DensityGain
= 0.0f
;
355 state
->Echo
.Delay
[l
].Feedback
.Mask
= 0;
356 state
->Echo
.Delay
[l
].Feedback
.Line
= NULL
;
357 state
->Echo
.Delay
[l
].Ap
.Mask
= 0;
358 state
->Echo
.Delay
[l
].Ap
.Line
= NULL
;
360 state
->Echo
.Coeff
= 0.0f
;
361 state
->Echo
.ApFeedCoeff
= 0.0f
;
362 state
->Echo
.Offset
= 0;
363 state
->Echo
.ApOffset
= 0;
364 state
->Echo
.LpCoeff
= 0.0f
;
366 state
->Echo
.LpSample
[l
] = 0.0f
;
367 state
->Echo
.MixCoeff
= 0.0f
;
372 static ALvoid
ALreverbState_Destruct(ALreverbState
*State
)
374 al_free(State
->SampleBuffer
);
375 State
->SampleBuffer
= NULL
;
377 ALeffectState_Destruct(STATIC_CAST(ALeffectState
,State
));
380 /* This is a user config option for modifying the overall output of the reverb
383 ALfloat ReverbBoost
= 1.0f
;
385 /* Specifies whether to use a standard reverb effect in place of EAX reverb (no
386 * high-pass, modulation, or echo).
388 ALboolean EmulateEAXReverb
= AL_FALSE
;
390 /* This coefficient is used to define the maximum frequency range controlled
391 * by the modulation depth. The current value of 0.1 will allow it to swing
392 * from 0.9x to 1.1x. This value must be below 1. At 1 it will cause the
393 * sampler to stall on the downswing, and above 1 it will cause it to sample
396 static const ALfloat MODULATION_DEPTH_COEFF
= 0.1f
;
398 /* A filter is used to avoid the terrible distortion caused by changing
399 * modulation time and/or depth. To be consistent across different sample
400 * rates, the coefficient must be raised to a constant divided by the sample
401 * rate: coeff^(constant / rate).
403 static const ALfloat MODULATION_FILTER_COEFF
= 0.048f
;
404 static const ALfloat MODULATION_FILTER_CONST
= 100000.0f
;
406 // When diffusion is above 0, an all-pass filter is used to take the edge off
407 // the echo effect. It uses the following line length (in seconds).
408 static const ALfloat ECHO_ALLPASS_LENGTH
= 0.0133f
;
410 /* Input into the early reflections and late reverb are decorrelated between
411 * four channels. Their timings are dependent on a fraction and multiplier. See
412 * the UpdateDelayLine() routine for the calculations involved.
414 static const ALfloat DECO_FRACTION
= 0.15f
;
415 static const ALfloat DECO_MULTIPLIER
= 2.0f
;
417 // All delay line lengths are specified in seconds.
419 // The lengths of the early delay lines.
420 static const ALfloat EARLY_LINE_LENGTH
[4] =
422 0.0015f
, 0.0045f
, 0.0135f
, 0.0405f
425 /* The lengths of the late delay lines. */
426 static const ALfloat LATE_LINE_LENGTH
[4] =
428 0.0211f
, 0.0311f
, 0.0461f
, 0.0680f
431 /* The late delay lines have a variable length dependent on the effect's
432 * density parameter (inverted for some reason) and this multiplier.
434 static const ALfloat LATE_LINE_MULTIPLIER
= 3.0f
;
437 #if defined(_WIN32) && !defined (_M_X64) && !defined(_M_ARM)
438 /* HACK: Workaround for a modff bug in 32-bit Windows, which attempts to write
439 * a 64-bit double to the 32-bit float parameter.
441 static inline float hack_modff(float x
, float *y
)
444 double df
= modf((double)x
, &di
);
448 #define modff hack_modff
452 /**************************************
454 **************************************/
456 // Given the allocated sample buffer, this function updates each delay line
458 static inline ALvoid
RealizeLineOffset(ALfloat
*sampleBuffer
, DelayLine
*Delay
)
460 Delay
->Line
= &sampleBuffer
[(ptrdiff_t)Delay
->Line
];
463 // Calculate the length of a delay line and store its mask and offset.
464 static ALuint
CalcLineLength(ALfloat length
, ptrdiff_t offset
, ALuint frequency
, ALuint extra
, DelayLine
*Delay
)
468 // All line lengths are powers of 2, calculated from their lengths, with
469 // an additional sample in case of rounding errors.
470 samples
= fastf2u(length
*frequency
) + extra
;
471 samples
= NextPowerOf2(samples
+ 1);
472 // All lines share a single sample buffer.
473 Delay
->Mask
= samples
- 1;
474 Delay
->Line
= (ALfloat
*)offset
;
475 // Return the sample count for accumulation.
480 static int FindClosestPrime(int desired
, ALboolean
*used
)
483 ALsizei count
= COUNTOF(PrimeTable
)-1;
484 /* First, a binary search to find the closest prime that's not less than
485 * the desired value (lower_bound).
489 ALsizei step
= count
>>1;
490 ALsizei i
= curidx
+step
;
491 if(!(PrimeTable
[i
] < desired
))
499 /* If the next lesser prime is closer to the desired value, use it. */
500 if(curidx
> 0 && abs(PrimeTable
[curidx
-1]-desired
) < abs(PrimeTable
[curidx
]-desired
))
503 #define GET_BIT(arr, b) (!!(arr[(b)>>4]&(1<<((b)&7))))
504 #define SET_BIT(arr, b) ((void)(arr[(b)>>4] |= (1<<((b)&7))))
505 if(GET_BIT(used
, curidx
))
507 ALsizei off1
=0, off2
=0;
508 /* If this prime is already used, find the next unused larger and next
509 * unused smaller one.
511 while(off1
< curidx
&& GET_BIT(used
, curidx
-off1
))
513 while(off2
< 1024-curidx
&& GET_BIT(used
, curidx
+off2
))
516 /* Select the closest unused prime to the desired value. */
517 if(GET_BIT(used
, curidx
-off1
))
519 else if(GET_BIT(used
, curidx
+off2
))
522 curidx
= (abs(PrimeTable
[curidx
-off1
]-desired
) <
523 abs(PrimeTable
[curidx
+off2
]-desired
)) ? (curidx
-off1
) : (curidx
+off2
);
525 /* Mark this prime as used. */
526 SET_BIT(used
, curidx
);
530 return PrimeTable
[curidx
];
533 /* The lengths of the late reverb all-pass filter series are roughly calculated
534 * as: 15ms / (3**idx), where idx is the filter index of the series. On top of
535 * that, the filter lengths (in samples) should be prime numbers so they don't
536 * share any common factors.
538 * To accomplish this, a lookup table is used to search among the first 1024
539 * primes, along with a packed bit table to mark used primes, which should be
540 * enough to handle any reasonable sample rate.
542 * NOTE: The returned length is in *samples*, not seconds!
544 static ALfloat
CalcAllpassLength(ALuint idx
, ALuint frequency
, ALboolean
*used
)
546 ALfloat samples
= frequency
*0.015f
/ powf(3.0f
, (ALfloat
)idx
);
548 return FindClosestPrime((int)floorf(samples
+ 0.5f
), used
);
551 /* Calculates the delay line metrics and allocates the shared sample buffer
552 * for all lines given the sample rate (frequency). If an allocation failure
553 * occurs, it returns AL_FALSE.
555 static ALboolean
AllocLines(ALuint frequency
, ALreverbState
*State
)
557 ALboolean used_primes
[COUNTOF(PrimeTable
)>>4] = { 0 };
558 ALuint totalSamples
, index
;
561 // All delay line lengths are calculated to accomodate the full range of
562 // lengths given their respective paramters.
565 /* The modulator's line length is calculated from the maximum modulation
566 * time and depth coefficient, and halfed for the low-to-high frequency
567 * swing. An additional sample is added to keep it stable when there is no
570 length
= (AL_EAXREVERB_MAX_MODULATION_TIME
*MODULATION_DEPTH_COEFF
/2.0f
);
571 for(index
= 0;index
< 4;index
++)
572 totalSamples
+= CalcLineLength(length
, totalSamples
, frequency
, 1,
573 &State
->Mod
.Delay
[index
]);
575 /* The initial delay is the sum of the reflections and late reverb delays.
576 * The decorrelator length is calculated from the lowest reverb density (a
577 * parameter value of 1). This must include space for storing a loop
580 length
= AL_EAXREVERB_MAX_REFLECTIONS_DELAY
+
581 AL_EAXREVERB_MAX_LATE_REVERB_DELAY
;
582 length
+= (DECO_FRACTION
* DECO_MULTIPLIER
* DECO_MULTIPLIER
) *
583 LATE_LINE_LENGTH
[0] * (1.0f
+ LATE_LINE_MULTIPLIER
);
584 /* Multiply length by 4, since we're storing 4 interleaved channels in the
587 totalSamples
+= CalcLineLength(length
*4, totalSamples
, frequency
,
588 MAX_UPDATE_SAMPLES
*4, &State
->Delay
);
590 // The early reflection lines.
591 for(index
= 0;index
< 4;index
++)
592 totalSamples
+= CalcLineLength(EARLY_LINE_LENGTH
[index
], totalSamples
,
593 frequency
, 0, &State
->Early
.Delay
[index
]);
595 // The late delay lines are calculated from the lowest reverb density.
596 for(index
= 0;index
< 4;index
++)
598 length
= LATE_LINE_LENGTH
[index
] * (1.0f
+ LATE_LINE_MULTIPLIER
);
599 totalSamples
+= CalcLineLength(length
, totalSamples
, frequency
, 0,
600 &State
->Late
.Delay
[index
]);
603 // The late all-pass lines.
604 for(index
= 0;index
< 4;index
++)
610 length
+= CalcAllpassLength(k
, frequency
, used_primes
);
611 /* NOTE: Since 'length' is already the number of samples for the all-
612 * pass series, pass a sample rate of 1 so the sample length remains
615 totalSamples
+= CalcLineLength(length
, totalSamples
, 1, 1,
616 &State
->Late
.Ap
[index
].Delay
);
619 // The echo all-pass and delay lines.
620 for(index
= 0;index
< 4;index
++)
622 totalSamples
+= CalcLineLength(ECHO_ALLPASS_LENGTH
, totalSamples
,
623 frequency
, 0, &State
->Echo
.Delay
[index
].Ap
);
624 totalSamples
+= CalcLineLength(AL_EAXREVERB_MAX_ECHO_TIME
, totalSamples
,
625 frequency
, 0, &State
->Echo
.Delay
[index
].Feedback
);
628 if(totalSamples
!= State
->TotalSamples
)
632 TRACE("New reverb buffer length: %u samples\n", totalSamples
);
633 newBuffer
= al_calloc(16, sizeof(ALfloat
) * totalSamples
);
634 if(!newBuffer
) return AL_FALSE
;
636 al_free(State
->SampleBuffer
);
637 State
->SampleBuffer
= newBuffer
;
638 State
->TotalSamples
= totalSamples
;
641 // Update all delays to reflect the new sample buffer.
642 RealizeLineOffset(State
->SampleBuffer
, &State
->Delay
);
643 for(index
= 0;index
< 4;index
++)
645 RealizeLineOffset(State
->SampleBuffer
, &State
->Mod
.Delay
[index
]);
647 RealizeLineOffset(State
->SampleBuffer
, &State
->Early
.Delay
[index
]);
649 RealizeLineOffset(State
->SampleBuffer
, &State
->Late
.Ap
[index
].Delay
);
650 RealizeLineOffset(State
->SampleBuffer
, &State
->Late
.Delay
[index
]);
652 RealizeLineOffset(State
->SampleBuffer
, &State
->Echo
.Delay
[index
].Ap
);
653 RealizeLineOffset(State
->SampleBuffer
, &State
->Echo
.Delay
[index
].Feedback
);
656 // Clear the sample buffer.
657 for(index
= 0;index
< State
->TotalSamples
;index
++)
658 State
->SampleBuffer
[index
] = 0.0f
;
663 static ALboolean
ALreverbState_deviceUpdate(ALreverbState
*State
, ALCdevice
*Device
)
665 ALboolean used_primes
[COUNTOF(PrimeTable
)>>4] = { 0 };
666 ALuint frequency
= Device
->Frequency
, index
;
668 // Allocate the delay lines.
669 if(!AllocLines(frequency
, State
))
672 // Calculate the modulation filter coefficient. Notice that the exponent
673 // is calculated given the current sample rate. This ensures that the
674 // resulting filter response over time is consistent across all sample
676 State
->Mod
.Coeff
= powf(MODULATION_FILTER_COEFF
,
677 MODULATION_FILTER_CONST
/ frequency
);
679 // The early reflection and late all-pass filter line lengths are static,
680 // so their offsets only need to be calculated once.
681 for(index
= 0;index
< 4;index
++)
685 State
->Early
.Offset
[index
] = fastf2u(EARLY_LINE_LENGTH
[index
] * frequency
);
687 State
->Late
.Ap
[index
].Offsets
[k
] = (ALuint
)CalcAllpassLength(
688 k
, frequency
, used_primes
690 State
->Late
.Ap
[index
].Offsets
[1] += State
->Late
.Ap
[index
].Offsets
[0];
691 State
->Late
.Ap
[index
].Offsets
[2] += State
->Late
.Ap
[index
].Offsets
[1];
692 TRACE("Late all-pass %u: %u %u (%+d) %u (%+d)\n", index
,
693 State
->Late
.Ap
[index
].Offsets
[0], State
->Late
.Ap
[index
].Offsets
[1],
694 (State
->Late
.Ap
[index
].Offsets
[1] - State
->Late
.Ap
[index
].Offsets
[0]),
695 State
->Late
.Ap
[index
].Offsets
[2],
696 (State
->Late
.Ap
[index
].Offsets
[2] - State
->Late
.Ap
[index
].Offsets
[1])
700 // The echo all-pass filter line length is static, so its offset only
701 // needs to be calculated once.
702 State
->Echo
.ApOffset
= fastf2u(ECHO_ALLPASS_LENGTH
* frequency
);
707 /**************************************
709 **************************************/
711 // Calculate a decay coefficient given the length of each cycle and the time
712 // until the decay reaches -60 dB.
713 static inline ALfloat
CalcDecayCoeff(ALfloat length
, ALfloat decayTime
)
715 return powf(0.001f
/*-60 dB*/, length
/decayTime
);
718 // Calculate a decay length from a coefficient and the time until the decay
720 static inline ALfloat
CalcDecayLength(ALfloat coeff
, ALfloat decayTime
)
722 return log10f(coeff
) * decayTime
/ log10f(0.001f
)/*-60 dB*/;
725 // Calculate an attenuation to be applied to the input of any echo models to
726 // compensate for modal density and decay time.
727 static inline ALfloat
CalcDensityGain(ALfloat a
)
729 /* The energy of a signal can be obtained by finding the area under the
730 * squared signal. This takes the form of Sum(x_n^2), where x is the
731 * amplitude for the sample n.
733 * Decaying feedback matches exponential decay of the form Sum(a^n),
734 * where a is the attenuation coefficient, and n is the sample. The area
735 * under this decay curve can be calculated as: 1 / (1 - a).
737 * Modifying the above equation to find the squared area under the curve
738 * (for energy) yields: 1 / (1 - a^2). Input attenuation can then be
739 * calculated by inverting the square root of this approximation,
740 * yielding: 1 / sqrt(1 / (1 - a^2)), simplified to: sqrt(1 - a^2).
742 return sqrtf(1.0f
- (a
* a
));
745 // Calculate the mixing matrix coefficients given a diffusion factor.
746 static inline ALvoid
CalcMatrixCoeffs(ALfloat diffusion
, ALfloat
*x
, ALfloat
*y
)
750 // The matrix is of order 4, so n is sqrt (4 - 1).
752 t
= diffusion
* atanf(n
);
754 // Calculate the first mixing matrix coefficient.
756 // Calculate the second mixing matrix coefficient.
760 // Calculate the limited HF ratio for use with the late reverb low-pass
762 static ALfloat
CalcLimitedHfRatio(ALfloat hfRatio
, ALfloat airAbsorptionGainHF
, ALfloat decayTime
)
766 /* Find the attenuation due to air absorption in dB (converting delay
767 * time to meters using the speed of sound). Then reversing the decay
768 * equation, solve for HF ratio. The delay length is cancelled out of
769 * the equation, so it can be calculated once for all lines.
771 limitRatio
= 1.0f
/ (CalcDecayLength(airAbsorptionGainHF
, decayTime
) *
772 SPEEDOFSOUNDMETRESPERSEC
);
773 /* Using the limit calculated above, apply the upper bound to the HF
774 * ratio. Also need to limit the result to a minimum of 0.1, just like the
775 * HF ratio parameter. */
776 return clampf(limitRatio
, 0.1f
, hfRatio
);
779 // Calculate the coefficient for a HF (and eventually LF) decay damping
781 static inline ALfloat
CalcDampingCoeff(ALfloat hfRatio
, ALfloat length
, ALfloat decayTime
, ALfloat decayCoeff
, ALfloat cw
)
785 // Eventually this should boost the high frequencies when the ratio
790 // Calculate the low-pass coefficient by dividing the HF decay
791 // coefficient by the full decay coefficient.
792 g
= CalcDecayCoeff(length
, decayTime
* hfRatio
) / decayCoeff
;
794 // Damping is done with a 1-pole filter, so g needs to be squared.
796 if(g
< 0.9999f
) /* 1-epsilon */
798 /* Be careful with gains < 0.001, as that causes the coefficient
799 * head towards 1, which will flatten the signal. */
801 coeff
= (1 - g
*cw
- sqrtf(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) /
805 // Very low decay times will produce minimal output, so apply an
806 // upper bound to the coefficient.
807 coeff
= minf(coeff
, 0.98f
);
812 // Update the EAX modulation index, range, and depth. Keep in mind that this
813 // kind of vibrato is additive and not multiplicative as one may expect. The
814 // downswing will sound stronger than the upswing.
815 static ALvoid
UpdateModulator(ALfloat modTime
, ALfloat modDepth
, ALuint frequency
, ALreverbState
*State
)
819 /* Modulation is calculated in two parts.
821 * The modulation time effects the sinus applied to the change in
822 * frequency. An index out of the current time range (both in samples)
823 * is incremented each sample. The range is bound to a reasonable
824 * minimum (1 sample) and when the timing changes, the index is rescaled
825 * to the new range (to keep the sinus consistent).
827 range
= maxu(fastf2u(modTime
*frequency
), 1);
828 State
->Mod
.Index
= (ALuint
)(State
->Mod
.Index
* (ALuint64
)range
/
830 State
->Mod
.Range
= range
;
832 /* The modulation depth effects the amount of frequency change over the
833 * range of the sinus. It needs to be scaled by the modulation time so
834 * that a given depth produces a consistent change in frequency over all
835 * ranges of time. Since the depth is applied to a sinus value, it needs
836 * to be halfed once for the sinus range and again for the sinus swing
837 * in time (half of it is spent decreasing the frequency, half is spent
840 State
->Mod
.Depth
= modDepth
* MODULATION_DEPTH_COEFF
* modTime
/ 2.0f
/
844 // Update the offsets for the main effect delay line.
845 static ALvoid
UpdateDelayLine(ALfloat earlyDelay
, ALfloat lateDelay
, ALfloat density
, ALuint frequency
, ALreverbState
*State
)
850 /* The early reflections and late reverb inputs are decorrelated to provide
851 * time-varying reflections, smooth out the reverb tail, and reduce harsh
852 * echoes. The first tap occurs immediately, while the remaining taps are
853 * delayed by multiples of a fraction of the smallest delay time.
855 * offset[index] = (FRACTION (MULTIPLIER^(index-1))) smallest_delay
857 * for index = 1...max_lines
859 State
->EarlyDelayTap
[0] = fastf2u(earlyDelay
*frequency
+ 0.5f
);
862 length
= (DECO_FRACTION
* powf(DECO_MULTIPLIER
, (ALfloat
)i
-1.0f
)) *
863 EARLY_LINE_LENGTH
[0];
864 State
->EarlyDelayTap
[i
] = fastf2u(length
*frequency
+ 0.5f
) + State
->EarlyDelayTap
[0];
867 State
->LateDelayTap
[0] = fastf2u((earlyDelay
+ lateDelay
)*frequency
+ 0.5f
);
870 length
= (DECO_FRACTION
* powf(DECO_MULTIPLIER
, (ALfloat
)i
-1.0f
)) *
871 LATE_LINE_LENGTH
[0] * (1.0f
+ (density
* LATE_LINE_MULTIPLIER
));
872 State
->LateDelayTap
[i
] = fastf2u(length
*frequency
+ 0.5f
) + State
->LateDelayTap
[0];
876 // Update the late reverb mix, line lengths, and line coefficients.
877 static ALvoid
UpdateLateLines(ALfloat xMix
, ALfloat density
, ALfloat decayTime
, ALfloat diffusion
, ALfloat echoDepth
, ALfloat hfRatio
, ALfloat cw
, ALuint frequency
, ALreverbState
*State
)
882 /* Calculate the late reverb gain. Since the output is tapped prior to the
883 * application of the next delay line coefficients, the output needs to be
884 * attenuated by the 'x' mixing matrix coefficient. Also attenuate the
885 * late reverb when echo depth is high and diffusion is low, so the echo is
886 * slightly stronger than the decorrelated echos in the reverb tail.
888 State
->Late
.Gain
= xMix
* (1.0f
- (echoDepth
*0.5f
*(1.0f
- diffusion
)));
890 /* To compensate for changes in modal density and decay time of the late
891 * reverb signal, the input is attenuated based on the maximal energy of
892 * the outgoing signal. This approximation is used to keep the apparent
893 * energy of the signal equal for all ranges of density and decay time.
895 * The average length of the cyclcical delay lines is used to calculate
896 * the attenuation coefficient.
898 length
= (LATE_LINE_LENGTH
[0] + LATE_LINE_LENGTH
[1] +
899 LATE_LINE_LENGTH
[2] + LATE_LINE_LENGTH
[3]) / 4.0f
;
900 length
*= 1.0f
+ (density
* LATE_LINE_MULTIPLIER
);
901 State
->Late
.DensityGain
= CalcDensityGain(
902 CalcDecayCoeff(length
, decayTime
)
905 // Calculate the all-pass feed-back and feed-forward coefficient.
906 State
->Late
.ApFeedCoeff
= sqrtf(0.5f
) * powf(diffusion
, 2.0f
);
910 // Calculate the length (in seconds) of each delay line.
911 length
= LATE_LINE_LENGTH
[i
] * (1.0f
+ (density
*LATE_LINE_MULTIPLIER
));
913 // Calculate the delay offset for each delay line.
914 State
->Late
.Offset
[i
] = fastf2u(length
* frequency
);
916 // Calculate the gain (coefficient) for each line.
917 State
->Late
.Coeff
[i
] = CalcDecayCoeff(length
, decayTime
);
919 // Calculate the damping coefficient for each low-pass filter.
920 State
->Late
.Lp
[i
].Coeff
= CalcDampingCoeff(
921 hfRatio
, length
, decayTime
, State
->Late
.Coeff
[i
], cw
924 // Attenuate the line coefficients by the mixing coefficient (x).
925 State
->Late
.Coeff
[i
] *= xMix
;
929 // Update the echo gain, line offset, line coefficients, and mixing
931 static ALvoid
UpdateEchoLine(ALfloat echoTime
, ALfloat decayTime
, ALfloat diffusion
, ALfloat echoDepth
, ALfloat hfRatio
, ALfloat cw
, ALuint frequency
, ALreverbState
*State
)
933 // Update the offset and coefficient for the echo delay line.
934 State
->Echo
.Offset
= fastf2u(echoTime
* frequency
);
936 // Calculate the decay coefficient for the echo line.
937 State
->Echo
.Coeff
= CalcDecayCoeff(echoTime
, decayTime
);
939 // Calculate the energy-based attenuation coefficient for the echo delay
941 State
->Echo
.DensityGain
= CalcDensityGain(State
->Echo
.Coeff
);
943 // Calculate the echo all-pass feed coefficient.
944 State
->Echo
.ApFeedCoeff
= sqrtf(0.5f
) * powf(diffusion
, 2.0f
);
946 // Calculate the damping coefficient for each low-pass filter.
947 State
->Echo
.LpCoeff
= CalcDampingCoeff(hfRatio
, echoTime
, decayTime
,
948 State
->Echo
.Coeff
, cw
);
950 /* Calculate the echo mixing coefficient. This is applied to the output mix
951 * only, not the feedback.
953 State
->Echo
.MixCoeff
= echoDepth
;
956 /* Creates a transform matrix given a reverb vector. This works by creating a
957 * Z-focus transform, then a rotate transform around X, then Y, to place the
958 * focal point in the direction of the vector, using the vector length as a
961 * This isn't technically correct since the vector is supposed to define the
962 * aperture and not rotate the perceived soundfield, but in practice it's
963 * probably good enough.
965 static aluMatrixf
GetTransformFromVector(const ALfloat
*vec
)
967 aluMatrixf zfocus
, xrot
, yrot
;
968 aluMatrixf tmp1
, tmp2
;
972 length
= sqrtf(vec
[0]*vec
[0] + vec
[1]*vec
[1] + vec
[2]*vec
[2]);
974 /* Define a Z-focus (X in Ambisonics) transform, given the panning vector
977 sa
= sinf(minf(length
, 1.0f
) * (F_PI
/4.0f
));
978 aluMatrixfSet(&zfocus
,
979 1.0f
/(1.0f
+sa
), 0.0f
, 0.0f
, (sa
/(1.0f
+sa
))/1.732050808f
,
980 0.0f
, sqrtf((1.0f
-sa
)/(1.0f
+sa
)), 0.0f
, 0.0f
,
981 0.0f
, 0.0f
, sqrtf((1.0f
-sa
)/(1.0f
+sa
)), 0.0f
,
982 (sa
/(1.0f
+sa
))*1.732050808f
, 0.0f
, 0.0f
, 1.0f
/(1.0f
+sa
)
985 /* Define rotation around X (Y in Ambisonics) */
986 a
= atan2f(vec
[1], sqrtf(vec
[0]*vec
[0] + vec
[2]*vec
[2]));
988 1.0f
, 0.0f
, 0.0f
, 0.0f
,
989 0.0f
, 1.0f
, 0.0f
, 0.0f
,
990 0.0f
, 0.0f
, cosf(a
), sinf(a
),
991 0.0f
, 0.0f
, -sinf(a
), cosf(a
)
994 /* Define rotation around Y (Z in Ambisonics). NOTE: EFX's reverb vectors
995 * use a right-handled coordinate system, compared to the rest of OpenAL
996 * which uses left-handed. This is fixed by negating Z, however it would
997 * need to also be negated to get a proper Ambisonics angle, thus
1000 a
= atan2f(-vec
[0], vec
[2]);
1001 aluMatrixfSet(&yrot
,
1002 1.0f
, 0.0f
, 0.0f
, 0.0f
,
1003 0.0f
, cosf(a
), 0.0f
, sinf(a
),
1004 0.0f
, 0.0f
, 1.0f
, 0.0f
,
1005 0.0f
, -sinf(a
), 0.0f
, cosf(a
)
1008 #define MATRIX_MULT(_res, _m1, _m2) do { \
1010 for(col = 0;col < 4;col++) \
1012 for(row = 0;row < 4;row++) \
1013 _res.m[row][col] = _m1.m[row][0]*_m2.m[0][col] + _m1.m[row][1]*_m2.m[1][col] + \
1014 _m1.m[row][2]*_m2.m[2][col] + _m1.m[row][3]*_m2.m[3][col]; \
1017 /* Define a matrix that first focuses on Z, then rotates around X then Y to
1018 * focus the output in the direction of the vector.
1020 MATRIX_MULT(tmp1
, xrot
, zfocus
);
1021 MATRIX_MULT(tmp2
, yrot
, tmp1
);
1027 // Update the early and late 3D panning gains.
1028 static ALvoid
Update3DPanning(const ALCdevice
*Device
, const ALfloat
*ReflectionsPan
, const ALfloat
*LateReverbPan
, ALfloat Gain
, ALfloat EarlyGain
, ALfloat LateGain
, ALreverbState
*State
)
1030 /* Converts early reflections A-Format to B-Format (transposed). */
1031 static const aluMatrixf EarlyA2B
= {{
1032 { 0.8660254038f
, 0.8660254038f
, 0.8660254038f
, 0.8660254038f
},
1033 { 0.8660254038f
, 0.8660254038f
, -0.8660254038f
, -0.8660254038f
},
1034 { 0.8660254038f
, -0.8660254038f
, 0.8660254038f
, -0.8660254038f
},
1035 { 0.8660254038f
, -0.8660254038f
, -0.8660254038f
, 0.8660254038f
}
1037 /* Converts late reverb A-Format to B-Format (transposed). */
1038 static const aluMatrixf LateA2B
= {{
1039 { 0.8660254038f
, 1.2247448714f
, 0.0f
, 0.8660254038f
},
1040 { 0.8660254038f
, 0.0f
, -1.2247448714f
, -0.8660254038f
},
1041 { 0.8660254038f
, 0.0f
, 1.2247448714f
, -0.8660254038f
},
1042 { 0.8660254038f
, -1.2247448714f
, 0.0f
, 0.8660254038f
}
1044 aluMatrixf transform
, rot
;
1047 STATIC_CAST(ALeffectState
,State
)->OutBuffer
= Device
->FOAOut
.Buffer
;
1048 STATIC_CAST(ALeffectState
,State
)->OutChannels
= Device
->FOAOut
.NumChannels
;
1050 /* Note: Both _m2 and _res are transposed. */
1051 #define MATRIX_MULT(_res, _m1, _m2) do { \
1053 for(col = 0;col < 4;col++) \
1055 for(row = 0;row < 4;row++) \
1056 _res.m[col][row] = _m1.m[row][0]*_m2.m[col][0] + _m1.m[row][1]*_m2.m[col][1] + \
1057 _m1.m[row][2]*_m2.m[col][2] + _m1.m[row][3]*_m2.m[col][3]; \
1060 /* Create a matrix that first converts A-Format to B-Format, then rotates
1061 * the B-Format soundfield according to the panning vector.
1063 rot
= GetTransformFromVector(ReflectionsPan
);
1064 MATRIX_MULT(transform
, rot
, EarlyA2B
);
1065 memset(&State
->Early
.PanGain
, 0, sizeof(State
->Early
.PanGain
));
1066 for(i
= 0;i
< MAX_EFFECT_CHANNELS
;i
++)
1067 ComputeFirstOrderGains(Device
->FOAOut
, transform
.m
[i
], Gain
*EarlyGain
, State
->Early
.PanGain
[i
]);
1069 rot
= GetTransformFromVector(LateReverbPan
);
1070 MATRIX_MULT(transform
, rot
, LateA2B
);
1071 memset(&State
->Late
.PanGain
, 0, sizeof(State
->Late
.PanGain
));
1072 for(i
= 0;i
< MAX_EFFECT_CHANNELS
;i
++)
1073 ComputeFirstOrderGains(Device
->FOAOut
, transform
.m
[i
], Gain
*LateGain
, State
->Late
.PanGain
[i
]);
1077 static ALvoid
ALreverbState_update(ALreverbState
*State
, const ALCdevice
*Device
, const ALeffectslot
*Slot
, const ALeffectProps
*props
)
1079 ALuint frequency
= Device
->Frequency
;
1080 ALfloat lfscale
, hfscale
, hfRatio
;
1081 ALfloat gain
, gainlf
, gainhf
;
1085 if(Slot
->Params
.EffectType
== AL_EFFECT_EAXREVERB
&& !EmulateEAXReverb
)
1086 State
->IsEax
= AL_TRUE
;
1087 else if(Slot
->Params
.EffectType
== AL_EFFECT_REVERB
|| EmulateEAXReverb
)
1088 State
->IsEax
= AL_FALSE
;
1090 // Calculate the master filters
1091 hfscale
= props
->Reverb
.HFReference
/ frequency
;
1092 gainhf
= maxf(props
->Reverb
.GainHF
, 0.0001f
);
1093 ALfilterState_setParams(&State
->Filter
[0].Lp
, ALfilterType_HighShelf
,
1094 gainhf
, hfscale
, calc_rcpQ_from_slope(gainhf
, 0.75f
));
1095 lfscale
= props
->Reverb
.LFReference
/ frequency
;
1096 gainlf
= maxf(props
->Reverb
.GainLF
, 0.0001f
);
1097 ALfilterState_setParams(&State
->Filter
[0].Hp
, ALfilterType_LowShelf
,
1098 gainlf
, lfscale
, calc_rcpQ_from_slope(gainlf
, 0.75f
));
1099 for(i
= 1;i
< 4;i
++)
1101 State
->Filter
[i
].Lp
.b0
= State
->Filter
[0].Lp
.b0
;
1102 State
->Filter
[i
].Lp
.b1
= State
->Filter
[0].Lp
.b1
;
1103 State
->Filter
[i
].Lp
.b2
= State
->Filter
[0].Lp
.b2
;
1104 State
->Filter
[i
].Lp
.a1
= State
->Filter
[0].Lp
.a1
;
1105 State
->Filter
[i
].Lp
.a2
= State
->Filter
[0].Lp
.a2
;
1107 State
->Filter
[i
].Hp
.b0
= State
->Filter
[0].Hp
.b0
;
1108 State
->Filter
[i
].Hp
.b1
= State
->Filter
[0].Hp
.b1
;
1109 State
->Filter
[i
].Hp
.b2
= State
->Filter
[0].Hp
.b2
;
1110 State
->Filter
[i
].Hp
.a1
= State
->Filter
[0].Hp
.a1
;
1111 State
->Filter
[i
].Hp
.a2
= State
->Filter
[0].Hp
.a2
;
1114 // Update the modulator line.
1115 UpdateModulator(props
->Reverb
.ModulationTime
, props
->Reverb
.ModulationDepth
,
1118 // Update the main effect delay.
1119 UpdateDelayLine(props
->Reverb
.ReflectionsDelay
, props
->Reverb
.LateReverbDelay
,
1120 props
->Reverb
.Density
, frequency
, State
);
1122 // Get the mixing matrix coefficients (x and y).
1123 CalcMatrixCoeffs(props
->Reverb
.Diffusion
, &x
, &y
);
1124 // Then divide x into y to simplify the matrix calculation.
1125 State
->Late
.MixCoeff
= y
/ x
;
1127 // If the HF limit parameter is flagged, calculate an appropriate limit
1128 // based on the air absorption parameter.
1129 hfRatio
= props
->Reverb
.DecayHFRatio
;
1130 if(props
->Reverb
.DecayHFLimit
&& props
->Reverb
.AirAbsorptionGainHF
< 1.0f
)
1131 hfRatio
= CalcLimitedHfRatio(hfRatio
, props
->Reverb
.AirAbsorptionGainHF
,
1132 props
->Reverb
.DecayTime
);
1134 cw
= cosf(F_TAU
* hfscale
);
1135 // Update the late lines.
1136 UpdateLateLines(x
, props
->Reverb
.Density
, props
->Reverb
.DecayTime
,
1137 props
->Reverb
.Diffusion
, props
->Reverb
.EchoDepth
,
1138 hfRatio
, cw
, frequency
, State
);
1140 // Update the echo line.
1141 UpdateEchoLine(props
->Reverb
.EchoTime
, props
->Reverb
.DecayTime
,
1142 props
->Reverb
.Diffusion
, props
->Reverb
.EchoDepth
,
1143 hfRatio
, cw
, frequency
, State
);
1145 gain
= props
->Reverb
.Gain
* Slot
->Params
.Gain
* ReverbBoost
;
1146 // Update early and late 3D panning.
1147 Update3DPanning(Device
, props
->Reverb
.ReflectionsPan
,
1148 props
->Reverb
.LateReverbPan
, gain
,
1149 props
->Reverb
.ReflectionsGain
,
1150 props
->Reverb
.LateReverbGain
, State
);
1154 /**************************************
1155 * Effect Processing *
1156 **************************************/
1158 // Basic delay line input/output routines.
1159 static inline ALfloat
DelayLineOut(DelayLine
*Delay
, ALsizei offset
)
1161 return Delay
->Line
[offset
&Delay
->Mask
];
1164 static inline ALvoid
DelayLineIn(DelayLine
*Delay
, ALsizei offset
, ALfloat in
)
1166 Delay
->Line
[offset
&Delay
->Mask
] = in
;
1169 static inline ALfloat
DelayLineInOut(DelayLine
*Delay
, ALsizei offset
, ALsizei outoffset
, ALfloat in
)
1171 Delay
->Line
[offset
&Delay
->Mask
] = in
;
1172 return Delay
->Line
[(offset
-outoffset
)&Delay
->Mask
];
1175 static void CalcModulationDelays(ALreverbState
*State
, ALfloat
*restrict delays
, ALsizei todo
)
1177 ALfloat sinus
, range
;
1180 index
= State
->Mod
.Index
;
1181 range
= State
->Mod
.Filter
;
1182 for(i
= 0;i
< todo
;i
++)
1184 /* Calculate the sinus rythm (dependent on modulation time and the
1185 * sampling rate). The center of the sinus is moved to reduce the
1186 * delay of the effect when the time or depth are low.
1188 sinus
= 1.0f
- cosf(F_TAU
* index
/ State
->Mod
.Range
);
1190 /* Step the modulation index forward, keeping it bound to its range. */
1191 index
= (index
+1) % State
->Mod
.Range
;
1193 /* The depth determines the range over which to read the input samples
1194 * from, so it must be filtered to reduce the distortion caused by even
1195 * small parameter changes.
1197 range
= lerp(range
, State
->Mod
.Depth
, State
->Mod
.Coeff
);
1199 /* Calculate the read offset with fraction. */
1200 delays
[i
] = range
*sinus
;
1202 State
->Mod
.Index
= index
;
1203 State
->Mod
.Filter
= range
;
1206 // Given some input samples, this function produces modulation for the late
1208 static void EAXModulation(DelayLine
*ModDelay
, ALsizei offset
, const ALfloat
*restrict delays
, ALfloat
*restrict dst
, const ALfloat
*restrict src
, ALsizei todo
)
1210 ALfloat frac
, fdelay
;
1214 for(i
= 0;i
< todo
;i
++)
1216 /* Separate the integer offset and fraction between it and the next
1219 frac
= modff(delays
[i
], &fdelay
);
1220 delay
= fastf2u(fdelay
);
1222 /* Add the incoming sample to the delay line, and get the two samples
1223 * crossed by the offset delay.
1225 out0
= DelayLineInOut(ModDelay
, offset
, delay
, src
[i
]);
1226 out1
= DelayLineOut(ModDelay
, offset
- delay
- 1);
1229 /* The output is obtained by linearly interpolating the two samples
1230 * that were acquired above.
1232 dst
[i
] = lerp(out0
, out1
, frac
);
1236 /* Given some input samples from the main delay line, this function produces
1237 * four-channel outputs for the early reflections.
1239 static ALvoid
EarlyReflection(ALreverbState
*State
, ALsizei todo
, ALfloat (*restrict out
)[MAX_UPDATE_SAMPLES
])
1241 ALsizei offset
= State
->Offset
;
1242 ALfloat d
[4], v
, f
[4];
1245 for(i
= 0;i
< todo
;i
++)
1247 /* Obtain the first reflection samples from the main delay line. */
1248 f
[0] = DelayLineOut(&State
->Delay
, (offset
-State
->EarlyDelayTap
[0])*4 + 0);
1249 f
[1] = DelayLineOut(&State
->Delay
, (offset
-State
->EarlyDelayTap
[1])*4 + 1);
1250 f
[2] = DelayLineOut(&State
->Delay
, (offset
-State
->EarlyDelayTap
[2])*4 + 2);
1251 f
[3] = DelayLineOut(&State
->Delay
, (offset
-State
->EarlyDelayTap
[3])*4 + 3);
1253 /* The following is a Householder matrix that was derived from a
1254 * lossless scattering junction from waveguide theory. In this case,
1255 * it's maximally diffuse scattering is used without feedback.
1264 v
= (f
[0] + f
[1] + f
[2] + f
[3]) * 0.5f
;
1266 /* Calculate the values to pass through the delay lines. */
1272 /* Store the post-junction results in the main delay line, helping
1273 * compensate for the late reverb starting with a low echo density.
1275 DelayLineIn(&State
->Delay
, (offset
-State
->EarlyDelayTap
[0])*4 + 0, d
[0]);
1276 DelayLineIn(&State
->Delay
, (offset
-State
->EarlyDelayTap
[1])*4 + 1, d
[1]);
1277 DelayLineIn(&State
->Delay
, (offset
-State
->EarlyDelayTap
[2])*4 + 2, d
[2]);
1278 DelayLineIn(&State
->Delay
, (offset
-State
->EarlyDelayTap
[3])*4 + 3, d
[3]);
1280 /* Feed the early delay lines, and load the delayed results. */
1281 f
[0] += DelayLineInOut(&State
->Early
.Delay
[0], offset
, State
->Early
.Offset
[0], d
[0]);
1282 f
[1] += DelayLineInOut(&State
->Early
.Delay
[1], offset
, State
->Early
.Offset
[1], d
[1]);
1283 f
[2] += DelayLineInOut(&State
->Early
.Delay
[2], offset
, State
->Early
.Offset
[2], d
[2]);
1284 f
[3] += DelayLineInOut(&State
->Early
.Delay
[3], offset
, State
->Early
.Offset
[3], d
[3]);
1287 /* Output the initial reflection taps and the results of the delayed
1288 * junction for all four channels.
1297 // Basic attenuated all-pass input/output routine.
1298 static inline ALfloat
AllpassInOut(DelayLine
*Delay
, ALsizei outOffset
, ALsizei inOffset
, ALfloat in
, ALfloat feedCoeff
)
1302 out
= DelayLineOut(Delay
, outOffset
);
1303 feed
= feedCoeff
* in
;
1304 DelayLineIn(Delay
, inOffset
, in
+ feedCoeff
*(out
- feed
));
1309 // All-pass series input/output routine for late reverb.
1310 static inline ALfloat
LateAllPassInOut(ALreverbState
*State
, ALsizei offset
, ALsizei index
, ALfloat sample
)
1316 for(i
= 0;i
< 3;i
++)
1318 ALuint outOffset
= offset
- State
->Late
.Ap
[index
].Offsets
[i
];
1319 sample
= AllpassInOut(&State
->Late
.Ap
[index
].Delay
,
1320 outOffset
, inOffset
, sample
, State
->Late
.ApFeedCoeff
1322 inOffset
= outOffset
;
1328 // Low-pass filter input/output routine for late reverb.
1329 static inline ALfloat
LateLowPassInOut(ALreverbState
*State
, ALsizei index
, ALfloat in
)
1331 in
= lerp(in
, State
->Late
.Lp
[index
].Sample
, State
->Late
.Lp
[index
].Coeff
);
1332 State
->Late
.Lp
[index
].Sample
= in
;
1336 /* Given decorrelated input samples from the main delay line, this function
1337 * produces four-channel output for the late reverb.
1339 static ALvoid
LateReverb(ALreverbState
*State
, ALsizei todo
, ALfloat (*restrict out
)[MAX_UPDATE_SAMPLES
])
1345 offset
= State
->Offset
;
1346 for(i
= 0;i
< todo
;i
++)
1348 /* Obtain four decorrelated input samples. */
1349 for(j
= 0;j
< 4;j
++)
1350 f
[j
] = DelayLineOut(&State
->Delay
, (offset
-State
->LateDelayTap
[j
])*4 + j
) *
1351 State
->Late
.DensityGain
;
1353 /* Add the decayed results of the delay lines. */
1354 for(j
= 0;j
< 4;j
++)
1355 f
[j
] += DelayLineOut(&State
->Late
.Delay
[j
], offset
-State
->Late
.Offset
[j
]) *
1356 State
->Late
.Coeff
[j
];
1358 /* Apply a low-pass filter to simulate surface absorption. */
1359 for(j
= 0;j
< 4;j
++)
1360 f
[j
] = LateLowPassInOut(State
, j
, f
[j
]);
1362 /* To help increase diffusion, run each line through three all-pass
1363 * filters. This is where the feedback cycles from line 0 to 3 to 1 to
1366 d
[0] = LateAllPassInOut(State
, offset
, 2, f
[2]);
1367 d
[1] = LateAllPassInOut(State
, offset
, 3, f
[3]);
1368 d
[2] = LateAllPassInOut(State
, offset
, 1, f
[1]);
1369 d
[3] = LateAllPassInOut(State
, offset
, 0, f
[0]);
1371 /* Late reverb is done with a modified feed-back delay network (FDN)
1372 * topology. Four input lines are each fed through their own all-pass
1373 * filters and then into the mixing matrix. The four outputs of the
1374 * mixing matrix are then cycled back to the inputs.
1376 * The mixing matrix used is a 4D skew-symmetric rotation matrix
1377 * derived using a single unitary rotational parameter:
1379 * [ d, a, b, c ] 1 = a^2 + b^2 + c^2 + d^2
1384 * The rotation is constructed from the effect's diffusion parameter,
1385 * yielding: 1 = x^2 + 3 y^2; where a, b, and c are the coefficient y
1386 * with differing signs, and d is the coefficient x. The matrix is
1389 * [ x, y, -y, y ] n = sqrt(matrix_order - 1)
1390 * [ -y, x, y, y ] t = diffusion_parameter * atan(n)
1391 * [ y, -y, x, y ] x = cos(t)
1392 * [ -y, -y, -y, x ] y = sin(t) / n
1394 * To reduce the number of multiplies, the x coefficient is applied
1395 * with the delay line coefficients. Thus only the y coefficient
1396 * is applied when mixing, and is modified to be: y / x.
1398 f
[0] = d
[0] + (State
->Late
.MixCoeff
* ( d
[1] + -d
[2] + d
[3]));
1399 f
[1] = d
[1] + (State
->Late
.MixCoeff
* (-d
[0] + d
[2] + d
[3]));
1400 f
[2] = d
[2] + (State
->Late
.MixCoeff
* ( d
[0] + -d
[1] + d
[3]));
1401 f
[3] = d
[3] + (State
->Late
.MixCoeff
* (-d
[0] + -d
[1] + -d
[2] ));
1403 /* Re-feed the delay lines. */
1404 for(j
= 0;j
< 4;j
++)
1405 DelayLineIn(&State
->Late
.Delay
[j
], offset
, f
[j
]);
1408 /* Output the results of the matrix for all four channels, attenuated
1409 * by the late reverb gain (which is attenuated by the 'x' mix
1412 for(j
= 0;j
< 4;j
++)
1413 out
[j
][i
] = f
[j
] * State
->Late
.Gain
;
1417 /* This function reads from the main delay line's late reverb tap, and mixes a
1418 * continuous echo feedback into the four-channel late reverb output.
1420 static ALvoid
EAXEcho(ALreverbState
*State
, ALsizei todo
, ALfloat (*restrict late
)[MAX_UPDATE_SAMPLES
])
1426 for(c
= 0;c
< 4;c
++)
1428 offset
= State
->Offset
;
1429 for(i
= 0;i
< todo
;i
++)
1431 // Get the attenuated echo feedback sample for output.
1432 feed
= DelayLineOut(&State
->Echo
.Delay
[c
].Feedback
, offset
-State
->Echo
.Offset
) *
1435 // Write the output.
1436 late
[c
][i
] += State
->Echo
.MixCoeff
* feed
;
1438 // Mix the energy-attenuated input with the output and pass it through
1439 // the echo low-pass filter.
1440 feed
+= DelayLineOut(&State
->Delay
, (offset
-State
->LateDelayTap
[0])*4 + c
) *
1441 State
->Echo
.DensityGain
;
1442 feed
= lerp(feed
, State
->Echo
.LpSample
[c
], State
->Echo
.LpCoeff
);
1443 State
->Echo
.LpSample
[c
] = feed
;
1445 // Then the echo all-pass filter.
1446 feed
= AllpassInOut(&State
->Echo
.Delay
[c
].Ap
, offset
-State
->Echo
.ApOffset
,
1447 offset
, feed
, State
->Echo
.ApFeedCoeff
);
1449 // Feed the delay with the mixed and filtered sample.
1450 DelayLineIn(&State
->Echo
.Delay
[c
].Feedback
, offset
, feed
);
1456 // Perform the non-EAX reverb pass on a given input sample, resulting in
1457 // four-channel output.
1458 static ALvoid
VerbPass(ALreverbState
*State
, ALsizei todo
, ALfloat (*restrict input
)[MAX_UPDATE_SAMPLES
], ALfloat (*restrict early
)[MAX_UPDATE_SAMPLES
], ALfloat (*restrict late
)[MAX_UPDATE_SAMPLES
])
1462 for(c
= 0;c
< 4;c
++)
1464 /* Low-pass filter the incoming samples (use the early buffer as temp
1467 ALfilterState_process(&State
->Filter
[c
].Lp
, &early
[0][0], input
[c
], todo
);
1468 for(i
= 0;i
< todo
;i
++)
1469 DelayLineIn(&State
->Delay
, (State
->Offset
+i
)*4 + c
, early
[0][i
]);
1472 // Calculate the early reflection from the first delay tap.
1473 EarlyReflection(State
, todo
, early
);
1475 // Calculate the late reverb from the decorrelator taps.
1476 LateReverb(State
, todo
, late
);
1478 // Step all delays forward one sample.
1479 State
->Offset
+= todo
;
1482 // Perform the EAX reverb pass on a given input sample, resulting in four-
1484 static ALvoid
EAXVerbPass(ALreverbState
*State
, ALsizei todo
, ALfloat (*restrict input
)[MAX_UPDATE_SAMPLES
], ALfloat (*restrict early
)[MAX_UPDATE_SAMPLES
], ALfloat (*restrict late
)[MAX_UPDATE_SAMPLES
])
1488 /* Perform any modulation on the input (use the early and late buffers as
1491 CalcModulationDelays(State
, &late
[0][0], todo
);
1492 for(c
= 0;c
< 4;c
++)
1494 EAXModulation(&State
->Mod
.Delay
[c
], State
->Offset
, &late
[0][0],
1495 &early
[0][0], input
[c
], todo
);
1497 /* Band-pass the incoming samples */
1498 ALfilterState_process(&State
->Filter
[c
].Lp
, &early
[1][0], &early
[0][0], todo
);
1499 ALfilterState_process(&State
->Filter
[c
].Hp
, &early
[2][0], &early
[1][0], todo
);
1501 /* Feed the initial delay line. */
1502 for(i
= 0;i
< todo
;i
++)
1503 DelayLineIn(&State
->Delay
, (State
->Offset
+i
)*4 + c
, early
[2][i
]);
1506 // Calculate the early reflection from the first delay tap.
1507 EarlyReflection(State
, todo
, early
);
1509 // Calculate the late reverb from the decorrelator taps.
1510 LateReverb(State
, todo
, late
);
1512 // Calculate and mix in any echo.
1513 EAXEcho(State
, todo
, late
);
1515 // Step all delays forward.
1516 State
->Offset
+= todo
;
1520 static ALvoid
ALreverbState_processStandard(ALreverbState
*State
, ALuint SamplesToDo
, const ALfloat (*restrict SamplesIn
)[BUFFERSIZE
], ALfloat (*restrict SamplesOut
)[BUFFERSIZE
], ALuint NumChannels
)
1522 static const aluMatrixf B2A
= {{
1523 { 0.288675134595f
, 0.288675134595f
, 0.288675134595f
, 0.288675134595f
},
1524 { 0.288675134595f
, 0.288675134595f
, -0.288675134595f
, -0.288675134595f
},
1525 { 0.288675134595f
, -0.288675134595f
, 0.288675134595f
, -0.288675134595f
},
1526 { 0.288675134595f
, -0.288675134595f
, -0.288675134595f
, 0.288675134595f
}
1528 ALfloat (*restrict afmt
)[MAX_UPDATE_SAMPLES
] = State
->AFormatSamples
;
1529 ALfloat (*restrict early
)[MAX_UPDATE_SAMPLES
] = State
->EarlySamples
;
1530 ALfloat (*restrict late
)[MAX_UPDATE_SAMPLES
] = State
->ReverbSamples
;
1533 /* Process reverb for these samples. */
1534 for(base
= 0;base
< SamplesToDo
;)
1536 ALsizei todo
= minu(SamplesToDo
-base
, MAX_UPDATE_SAMPLES
);
1538 /* Convert B-Format to A-Format for processing. */
1539 memset(afmt
, 0, sizeof(*afmt
)*4);
1540 for(c
= 0;c
< 4;c
++)
1541 MixRowSamples(afmt
[c
], B2A
.m
[c
],
1542 SamplesIn
, MAX_EFFECT_CHANNELS
, base
, todo
1545 VerbPass(State
, todo
, afmt
, early
, late
);
1547 /* Mix the A-Format results to output, implicitly converting back to
1550 for(c
= 0;c
< 4;c
++)
1551 MixSamples(early
[c
], NumChannels
, SamplesOut
,
1552 State
->Early
.CurrentGain
[c
], State
->Early
.PanGain
[c
],
1553 SamplesToDo
-base
, base
, todo
1555 for(c
= 0;c
< 4;c
++)
1556 MixSamples(late
[c
], NumChannels
, SamplesOut
,
1557 State
->Late
.CurrentGain
[c
], State
->Late
.PanGain
[c
],
1558 SamplesToDo
-base
, base
, todo
1565 static ALvoid
ALreverbState_processEax(ALreverbState
*State
, ALuint SamplesToDo
, const ALfloat (*restrict SamplesIn
)[BUFFERSIZE
], ALfloat (*restrict SamplesOut
)[BUFFERSIZE
], ALuint NumChannels
)
1567 static const aluMatrixf B2A
= {{
1568 { 0.288675134595f
, 0.288675134595f
, 0.288675134595f
, 0.288675134595f
},
1569 { 0.288675134595f
, 0.288675134595f
, -0.288675134595f
, -0.288675134595f
},
1570 { 0.288675134595f
, -0.288675134595f
, 0.288675134595f
, -0.288675134595f
},
1571 { 0.288675134595f
, -0.288675134595f
, -0.288675134595f
, 0.288675134595f
}
1573 ALfloat (*restrict afmt
)[MAX_UPDATE_SAMPLES
] = State
->AFormatSamples
;
1574 ALfloat (*restrict early
)[MAX_UPDATE_SAMPLES
] = State
->EarlySamples
;
1575 ALfloat (*restrict late
)[MAX_UPDATE_SAMPLES
] = State
->ReverbSamples
;
1578 /* Process reverb for these samples. */
1579 for(base
= 0;base
< SamplesToDo
;)
1581 ALsizei todo
= minu(SamplesToDo
-base
, MAX_UPDATE_SAMPLES
);
1583 memset(afmt
, 0, 4*MAX_UPDATE_SAMPLES
*sizeof(float));
1584 for(c
= 0;c
< 4;c
++)
1585 MixRowSamples(afmt
[c
], B2A
.m
[c
],
1586 SamplesIn
, MAX_EFFECT_CHANNELS
, base
, todo
1589 EAXVerbPass(State
, todo
, afmt
, early
, late
);
1591 for(c
= 0;c
< 4;c
++)
1592 MixSamples(early
[c
], NumChannels
, SamplesOut
,
1593 State
->Early
.CurrentGain
[c
], State
->Early
.PanGain
[c
],
1594 SamplesToDo
-base
, base
, todo
1596 for(c
= 0;c
< 4;c
++)
1597 MixSamples(late
[c
], NumChannels
, SamplesOut
,
1598 State
->Late
.CurrentGain
[c
], State
->Late
.PanGain
[c
],
1599 SamplesToDo
-base
, base
, todo
1606 static ALvoid
ALreverbState_process(ALreverbState
*State
, ALuint SamplesToDo
, const ALfloat (*restrict SamplesIn
)[BUFFERSIZE
], ALfloat (*restrict SamplesOut
)[BUFFERSIZE
], ALuint NumChannels
)
1609 ALreverbState_processEax(State
, SamplesToDo
, SamplesIn
, SamplesOut
, NumChannels
);
1611 ALreverbState_processStandard(State
, SamplesToDo
, SamplesIn
, SamplesOut
, NumChannels
);
1615 typedef struct ALreverbStateFactory
{
1616 DERIVE_FROM_TYPE(ALeffectStateFactory
);
1617 } ALreverbStateFactory
;
1619 static ALeffectState
*ALreverbStateFactory_create(ALreverbStateFactory
* UNUSED(factory
))
1621 ALreverbState
*state
;
1623 alcall_once(&mixfunc_inited
, init_mixfunc
);
1625 NEW_OBJ0(state
, ALreverbState
)();
1626 if(!state
) return NULL
;
1628 return STATIC_CAST(ALeffectState
, state
);
1631 DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALreverbStateFactory
);
1633 ALeffectStateFactory
*ALreverbStateFactory_getFactory(void)
1635 static ALreverbStateFactory ReverbFactory
= { { GET_VTABLE2(ALreverbStateFactory
, ALeffectStateFactory
) } };
1637 return STATIC_CAST(ALeffectStateFactory
, &ReverbFactory
);
1641 void ALeaxreverb_setParami(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint val
)
1643 ALeffectProps
*props
= &effect
->Props
;
1646 case AL_EAXREVERB_DECAY_HFLIMIT
:
1647 if(!(val
>= AL_EAXREVERB_MIN_DECAY_HFLIMIT
&& val
<= AL_EAXREVERB_MAX_DECAY_HFLIMIT
))
1648 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1649 props
->Reverb
.DecayHFLimit
= val
;
1653 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
1656 void ALeaxreverb_setParamiv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALint
*vals
)
1658 ALeaxreverb_setParami(effect
, context
, param
, vals
[0]);
1660 void ALeaxreverb_setParamf(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat val
)
1662 ALeffectProps
*props
= &effect
->Props
;
1665 case AL_EAXREVERB_DENSITY
:
1666 if(!(val
>= AL_EAXREVERB_MIN_DENSITY
&& val
<= AL_EAXREVERB_MAX_DENSITY
))
1667 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1668 props
->Reverb
.Density
= val
;
1671 case AL_EAXREVERB_DIFFUSION
:
1672 if(!(val
>= AL_EAXREVERB_MIN_DIFFUSION
&& val
<= AL_EAXREVERB_MAX_DIFFUSION
))
1673 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1674 props
->Reverb
.Diffusion
= val
;
1677 case AL_EAXREVERB_GAIN
:
1678 if(!(val
>= AL_EAXREVERB_MIN_GAIN
&& val
<= AL_EAXREVERB_MAX_GAIN
))
1679 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1680 props
->Reverb
.Gain
= val
;
1683 case AL_EAXREVERB_GAINHF
:
1684 if(!(val
>= AL_EAXREVERB_MIN_GAINHF
&& val
<= AL_EAXREVERB_MAX_GAINHF
))
1685 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1686 props
->Reverb
.GainHF
= val
;
1689 case AL_EAXREVERB_GAINLF
:
1690 if(!(val
>= AL_EAXREVERB_MIN_GAINLF
&& val
<= AL_EAXREVERB_MAX_GAINLF
))
1691 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1692 props
->Reverb
.GainLF
= val
;
1695 case AL_EAXREVERB_DECAY_TIME
:
1696 if(!(val
>= AL_EAXREVERB_MIN_DECAY_TIME
&& val
<= AL_EAXREVERB_MAX_DECAY_TIME
))
1697 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1698 props
->Reverb
.DecayTime
= val
;
1701 case AL_EAXREVERB_DECAY_HFRATIO
:
1702 if(!(val
>= AL_EAXREVERB_MIN_DECAY_HFRATIO
&& val
<= AL_EAXREVERB_MAX_DECAY_HFRATIO
))
1703 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1704 props
->Reverb
.DecayHFRatio
= val
;
1707 case AL_EAXREVERB_DECAY_LFRATIO
:
1708 if(!(val
>= AL_EAXREVERB_MIN_DECAY_LFRATIO
&& val
<= AL_EAXREVERB_MAX_DECAY_LFRATIO
))
1709 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1710 props
->Reverb
.DecayLFRatio
= val
;
1713 case AL_EAXREVERB_REFLECTIONS_GAIN
:
1714 if(!(val
>= AL_EAXREVERB_MIN_REFLECTIONS_GAIN
&& val
<= AL_EAXREVERB_MAX_REFLECTIONS_GAIN
))
1715 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1716 props
->Reverb
.ReflectionsGain
= val
;
1719 case AL_EAXREVERB_REFLECTIONS_DELAY
:
1720 if(!(val
>= AL_EAXREVERB_MIN_REFLECTIONS_DELAY
&& val
<= AL_EAXREVERB_MAX_REFLECTIONS_DELAY
))
1721 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1722 props
->Reverb
.ReflectionsDelay
= val
;
1725 case AL_EAXREVERB_LATE_REVERB_GAIN
:
1726 if(!(val
>= AL_EAXREVERB_MIN_LATE_REVERB_GAIN
&& val
<= AL_EAXREVERB_MAX_LATE_REVERB_GAIN
))
1727 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1728 props
->Reverb
.LateReverbGain
= val
;
1731 case AL_EAXREVERB_LATE_REVERB_DELAY
:
1732 if(!(val
>= AL_EAXREVERB_MIN_LATE_REVERB_DELAY
&& val
<= AL_EAXREVERB_MAX_LATE_REVERB_DELAY
))
1733 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1734 props
->Reverb
.LateReverbDelay
= val
;
1737 case AL_EAXREVERB_AIR_ABSORPTION_GAINHF
:
1738 if(!(val
>= AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF
&& val
<= AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF
))
1739 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1740 props
->Reverb
.AirAbsorptionGainHF
= val
;
1743 case AL_EAXREVERB_ECHO_TIME
:
1744 if(!(val
>= AL_EAXREVERB_MIN_ECHO_TIME
&& val
<= AL_EAXREVERB_MAX_ECHO_TIME
))
1745 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1746 props
->Reverb
.EchoTime
= val
;
1749 case AL_EAXREVERB_ECHO_DEPTH
:
1750 if(!(val
>= AL_EAXREVERB_MIN_ECHO_DEPTH
&& val
<= AL_EAXREVERB_MAX_ECHO_DEPTH
))
1751 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1752 props
->Reverb
.EchoDepth
= val
;
1755 case AL_EAXREVERB_MODULATION_TIME
:
1756 if(!(val
>= AL_EAXREVERB_MIN_MODULATION_TIME
&& val
<= AL_EAXREVERB_MAX_MODULATION_TIME
))
1757 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1758 props
->Reverb
.ModulationTime
= val
;
1761 case AL_EAXREVERB_MODULATION_DEPTH
:
1762 if(!(val
>= AL_EAXREVERB_MIN_MODULATION_DEPTH
&& val
<= AL_EAXREVERB_MAX_MODULATION_DEPTH
))
1763 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1764 props
->Reverb
.ModulationDepth
= val
;
1767 case AL_EAXREVERB_HFREFERENCE
:
1768 if(!(val
>= AL_EAXREVERB_MIN_HFREFERENCE
&& val
<= AL_EAXREVERB_MAX_HFREFERENCE
))
1769 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1770 props
->Reverb
.HFReference
= val
;
1773 case AL_EAXREVERB_LFREFERENCE
:
1774 if(!(val
>= AL_EAXREVERB_MIN_LFREFERENCE
&& val
<= AL_EAXREVERB_MAX_LFREFERENCE
))
1775 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1776 props
->Reverb
.LFReference
= val
;
1779 case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
:
1780 if(!(val
>= AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR
&& val
<= AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR
))
1781 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1782 props
->Reverb
.RoomRolloffFactor
= val
;
1786 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
1789 void ALeaxreverb_setParamfv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
1791 ALeffectProps
*props
= &effect
->Props
;
1794 case AL_EAXREVERB_REFLECTIONS_PAN
:
1795 if(!(isfinite(vals
[0]) && isfinite(vals
[1]) && isfinite(vals
[2])))
1796 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1797 props
->Reverb
.ReflectionsPan
[0] = vals
[0];
1798 props
->Reverb
.ReflectionsPan
[1] = vals
[1];
1799 props
->Reverb
.ReflectionsPan
[2] = vals
[2];
1801 case AL_EAXREVERB_LATE_REVERB_PAN
:
1802 if(!(isfinite(vals
[0]) && isfinite(vals
[1]) && isfinite(vals
[2])))
1803 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1804 props
->Reverb
.LateReverbPan
[0] = vals
[0];
1805 props
->Reverb
.LateReverbPan
[1] = vals
[1];
1806 props
->Reverb
.LateReverbPan
[2] = vals
[2];
1810 ALeaxreverb_setParamf(effect
, context
, param
, vals
[0]);
1815 void ALeaxreverb_getParami(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*val
)
1817 const ALeffectProps
*props
= &effect
->Props
;
1820 case AL_EAXREVERB_DECAY_HFLIMIT
:
1821 *val
= props
->Reverb
.DecayHFLimit
;
1825 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
1828 void ALeaxreverb_getParamiv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*vals
)
1830 ALeaxreverb_getParami(effect
, context
, param
, vals
);
1832 void ALeaxreverb_getParamf(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
1834 const ALeffectProps
*props
= &effect
->Props
;
1837 case AL_EAXREVERB_DENSITY
:
1838 *val
= props
->Reverb
.Density
;
1841 case AL_EAXREVERB_DIFFUSION
:
1842 *val
= props
->Reverb
.Diffusion
;
1845 case AL_EAXREVERB_GAIN
:
1846 *val
= props
->Reverb
.Gain
;
1849 case AL_EAXREVERB_GAINHF
:
1850 *val
= props
->Reverb
.GainHF
;
1853 case AL_EAXREVERB_GAINLF
:
1854 *val
= props
->Reverb
.GainLF
;
1857 case AL_EAXREVERB_DECAY_TIME
:
1858 *val
= props
->Reverb
.DecayTime
;
1861 case AL_EAXREVERB_DECAY_HFRATIO
:
1862 *val
= props
->Reverb
.DecayHFRatio
;
1865 case AL_EAXREVERB_DECAY_LFRATIO
:
1866 *val
= props
->Reverb
.DecayLFRatio
;
1869 case AL_EAXREVERB_REFLECTIONS_GAIN
:
1870 *val
= props
->Reverb
.ReflectionsGain
;
1873 case AL_EAXREVERB_REFLECTIONS_DELAY
:
1874 *val
= props
->Reverb
.ReflectionsDelay
;
1877 case AL_EAXREVERB_LATE_REVERB_GAIN
:
1878 *val
= props
->Reverb
.LateReverbGain
;
1881 case AL_EAXREVERB_LATE_REVERB_DELAY
:
1882 *val
= props
->Reverb
.LateReverbDelay
;
1885 case AL_EAXREVERB_AIR_ABSORPTION_GAINHF
:
1886 *val
= props
->Reverb
.AirAbsorptionGainHF
;
1889 case AL_EAXREVERB_ECHO_TIME
:
1890 *val
= props
->Reverb
.EchoTime
;
1893 case AL_EAXREVERB_ECHO_DEPTH
:
1894 *val
= props
->Reverb
.EchoDepth
;
1897 case AL_EAXREVERB_MODULATION_TIME
:
1898 *val
= props
->Reverb
.ModulationTime
;
1901 case AL_EAXREVERB_MODULATION_DEPTH
:
1902 *val
= props
->Reverb
.ModulationDepth
;
1905 case AL_EAXREVERB_HFREFERENCE
:
1906 *val
= props
->Reverb
.HFReference
;
1909 case AL_EAXREVERB_LFREFERENCE
:
1910 *val
= props
->Reverb
.LFReference
;
1913 case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
:
1914 *val
= props
->Reverb
.RoomRolloffFactor
;
1918 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
1921 void ALeaxreverb_getParamfv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
1923 const ALeffectProps
*props
= &effect
->Props
;
1926 case AL_EAXREVERB_REFLECTIONS_PAN
:
1927 vals
[0] = props
->Reverb
.ReflectionsPan
[0];
1928 vals
[1] = props
->Reverb
.ReflectionsPan
[1];
1929 vals
[2] = props
->Reverb
.ReflectionsPan
[2];
1931 case AL_EAXREVERB_LATE_REVERB_PAN
:
1932 vals
[0] = props
->Reverb
.LateReverbPan
[0];
1933 vals
[1] = props
->Reverb
.LateReverbPan
[1];
1934 vals
[2] = props
->Reverb
.LateReverbPan
[2];
1938 ALeaxreverb_getParamf(effect
, context
, param
, vals
);
1943 DEFINE_ALEFFECT_VTABLE(ALeaxreverb
);
1945 void ALreverb_setParami(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint val
)
1947 ALeffectProps
*props
= &effect
->Props
;
1950 case AL_REVERB_DECAY_HFLIMIT
:
1951 if(!(val
>= AL_REVERB_MIN_DECAY_HFLIMIT
&& val
<= AL_REVERB_MAX_DECAY_HFLIMIT
))
1952 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1953 props
->Reverb
.DecayHFLimit
= val
;
1957 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
1960 void ALreverb_setParamiv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALint
*vals
)
1962 ALreverb_setParami(effect
, context
, param
, vals
[0]);
1964 void ALreverb_setParamf(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat val
)
1966 ALeffectProps
*props
= &effect
->Props
;
1969 case AL_REVERB_DENSITY
:
1970 if(!(val
>= AL_REVERB_MIN_DENSITY
&& val
<= AL_REVERB_MAX_DENSITY
))
1971 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1972 props
->Reverb
.Density
= val
;
1975 case AL_REVERB_DIFFUSION
:
1976 if(!(val
>= AL_REVERB_MIN_DIFFUSION
&& val
<= AL_REVERB_MAX_DIFFUSION
))
1977 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1978 props
->Reverb
.Diffusion
= val
;
1981 case AL_REVERB_GAIN
:
1982 if(!(val
>= AL_REVERB_MIN_GAIN
&& val
<= AL_REVERB_MAX_GAIN
))
1983 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1984 props
->Reverb
.Gain
= val
;
1987 case AL_REVERB_GAINHF
:
1988 if(!(val
>= AL_REVERB_MIN_GAINHF
&& val
<= AL_REVERB_MAX_GAINHF
))
1989 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1990 props
->Reverb
.GainHF
= val
;
1993 case AL_REVERB_DECAY_TIME
:
1994 if(!(val
>= AL_REVERB_MIN_DECAY_TIME
&& val
<= AL_REVERB_MAX_DECAY_TIME
))
1995 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
1996 props
->Reverb
.DecayTime
= val
;
1999 case AL_REVERB_DECAY_HFRATIO
:
2000 if(!(val
>= AL_REVERB_MIN_DECAY_HFRATIO
&& val
<= AL_REVERB_MAX_DECAY_HFRATIO
))
2001 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
2002 props
->Reverb
.DecayHFRatio
= val
;
2005 case AL_REVERB_REFLECTIONS_GAIN
:
2006 if(!(val
>= AL_REVERB_MIN_REFLECTIONS_GAIN
&& val
<= AL_REVERB_MAX_REFLECTIONS_GAIN
))
2007 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
2008 props
->Reverb
.ReflectionsGain
= val
;
2011 case AL_REVERB_REFLECTIONS_DELAY
:
2012 if(!(val
>= AL_REVERB_MIN_REFLECTIONS_DELAY
&& val
<= AL_REVERB_MAX_REFLECTIONS_DELAY
))
2013 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
2014 props
->Reverb
.ReflectionsDelay
= val
;
2017 case AL_REVERB_LATE_REVERB_GAIN
:
2018 if(!(val
>= AL_REVERB_MIN_LATE_REVERB_GAIN
&& val
<= AL_REVERB_MAX_LATE_REVERB_GAIN
))
2019 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
2020 props
->Reverb
.LateReverbGain
= val
;
2023 case AL_REVERB_LATE_REVERB_DELAY
:
2024 if(!(val
>= AL_REVERB_MIN_LATE_REVERB_DELAY
&& val
<= AL_REVERB_MAX_LATE_REVERB_DELAY
))
2025 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
2026 props
->Reverb
.LateReverbDelay
= val
;
2029 case AL_REVERB_AIR_ABSORPTION_GAINHF
:
2030 if(!(val
>= AL_REVERB_MIN_AIR_ABSORPTION_GAINHF
&& val
<= AL_REVERB_MAX_AIR_ABSORPTION_GAINHF
))
2031 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
2032 props
->Reverb
.AirAbsorptionGainHF
= val
;
2035 case AL_REVERB_ROOM_ROLLOFF_FACTOR
:
2036 if(!(val
>= AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR
&& val
<= AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR
))
2037 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
2038 props
->Reverb
.RoomRolloffFactor
= val
;
2042 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
2045 void ALreverb_setParamfv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
2047 ALreverb_setParamf(effect
, context
, param
, vals
[0]);
2050 void ALreverb_getParami(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*val
)
2052 const ALeffectProps
*props
= &effect
->Props
;
2055 case AL_REVERB_DECAY_HFLIMIT
:
2056 *val
= props
->Reverb
.DecayHFLimit
;
2060 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
2063 void ALreverb_getParamiv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*vals
)
2065 ALreverb_getParami(effect
, context
, param
, vals
);
2067 void ALreverb_getParamf(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
2069 const ALeffectProps
*props
= &effect
->Props
;
2072 case AL_REVERB_DENSITY
:
2073 *val
= props
->Reverb
.Density
;
2076 case AL_REVERB_DIFFUSION
:
2077 *val
= props
->Reverb
.Diffusion
;
2080 case AL_REVERB_GAIN
:
2081 *val
= props
->Reverb
.Gain
;
2084 case AL_REVERB_GAINHF
:
2085 *val
= props
->Reverb
.GainHF
;
2088 case AL_REVERB_DECAY_TIME
:
2089 *val
= props
->Reverb
.DecayTime
;
2092 case AL_REVERB_DECAY_HFRATIO
:
2093 *val
= props
->Reverb
.DecayHFRatio
;
2096 case AL_REVERB_REFLECTIONS_GAIN
:
2097 *val
= props
->Reverb
.ReflectionsGain
;
2100 case AL_REVERB_REFLECTIONS_DELAY
:
2101 *val
= props
->Reverb
.ReflectionsDelay
;
2104 case AL_REVERB_LATE_REVERB_GAIN
:
2105 *val
= props
->Reverb
.LateReverbGain
;
2108 case AL_REVERB_LATE_REVERB_DELAY
:
2109 *val
= props
->Reverb
.LateReverbDelay
;
2112 case AL_REVERB_AIR_ABSORPTION_GAINHF
:
2113 *val
= props
->Reverb
.AirAbsorptionGainHF
;
2116 case AL_REVERB_ROOM_ROLLOFF_FACTOR
:
2117 *val
= props
->Reverb
.RoomRolloffFactor
;
2121 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
2124 void ALreverb_getParamfv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
2126 ALreverb_getParamf(effect
, context
, param
, vals
);
2129 DEFINE_ALEFFECT_VTABLE(ALreverb
);