prosperon/scripts/sound.js

199 lines
4.6 KiB
JavaScript
Raw Normal View History

2024-04-10 16:21:46 -05:00
/* This file runs after the audio system is initiated */
2024-09-26 11:36:09 -05:00
Object.readonly(audio, "samplerate");
Object.readonly(audio, "channels");
Object.readonly(audio, "buffer_frames");
2024-04-10 16:21:46 -05:00
2024-09-15 17:49:35 -05:00
var sources = [];
var pcms = {};
2024-09-15 17:49:35 -05:00
audio.pcm = function(file)
{
2024-03-19 17:00:49 -05:00
file = Resources.find_sound(file);
if (!file) return;
if (pcms[file]) return pcms[file];
var newpcm = os.make_pcm(file);
if (!newpcm) return;
pcms[file] = newpcm;
newpcm.format(audio.samplerate, audio.channels);
return newpcm;
}
audio.play = function (file, bus = audio.bus.master) {
var pcm = audio.pcm(file);
if (!pcm) return;
var src = audio.dsp.source(pcm);
2024-03-19 17:00:49 -05:00
src.plugin(bus);
2024-04-04 17:28:11 -05:00
src.guid = prosperon.guid();
2024-09-15 17:49:35 -05:00
src.name = file;
src._pcm = pcm;
2024-09-15 17:49:35 -05:00
src.type = "source";
sources.push(src);
2024-03-19 17:00:49 -05:00
return src;
2024-09-26 11:36:09 -05:00
};
2024-03-19 17:00:49 -05:00
audio.bus = {};
audio.bus.master = dspsound.master();
2024-03-19 14:39:19 -05:00
audio.dsp = {};
2024-03-19 17:00:49 -05:00
audio.dsp = dspsound;
2024-03-19 14:39:19 -05:00
2024-09-15 17:49:35 -05:00
audio.bus.master.__proto__.type = "bus";
audio.bus.master.name = "master";
var plugin_node = audio.bus.master.plugin;
2024-09-26 11:36:09 -05:00
audio.bus.master.__proto__.plugin = function (to) {
2024-09-15 17:49:35 -05:00
this.tos ??= [];
this.tos.push(to);
to.ins ??= [];
to.ins.push(this);
plugin_node.call(this, to);
2024-09-26 11:36:09 -05:00
};
2024-09-15 17:49:35 -05:00
var unplug_node = audio.bus.master.unplug;
2024-09-26 11:36:09 -05:00
audio.bus.master.__proto__.unplug = function () {
2024-09-15 17:49:35 -05:00
if (this.tos) {
2024-09-26 11:36:09 -05:00
for (var node of this.tos) node.ins.remove(this);
2024-09-15 17:49:35 -05:00
this.tos = [];
}
2024-09-26 11:36:09 -05:00
2024-09-15 17:49:35 -05:00
unplug_node.call(this);
2024-09-26 11:36:09 -05:00
};
2024-09-15 17:49:35 -05:00
2024-09-26 11:36:09 -05:00
audio.dsp.mix().__proto__.imgui = function () {
2024-08-25 14:23:22 -05:00
imgui.pushid(this.memid());
2024-08-25 06:35:04 -05:00
this.volume = imgui.slider("Volume", this.volume);
this.off = imgui.checkbox("Mute", this.off);
2024-08-25 14:23:22 -05:00
imgui.popid();
2024-09-26 11:36:09 -05:00
};
2024-08-25 06:35:04 -05:00
2024-09-26 11:36:09 -05:00
audio.cry = function (file, bus = audio.bus.sfx) {
2024-08-25 06:35:04 -05:00
var player = audio.play(file, bus);
2024-04-14 14:53:41 -05:00
if (!player) return;
2024-09-26 11:36:09 -05:00
player.ended = function () {
2024-10-06 17:18:18 -05:00
player?.unplug();
2024-09-26 11:36:09 -05:00
player = undefined;
};
2024-04-04 17:28:11 -05:00
return player.ended;
2024-09-26 11:36:09 -05:00
};
2024-04-01 08:13:57 -05:00
2024-09-15 17:49:35 -05:00
// This function is called when every audio source is finished
2024-09-26 11:36:09 -05:00
var killer = Register.appupdate.register(function () {
2024-09-15 17:49:35 -05:00
for (var src of sources) {
if (!src.loop && (src.frame < src.lastframe || src.frame === src.frames())) {
src.unplug();
src.ended?.();
}
src.lastframe = src.frame;
2024-04-04 17:28:11 -05:00
}
});
2024-04-01 08:13:57 -05:00
var song;
2024-08-24 18:40:29 -05:00
// Play 'file' for new song, cross fade for seconds
2024-09-26 11:36:09 -05:00
audio.music = function (file, fade = 0.5) {
2024-09-07 15:14:03 -05:00
if (!file) {
2024-09-26 11:36:09 -05:00
if (song) song.volume = 0;
2024-09-09 18:55:07 -05:00
return;
2024-09-07 15:14:03 -05:00
}
2024-04-01 08:13:57 -05:00
if (!fade) {
2024-08-25 06:35:04 -05:00
song = audio.play(file, audio.bus.music);
2024-04-14 14:53:41 -05:00
song.loop = true;
2024-04-01 08:13:57 -05:00
return;
}
2024-08-24 18:40:29 -05:00
if (!song) {
2024-08-25 06:35:04 -05:00
song = audio.play(file, audio.bus.music);
2024-08-24 18:40:29 -05:00
song.volume = 1;
2024-09-26 11:36:09 -05:00
// tween(song,'volume', 1, fade);
2024-08-24 18:40:29 -05:00
return;
}
2024-09-26 11:36:09 -05:00
2024-08-25 06:35:04 -05:00
var temp = audio.play(file, audio.bus.music);
2024-04-14 14:53:41 -05:00
if (!temp) return;
2024-09-26 11:36:09 -05:00
2024-08-24 18:40:29 -05:00
temp.volume = 1;
2024-04-01 08:13:57 -05:00
var temp2 = song;
2024-09-26 11:36:09 -05:00
// tween(temp, 'volume', 1, fade);
// tween(temp2, 'volume', 0, fade);
2024-04-01 08:13:57 -05:00
song = temp;
2024-04-14 14:53:41 -05:00
song.loop = true;
2024-09-26 11:36:09 -05:00
};
2024-04-01 08:13:57 -05:00
2024-10-06 17:18:18 -05:00
audio.music.playing = function()
{
return song;
}
2024-08-25 06:35:04 -05:00
audio.bus.music = audio.dsp.mix();
audio.bus.music.plugin(audio.bus.master);
2024-09-15 17:49:35 -05:00
audio.bus.music.name = "music";
2024-08-25 14:23:22 -05:00
audio.bus.sfx = audio.dsp.mix();
audio.bus.sfx.plugin(audio.bus.master);
2024-09-15 17:49:35 -05:00
audio.bus.sfx.name = "sfx";
2024-08-25 14:23:22 -05:00
2024-09-26 11:36:09 -05:00
audio.dsp.allpass = function (secs, decay) {
2024-03-19 14:39:19 -05:00
var composite = {};
2024-09-26 11:36:09 -05:00
var fwd = audio.dsp.fwd_delay(secs, -decay);
var fbk = audio.dsp.delay(secs, decay);
2024-03-19 14:39:19 -05:00
composite.id = fwd.id;
composite.plugin = composite.plugin.bind(fbk);
composite.unplug = dsp_node.unplug.bind(fbk);
fwd.plugin(fbk);
return composite;
2024-09-26 11:36:09 -05:00
};
2024-03-19 14:39:19 -05:00
2024-02-25 17:31:48 -06:00
audio.dsp.doc = {
2024-01-14 10:24:31 -06:00
delay: "Delays the input by secs, multiplied by decay",
fwd_delay: "Forward feedback delays the input by secs, multiplied by decay",
allpass: "Composite node of a delay and fwd_delay",
lpf: "Low pass filter at a given frequency",
hpf: "High pass filter at a given frequency",
midi: "A source node for a midi file with a given soundfont file",
crush: "Bitcrush the input to a given rate and bit depth",
limiter: "Limit audio to ceil with pleasent rolloff",
noise_gate: "Do not pass audio below the given floor",
pitchshift: "Shift sound by octaves",
noise: "Plain randon noise",
pink: "Pink noise",
2024-09-26 11:36:09 -05:00
red: "Red noise",
2024-01-14 10:24:31 -06:00
};
2024-09-26 11:36:09 -05:00
audio.dsp.obscure("doc");
2024-08-25 06:35:04 -05:00
2024-03-19 17:00:49 -05:00
Object.mixin(audio.bus.master.__proto__, {
2024-09-26 11:36:09 -05:00
get db() {
return 20 * Math.log10(Math.abs(this.volume));
},
set db(x) {
x = Math.clamp(x, -100, 0);
this.volume = Math.pow(10, x / 20);
},
get volume() {
return this.gain;
},
set volume(x) {
this.gain = x;
},
2024-01-14 10:24:31 -06:00
});
2024-09-26 11:36:09 -05:00
audio.bus.master.__proto__.toJSON = function () {
2024-08-25 00:18:30 -05:00
return {
volume: this.volume,
off: this.off,
pan: this.pan,
2024-09-26 11:36:09 -05:00
pass: this.pass,
2024-08-25 00:18:30 -05:00
};
2024-09-26 11:36:09 -05:00
};
2024-08-25 00:18:30 -05:00
2024-02-25 17:31:48 -06:00
/*Object.mixin(audio.dsp.source().__proto__, {
2024-03-19 17:00:49 -05:00
length() { return this.frames()/audio.samplerate(); },
2024-02-25 17:31:48 -06:00
time() { return this.frame/sound.samplerate(); },
2024-01-14 10:24:31 -06:00
pct() { return this.time()/this.length(); },
});
2024-01-31 02:42:15 -06:00
*/
2024-09-26 11:36:09 -05:00
return { audio };