2023-11-27 14:29:55 -06:00
|
|
|
|
2023-09-07 16:46:35 -05:00
|
|
|
var Sound = {
|
2023-11-27 14:29:55 -06:00
|
|
|
bus: {},
|
2023-11-27 17:04:04 -06:00
|
|
|
samplerate() { return cmd(198); },
|
2023-09-07 16:46:35 -05:00
|
|
|
sounds: [], /* array of loaded sound files */
|
2023-11-27 14:29:55 -06:00
|
|
|
play(file, bus) {
|
2023-10-09 13:03:12 -05:00
|
|
|
if (!IO.exists(file)) {
|
2023-10-11 17:22:41 -05:00
|
|
|
Log.error(`Cannot play sound ${file}: does not exist.`);
|
2023-10-09 13:03:12 -05:00
|
|
|
return;
|
|
|
|
}
|
2023-11-27 14:29:55 -06:00
|
|
|
var src = DSP.source(file);
|
|
|
|
bus ??= Sound.bus.master;
|
|
|
|
src.plugin(bus);
|
|
|
|
return src;
|
2023-11-17 15:16:13 -06:00
|
|
|
},
|
2023-11-27 14:29:55 -06:00
|
|
|
};
|
2023-09-07 16:46:35 -05:00
|
|
|
|
2023-11-27 14:29:55 -06:00
|
|
|
var DSP = {
|
|
|
|
mix(to) {
|
2024-01-14 10:24:31 -06:00
|
|
|
var n = cmd(181);
|
2023-11-27 14:29:55 -06:00
|
|
|
if (to) n.plugin(to);
|
|
|
|
return n;
|
|
|
|
},
|
|
|
|
source(path) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(182,path);
|
2023-11-27 14:29:55 -06:00
|
|
|
},
|
|
|
|
delay(secs,decay) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(185, secs, decay);
|
2023-11-27 14:29:55 -06:00
|
|
|
},
|
2023-11-28 22:48:32 -06:00
|
|
|
fwd_delay(secs, decay) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(207,secs,decay);
|
2023-11-28 22:48:32 -06:00
|
|
|
},
|
|
|
|
allpass(secs, decay) {
|
2023-12-04 13:38:37 -06:00
|
|
|
var composite = {};
|
2023-11-28 22:48:32 -06:00
|
|
|
var fwd = DSP.fwd_delay(secs,-decay);
|
|
|
|
var fbk = DSP.delay(secs,decay);
|
2023-12-04 13:38:37 -06:00
|
|
|
composite.id = fwd.id;
|
|
|
|
composite.plugin = composite.plugin.bind(fbk);
|
|
|
|
composite.unplug = dsp_node.unplug.bind(fbk);
|
2023-11-28 22:48:32 -06:00
|
|
|
fwd.plugin(fbk);
|
2023-12-04 13:38:37 -06:00
|
|
|
return composite;
|
2023-11-28 22:48:32 -06:00
|
|
|
},
|
2023-11-27 14:29:55 -06:00
|
|
|
lpf(f) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(186,f);
|
2023-11-27 14:29:55 -06:00
|
|
|
},
|
|
|
|
hpf(f) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(187,f);
|
2023-11-27 14:29:55 -06:00
|
|
|
},
|
|
|
|
mod(path) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(188,path);
|
2023-11-27 14:29:55 -06:00
|
|
|
},
|
2023-11-28 22:48:32 -06:00
|
|
|
midi(midi,sf) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(206,midi,sf);
|
2023-11-28 22:48:32 -06:00
|
|
|
},
|
2023-11-27 14:29:55 -06:00
|
|
|
crush(rate, depth) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(189,rate,depth);
|
2023-11-27 14:29:55 -06:00
|
|
|
},
|
|
|
|
compressor() {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(190);
|
2023-11-27 14:29:55 -06:00
|
|
|
},
|
|
|
|
limiter(ceil) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(191,ceil);
|
2023-11-27 14:29:55 -06:00
|
|
|
},
|
|
|
|
noise_gate(floor) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(192,floor);
|
2023-09-07 16:46:35 -05:00
|
|
|
},
|
2023-11-28 22:48:32 -06:00
|
|
|
pitchshift(octaves) {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(200,octaves);
|
2023-11-28 22:48:32 -06:00
|
|
|
},
|
|
|
|
noise() {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(203);
|
2023-11-28 22:48:32 -06:00
|
|
|
},
|
|
|
|
pink() {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(204);
|
2023-11-28 22:48:32 -06:00
|
|
|
},
|
|
|
|
red() {
|
2024-01-14 10:24:31 -06:00
|
|
|
return cmd(205);
|
2023-11-28 22:48:32 -06:00
|
|
|
},
|
2023-09-07 16:46:35 -05:00
|
|
|
};
|
2023-10-23 08:08:11 -05:00
|
|
|
|
2024-01-14 10:24:31 -06:00
|
|
|
Sound.bus.master = cmd(180);
|
2023-11-27 14:29:55 -06:00
|
|
|
Sound.master = Sound.bus.master;
|
|
|
|
|
2023-10-23 08:08:11 -05:00
|
|
|
Sound.play.doc = "Play the given file once.";
|
|
|
|
Sound.doc = {};
|
|
|
|
Sound.doc.volume = "Set the master volume. 0 is no sound and 100 is loudest.";
|
2024-01-14 10:24:31 -06:00
|
|
|
|
|
|
|
DSP.doc = {
|
|
|
|
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"
|
|
|
|
};
|
|
|
|
|
|
|
|
Object.mixin(cmd(180).__proto__, {
|
|
|
|
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; },
|
|
|
|
});
|
|
|
|
|
|
|
|
Object.mixin(DSP.source().__proto__, {
|
|
|
|
frames() { return cmd(197,this); },
|
|
|
|
length() { return this.frames()/Sound.samplerate(); },
|
|
|
|
time() { return this.frame/Sound.samplerate(); },
|
|
|
|
pct() { return this.time()/this.length(); },
|
|
|
|
});
|