Remove the separate surround51rear decoder option
[openal-soft.git] / Alc / effects / reverb.c
blob456b25dcec4efc667593b9f630f417821ed0e8c6
1 /**
2 * Reverb for the OpenAL cross platform audio library
3 * Copyright (C) 2008-2009 by Christopher Fitzgerald.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
27 #include "alMain.h"
28 #include "alu.h"
29 #include "alAuxEffectSlot.h"
30 #include "alEffect.h"
31 #include "alFilter.h"
32 #include "alError.h"
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
126 * iteration. */
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.
144 ALsizei Mask;
145 ALfloat *Line;
146 } DelayLine;
148 typedef struct ALreverbState {
149 DERIVE_FROM_TYPE(ALeffectState);
151 ALboolean IsEax;
153 // All delay lines are allocated as a single buffer to reduce memory
154 // fragmentation and management code.
155 ALfloat *SampleBuffer;
156 ALuint TotalSamples;
158 // Master effect filters
159 struct {
160 ALfilterState Lp;
161 ALfilterState Hp; // EAX only
162 } Filter[4];
164 struct {
165 // Modulator delay line.
166 DelayLine Delay[4];
168 // The vibrato time is tracked with an index over a modulus-wrapped
169 // range (in samples).
170 ALuint Index;
171 ALuint Range;
173 // The depth of frequency change (also in samples) and its filter.
174 ALfloat Depth;
175 ALfloat Coeff;
176 ALfloat Filter;
177 } Mod; // EAX only
179 /* Core delay line (early reflections and late reverb tap from this). */
180 DelayLine Delay;
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];
187 struct {
188 // Early reflections are done with 4 delay lines.
189 DelayLine Delay[4];
190 ALsizei Offset[4];
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];
195 } Early;
197 struct {
198 // Attenuation to compensate for the modal density and decay rate of
199 // the late lines.
200 ALfloat DensityGain;
202 // In addition to 4 delay lines.
203 ALfloat Coeff[4];
204 DelayLine Delay[4];
205 ALsizei Offset[4];
207 // The delay lines are 1-pole low-pass filtered.
208 struct {
209 ALfloat Sample;
210 ALfloat Coeff;
211 } Lp[4];
213 /* Late reverb has 3 all-pass filters in series on each of the 4 lines.
215 struct {
216 ALsizei Offsets[3];
218 /* One delay line is used for all 3 all-pass filters. */
219 DelayLine Delay;
220 } Ap[4];
222 // The feed-back and feed-forward all-pass coefficient.
223 ALfloat ApFeedCoeff;
225 // Mixing matrix coefficient.
226 ALfloat MixCoeff;
228 // Output gain for late reverb.
229 ALfloat Gain;
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];
234 } Late;
236 struct {
237 // Attenuation to compensate for the modal density and decay rate of
238 // the echo line.
239 ALfloat DensityGain;
241 // Echo delay and all-pass lines.
242 struct {
243 DelayLine Feedback;
244 DelayLine Ap;
245 } Delay[4];
247 ALfloat Coeff;
248 ALfloat ApFeedCoeff;
250 ALsizei Offset;
251 ALsizei ApOffset;
253 // The echo line is 1-pole low-pass filtered.
254 ALfloat LpCoeff;
255 ALfloat LpSample[4];
257 // Echo mixing coefficient.
258 ALfloat MixCoeff;
259 } Echo; // EAX only
261 // The current read offset for all delay lines.
262 ALsizei Offset;
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];
268 } ALreverbState;
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)
281 ALuint index, l;
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++)
326 ALuint k;
327 for(k = 0;k < 3;k++)
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;
341 for(l = 0;l < 4;l++)
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;
353 for(l = 0;l < 4;l++)
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;
365 for(l = 0;l < 4;l++)
366 state->Echo.LpSample[l] = 0.0f;
367 state->Echo.MixCoeff = 0.0f;
369 state->Offset = 0;
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
381 * effect.
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
394 * backwards.
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)
443 double di;
444 double df = modf((double)x, &di);
445 *y = (float)di;
446 return (float)df;
448 #define modff hack_modff
449 #endif
452 /**************************************
453 * Device Update *
454 **************************************/
456 // Given the allocated sample buffer, this function updates each delay line
457 // offset.
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)
466 ALuint samples;
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.
476 return samples;
480 static int FindClosestPrime(int desired, ALboolean *used)
482 ALsizei curidx = 0;
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).
487 while(count > 0)
489 ALsizei step = count>>1;
490 ALsizei i = curidx+step;
491 if(!(PrimeTable[i] < desired))
492 count = step;
493 else
495 curidx = i+1;
496 count -= step+1;
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))
501 curidx--;
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))
512 off1++;
513 while(off2 < 1024-curidx && GET_BIT(used, curidx+off2))
514 off2++;
516 /* Select the closest unused prime to the desired value. */
517 if(GET_BIT(used, curidx-off1))
518 curidx += off2;
519 else if(GET_BIT(used, curidx+off2))
520 curidx -= off1;
521 else
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);
527 #undef SET_BIT
528 #undef GET_BIT
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;
559 ALfloat length;
561 // All delay line lengths are calculated to accomodate the full range of
562 // lengths given their respective paramters.
563 totalSamples = 0;
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
568 * modulation.
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
578 * update.
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
585 * main delay line.
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++)
606 ALuint k;
608 length = 0.0f;
609 for(k = 0;k < 3;k++)
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
613 * correct.
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)
630 ALfloat *newBuffer;
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;
660 return AL_TRUE;
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))
670 return AL_FALSE;
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
675 // rates.
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++)
683 ALuint k;
685 State->Early.Offset[index] = fastf2u(EARLY_LINE_LENGTH[index] * frequency);
686 for(k = 0;k < 3;k++)
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);
704 return AL_TRUE;
707 /**************************************
708 * Effect Update *
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
719 // reaches -60 dB.
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)
748 ALfloat n, t;
750 // The matrix is of order 4, so n is sqrt (4 - 1).
751 n = sqrtf(3.0f);
752 t = diffusion * atanf(n);
754 // Calculate the first mixing matrix coefficient.
755 *x = cosf(t);
756 // Calculate the second mixing matrix coefficient.
757 *y = sinf(t) / n;
760 // Calculate the limited HF ratio for use with the late reverb low-pass
761 // filters.
762 static ALfloat CalcLimitedHfRatio(ALfloat hfRatio, ALfloat airAbsorptionGainHF, ALfloat decayTime)
764 ALfloat limitRatio;
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
780 // filter.
781 static inline ALfloat CalcDampingCoeff(ALfloat hfRatio, ALfloat length, ALfloat decayTime, ALfloat decayCoeff, ALfloat cw)
783 ALfloat coeff, g;
785 // Eventually this should boost the high frequencies when the ratio
786 // exceeds 1.
787 coeff = 0.0f;
788 if (hfRatio < 1.0f)
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.
795 g *= g;
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. */
800 g = maxf(g, 0.001f);
801 coeff = (1 - g*cw - sqrtf(2*g*(1-cw) - g*g*(1 - cw*cw))) /
802 (1 - g);
805 // Very low decay times will produce minimal output, so apply an
806 // upper bound to the coefficient.
807 coeff = minf(coeff, 0.98f);
809 return coeff;
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)
817 ALuint range;
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 /
829 State->Mod.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
838 * increasing it).
840 State->Mod.Depth = modDepth * MODULATION_DEPTH_COEFF * modTime / 2.0f /
841 2.0f * frequency;
844 // Update the offsets for the main effect delay line.
845 static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALfloat density, ALuint frequency, ALreverbState *State)
847 ALfloat length;
848 ALuint i;
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);
860 for(i = 1;i < 4;i++)
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);
868 for(i = 1;i < 4;i++)
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)
879 ALfloat length;
880 ALsizei i;
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);
908 for(i = 0;i < 4;i++)
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
930 // coefficients.
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
940 // line.
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
959 * focus strength.
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;
969 ALfloat length;
970 ALfloat sa, a;
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
975 * length.
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]));
987 aluMatrixfSet(&xrot,
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
998 * cancelling it out.
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 { \
1009 int row, col; \
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]; \
1016 } while(0)
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);
1022 #undef MATRIX_MULT
1024 return tmp2;
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;
1045 ALsizei i;
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 { \
1052 int row, col; \
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]; \
1059 } while(0)
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]);
1074 #undef MATRIX_MULT
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;
1082 ALfloat cw, x, y;
1083 ALsizei i;
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,
1116 frequency, State);
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;
1178 ALsizei index, i;
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
1207 // reverb.
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;
1211 ALfloat out0, out1;
1212 ALsizei delay, i;
1214 for(i = 0;i < todo;i++)
1216 /* Separate the integer offset and fraction between it and the next
1217 * sample.
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);
1227 offset++;
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];
1243 ALsizei i;
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.
1258 * ---
1260 * v = 2/N / d_i
1261 * ---
1262 * i=1
1264 v = (f[0] + f[1] + f[2] + f[3]) * 0.5f;
1266 /* Calculate the values to pass through the delay lines. */
1267 d[0] = v - f[0];
1268 d[1] = v - f[1];
1269 d[2] = v - f[2];
1270 d[3] = v - f[3];
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]);
1285 offset++;
1287 /* Output the initial reflection taps and the results of the delayed
1288 * junction for all four channels.
1290 out[0][i] = f[0];
1291 out[1][i] = f[1];
1292 out[2][i] = f[2];
1293 out[3][i] = f[3];
1297 // Basic attenuated all-pass input/output routine.
1298 static inline ALfloat AllpassInOut(DelayLine *Delay, ALsizei outOffset, ALsizei inOffset, ALfloat in, ALfloat feedCoeff)
1300 ALfloat out, feed;
1302 out = DelayLineOut(Delay, outOffset);
1303 feed = feedCoeff * in;
1304 DelayLineIn(Delay, inOffset, in + feedCoeff*(out - feed));
1306 return 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)
1312 ALsizei inOffset;
1313 ALsizei i;
1315 inOffset = offset;
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;
1325 return sample;
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;
1333 return 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])
1341 ALfloat d[4], f[4];
1342 ALsizei offset;
1343 ALsizei i, j;
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
1364 * 2 and back to 0.
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
1380 * [ -a, d, c, -b ]
1381 * [ -b, -c, d, a ]
1382 * [ -c, b, -a, d ]
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
1387 * thus:
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]);
1406 offset++;
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
1410 * coefficient).
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])
1422 ALfloat feed;
1423 ALsizei offset;
1424 ALsizei c, i;
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) *
1433 State->Echo.Coeff;
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);
1451 offset++;
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])
1460 ALsizei i, c;
1462 for(c = 0;c < 4;c++)
1464 /* Low-pass filter the incoming samples (use the early buffer as temp
1465 * storage).
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-
1483 // channel output.
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])
1486 ALsizei i, c;
1488 /* Perform any modulation on the input (use the early and late buffers as
1489 * temp storage).
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;
1531 ALuint base, c;
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
1548 * B-Format.
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
1561 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;
1576 ALuint base, c;
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
1602 base += todo;
1606 static ALvoid ALreverbState_process(ALreverbState *State, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
1608 if(State->IsEax)
1609 ALreverbState_processEax(State, SamplesToDo, SamplesIn, SamplesOut, NumChannels);
1610 else
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;
1644 switch(param)
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;
1650 break;
1652 default:
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;
1663 switch(param)
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;
1669 break;
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;
1675 break;
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;
1681 break;
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;
1687 break;
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;
1693 break;
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;
1699 break;
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;
1705 break;
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;
1711 break;
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;
1717 break;
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;
1723 break;
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;
1729 break;
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;
1735 break;
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;
1741 break;
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;
1747 break;
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;
1753 break;
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;
1759 break;
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;
1765 break;
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;
1771 break;
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;
1777 break;
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;
1783 break;
1785 default:
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;
1792 switch(param)
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];
1800 break;
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];
1807 break;
1809 default:
1810 ALeaxreverb_setParamf(effect, context, param, vals[0]);
1811 break;
1815 void ALeaxreverb_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
1817 const ALeffectProps *props = &effect->Props;
1818 switch(param)
1820 case AL_EAXREVERB_DECAY_HFLIMIT:
1821 *val = props->Reverb.DecayHFLimit;
1822 break;
1824 default:
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;
1835 switch(param)
1837 case AL_EAXREVERB_DENSITY:
1838 *val = props->Reverb.Density;
1839 break;
1841 case AL_EAXREVERB_DIFFUSION:
1842 *val = props->Reverb.Diffusion;
1843 break;
1845 case AL_EAXREVERB_GAIN:
1846 *val = props->Reverb.Gain;
1847 break;
1849 case AL_EAXREVERB_GAINHF:
1850 *val = props->Reverb.GainHF;
1851 break;
1853 case AL_EAXREVERB_GAINLF:
1854 *val = props->Reverb.GainLF;
1855 break;
1857 case AL_EAXREVERB_DECAY_TIME:
1858 *val = props->Reverb.DecayTime;
1859 break;
1861 case AL_EAXREVERB_DECAY_HFRATIO:
1862 *val = props->Reverb.DecayHFRatio;
1863 break;
1865 case AL_EAXREVERB_DECAY_LFRATIO:
1866 *val = props->Reverb.DecayLFRatio;
1867 break;
1869 case AL_EAXREVERB_REFLECTIONS_GAIN:
1870 *val = props->Reverb.ReflectionsGain;
1871 break;
1873 case AL_EAXREVERB_REFLECTIONS_DELAY:
1874 *val = props->Reverb.ReflectionsDelay;
1875 break;
1877 case AL_EAXREVERB_LATE_REVERB_GAIN:
1878 *val = props->Reverb.LateReverbGain;
1879 break;
1881 case AL_EAXREVERB_LATE_REVERB_DELAY:
1882 *val = props->Reverb.LateReverbDelay;
1883 break;
1885 case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
1886 *val = props->Reverb.AirAbsorptionGainHF;
1887 break;
1889 case AL_EAXREVERB_ECHO_TIME:
1890 *val = props->Reverb.EchoTime;
1891 break;
1893 case AL_EAXREVERB_ECHO_DEPTH:
1894 *val = props->Reverb.EchoDepth;
1895 break;
1897 case AL_EAXREVERB_MODULATION_TIME:
1898 *val = props->Reverb.ModulationTime;
1899 break;
1901 case AL_EAXREVERB_MODULATION_DEPTH:
1902 *val = props->Reverb.ModulationDepth;
1903 break;
1905 case AL_EAXREVERB_HFREFERENCE:
1906 *val = props->Reverb.HFReference;
1907 break;
1909 case AL_EAXREVERB_LFREFERENCE:
1910 *val = props->Reverb.LFReference;
1911 break;
1913 case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
1914 *val = props->Reverb.RoomRolloffFactor;
1915 break;
1917 default:
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;
1924 switch(param)
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];
1930 break;
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];
1935 break;
1937 default:
1938 ALeaxreverb_getParamf(effect, context, param, vals);
1939 break;
1943 DEFINE_ALEFFECT_VTABLE(ALeaxreverb);
1945 void ALreverb_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val)
1947 ALeffectProps *props = &effect->Props;
1948 switch(param)
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;
1954 break;
1956 default:
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;
1967 switch(param)
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;
1973 break;
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;
1979 break;
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;
1985 break;
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;
1991 break;
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;
1997 break;
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;
2003 break;
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;
2009 break;
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;
2015 break;
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;
2021 break;
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;
2027 break;
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;
2033 break;
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;
2039 break;
2041 default:
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;
2053 switch(param)
2055 case AL_REVERB_DECAY_HFLIMIT:
2056 *val = props->Reverb.DecayHFLimit;
2057 break;
2059 default:
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;
2070 switch(param)
2072 case AL_REVERB_DENSITY:
2073 *val = props->Reverb.Density;
2074 break;
2076 case AL_REVERB_DIFFUSION:
2077 *val = props->Reverb.Diffusion;
2078 break;
2080 case AL_REVERB_GAIN:
2081 *val = props->Reverb.Gain;
2082 break;
2084 case AL_REVERB_GAINHF:
2085 *val = props->Reverb.GainHF;
2086 break;
2088 case AL_REVERB_DECAY_TIME:
2089 *val = props->Reverb.DecayTime;
2090 break;
2092 case AL_REVERB_DECAY_HFRATIO:
2093 *val = props->Reverb.DecayHFRatio;
2094 break;
2096 case AL_REVERB_REFLECTIONS_GAIN:
2097 *val = props->Reverb.ReflectionsGain;
2098 break;
2100 case AL_REVERB_REFLECTIONS_DELAY:
2101 *val = props->Reverb.ReflectionsDelay;
2102 break;
2104 case AL_REVERB_LATE_REVERB_GAIN:
2105 *val = props->Reverb.LateReverbGain;
2106 break;
2108 case AL_REVERB_LATE_REVERB_DELAY:
2109 *val = props->Reverb.LateReverbDelay;
2110 break;
2112 case AL_REVERB_AIR_ABSORPTION_GAINHF:
2113 *val = props->Reverb.AirAbsorptionGainHF;
2114 break;
2116 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
2117 *val = props->Reverb.RoomRolloffFactor;
2118 break;
2120 default:
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);