Don't calculate reverb HF limit if air absorption is 1
[openal-soft.git] / Alc / alcReverb.c
blob1f569d27395bbfc2982587ca80a2ff406d564c05
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 2008 by Christopher Fitzgerald.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
26 #include "AL/al.h"
27 #include "AL/alc.h"
28 #include "alMain.h"
29 #include "alAuxEffectSlot.h"
30 #include "alEffect.h"
31 #include "alReverb.h"
33 #ifdef HAVE_SQRTF
34 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
35 #else
36 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
37 #endif
39 // fixes for mingw32.
40 #if defined(max) && !defined(__max)
41 #define __max max
42 #endif
43 #if defined(min) && !defined(__min)
44 #define __min min
45 #endif
47 typedef struct DelayLine
49 // The delay lines use lengths that are powers of 2 to allow bitmasking
50 // instead of modulus wrapping.
51 ALuint Mask;
52 ALfloat *Line;
53 } DelayLine;
55 struct ALverbState
57 // All delay lines are allocated as a single buffer to reduce memory
58 // fragmentation and teardown code.
59 ALfloat *SampleBuffer;
60 // Master reverb gain.
61 ALfloat Gain;
62 // Initial reverb delay.
63 DelayLine Delay;
64 // The tap points for the initial delay. First tap goes to early
65 // reflections, the second to late reverb.
66 ALuint Tap[2];
67 struct {
68 // Gain for early reflections.
69 ALfloat Gain;
70 // Early reflections are done with 4 delay lines.
71 ALfloat Coeff[4];
72 DelayLine Delay[4];
73 ALuint Offset[4];
74 } Early;
75 struct {
76 // Gain for late reverb.
77 ALfloat Gain;
78 // Diffusion of late reverb.
79 ALfloat Diffusion;
80 // Late reverb is done with 8 delay lines.
81 ALfloat Coeff[8];
82 DelayLine Delay[8];
83 ALuint Offset[8];
84 // The input and last 4 delay lines are low-pass filtered.
85 ALfloat LpCoeff[5];
86 ALfloat LpSample[5];
87 } Late;
88 ALuint Offset;
91 // All delay line lengths are specified in seconds.
93 // The length of the initial delay line (a sum of the maximum delay before
94 // early reflections and late reverb; 0.3 + 0.1).
95 static const ALfloat MASTER_LINE_LENGTH = 0.4000f;
97 // The lengths of the early delay lines.
98 static const ALfloat EARLY_LINE_LENGTH[4] =
100 0.0015f, 0.0045f, 0.0135f, 0.0405f
103 // The lengths of the late delay lines.
104 static const ALfloat LATE_LINE_LENGTH[8] =
106 0.0015f, 0.0037f, 0.0093f, 0.0234f,
107 0.0100f, 0.0150f, 0.0225f, 0.0337f
110 // The last 4 late delay lines have a variable length dependent on the effect
111 // density parameter and this multiplier.
112 static const ALfloat LATE_LINE_MULTIPLIER = 9.0f;
114 static ALuint NextPowerOf2(ALuint value)
116 ALuint powerOf2 = 1;
118 if(value)
120 value--;
121 while(value)
123 value >>= 1;
124 powerOf2 <<= 1;
127 return powerOf2;
130 // Basic delay line input/output routines.
131 static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
133 return Delay->Line[offset&Delay->Mask];
136 static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
138 Delay->Line[offset&Delay->Mask] = in;
141 // Delay line output routine for early reflections.
142 static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
144 return State->Early.Coeff[index] *
145 DelayLineOut(&State->Early.Delay[index],
146 State->Offset - State->Early.Offset[index]);
149 // Given an input sample, this function produces a decorrelated stereo output
150 // for early reflections.
151 static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *out)
153 ALfloat d[4], v, f[4];
155 // Obtain the decayed results of each early delay line.
156 d[0] = EarlyDelayLineOut(State, 0);
157 d[1] = EarlyDelayLineOut(State, 1);
158 d[2] = EarlyDelayLineOut(State, 2);
159 d[3] = EarlyDelayLineOut(State, 3);
161 /* The following uses a lossless scattering junction from waveguide
162 * theory. It actually amounts to a householder mixing matrix, which
163 * will produce a maximally diffuse response, and means this can probably
164 * be considered a simple FDN.
166 * ---
168 * v = 2/N / di
169 * ---
170 * i=1
172 v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
173 // The junction is loaded with the input here.
174 v += in;
176 // Calculate the feed values for the delay lines.
177 f[0] = v - d[0];
178 f[1] = v - d[1];
179 f[2] = v - d[2];
180 f[3] = v - d[3];
182 // To increase reflection complexity (and help reduce coloration) the
183 // delay lines cyclicly refeed themselves (0 -> 1 -> 3 -> 2 -> 0...).
184 DelayLineIn(&State->Early.Delay[0], State->Offset, f[2]);
185 DelayLineIn(&State->Early.Delay[1], State->Offset, f[0]);
186 DelayLineIn(&State->Early.Delay[2], State->Offset, f[3]);
187 DelayLineIn(&State->Early.Delay[3], State->Offset, f[1]);
189 // To decorrelate the output for stereo separation, the cyclical nature
190 // of the feed path is exploited. The two outputs are obtained from the
191 // inner delay lines.
192 // Output is instant by using the inputs to them instead of taking the
193 // result of the two delay lines directly (f[0] and f[3] instead of d[1]
194 // and d[2]).
195 out[0] = State->Early.Gain * f[0];
196 out[1] = State->Early.Gain * f[3];
199 // Delay line output routine for late reverb.
200 static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
202 return State->Late.Coeff[index] *
203 DelayLineOut(&State->Late.Delay[index],
204 State->Offset - State->Late.Offset[index]);
207 // Low-pass filter input/output routine for late reverb.
208 static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
210 State->Late.LpSample[index] = in + ((State->Late.LpSample[index] - in) *
211 State->Late.LpCoeff[index]);
212 return State->Late.LpSample[index];
215 // Given an input sample, this function produces a decorrelated stereo output
216 // for late reverb.
217 static __inline ALvoid LateReverb(ALverbState *State, ALfloat in, ALfloat *out)
219 ALfloat din, d[8], v, dv, f[8];
221 // Since the input will be sent directly to the output as in the early
222 // reflections function, it needs to take into account some immediate
223 // absorption.
224 in = LateLowPassInOut(State, 0, in);
226 // When diffusion is full, no input is directly passed to the variable-
227 // length delay lines (the last 4).
228 din = (1.0f - State->Late.Diffusion) * in;
230 // Obtain the decayed results of the fixed-length delay lines.
231 d[0] = LateDelayLineOut(State, 0);
232 d[1] = LateDelayLineOut(State, 1);
233 d[2] = LateDelayLineOut(State, 2);
234 d[3] = LateDelayLineOut(State, 3);
235 // Obtain the decayed and low-pass filtered results of the variable-
236 // length delay lines.
237 d[4] = LateLowPassInOut(State, 1, LateDelayLineOut(State, 4));
238 d[5] = LateLowPassInOut(State, 2, LateDelayLineOut(State, 5));
239 d[6] = LateLowPassInOut(State, 3, LateDelayLineOut(State, 6));
240 d[7] = LateLowPassInOut(State, 4, LateDelayLineOut(State, 7));
242 // The waveguide formula used in the early reflections function works
243 // great for high diffusion, but it is not obviously paramerized to allow
244 // a variable diffusion. With only limited time and resources, what
245 // follows is the best variation of that formula I could come up with.
246 // First, there are 8 delay lines used. The first 4 are fixed-length and
247 // generate the highest density of the diffuse response. The last 4 are
248 // variable-length, and are used to smooth out the diffuse response. The
249 // density effect parameter alters their length. The inner two delay
250 // lines of each group have their signs reversed (more about this later).
251 v = (d[0] - d[1] - d[2] + d[3] +
252 d[4] - d[5] - d[6] + d[7]) * 0.25f;
253 // Diffusion is applied as a reduction of the junction pressure for all
254 // branches. This presents two problems. When the diffusion factor (0
255 // to 1) reaches 0.5, the average feed value is reduced (the junction
256 // becomes lossy). Thus, at 0.5 the signal decays almost twice as fast
257 // as it should. The second problem is the introduction of some
258 // resonant frequencies (coloration). The reversed signs above are used
259 // to help combat some of the coloration by adding variations along the
260 // feed cycle.
261 v *= State->Late.Diffusion;
262 // Load the junction with the input. To reduce the noticeable echo of
263 // the longer delay lines (the variable-length ones) the input is loaded
264 // with the inverse of the effect diffusion. So at full diffusion, the
265 // input is not applied to the last 4 delay lines. Input signs reversed
266 // to balance the equation.
267 dv = v + din;
268 v += in;
270 // As with the reversed signs above, to balance the equation the signs
271 // need to be reversed here, too.
272 f[0] = d[0] - v;
273 f[1] = d[1] + v;
274 f[2] = d[2] + v;
275 f[3] = d[3] - v;
276 f[4] = d[4] - dv;
277 f[5] = d[5] + dv;
278 f[6] = d[6] + dv;
279 f[7] = d[7] - dv;
281 // Feed the fixed-length delay lines with their own cycle (0 -> 1 -> 3 ->
282 // 2 -> 0...).
283 DelayLineIn(&State->Late.Delay[0], State->Offset, f[2]);
284 DelayLineIn(&State->Late.Delay[1], State->Offset, f[0]);
285 DelayLineIn(&State->Late.Delay[2], State->Offset, f[3]);
286 DelayLineIn(&State->Late.Delay[3], State->Offset, f[1]);
287 // Feed the variable-length delay lines with their cycle (4 -> 6 -> 7 ->
288 // 5 -> 4...).
289 DelayLineIn(&State->Late.Delay[4], State->Offset, f[5]);
290 DelayLineIn(&State->Late.Delay[5], State->Offset, f[7]);
291 DelayLineIn(&State->Late.Delay[6], State->Offset, f[4]);
292 DelayLineIn(&State->Late.Delay[7], State->Offset, f[6]);
294 // Output is derived from the values fed to the inner two variable-length
295 // delay lines (5 and 6).
296 out[0] = State->Late.Gain * f[7];
297 out[1] = State->Late.Gain * f[4];
300 // This creates the reverb state. It should be called only when the reverb
301 // effect is loaded into a slot that doesn't already have a reverb effect.
302 ALverbState *VerbCreate(ALCcontext *Context)
304 ALverbState *State = NULL;
305 ALuint length[13], totalLength, index;
307 State = malloc(sizeof(ALverbState));
308 if(!State)
309 return NULL;
311 // All line lengths are powers of 2, calculated from the line timings and
312 // the addition of an extra sample (for safety).
313 length[0] = NextPowerOf2((ALuint)(MASTER_LINE_LENGTH*Context->Frequency) + 1);
314 totalLength = length[0];
315 for(index = 0;index < 4;index++)
317 length[1+index] = NextPowerOf2((ALuint)(EARLY_LINE_LENGTH[index]*Context->Frequency) + 1);
318 totalLength += length[1+index];
320 for(index = 0;index < 4;index++)
322 length[5+index] = NextPowerOf2((ALuint)(LATE_LINE_LENGTH[index]*Context->Frequency) + 1);
323 totalLength += length[5+index];
325 for(index = 4;index < 8;index++)
327 length[5+index] = NextPowerOf2((ALuint)(LATE_LINE_LENGTH[index]*(1.0f + LATE_LINE_MULTIPLIER)*Context->Frequency) + 1);
328 totalLength += length[5+index];
331 // They all share a single sample buffer.
332 State->SampleBuffer = malloc(totalLength * sizeof(ALfloat));
333 if(!State->SampleBuffer)
335 free(State);
336 return NULL;
338 for(index = 0; index < totalLength;index++)
339 State->SampleBuffer[index] = 0.0f;
341 // Each one has its mask and start address calculated one time.
342 State->Gain = 0.0f;
343 State->Delay.Mask = length[0] - 1;
344 State->Delay.Line = &State->SampleBuffer[0];
345 totalLength = length[0];
347 State->Tap[0] = 0;
348 State->Tap[1] = 0;
350 State->Early.Gain = 0.0f;
351 // All fixed-length delay lines have their read-write offsets calculated
352 // one time.
353 for(index = 0;index < 4;index++)
355 State->Early.Coeff[index] = 0.0f;
356 State->Early.Delay[index].Mask = length[1 + index] - 1;
357 State->Early.Delay[index].Line = &State->SampleBuffer[totalLength];
358 totalLength += length[1 + index];
360 State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] * Context->Frequency);
363 State->Late.Gain = 0.0f;
364 State->Late.Diffusion = 0.0f;
365 for(index = 0;index < 8;index++)
367 State->Late.Coeff[index] = 0.0f;
368 State->Late.Delay[index].Mask = length[5 + index] - 1;
369 State->Late.Delay[index].Line = &State->SampleBuffer[totalLength];
370 totalLength += length[5 + index];
372 State->Late.Offset[index] = 0;
373 if(index < 4)
375 State->Late.Offset[index] = (ALuint)(LATE_LINE_LENGTH[index] * Context->Frequency);
376 State->Late.LpCoeff[index] = 0.0f;
377 State->Late.LpSample[index] = 0.0f;
379 else if(index == 4)
381 State->Late.LpCoeff[index] = 0.0f;
382 State->Late.LpSample[index] = 0.0f;
386 State->Offset = 0;
387 return State;
390 // This destroys the reverb state. It should be called only when the effect
391 // slot has a different (or no) effect loaded over the reverb effect.
392 ALvoid VerbDestroy(ALverbState *State)
394 if(State)
396 free(State->SampleBuffer);
397 State->SampleBuffer = NULL;
398 free(State);
402 // This updates the reverb state. This is called any time the reverb effect
403 // is loaded into a slot.
404 ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
406 ALverbState *State = Slot->ReverbState;
407 ALuint index, index2;
408 ALfloat length, lpcoeff, cw, g;
409 ALfloat hfRatio = Effect->Reverb.DecayHFRatio;
411 // Calculate the master gain (from the slot and master reverb gain).
412 State->Gain = Slot->Gain * Effect->Reverb.Gain;
414 // Calculate the initial delay taps.
415 length = Effect->Reverb.ReflectionsDelay;
416 State->Tap[0] = (ALuint)(length * Context->Frequency);
417 length += Effect->Reverb.LateReverbDelay;
418 State->Tap[1] = (ALuint)(length * Context->Frequency);
420 // Calculate the early reflections gain. Right now this uses a gain of
421 // 0.75 to compensate for the increase in density. It should probably
422 // use a power (RMS) based measurement from the resulting distribution of
423 // early delay lines.
424 State->Early.Gain = Effect->Reverb.ReflectionsGain * 0.75f;
426 // Calculate the gain (coefficient) for each early delay line.
427 for(index = 0;index < 4;index++)
428 State->Early.Coeff[index] = pow(10.0f, EARLY_LINE_LENGTH[index] /
429 Effect->Reverb.LateReverbDelay *
430 -60.0f / 20.0f);
432 // Calculate the late reverb gain, adjusted by density, diffusion, and
433 // decay time. To be accurate, the adjustments should probably use power
434 // measurements for each contribution, but they are not too bad as they
435 // are.
436 State->Late.Gain = Effect->Reverb.LateReverbGain *
437 (0.45f + (0.55f * Effect->Reverb.Density)) *
438 (1.0f - (0.25f * Effect->Reverb.Diffusion)) *
439 (1.0f - (0.025f * Effect->Reverb.DecayTime));
440 State->Late.Diffusion = Effect->Reverb.Diffusion;
442 // The EFX specification does not make it clear whether the air
443 // absorption parameter should always take effect. Both Generic Software
444 // and Generic Hardware only apply it when HF limit is flagged, so that's
445 // what is done here.
446 // If the HF limit parameter is flagged, calculate an appropriate limit
447 // based on the air absorption parameter.
448 if(Effect->Reverb.DecayHFLimit && Effect->Reverb.AirAbsorptionGainHF < 1.0f)
450 ALfloat limitRatio;
452 // The following is my best guess at how to limit the HF ratio by the
453 // air absorption parameter.
454 // For each of the last 4 delays, find the attenuation due to air
455 // absorption in dB (converting delay time to meters using the speed
456 // of sound). Then reversing the decay equation, solve for HF ratio.
457 // The delay length is cancelled out of the equation, so it can be
458 // calculated once for all lines.
459 limitRatio = 1.0f / (log10(Effect->Reverb.AirAbsorptionGainHF) *
460 SPEEDOFSOUNDMETRESPERSEC *
461 Effect->Reverb.DecayTime / -60.0f * 20.0f);
462 // Need to limit the result to a minimum of 0.1, just like the HF
463 // ratio parameter.
464 limitRatio = __max(limitRatio, 0.1f);
466 // Using the limit calculated above, apply the upper bound to the
467 // HF ratio.
468 hfRatio = __min(hfRatio, limitRatio);
471 cw = cos(2.0f*3.141592654f * LOWPASSFREQCUTOFF / Context->Frequency);
473 for(index = 0;index < 8;index++)
475 // Calculate the length (in seconds) of each delay line.
476 length = LATE_LINE_LENGTH[index];
477 if(index >= 4)
479 index2 = index - 3;
481 length *= 1.0f + (Effect->Reverb.Density * LATE_LINE_MULTIPLIER);
483 // Calculate the delay offset for the variable-length delay
484 // lines.
485 State->Late.Offset[index] = (ALuint)(length * Context->Frequency);
487 // Calculate the decay equation for each low-pass filter.
488 g = pow(10.0f, length / (Effect->Reverb.DecayTime * hfRatio) *
489 -60.0f / 20.0f);
490 g = __max(g, 0.1f);
491 g *= g;
492 // Calculate the gain (coefficient) for each low-pass filter.
493 lpcoeff = 0.0f;
494 if(g < 0.9999f) // 1-epsilon
495 lpcoeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
497 // Very low decay times will produce minimal output, so apply an
498 // upper bound to the coefficient.
499 State->Late.LpCoeff[index2] = __min(lpcoeff, 0.98f);
502 // Calculate the gain (coefficient) for each line.
503 State->Late.Coeff[index] = pow(10.0f, length / Effect->Reverb.DecayTime *
504 -60.0f / 20.0f);
507 // This just calculates the coefficient for the late reverb input low-
508 // pass filter. It is calculated based the average (hence -30 instead
509 // of -60) length of the inner two variable-length delay lines.
510 length = LATE_LINE_LENGTH[5] * (1.0f + Effect->Reverb.Density * LATE_LINE_MULTIPLIER) +
511 LATE_LINE_LENGTH[6] * (1.0f + Effect->Reverb.Density * LATE_LINE_MULTIPLIER);
513 g = pow(10.0f, length / (Effect->Reverb.DecayTime * hfRatio) * -30.0f / 20.0f);
514 g = __max(g, 0.1f);
515 g *= g;
517 lpcoeff = 0.0f;
518 if(g < 0.9999f) // 1-epsilon
519 lpcoeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
521 State->Late.LpCoeff[0] = __min(lpcoeff, 0.98f);
524 // This processes the reverb state, given the input samples and an output
525 // buffer.
526 ALvoid VerbProcess(ALverbState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
528 ALuint index;
529 ALfloat in, early[2], late[2], out[2];
531 for(index = 0;index < SamplesToDo;index++)
533 // Feed the initial delay line.
534 DelayLineIn(&State->Delay, State->Offset, SamplesIn[index]);
536 // Calculate the early reflection from the first delay tap.
537 in = DelayLineOut(&State->Delay, State->Offset - State->Tap[0]);
538 EarlyReflection(State, in, early);
540 // Calculate the late reverb from the second delay tap.
541 in = DelayLineOut(&State->Delay, State->Offset - State->Tap[1]);
542 LateReverb(State, in, late);
544 // Mix early reflections and late reverb.
545 out[0] = State->Gain * (early[0] + late[0]);
546 out[1] = State->Gain * (early[1] + late[1]);
548 // Step all delays forward one sample.
549 State->Offset++;
551 // Output the results.
552 SamplesOut[index][FRONT_LEFT] += out[0];
553 SamplesOut[index][FRONT_RIGHT] += out[1];
554 SamplesOut[index][SIDE_LEFT] += out[0];
555 SamplesOut[index][SIDE_RIGHT] += out[1];
556 SamplesOut[index][BACK_LEFT] += out[0];
557 SamplesOut[index][BACK_RIGHT] += out[1];