2024-04-10 16:21:46 -05:00
|
|
|
/* This file runs after the audio system is initiated */
|
|
|
|
|
|
|
|
Object.readonly(audio, 'samplerate');
|
|
|
|
Object.readonly(audio, 'channels');
|
|
|
|
Object.readonly(audio, 'buffer_frames');
|
|
|
|
|
2024-09-15 17:49:35 -05:00
|
|
|
var sources = [];
|
|
|
|
|
2024-04-07 13:16:54 -05:00
|
|
|
audio.play = function(file,bus = audio.bus.master) {
|
2024-09-15 17:49:35 -05:00
|
|
|
var filename = file;
|
2024-03-19 17:00:49 -05:00
|
|
|
file = Resources.find_sound(file);
|
|
|
|
if (!file) {
|
|
|
|
console.error(`Cannot play sound ${file}: does not exist.`);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var src = audio.dsp.source(file);
|
|
|
|
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.type = "source";
|
|
|
|
sources.push(src);
|
2024-03-19 17:00:49 -05:00
|
|
|
return src;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
audio.bus.master.__proto__.plugin = function(to)
|
|
|
|
{
|
|
|
|
this.tos ??= [];
|
|
|
|
this.tos.push(to);
|
|
|
|
to.ins ??= [];
|
|
|
|
to.ins.push(this);
|
|
|
|
plugin_node.call(this, to);
|
|
|
|
}
|
|
|
|
|
|
|
|
var unplug_node = audio.bus.master.unplug;
|
|
|
|
audio.bus.master.__proto__.unplug = function()
|
|
|
|
{
|
|
|
|
if (this.tos) {
|
|
|
|
for (var node of this.tos)
|
|
|
|
node.ins.remove(this);
|
|
|
|
|
|
|
|
this.tos = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
unplug_node.call(this);
|
|
|
|
}
|
|
|
|
|
2024-08-25 14:23:22 -05:00
|
|
|
audio.dsp.mix().__proto__.imgui = function()
|
2024-08-25 06:35:04 -05:00
|
|
|
{
|
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-08-25 06:35:04 -05:00
|
|
|
}
|
|
|
|
|
2024-08-25 14:23:22 -05:00
|
|
|
audio.cry = function(file, bus = audio.bus.sfx)
|
2024-04-01 08:13:57 -05:00
|
|
|
{
|
2024-08-24 18:40:29 -05:00
|
|
|
file = Resources.find_sound(file);
|
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-15 17:49:35 -05:00
|
|
|
player.ended = function() { player.unplug(); player = undefined; }
|
2024-04-04 17:28:11 -05:00
|
|
|
return player.ended;
|
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-04-04 17:28:11 -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
|
|
|
|
audio.music = function(file, fade = 0.5) {
|
2024-09-07 15:14:03 -05:00
|
|
|
if (!file) {
|
2024-09-09 18:55:07 -05:00
|
|
|
if (song)
|
2024-09-07 15:14:03 -05:00
|
|
|
song.volume = 0;
|
2024-09-09 18:55:07 -05:00
|
|
|
return;
|
2024-09-07 15:14:03 -05:00
|
|
|
}
|
2024-08-24 18:40:29 -05:00
|
|
|
file = Resources.find_sound(file);
|
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;
|
|
|
|
// tween(song,'volume', 1, fade);
|
|
|
|
return;
|
|
|
|
}
|
2024-04-01 08:13:57 -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-08-24 18:40:29 -05:00
|
|
|
temp.volume = 1;
|
2024-04-01 08:13:57 -05:00
|
|
|
var temp2 = song;
|
2024-08-24 18:40:29 -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-04-01 08:13:57 -05:00
|
|
|
}
|
|
|
|
|
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";
|
2023-10-23 08:08:11 -05:00
|
|
|
|
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-03-19 14:39:19 -05:00
|
|
|
audio.dsp.allpass = function(secs, decay) {
|
|
|
|
var composite = {};
|
|
|
|
var fwd = audio.dsp.fwd_delay(secs,-decay);
|
|
|
|
var fbk = audio.dsp.delay(secs,decay);
|
|
|
|
composite.id = fwd.id;
|
|
|
|
composite.plugin = composite.plugin.bind(fbk);
|
|
|
|
composite.unplug = dsp_node.unplug.bind(fbk);
|
|
|
|
fwd.plugin(fbk);
|
|
|
|
return composite;
|
|
|
|
}
|
|
|
|
|
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",
|
|
|
|
red: "Red noise"
|
|
|
|
};
|
|
|
|
|
2024-08-25 06:35:04 -05:00
|
|
|
audio.dsp.obscure('doc');
|
|
|
|
|
2024-03-19 17:00:49 -05:00
|
|
|
Object.mixin(audio.bus.master.__proto__, {
|
2024-01-14 10:24:31 -06: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-08-25 00:18:30 -05:00
|
|
|
audio.bus.master.__proto__.toJSON = function()
|
|
|
|
{
|
|
|
|
return {
|
|
|
|
volume: this.volume,
|
|
|
|
off: this.off,
|
|
|
|
pan: this.pan,
|
|
|
|
pass: this.pass
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
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-02-29 13:54:33 -06:00
|
|
|
|
|
|
|
return {audio};
|