43 lines
1.6 KiB
JavaScript
43 lines
1.6 KiB
JavaScript
|
|
"use strict";
|
||
|
|
const audio = {
|
||
|
|
enabled: false,
|
||
|
|
ctx: null,
|
||
|
|
ensure() {
|
||
|
|
const AudioClass = window.AudioContext || window.webkitAudioContext;
|
||
|
|
if (!AudioClass) return null;
|
||
|
|
if (!this.ctx) this.ctx = new AudioClass();
|
||
|
|
if (this.ctx.state === "suspended") this.ctx.resume();
|
||
|
|
return this.ctx;
|
||
|
|
},
|
||
|
|
toggle() {
|
||
|
|
this.enabled = !this.enabled;
|
||
|
|
if (this.enabled) this.ensure();
|
||
|
|
return this.enabled;
|
||
|
|
},
|
||
|
|
tone(freq, dur = 0.08, type = "sine", gain = 0.035, slide = 0) {
|
||
|
|
if (!this.enabled) return;
|
||
|
|
const ctx = this.ensure();
|
||
|
|
if (!ctx) return;
|
||
|
|
const t0 = ctx.currentTime;
|
||
|
|
const osc = ctx.createOscillator();
|
||
|
|
const g = ctx.createGain();
|
||
|
|
osc.type = type;
|
||
|
|
osc.frequency.setValueAtTime(freq, t0);
|
||
|
|
if (slide) osc.frequency.linearRampToValueAtTime(Math.max(40, freq + slide), t0 + dur);
|
||
|
|
g.gain.setValueAtTime(0.0001, t0);
|
||
|
|
g.gain.exponentialRampToValueAtTime(gain, t0 + 0.01);
|
||
|
|
g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur);
|
||
|
|
osc.connect(g).connect(ctx.destination);
|
||
|
|
osc.start(t0);
|
||
|
|
osc.stop(t0 + dur + 0.02);
|
||
|
|
},
|
||
|
|
eat() { this.tone(660 + Math.random() * 140, 0.055, "triangle", 0.026, 120); },
|
||
|
|
poke() { this.tone(180, 0.09, "sawtooth", 0.022, -70); },
|
||
|
|
birth() { this.tone(520, 0.08, "sine", 0.028, 100); setTimeout(() => this.tone(760, 0.10, "triangle", 0.024, 80), 70); },
|
||
|
|
death() { this.tone(150, 0.22, "sine", 0.028, -70); },
|
||
|
|
fight() { this.tone(110, 0.055, "square", 0.018, 70); setTimeout(() => this.tone(90, 0.045, "sawtooth", 0.014, -40), 35); },
|
||
|
|
phase() { this.tone(440, 0.06, "sine", 0.018, 60); },
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
window.TarinaiAudio = audio;
|