Works out the reverberation time of a box-shaped room in each frequency band by four formulas: Sabine, Eyring, Fitzroy and Arau-Puchades.
How the precision is kept
Each formula is evaluated directly in 64-bit from the room's three sizes and the absorption of its six surfaces. The formulas themselves are statistical models with the conventional constant 0.161, so the result is as good as the model and the absorption data, not as the arithmetic.
Calculations under this policy
2 calculations in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.
stat.jsBimCraft 0.8.164-bit2 calculationsReviewed
Tests tools/acoustics-test/geo-test.mjs
Surface areas and mean absorption of each pair
64-bit
The area of each pair of opposite surfaces and their mean absorption in a band.
Math.log(1 − ᾱ) is used with ᾱ limited to [1e-4, 0.999]. At the lower limit the subtraction's rounding of about 1e-16 is about 1e-12 of the result; Math.log1p is not used.
stat.js
lines 23 to 30
BimCraft 0.8.1
const SX = 2 * ly * lz, SY = 2 * lx * lz, SZ = 2 * lx * ly, S = SX + SY + SZ;
const A = (a, i) => a[i];
const notes = [];
const bands = BANDS.map((f, i) => {
// mean absorption of each pair, area-weighted (opposite surfaces have the same area)
const ax = (A(p.west, i) + A(p.east, i)) / 2, ay = (A(p.south, i) + A(p.north, i)) / 2, az = (A(p.floor, i) + A(p.ceiling, i)) / 2;
const cl = (a) => Math.min(0.999, Math.max(1e-4, a)), air = env.air === false ? 0 : 4 * airM(f, env) * V;
const lx_ = -Math.log(1 - cl(ax)), ly_ = -Math.log(1 - cl(ay)), lz_ = -Math.log(1 - cl(az));
Sabine, Eyring, Fitzroy and Arau-Puchades times
64-bit
The four reverberation times of the room in a band.
Sabine: 0.161 V ÷ (S ᾱ + A_air); Eyring: 0.161 V ÷ (−S ln(1 − ᾱ) + A_air); Fitzroy: 0.161 V ÷ S² × Σ Sᵢ ÷ (−ln(1 − ᾱᵢ)); Arau: Π [0.161 V ÷ (−S ln(1 − ᾱᵢ) + A_air)]^(Sᵢ ÷ S)
The constant is written 0.161. Sabine divides by S ᾱ + air with the mean absorption not clamped, so it is infinite when both are zero. The Arau product uses Math.pow with exponents Sᵢ ÷ S that add up to 1.
stat.js
lines 31 to 35
BimCraft 0.8.1
const aMean = (SX * ax + SY * ay + SZ * az) / S, sabine = K * V / (S * aMean + air), eyring = K * V / (-S * Math.log(1 - cl(aMean)) + air);
const fitzroy = K * V / (S * S) * (SX / lx_ + SY / ly_ + SZ / lz_);
const arau = Math.pow(K * V / (S * lx_ + air), SX / S) * Math.pow(K * V / (S * ly_ + air), SY / S) * Math.pow(K * V / (S * lz_ + air), SZ / S);
// air: the same term joins each pair's −ln(1−ᾱ_i) as air / S (so the sum reduces to Eyring-with-air when the pairs are equal)
const fz = air ? K * V / (S * S) * (SX / (lx_ + air / S) + SY / (ly_ + air / S) + SZ / (lz_ + air / S)) : fitzroy;
In detail
Method
Sabine T = 0.161 V ÷ (S ᾱ + 4mV); Eyring with −S ln(1 − ᾱ); Fitzroy (1959) and Arau-Puchades (1988) on the mean absorption of each pair of opposite surfaces, as the file's header cites them.
Number types
64-bit numbers.
Tolerances
Absorption is limited to between 1e-4 and 0.999 before a logarithm is taken. A note is raised when the pairs' absorption differs by more than a factor of 3.
Limits
The constant 0.161 is the conventional rounded value. The Sabine line uses the unclamped mean absorption, so zero absorption with no air term divides by zero.
Approach: 64-bit, stated limit
The arithmetic is 64-bit, but the method or the data sets the accuracy: a solver tolerance, a mesh, a step size, a datum shift, a table. The limit is stated where the result is shown.