Skip to content

Commit ec269ea

Browse files
committed
audio context
Signed-off-by: Soldy <4786022+Soldy@users.noreply.github.com>
1 parent 917617f commit ec269ea

1 file changed

Lines changed: 395 additions & 0 deletions

File tree

SC.js

Lines changed: 395 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,395 @@
1+
2+
const sClass = function(){
3+
this.Init=function(){
4+
init();
5+
};
6+
this.PrecacheSound = function(name){
7+
if (this.nosound !== 0)
8+
return name;
9+
if (this.precache === 0)
10+
return name;
11+
return precacheSound(name);
12+
};
13+
this.LoadSound = function(source){
14+
if (this.nosound.value !== 0)
15+
return;
16+
return loadSound(source);
17+
};
18+
this.SounList = function(){
19+
for(let i in sfxs)
20+
Con.Print(
21+
sizeGet(i) + ' : ' + i + '\n'
22+
);
23+
Con.Print(
24+
'Total resident: ' +
25+
total +
26+
'\n'
27+
);
28+
};
29+
this.StartSound = function(entnum, entchannel, sfx, origin, vol, attenuation){
30+
startSound(entnum, entchannel, sfx, origin, vol, attenuation);
31+
}
32+
this.StartAmbient = function(name){
33+
return startAmbient(name);
34+
}
35+
this.listAmbient = function(){
36+
let out = [];
37+
for(let i in ambient_channels)
38+
out.push(i);
39+
return out;
40+
}
41+
this.LocalSound = function(sound){
42+
startSound(
43+
CL.state.viewentity,
44+
1,
45+
sound,
46+
Vec.origin,
47+
1.0,
48+
1.0
49+
);
50+
};
51+
this.StopAllSounds = function(){
52+
stopAllSounds();
53+
}
54+
this.StopSound = function(etnum, etchannel){
55+
stopSound(etnum, etchannel);
56+
}
57+
this.Play = function(){
58+
59+
}
60+
this.PlayVol = function(){
61+
62+
}
63+
this.StaticSound = async function(sfx, origin, vol, attenuation){
64+
await startSound(
65+
"static",
66+
staticSerial,
67+
sfx,
68+
origin,
69+
vol,
70+
attenuation
71+
);
72+
channels["static"].sub[staticSerial].sx.loop = true;
73+
staticSerial++;
74+
if(staticSerial >10) // 11 static channels
75+
staticSerial = 0;
76+
77+
}
78+
this.UpdateDynamicSounds = function(){
79+
for (let i of activeChannels){ //ia:string
80+
if(Host.realtime >= channels[
81+
activeChannels[i].entnum
82+
].sub[
83+
activeChannels[i].entchannel
84+
].end
85+
){
86+
activeChannels.splice(i, 1);
87+
continue;
88+
}
89+
spatialize(
90+
activeChannels[i].entnum,
91+
activeChannels[i].entchannel
92+
);
93+
channelVolume(
94+
activeChannels[i].entnum,
95+
activeChannels[i].entchannel
96+
);
97+
}
98+
}
99+
this.UpdateAmbientSounds = function(){}
100+
this.UpdateStaticSounds = function(){}
101+
this.Update = function(origin, forward, right, up){
102+
listener_origin = origin;
103+
listener_forward = forward;
104+
listener_right = right;
105+
listener_up = up;
106+
if (volume.value < 0.0)
107+
Cvar.SetValue('volume', 0.0);
108+
else if (volume.value > 1.0)
109+
Cvar.SetValue('volume', 1.0);
110+
}
111+
this.Spatialize = function(ch){}
112+
this.size = 0;
113+
this.bgmvolume = 0;
114+
this.volume = 0;
115+
this.ambient_level = 0.3;
116+
this.ambient_fade = 100;
117+
this.precache = 1;
118+
this.nosound = 0;
119+
this.static_channels = [];
120+
this.known_sfx = [];
121+
this.started = false;
122+
let staticSerial = 0;
123+
let activeChannels = [];
124+
let channels = {};
125+
let ambient_channels = {};
126+
let listener_origin = [0.0, 0.0, 0.0];
127+
let listener_forward = [0.0, 0.0, 0.0];
128+
let listener_right = [0.0, 0.0, 0.0];
129+
let listener_up = [0.0, 0.0, 0.0];
130+
let sfxs = {};
131+
let audioCTX;
132+
let init = async function(){
133+
Con.Print('\nSound Initialization\n');
134+
Cmd.AddCommand('play', S.Play);
135+
Cmd.AddCommand('playvol', S.PlayVol);
136+
Cmd.AddCommand('stopsound', S.StopAllSounds);
137+
Cmd.AddCommand('soundlist', S.SoundList);
138+
this.nosound = Cvar.RegisterVariable(
139+
'nosound',
140+
(COM.CheckParm(
141+
'-nosound'
142+
) != null) ? '1' : '0'
143+
);
144+
this.volume = Cvar.RegisterVariable(
145+
'volume',
146+
'0.7',
147+
true
148+
);
149+
this.precache = Cvar.RegisterVariable(
150+
'precache',
151+
'1'
152+
);
153+
this.bgmvolume = Cvar.RegisterVariable(
154+
'bgmvolume',
155+
'1',
156+
true
157+
);
158+
this.ambient_level = Cvar.RegisterVariable(
159+
'ambient_level',
160+
'0.3'
161+
);
162+
this.ambient_fade = Cvar.RegisterVariable(
163+
'ambient_fade',
164+
'100'
165+
);
166+
this.started = true;
167+
audioCTX = new (window.AudioContext || window.webkitAudioContext)({
168+
latencyHint: 'interactive',
169+
sampleRate: 44100,
170+
});
171+
let ambient_sfx = ['water1', 'wind2'];
172+
for (let i of ambient_sfx)
173+
startAmbient('ambience/' + i + '.wav');
174+
175+
}
176+
let upldate = function(){
177+
178+
}
179+
let spatialize = function(en, ec){
180+
"use asm"
181+
if(en === CL.state.viewentity){
182+
channels[en].sub[ec].volLeft = channels[en].sub[ec].vol;
183+
channels[en].sub[ec].volRight = channels[en].sub[ec].vol;
184+
return ;
185+
}
186+
let source = [
187+
channels[en].sub[ec].origin[0] - listener_origin[0],
188+
channels[en].sub[ec].origin[1] - listener_origin[1],
189+
channels[en].sub[ec].origin[2] - listener_origin[2]
190+
];
191+
let dist = Math.sqrt(source[0] * source[0] + source[1] * source[1] + source[2] * source[2]);
192+
193+
if (dist !== 0.0){
194+
source[0] /= dist;
195+
source[1] /= dist;
196+
source[2] /= dist;
197+
}
198+
dist *= (channels[en].sub[ec].mult*0.4);
199+
var dot = listener_right[0] * source[0]
200+
+ listener_right[1] * source[1]
201+
+ listener_right[2] * source[2];
202+
channels[en].sub[ec].volRight = channels[en].sub[ec].vol * (1.0 - dist) * (1.0 + dot);
203+
if (channels[en].sub[ec].volRight < 0.0)
204+
channels[en].sub[ec].volRight = 0.0;
205+
if (channels[en].sub[ec].volRight > 1.0)
206+
channels[en].sub[ec].volRight = 1.0;
207+
channels[en].sub[ec].volLeft = channels[en].sub[ec].vol * (1.0 - dist) * (1.0 - dot);
208+
if (channels[en].sub[ec].volLeft < 0.0)
209+
channels[en].sub[ec].volLeft = 0.0;
210+
if (channels[en].sub[ec].volLeft > 1.0)
211+
channels[en].sub[ec].volLeft = 1.0;
212+
}
213+
let channelVolume = function(en,ec){
214+
channels[en].sub[ec].g1.gain.value =
215+
channels[en].sub[ec].volLeft * volume.value;
216+
channels[en].sub[ec].g2.gain.value =
217+
channels[en].sub[ec].volRight * volume.value;
218+
}
219+
let startSound = async function(entnum, entchannel, sfx, origin, vol, attenuation){
220+
pickChannel(entnum, entchannel);
221+
await loadSound(sfx);
222+
channels[entnum].sub[entchannel].vol = vol;
223+
channels[entnum].sub[entchannel].mult = attenuation * 0.001;
224+
spatialize(entnum, entchannel);
225+
if (
226+
(channels[entnum].sub[entchannel].volLeft === 0.0)&&
227+
(channels[entnum].sub[entchannel].volRight === 0.0)
228+
)
229+
return;
230+
231+
if(channels[entnum].sub[entchannel].activeChannels === false){
232+
channels[entnum].sub[entchannel].activeChannels = parseInt(activeChannels.length);
233+
activeChannels.push({
234+
entnum,
235+
entchannel
236+
});
237+
}
238+
channels[entnum].sub[entchannel].sx.buffer = sfxs[sfx].cache;
239+
// channels[entnum].sub[entchannel].sx.connect(audioCTX.destination);
240+
channels[entnum].sub[entchannel].end = Host.realtime + sfxs[sfx].cache.length;
241+
channels[entnum].sub[entchannel].sx.connect(
242+
channels[entnum].sub[entchannel].m1
243+
);
244+
channels[entnum].sub[entchannel].sx.connect(
245+
channels[entnum].sub[entchannel].m1, 0, 1
246+
);
247+
channels[entnum].sub[entchannel].m1.connect(
248+
channels[entnum].sub[entchannel].sp
249+
);
250+
channels[entnum].sub[entchannel].sp.connect(
251+
channels[entnum].sub[entchannel].g1
252+
);
253+
channels[entnum].sub[entchannel].sp.connect(
254+
channels[entnum].sub[entchannel].g2
255+
);
256+
channels[entnum].sub[entchannel].g1.connect(
257+
channels[entnum].sub[entchannel].m2, 0, 0
258+
);
259+
channels[entnum].sub[entchannel].g2.connect(
260+
channels[entnum].sub[entchannel].m2, 0, 1
261+
);
262+
channels[entnum].sub[entchannel].m2.connect(
263+
audioCTX.destination
264+
);
265+
channelVolume(entnum,entchannel);
266+
return channels[entnum].sub[entchannel].sx.start();
267+
}
268+
let startAmbient = async (sfx)=>{
269+
try{
270+
ambient_channels[sfx].stop();
271+
}catch(e){};
272+
loadSound(sfx);
273+
ambient_channels[sfx] = audioCTX.createBufferSource();
274+
ambient_channels[sfx].loop = true ;
275+
ambient_channels[sfx].connect(audioCTX.destination);
276+
setTimeout(function(){
277+
try{
278+
console.info(sfx);
279+
ambient_channels[sfx].buffer = sfxs[sfx].cache;
280+
ambient_channels[sfx].start();
281+
}catch(e){
282+
console.error(e);
283+
}
284+
},2000);
285+
}
286+
let startAmbientAll = function(){
287+
for (let i in ambient_channels)
288+
startAmbient(i);
289+
}
290+
let precacheSound = function(name){
291+
if(typeof sfxs[name] === "undefined")
292+
sfxs[name] = {name: name};
293+
loadSound(name);
294+
return name;
295+
}
296+
let loadSound = async function(name){
297+
if (sfxs[name] == null)
298+
sfxs[name] = {
299+
name : name,
300+
cache : null
301+
};
302+
if (sfxs[name].cache != null)
303+
return true;
304+
let sc = {};
305+
let data = COM.LoadFile('sound/' + name);
306+
if (data == null){
307+
Con.Print(
308+
'Couldn\'t load sound/' +
309+
name +
310+
'\n'
311+
);
312+
return;
313+
}
314+
(await (async function(dataout, name){
315+
audioCTX.decodeAudioData(
316+
data,
317+
function(buffer){
318+
sfxs[name].cache = buffer;
319+
},
320+
(e) => { reject(e); }
321+
);
322+
})(data,name));
323+
return true;
324+
};
325+
let sizeGet = function(name){
326+
if(sfxs[name].cache== null)
327+
return '';
328+
let size = sfxs.cache.size.toString();
329+
if (sfxs.cache.loopstart != null)
330+
size = 'L' + size;
331+
return size.padStart(6, ' ');
332+
};
333+
let pickChannel = function(entnum,entchannel){
334+
if(channels[entnum] == null)
335+
newChannel(entnum);
336+
if(channels[entnum].sub[entchannel] != null)
337+
stopSound(entnum, entchannel);
338+
return channels[entnum].sub[entchannel]=
339+
emptyChannel();
340+
341+
};
342+
let emptyChannel = function(){
343+
return {
344+
vol : 1,
345+
volLeft : 1,
346+
volRight : 1,
347+
origin : [0,0,0],
348+
mult : 0.0001,
349+
end : null,
350+
sx : audioCTX.createBufferSource(),
351+
m1 : audioCTX.createChannelMerger(2),
352+
m2 : audioCTX.createChannelMerger(2),
353+
sp : audioCTX.createChannelSplitter(2),
354+
g1 : audioCTX.createGain(),
355+
g2 : audioCTX.createGain()
356+
}
357+
}
358+
let newChannel = function(entnum, sub){
359+
if((1 > sub)||(typeof sub === "undefined"))
360+
sub = 2;
361+
channels[entnum] = {
362+
sub:[]
363+
};
364+
};
365+
let stopAllSounds = function(){
366+
for(let iOne in channels)
367+
for(let iTwo in channels[iOne].sub)
368+
stopSound(iOne,iTwo);
369+
for(let iOne in ambient_channels)
370+
stopSoundAmbient(iOne);
371+
}
372+
let stopSoundAmbient = function(sfx){
373+
if(ambient_channels[sfx] == null)
374+
return ;
375+
try{
376+
ambient_channels[sfx].stop();
377+
ambient_channels[sfx]=null;
378+
}catch(e){
379+
380+
}
381+
}
382+
let stopSound = function(entnum, entchannel){
383+
if(channels[entnum].sub[entchannel].sx == null)
384+
return ;
385+
try{
386+
channels[entnum].sub[entchannel].sx.stop();
387+
channels[entnum].sub[entchannel].sx=null;
388+
}catch(e){
389+
390+
}
391+
}
392+
393+
};
394+
395+
const S = new sClass();

0 commit comments

Comments
 (0)