|
/* |
|
This is free and unencumbered software released into the public domain. |
|
|
|
Anyone is free to copy, modify, publish, use, compile, sell, or |
|
distribute this software, either in source code form or as a compiled |
|
binary, for any purpose, commercial or non-commercial, and by any |
|
means. |
|
|
|
In jurisdictions that recognize copyright laws, the author or authors |
|
of this software dedicate any and all copyright interest in the |
|
software to the public domain. We make this dedication for the benefit |
|
of the public at large and to the detriment of our heirs and |
|
successors. We intend this dedication to be an overt act of |
|
relinquishment in perpetuity of all present and future rights to this |
|
software under copyright law. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|
OTHER DEALINGS IN THE SOFTWARE. |
|
|
|
For more information, please refer to <https://unlicense.org/> |
|
|
|
-------------------------------------------------------------------------- |
|
|
|
This file contains some stuff, that is copy-pasted from a C-header belonging |
|
to OpenAL, namely "AL/efx-presets.h". The header itself doesn't have a |
|
Copyright notice. If you're unsure, remove everything down to BakePreset(). |
|
*/ |
|
|
|
function EfxArrayToObject(arr) |
|
{ |
|
let [ |
|
flDensity, |
|
flDiffusion, |
|
flGain, |
|
flGainHF, |
|
flGainLF, |
|
flDecayTime, |
|
flDecayHFRatio, |
|
flDecayLFRatio, |
|
flReflectionsGain, |
|
flReflectionsDelay, |
|
flReflectionsPan, |
|
flLateReverbGain, |
|
flLateReverbDelay, |
|
flLateReverbPan, |
|
flEchoTime, |
|
flEchoDepth, |
|
flModulationTime, |
|
flModulationDepth, |
|
flAirAbsorptionGainHF, |
|
flHFReference, |
|
flLFReference, |
|
flRoomRolloffFactor, |
|
iDecayHFLimit |
|
] = arr; |
|
return { |
|
flDensity, |
|
flDiffusion, |
|
flGain, |
|
flGainHF, |
|
flGainLF, |
|
flDecayTime, |
|
flDecayHFRatio, |
|
flDecayLFRatio, |
|
flReflectionsGain, |
|
flReflectionsDelay, |
|
flReflectionsPan, |
|
flLateReverbGain, |
|
flLateReverbDelay, |
|
flLateReverbPan, |
|
flEchoTime, |
|
flEchoDepth, |
|
flModulationTime, |
|
flModulationDepth, |
|
flAirAbsorptionGainHF, |
|
flHFReference, |
|
flLFReference, |
|
flRoomRolloffFactor, |
|
iDecayHFLimit |
|
}; |
|
} |
|
|
|
EfxPresets = { |
|
GENERIC : EfxArrayToObject([ 1.0000 , 1.0000 , 0.3162 , 0.8913 , 1.0000 , 1.4900 , 0.8300 , 1.0000 , 0.0500 , 0.0070 , [ 0.0000 , 0.0000 , 0.0000 ], 1.2589 , 0.0110 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
ROOM : EfxArrayToObject([ 0.4287 , 1.0000 , 0.3162 , 0.5929 , 1.0000 , 0.4000 , 0.8300 , 1.0000 , 0.1503 , 0.0020 , [ 0.0000 , 0.0000 , 0.0000 ], 1.0629 , 0.0030 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
BATH : EfxArrayToObject([ 0.1715 , 1.0000 , 0.3162 , 0.2512 , 1.0000 , 1.4900 , 0.5400 , 1.0000 , 0.6531 , 0.0070 , [ 0.0000 , 0.0000 , 0.0000 ], 3.2734 , 0.0110 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
LIVING : EfxArrayToObject([ 0.9766 , 1.0000 , 0.3162 , 0.0010 , 1.0000 , 0.5000 , 0.1000 , 1.0000 , 0.2051 , 0.0030 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2805 , 0.0040 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
STONE : EfxArrayToObject([ 1.0000 , 1.0000 , 0.3162 , 0.7079 , 1.0000 , 2.3100 , 0.6400 , 1.0000 , 0.4411 , 0.0120 , [ 0.0000 , 0.0000 , 0.0000 ], 1.1003 , 0.0170 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
AUDITORIUM : EfxArrayToObject([ 1.0000 , 1.0000 , 0.3162 , 0.5781 , 1.0000 , 4.3200 , 0.5900 , 1.0000 , 0.4032 , 0.0200 , [ 0.0000 , 0.0000 , 0.0000 ], 0.7170 , 0.0300 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
CONCERT : EfxArrayToObject([ 1.0000 , 1.0000 , 0.3162 , 0.5623 , 1.0000 , 3.9200 , 0.7000 , 1.0000 , 0.2427 , 0.0200 , [ 0.0000 , 0.0000 , 0.0000 ], 0.9977 , 0.0290 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
CARPET : EfxArrayToObject([ 0.4287 , 1.0000 , 0.3162 , 0.0100 , 1.0000 , 0.3000 , 0.1000 , 1.0000 , 0.1215 , 0.0020 , [ 0.0000 , 0.0000 , 0.0000 ], 0.1531 , 0.0300 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
HALLWAY : EfxArrayToObject([ 0.3645 , 1.0000 , 0.3162 , 0.7079 , 1.0000 , 1.4900 , 0.5900 , 1.0000 , 0.2458 , 0.0070 , [ 0.0000 , 0.0000 , 0.0000 ], 1.6615 , 0.0110 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
STONEHALLWAY : EfxArrayToObject([ 1.0000 , 1.0000 , 0.3162 , 0.7612 , 1.0000 , 2.7000 , 0.7900 , 1.0000 , 0.2472 , 0.0130 , [ 0.0000 , 0.0000 , 0.0000 ], 1.5758 , 0.0200 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
CASTLE : EfxArrayToObject([ 1.0000 , 0.9300 , 0.3162 , 0.2818 , 0.1000 , 2.0400 , 0.8300 , 0.4600 , 0.6310 , 0.0220 , [ 0.0000 , 0.0000 , 0.0000 ], 1.5849 , 0.0110 , [ 0.0000 , 0.0000 , 0.0000 ], 0.1550 , 0.0300 , 0.2500 , 0.0000 , 0.9943 , 5168.6001 , 139.5000 , 0.0000 , 0x1 ]), |
|
CASTLEHALL : EfxArrayToObject([ 1.0000 , 0.8100 , 0.3162 , 0.2818 , 0.1778 , 3.1400 , 0.7900 , 0.6200 , 0.1778 , 0.0560 , [ 0.0000 , 0.0000 , 0.0000 ], 1.1220 , 0.0240 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 5168.6001 , 139.5000 , 0.0000 , 0x1 ]), |
|
FACTORY : EfxArrayToObject([ 0.4287 , 0.8200 , 0.2512 , 0.7943 , 0.5012 , 2.7600 , 0.6500 , 1.3100 , 0.2818 , 0.0220 , [ 0.0000 , 0.0000 , 0.0000 ], 1.4125 , 0.0230 , [ 0.0000 , 0.0000 , 0.0000 ], 0.1740 , 0.0700 , 0.2500 , 0.0000 , 0.9943 , 3762.6001 , 362.5000 , 0.0000 , 0x1 ]), |
|
ICEPALACE : EfxArrayToObject([ 1.0000 , 0.8700 , 0.3162 , 0.5623 , 0.4467 , 2.2200 , 1.5300 , 0.3200 , 0.3981 , 0.0390 , [ 0.0000 , 0.0000 , 0.0000 ], 1.1220 , 0.0270 , [ 0.0000 , 0.0000 , 0.0000 ], 0.1860 , 0.1200 , 0.2500 , 0.0000 , 0.9943 , 12428.5000 , 99.6000 , 0.0000 , 0x1 ]), |
|
WOODEN : EfxArrayToObject([ 1.0000 , 1.0000 , 0.3162 , 0.1000 , 0.2818 , 1.4700 , 0.4200 , 0.8200 , 0.8913 , 0.0490 , [ 0.0000 , 0.0000 , 0.0000 ], 0.8913 , 0.0290 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.0000 , 0.9943 , 4705.0000 , 99.6000 , 0.0000 , 0x1 ]), |
|
MUSEUM : EfxArrayToObject([ 1.0000 , 0.8200 , 0.3162 , 0.1778 , 0.1778 , 3.2800 , 1.4000 , 0.5700 , 0.2512 , 0.0390 , [ 0.0000 , 0.0000 , -0.0000 ], 0.8913 , 0.0340 , [ 0.0000 , 0.0000 , 0.0000 ], 0.1300 , 0.1700 , 0.2500 , 0.0000 , 0.9943 , 2854.3999 , 107.5000 , 0.0000 , 0x0 ]), |
|
LIBRARY : EfxArrayToObject([ 1.0000 , 0.8200 , 0.3162 , 0.2818 , 0.0891 , 2.7600 , 0.8900 , 0.4100 , 0.3548 , 0.0290 , [ 0.0000 , 0.0000 , -0.0000 ], 0.8913 , 0.0200 , [ 0.0000 , 0.0000 , 0.0000 ], 0.1300 , 0.1700 , 0.2500 , 0.0000 , 0.9943 , 2854.3999 , 107.5000 , 0.0000 , 0x0 ]), |
|
DUSTYROOM : EfxArrayToObject([ 0.3645 , 0.5600 , 0.3162 , 0.7943 , 0.7079 , 1.7900 , 0.3800 , 0.2100 , 0.5012 , 0.0020 , [ 0.0000 , 0.0000 , 0.0000 ], 1.2589 , 0.0060 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2020 , 0.0500 , 0.2500 , 0.0000 , 0.9886 , 13046.0000 , 163.3000 , 0.0000 , 0x1 ]), |
|
CHAPEL : EfxArrayToObject([ 1.0000 , 0.8400 , 0.3162 , 0.5623 , 1.0000 , 4.6200 , 0.6400 , 1.2300 , 0.4467 , 0.0320 , [ 0.0000 , 0.0000 , 0.0000 ], 0.7943 , 0.0490 , [ 0.0000 , 0.0000 , 0.0000 ], 0.2500 , 0.0000 , 0.2500 , 0.1100 , 0.9943 , 5000.0000 , 250.0000 , 0.0000 , 0x1 ]), |
|
SMALLWATER :EfxArrayToObject([ 1.0000, 0.7000, 0.3162, 0.4477, 1.0000, 1.5100, 1.2500, 1.1400, 0.8913, 0.0200, [ 0.0000, 0.0000, 0.0000 ], 1.4125, 0.0300, [ 0.0000, 0.0000, 0.0000 ], 0.1790, 0.1500, 0.8950, 0.1900, 0.9920, 5000.0000, 250.0000, 0.0000, 0x0 ]), |
|
}; |
|
// console.log(EfxPresets.GENERIC) |
|
|
|
// ---------------------------------------------------------------------------------- |
|
// everything from here is essentially unencumbered. |
|
|
|
async function BakePreset(pso) |
|
{ |
|
let decaySamps = (48000*pso.flDecayTime)>>0; |
|
let decaySampsHf = (48000*pso.flDecayTime*pso.flDecayHFRatio)>>0; |
|
let decaySampsLf = (48000*pso.flDecayTime*pso.flDecayLFRatio)>>0; |
|
let ctx = new OfflineAudioContext(1,decaySamps,48000); |
|
await ctx.audioWorklet.addModule('./tools.js'); |
|
let n0 = new AudioWorkletNode(ctx,'noise-generator',{ numberOfInputs:0, outputChannelCount:[1]}); |
|
let n1 = new AudioWorkletNode(ctx,'noise-generator',{ numberOfInputs:0, outputChannelCount:[1]}); |
|
let n2 = new AudioWorkletNode(ctx,'noise-generator',{ numberOfInputs:0, outputChannelCount:[1]}); |
|
let n3 = new AudioWorkletNode(ctx,'noise-generator',{ numberOfInputs:0, outputChannelCount:[1]}); |
|
|
|
let f1 = new BiquadFilterNode(ctx,{type:'highpass', frequency: pso.flHFReference, channelCount: 1}); |
|
let f2a = new BiquadFilterNode(ctx,{type:'lowpass' , frequency: pso.flHFReference, channelCount: 1}); |
|
let f2b = new BiquadFilterNode(ctx,{type:'highpass', frequency: pso.flLFReference, channelCount: 1}); |
|
let f3 = new BiquadFilterNode(ctx,{type:'lowpass' , frequency: pso.flLFReference, channelCount: 1}); |
|
|
|
let m0 = new AudioWorkletNode(ctx,'multiplier-node',{ numberOfInputs:2, outputChannelCount:[1]}); |
|
let m1 = new AudioWorkletNode(ctx,'multiplier-node',{ numberOfInputs:2, outputChannelCount:[1]}); |
|
let m2 = new AudioWorkletNode(ctx,'multiplier-node',{ numberOfInputs:2, outputChannelCount:[1]}); |
|
let m3 = new AudioWorkletNode(ctx,'multiplier-node',{ numberOfInputs:2, outputChannelCount:[1]}); |
|
|
|
let d0 = ctx.createBuffer(1,480,48000); |
|
let d1 = ctx.createBuffer(1,decaySampsHf,48000); |
|
let d2 = ctx.createBuffer(1,decaySamps,48000); |
|
let d3 = ctx.createBuffer(1,decaySampsLf,48000); |
|
for(let x of [d0,d1,d2,d3]) |
|
{ |
|
let samps = x.getChannelData(0); |
|
for(let i=0,n=samps.length;i<n;++i) |
|
samps[i] = Math.pow((n-i)/n,2); |
|
} |
|
let gains = [ |
|
[d1, pso.flGain * pso.flGainHF], |
|
[d2, pso.flGain], |
|
[d3, pso.flGain * pso.flGainLF], |
|
]; |
|
for(let pair of gains) |
|
{ |
|
let [x,gain] = pair; |
|
let samps = x.getChannelData(0); |
|
for(let i=0,n=samps.length;i<n;++i) |
|
samps[i] *= gain; |
|
} |
|
|
|
let p0 = new AudioBufferSourceNode(ctx,{buffer:d0}); |
|
let p1 = new AudioBufferSourceNode(ctx,{buffer:d1}); |
|
let p2 = new AudioBufferSourceNode(ctx,{buffer:d2}); |
|
let p3 = new AudioBufferSourceNode(ctx,{buffer:d3}); |
|
for(let p of [p0,p1,p2,p3]) p.start(); |
|
|
|
let o = ctx.createGain(); |
|
let g = ctx.createGain(); |
|
|
|
n0.connect(m0).connect(o); |
|
n1.connect(f1).connect(m1).connect(o); |
|
n2.connect(f2a).connect(f2b).connect(m2).connect(o); |
|
n3.connect(f3).connect(m3).connect(o); |
|
|
|
p0.connect(m0,0,1); |
|
p1.connect(m1,0,1); |
|
p2.connect(m2,0,1); |
|
p3.connect(m3,0,1); |
|
|
|
o.connect(ctx.destination); |
|
let buf = await ctx.startRendering(); |
|
return buf; |
|
} |