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
29 #include "alAuxEffectSlot.h"
34 #define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
36 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
40 #if defined(max) && !defined(__max)
43 #if defined(min) && !defined(__min)
47 typedef struct DelayLine
49 // The delay lines use lengths that are powers of 2 to allow bitmasking
50 // instead of modulus wrapping.
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.
62 // Initial reverb delay.
64 // The tap points for the initial delay. First tap goes to early
65 // reflections, the second to late reverb.
68 // Gain for early reflections.
70 // Early reflections are done with 4 delay lines.
76 // Gain for late reverb.
78 // Diffusion of late reverb.
80 // Late reverb is done with 8 delay lines.
84 // The input and last 4 delay lines are low-pass filtered.
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
)
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.
172 v
= (d
[0] + d
[1] + d
[2] + d
[3]) * 0.5f
;
173 // The junction is loaded with the input here.
176 // Calculate the feed values for the delay lines.
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]
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
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
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
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.
270 // As with the reversed signs above, to balance the equation the signs
271 // need to be reversed here, too.
281 // Feed the fixed-length delay lines with their own cycle (0 -> 1 -> 3 ->
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 ->
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
));
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
)
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.
343 State
->Delay
.Mask
= length
[0] - 1;
344 State
->Delay
.Line
= &State
->SampleBuffer
[0];
345 totalLength
= length
[0];
350 State
->Early
.Gain
= 0.0f
;
351 // All fixed-length delay lines have their read-write offsets calculated
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;
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
;
381 State
->Late
.LpCoeff
[index
] = 0.0f
;
382 State
->Late
.LpSample
[index
] = 0.0f
;
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
)
396 free(State
->SampleBuffer
);
397 State
->SampleBuffer
= NULL
;
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
*
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
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
)
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
464 limitRatio
= __max(limitRatio
, 0.1f
);
466 // Using the limit calculated above, apply the upper bound to the
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
];
479 // Calculate the delay offset for the variable-length delay
481 length
*= 1.0f
+ (Effect
->Reverb
.Density
* LATE_LINE_MULTIPLIER
);
482 State
->Late
.Offset
[index
] = (ALuint
)(length
* Context
->Frequency
);
484 // Calculate the gain (coefficient) for each line.
485 State
->Late
.Coeff
[index
] = pow(10.0f
, length
/ Effect
->Reverb
.DecayTime
*
491 // Calculate the decay equation for each low-pass filter.
492 g
= pow(10.0f
, length
/ (Effect
->Reverb
.DecayTime
* hfRatio
) *
494 State
->Late
.Coeff
[index
];
497 // Calculate the gain (coefficient) for each low-pass filter.
499 if(g
< 0.9999f
) // 1-epsilon
500 lpcoeff
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
502 // Very low decay times will produce minimal output, so apply an
503 // upper bound to the coefficient.
504 State
->Late
.LpCoeff
[index2
] = __min(lpcoeff
, 0.98f
);
508 // This just calculates the coefficient for the late reverb input low-
509 // pass filter. It is calculated based the average (hence -30 instead
510 // of -60) length of the inner two variable-length delay lines.
511 length
= LATE_LINE_LENGTH
[5] * (1.0f
+ Effect
->Reverb
.Density
* LATE_LINE_MULTIPLIER
) +
512 LATE_LINE_LENGTH
[6] * (1.0f
+ Effect
->Reverb
.Density
* LATE_LINE_MULTIPLIER
);
514 g
= pow(10.0f
, ((length
/ (Effect
->Reverb
.DecayTime
* hfRatio
))-
515 (length
/ Effect
->Reverb
.DecayTime
)) * -30.0f
/ 20.0f
);
520 if(g
< 0.9999f
) // 1-epsilon
521 lpcoeff
= (1 - g
*cw
- aluSqrt(2*g
*(1-cw
) - g
*g
*(1 - cw
*cw
))) / (1 - g
);
523 State
->Late
.LpCoeff
[0] = __min(lpcoeff
, 0.98f
);
526 // This processes the reverb state, given the input samples and an output
528 ALvoid
VerbProcess(ALverbState
*State
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[OUTPUTCHANNELS
])
531 ALfloat in
, early
[2], late
[2], out
[2];
533 for(index
= 0;index
< SamplesToDo
;index
++)
535 // Feed the initial delay line.
536 DelayLineIn(&State
->Delay
, State
->Offset
, SamplesIn
[index
]);
538 // Calculate the early reflection from the first delay tap.
539 in
= DelayLineOut(&State
->Delay
, State
->Offset
- State
->Tap
[0]);
540 EarlyReflection(State
, in
, early
);
542 // Calculate the late reverb from the second delay tap.
543 in
= DelayLineOut(&State
->Delay
, State
->Offset
- State
->Tap
[1]);
544 LateReverb(State
, in
, late
);
546 // Mix early reflections and late reverb.
547 out
[0] = State
->Gain
* (early
[0] + late
[0]);
548 out
[1] = State
->Gain
* (early
[1] + late
[1]);
550 // Step all delays forward one sample.
553 // Output the results.
554 SamplesOut
[index
][FRONT_LEFT
] += out
[0];
555 SamplesOut
[index
][FRONT_RIGHT
] += out
[1];
556 SamplesOut
[index
][SIDE_LEFT
] += out
[0];
557 SamplesOut
[index
][SIDE_RIGHT
] += out
[1];
558 SamplesOut
[index
][BACK_LEFT
] += out
[0];
559 SamplesOut
[index
][BACK_RIGHT
] += out
[1];