thetascape-sound-engine
Version:
A sound engine by Jason Snell
586 lines (585 loc) • 27.1 kB
JavaScript
import { SongFrequencies as P, SongIDs as L } from "./thetascape-sound-engine.js";
class v {
constructor(t, e) {
this.tone = t, this.fft = new t.FFT(16), this.volume = new t.Volume(0), e.connect(this.volume), this.volume.connect(this.fft), this.volume.toDestination();
}
// Fade out to -100 dB over specified duration (default 4s)
fadeOut(t = 5) {
this.volume.volume.rampTo(-60, t);
}
// Fade in to 0 dB over specified duration (default 1s)
fadeIn(t = 1) {
this.volume.volume.rampTo(0, t);
}
// Returns array of 32 values in dB (range: ~[-100, 0])
getLevels() {
return !this.fft || typeof this.fft.getValue != "function" ? new Array(16).fill(0) : this.fft.getValue();
}
}
class s {
static TYPE_BG_LOOP = 1;
static TYPE_STANDARD = 2;
constructor(t, e, o) {
this.name = t, this.sampleMap = e, this.type = o, this.buffers = null, this.notes = null, this.loopLength = null, this.loopTotal = null, this.timingRange = null, this.velocityRange = null, this.skipChance = null, this.noteChance = null, this.attack = null, this.release = null, this.fxLevel = null, this.db = null;
}
updateBuffers(t) {
this.buffers = t;
}
}
class c {
static NAME_INTRO = "Intro";
static NAME_DELTA = "Delta";
static NAME_THETA = "Theta";
static NAME_ALPHA = "Alpha";
static NAME_BETA = "Beta";
static NAME_GAMMA = "Gamma";
constructor(t, e, o) {
this.tone = t, this.id = e, this.name = o, this.buffers = null, this.instruments = [];
}
async load() {
if (this.buffers)
return console.log("Song: Load already complete"), !0;
console.log("Song: Load URLs from", this.instruments.length, "instruments");
const t = {};
this.instruments.forEach((e) => {
const o = e.sampleMap;
Object.entries(o).forEach(([i, n]) => {
const a = `${e.name}_${i}`, l = `./../sounds/${n}`;
t[a] = l;
});
}), this.buffers = new this.tone.Buffers(t);
try {
return await this.tone.loaded(), this.instruments.forEach((e) => {
const i = Array.from(this.buffers._buffers.keys()).filter((n) => n.startsWith(e.name + "_")).map((n) => ({
note: n.substring(e.name.length + 1),
buffer: this.buffers.get(n)
// A ToneAudioBuffer
}));
e.updateBuffers(i);
}), console.log("Song: Load complete:", this.instruments.length, "instruments"), !0;
} catch (e) {
return console.error("Song: Error loading buffers:", e), !1;
}
}
//GETTERS FOR SONG PARTS
//get full set of instruments by type
//get random instrument of type
getInstrumentByName(t) {
return this.instruments.find((e) => e.name === t);
}
getBackgroundLoop() {
return this.instruments.filter((t) => t.type === s.TYPE_BG_LOOP)[0];
}
getInstruments() {
return this.instruments.filter((t) => t.type === s.TYPE_STANDARD);
}
getRandomInstrument() {
const t = this.getInstruments();
return t[Math.floor(Math.random() * t.length)];
}
}
class D extends c {
constructor(t, e) {
super(t, e, c.NAME_INTRO);
const o = new s("introBgLoop", { C3: "alpha/a_bg_loop_H5.mp3" }, s.TYPE_BG_LOOP);
o.notes = [
{ time: "0", pitch: "C3" }
], o.loopLength = "11m", o.loopTotal = -1, o.db = -22, this.instruments.push(o);
}
}
class R extends c {
constructor(t, e) {
super(t, e, c.NAME_DELTA);
const o = new s("deltaBgLoop", { C3: "delta/d_bg_loop_H5.mp3" }, s.TYPE_BG_LOOP);
o.notes = [
{ time: "0", pitch: "C3" }
], o.loopLength = "11m", o.loopTotal = -1, o.db = -7, this.instruments.push(o);
const i = new s("deltaPad", { C3: "delta/d_pad_H5.mp3" }, s.TYPE_STANDARD);
i.notes = [
{ time: "0", pitch: "G3", velocity: 0.8 },
{ time: "7m", pitch: "A3", velocity: 0.8 },
{ time: "14m", pitch: "G3", velocity: 0.8 },
{ time: "21m", pitch: ["G3", "C4"], velocity: 0.6 }
], i.loopLength = "28m", i.loopTotal = 1, i.velocityRange = 0.1, i.db = 4, this.instruments.push(i);
const n = new s("deltaSubBassNote", { C3: "delta/d_sub_bass_note_H5.mp3" }, s.TYPE_STANDARD);
n.notes = [
{ time: "0", pitch: "G3", velocity: 0.5 },
{ time: "6m", pitch: "A3", velocity: 0.5 },
{ time: "12m", pitch: "C3", velocity: 0.6 }
], n.loopLength = "16m", n.loopTotal = 1, n.velocityRange = 0.3, n.noteChance = 0.5, n.skipChance = 0.3, n.db = -10, this.instruments.push(n);
const a = new s("deltaAmbientTinesNote", { C3: "delta/d_ambient_tines_H5.mp3" }, s.TYPE_STANDARD);
a.notes = [
{ time: "0", pitch: "C3", velocity: 0.2 },
{ time: "5m", pitch: "C2", velocity: 0.65 }
], a.loopLength = "15m", a.loopTotal = 1, a.velocityRange = 0.4, a.skipChance = 0.5, a.db = 0, this.instruments.push(a);
}
}
class E extends c {
constructor(t, e) {
super(t, e, c.NAME_THETA);
const o = new s("thetaBgLoop", { C3: "theta/t_bg_loop_H5.mp3" }, s.TYPE_BG_LOOP);
o.notes = [
{ time: "0", pitch: "C3" }
], o.loopLength = "10m", o.loopTotal = -1, o.db = -8, this.instruments.push(o);
const i = new s("thetaBass", { C3: "theta/t_bass_note_H5.mp3" }, s.TYPE_STANDARD);
i.notes = [
{ time: "0", pitch: "F2" },
{ time: "6m", pitch: "G2" },
{ time: "12m", pitch: "C3" }
], i.loopLength = "18m", i.loopTotal = 1, i.velocityRange = 0.2, i.skipChance = 0.05, i.noteChance = 0.1, i.db = 0, this.instruments.push(i);
const n = new s("thetaChimesNote", { C3: "theta/t_chimes_note_H5.mp3" }, s.TYPE_STANDARD);
n.notes = [
{ time: "0:0:0", pitch: "C2" },
{ time: "1:0:0", pitch: "F2" },
{ time: "2:2:0", pitch: "G2" },
{ time: "3:2:0", pitch: "F2" }
], n.loopLength = "5m", n.loopTotal = 1, n.timingRange = 0.2, n.velocityRange = 0.5, n.skipChance = 0.23, n.noteChance = 0.25, n.db = 4, this.instruments.push(n);
const a = new s("thetaBellNote", { C3: "theta/t_bell_note_H5.mp3" }, s.TYPE_STANDARD);
a.notes = [
{ time: "0", pitch: "G2" },
{ time: "4m", pitch: "G3" }
], a.loopLength = "8m", a.loopTotal = 1, a.timingRange = 0.3, a.velocityRange = 0.3, a.skipChance = 0.2, a.noteChance = 0.5, a.db = -19, this.instruments.push(a);
}
}
class S extends c {
constructor(t, e) {
super(t, e, c.NAME_ALPHA);
const o = new s("alphaBgLoop", { C3: "alpha/a_bg_loop_H5.mp3" }, s.TYPE_BG_LOOP);
o.notes = [
{ time: "0", pitch: "C3" }
], o.loopLength = "12m", o.loopTotal = -1, o.db = -18, this.instruments.push(o);
const i = new s("alphaMindfullnessPad", { C3: "alpha/a_mindfulness_pad_H5.mp3" }, s.TYPE_STANDARD);
i.notes = [
{ time: "0", pitch: ["A2", "D3", "F3", "A3"], velocity: 1 },
//soft
{ time: "6m", pitch: ["E2", "G2", "C4", "E3"], velocity: 0.75 },
//bright
{ time: "12m", pitch: ["G2", "A2", "C3", "E3"], velocity: 1 },
//nice
{ time: "18m", pitch: ["E2", "A2", "C3", "F4"], velocity: 0.3 },
//very bright
{ time: "24m", pitch: ["G2", "C3", "E3"], velocity: 1 },
//floating
{ time: "30m", pitch: ["C3", "E3", "G3", "G4"], velocity: 0.3 }
//very bright
], i.loopLength = "36m", i.loopTotal = 1, i.velocityRange = 0.2, i.skipChance = 0.05, i.noteChance = 0.7, i.db = -14, this.instruments.push(i);
const n = new s("alphaJvAnalogPad", { C3: "alpha/a_JV_analog_pad_H5.mp3" }, s.TYPE_STANDARD);
n.notes = [
{ time: "0", pitch: "E3", velocity: 0.7 },
{ time: "6m", pitch: "F2", velocity: 0.7 },
{ time: "12m", pitch: "G2", velocity: 0.7 },
{ time: "18m", pitch: "A2", velocity: 0.7 },
{ time: "24m", pitch: "C3", velocity: 0.7 }
], n.loopLength = "30m", n.loopTotal = 1, n.velocityRange = 0.35, n.skipChance = 0.05, n.noteChance = 0.3, n.db = -4, this.instruments.push(n);
const a = new s("alphaDreamBg", { C3: "alpha/a_dream_bg_H5.mp3" }, s.TYPE_STANDARD);
a.notes = [
{ time: "0", pitch: "C3", velocity: 1 }
], a.loopLength = "7m", a.loopTotal = 1, a.velocityRange = 0.3, a.db = -6, this.instruments.push(a);
const l = new s("alphaTangerineBg", { C3: "alpha/a_tangerine_bg_H5.mp3" }, s.TYPE_STANDARD);
l.notes = [
{ time: "0", pitch: "C3", velocity: 0.5 },
{ time: "7m", pitch: "C2", velocity: 0.8 }
], l.loopLength = "19m", l.loopTotal = 1, l.skipChance = 0.1, l.db = -6, this.instruments.push(l);
const h = new s("betaHarpBg", { C3: "beta/b_harp_bg_H5.mp3" }, s.TYPE_STANDARD);
h.notes = [
{ time: "0", pitch: "C2" }
], h.loopLength = "12m", h.loopTotal = 1, h.velocityRange = 0.2, h.db = 2, this.instruments.push(h);
const r = new s("alphaSoftKey", { C3: "alpha/a_soft_key_H5.mp3" }, s.TYPE_STANDARD);
r.notes = [
{ time: "0:0:0", pitch: "C2" },
{ time: "0:4:0", pitch: "D2" },
{ time: "2:0:0", pitch: "E2" },
{ time: "2:4:0", pitch: "G2" },
{ time: "4:0:0", pitch: "A2" },
{ time: "4:4:0", pitch: "C3" },
{ time: "6:0:0", pitch: "D3" }
], r.loopLength = "6:3:0", r.loopTotal = 1, r.timingRange = 0.6, r.velocityRange = 0.2, r.skipChance = 0.45, r.noteChance = 0.9, r.db = -17, this.instruments.push(r);
}
}
class I extends c {
constructor(t, e) {
super(t, e, c.NAME_BETA);
const o = new s("betaBass", { C3: "beta/b_bass_H5.mp3" }, s.TYPE_BG_LOOP);
o.notes = [
{ time: "0", pitch: "C3" }
], o.loopLength = "11m", o.loopTotal = -1, o.db = -2, this.instruments.push(o);
const i = new s("betaBellsArp", { C3: "beta/b_bells_arp_H5.mp3" }, s.TYPE_STANDARD);
i.notes = [
{ time: "0", pitch: "C3" }
], i.loopLength = "16m", i.loopTotal = 1, i.db = -3, this.instruments.push(i);
const n = new s("betaBellsBg", { C3: "beta/b_bells_bg_H5.mp3" }, s.TYPE_STANDARD);
n.notes = [
{ time: "0", pitch: "C3" }
], n.loopLength = "10m", n.loopTotal = 1, n.velocityRange = 0.3, n.db = -10, this.instruments.push(n);
const a = new s("betaDreamPad", { C3: "beta/b_dream_pad_H5.mp3" }, s.TYPE_STANDARD);
a.notes = [
{ time: "0", pitch: "G3" },
{ time: "3m", pitch: "G2" }
], a.loopLength = "14m", a.loopTotal = 1, a.velocityRange = 0.5, a.skipChance = 0.4, a.db = -17, this.instruments.push(a);
const l = new s("betaDriftBg", { C3: "beta/b_drift_bg_H5.mp3" }, s.TYPE_STANDARD);
l.notes = [
{ time: "0", pitch: "C2", velocity: 0.55 },
{ time: "4m", pitch: "C4", velocity: 0.2 },
{ time: "9m", pitch: "C3", velocity: 0.6 }
], l.loopLength = "17m", l.loopTotal = 1, l.timingRange = 0.6, l.velocityRange = 0.15, l.skipChance = 0.3, l.db = -4, this.instruments.push(l);
const h = new s("betaHarpArp", { C3: "beta/b_harp_arp_H5.mp3" }, s.TYPE_STANDARD);
h.notes = [
{ time: "0", pitch: "C3" }
], h.loopLength = "14m", h.loopTotal = 1, h.velocityRange = 0.6, h.db = 3, this.instruments.push(h);
const r = new s("betaHarpBg", { C3: "beta/b_harp_bg_H5.mp3" }, s.TYPE_STANDARD);
r.notes = [
{ time: "0", pitch: "C3" }
], r.loopLength = "6m", r.loopTotal = 1, r.db = 2, this.instruments.push(r);
const p = new s("betaHarpNote", { C3: "beta/b_harp_note_H5.mp3" }, s.TYPE_STANDARD);
p.notes = [
{ time: "0:3:0", pitch: ["C2", "G1"] },
{ time: "3:3:0", pitch: ["G2", "C2"] },
{ time: "6:1:0", pitch: ["C3", "G2"] },
{ time: "8:3:0", pitch: ["C2", "G1"] },
{ time: "10:3:0", pitch: ["E2", "C3"] }
], p.loopLength = "12m", p.loopTotal = 1, p.timingRange = 0.4, p.velocityRange = 0.7, p.skipChance = 0.3, p.noteChance = 0.75, p.db = -23, this.instruments.push(p);
}
}
class N extends c {
constructor(t, e) {
super(t, e, c.NAME_GAMMA);
const o = new s("gammaBgLoop", { C3: "gamma/g_bg_loop_H5.mp3" }, s.TYPE_BG_LOOP);
o.notes = [
{ time: "0", pitch: "C3" }
], o.loopLength = "9m", o.loopTotal = -1, o.db = -26, this.instruments.push(o);
const i = new s("gammaShimmer1", { C3: "gamma/g_shimmer_H5.mp3" }, s.TYPE_STANDARD);
i.notes = [
{ time: "0", pitch: "C3" }
], i.loopLength = "9m", i.loopTotal = 1, i.velocityRange = 0.2, i.db = 0, this.instruments.push(i);
const n = new s("gammaChakraBg", { C3: "gamma/g_chakra_bg_H5.mp3" }, s.TYPE_STANDARD);
n.notes = [
{ time: "0", pitch: "G3" }
], n.loopLength = "13m", n.loopTotal = 1, n.velocityRange = 0.2, n.db = 0, this.instruments.push(n);
const a = new s("gammaChakraArpHigh", { C3: "gamma/g_chakra_arp_high_H5.mp3" }, s.TYPE_STANDARD);
a.notes = [
{ time: "0", pitch: "C3" }
], a.loopLength = "10m", a.loopTotal = 1, a.timingRange = 0, a.velocityRange = 0.5, a.db = -3, this.instruments.push(a);
const l = new s("gammaChakraArpMid", { C3: "gamma/g_chakra_arp_mid_H5.mp3" }, s.TYPE_STANDARD);
l.notes = [
{ time: "0", pitch: "C3" }
], l.loopLength = "12m", l.loopTotal = 1, l.timingRange = 0, l.velocityRange = 0.5, l.db = -3, this.instruments.push(l);
const h = new s("gammaChakraArpLow", { C3: "gamma/g_chakra_arp_low_H5.mp3" }, s.TYPE_STANDARD);
h.notes = [
{ time: "0", pitch: "C3" }
], h.loopLength = "32m", h.loopTotal = 1, h.timingRange = 0, h.velocityRange = 0.3, h.db = -3, this.instruments.push(h);
const r = new s("gammaCrystalSparkle", { C3: "gamma/g_crystal_sparkle_H5.mp3" }, s.TYPE_STANDARD);
r.notes = [
{ time: "0", pitch: "C1", velocity: 0.9 },
{ time: "2m", pitch: "G1", velocity: 0.7 },
{ time: "4m", pitch: "C2", velocity: 0.3 },
{ time: "6m", pitch: "G1", velocity: 0.6 },
{ time: "8m", pitch: "C3", velocity: 0.6 }
], r.loopLength = "10m", r.loopTotal = 1, r.velocityRange = 0.2, r.skipChance = 0.5, r.db = 1, this.instruments.push(r);
const p = new s("gammaChoirPad", { C3: "gamma/g_warm_choir_H5.mp3" }, s.TYPE_STANDARD);
p.notes = [
{ time: "0", pitch: ["C1", "C2"] },
{ time: "4:0:0", pitch: ["F1", "F2"] },
{ time: "7:0:0", pitch: ["G1", "G2"] },
{ time: "9:2:0", pitch: ["C2", "C3"] }
], p.loopLength = "13m", p.loopTotal = 4, p.velocityRange = 0.2, p.skipChance = 0.3, p.noteChance = 0.3, p.db = -3, this.instruments.push(p);
const u = new s("gammaBell", { C3: "gamma/g_bell_note_H5.mp3" }, s.TYPE_STANDARD);
u.notes = [
{ time: "0:0:0", pitch: "C3", velocity: 0.8 },
{ time: "0:1:0", pitch: "F3", velocity: 0.8 },
{ time: "0:2:0", pitch: "G3", velocity: 0.8 },
{ time: "2:0:0", pitch: "C1", velocity: 0.8 },
{ time: "2:1:0", pitch: "F1", velocity: 0.8 },
{ time: "2:2:0", pitch: "G1", velocity: 0.7 },
{ time: "4:0:0", pitch: "C2", velocity: 0.6 },
{ time: "4:1:0", pitch: "F2", velocity: 0.5 },
{ time: "4:2:0", pitch: "G2", velocity: 0.35 }
], u.loopLength = "6m", u.loopTotal = 1, u.velocityRange = 0.15, u.skipChance = 0.6, u.db = -4, this.instruments.push(u);
}
}
class T {
constructor(t, e, o, i) {
this.tone = t, this.id = e, this.mainOutput = o, this.onComplete = i, this.instrumentName = null, this.instrumentType = null;
const n = "./../sounds/global/z_test_tone.mp3";
this.player = new this.tone.Sampler({
urls: {
C1: n,
C2: n,
C3: n,
C4: n,
C5: n,
C6: n,
C7: n,
C8: n
},
attack: 0
}), this.player.connect(o), this.stop = this.stop.bind(this), this.part = null, this.onCompleteID = null, this.sixteenthSeconds = this.tone.Time("16n").toSeconds();
}
//PLAYBACK
playInstrument(t) {
if (this._checkInstrumentName(t.name))
console.log(""), console.log("//////////////////////////////"), console.log("PLYR", this.id, "Queued to play", t.name);
else
return;
if (this.instrumentType = t.type, !this._loadBuffers(t.buffers)) {
console.warn("PLYR", this.id, ": Error loading buffer.");
return;
}
const o = t.notes, i = t.loopLength, n = t.loopTotal;
let a = t.timingRange;
a || (a = 0);
let l = t.velocityRange;
l || (l = 0);
let h = t.skipChance;
h || (h = 0);
let r = t.noteChance;
r || (r = 0);
const p = t.db;
if (t.type === s.TYPE_BG_LOOP ? this.player.volume.rampTo(p, 10) : this.player.volume.rampTo(p, 3), this.part && this.part.dispose(), this.part = new this.tone.Part((_, f) => {
let y = f.pitch, g = f.velocity || 1;
if (r > 0 && o.length > 0 && Math.random() < r) {
const d = o[Math.floor(Math.random() * o.length)];
y = d.pitch, g = d.velocity || 1;
}
if (Math.random() < h)
g = 0;
else if (l !== 0) {
const d = Math.random() * l + (1 - l);
g *= d;
}
let A = _;
if (a !== 0) {
const d = (Math.random() * (a * 2) - a) * this.sixteenthSeconds;
A = Math.max(_ + d, 0);
}
g === 0 ? console.log("---------------- PLYR", this.id, this.instrumentName, "SKIPPED") : (console.log("++++++++++++++++ PLYR", this.id, this.instrumentName, "note at", A, "w/pitch", y, "& velo", g), this.player.triggerAttack(y, A, g));
}, o), n === 0) {
console.error("PLYR", this.id, this.instrumentName, ": Error: loopTotal is 0. This will not play. Use -1 to loop forever, 1 for single play, and 2 and above for multiple plays.");
return;
} else (n === -1 || n > 1) && (this.part.loop = !0, this.part.loopEnd = i);
const u = o[0], b = this.tone.Time(u.time).toSeconds(), C = this.tone.now() + b + 2.4;
if (n > 0) {
const _ = this.tone.Time(i).toSeconds(), f = C + _;
this.onCompleteID = this.tone.getTransport().scheduleOnce((y) => {
console.log("PLYR ---------------->>>> ", this.id, this.instrumentName, "onComplete at", y), this.onComplete && this.onComplete(this.instrumentName);
}, f);
}
this.part.start(C), this.tone.getTransport().state !== "started" && (console.log("PLYR", this.id, ": Transport not started, starting now."), this.tone.getTransport().start());
}
stop() {
this.part && this.part.stop(), this.tone.getTransport().clear(this.onCompleteID), this.onCompleteID = null, this.instrumentName = null, this.instrumentType = null;
}
getInstrumentName() {
return this.instrumentName;
}
resetInstrument() {
this.instrumentName = null, this.instrumentType = null;
}
//SUBS
_checkInstrumentName(t) {
return this.instrumentName ? (console.warn("PLYR", this.id, ": Already playing", this.instrumentName), !1) : (this.instrumentName = t, !0);
}
//load a new audio file buffers into the player's note slots
_loadBuffers(t) {
try {
if (!this.player)
return console.error("PLYR: this.player is not initialized"), !1;
if (!t)
return console.warn("PLYR: _loadBuffers: newBuffers is not defined."), !1;
if (t.length === 1) {
const e = t[0], o = e.note, i = e.buffer ? e.buffer._buffer : e._buffer;
return !i || !o ? (console.warn("PLYR: _loadBuffers: The single entry is missing a note or buffer.", e), !1) : (this.player._buffers._buffers.clear(), this.player.add(o, i), !0);
} else
return t.forEach((e) => {
const o = e.note, i = e.buffer;
if (!o || !i || !i._buffer) {
console.warn("PLYR: _loadBuffers: Missing note or buffer in entry:", e);
return;
}
this.player.add(o, i._buffer);
}), !0;
} catch (e) {
return console.error("PLYR: Error updating buffers in _loadBuffers:", e), !1;
}
}
}
class w {
constructor(t, e) {
this.osc = new t.Oscillator(523.25, "sine"), this.osc.volume.value = -35, this.ampEnv = new t.AmplitudeEnvelope({
attack: 3.5,
// gradual fade-in
decay: 1,
// slower drop to the sustain level
sustain: 0.9,
// lower level to simulate natural decay
release: "8m"
// long tail after note release
}), this.autoPan = new t.AutoPanner(
5,
//frequency
1
//depth
), this.osc.connect(this.ampEnv), this.ampEnv.connect(this.autoPan), this.autoPan.connect(e), this.frequencies = [392, 164.81, 392, 523.25, 783.99, 1046.5], this.volumes = [-35, -35, -38, -39, -40, -48];
}
setFrequency(t) {
this.autoPan.frequency.value = t;
}
start() {
this.autoPan.start(), this.osc.start();
}
play(t) {
this.osc.volume.value = this.volumes[t], this.osc.frequency.value = this.frequencies[t], this.ampEnv.triggerAttackRelease("2m");
}
}
class B {
//pass dry and wet output down into the players
constructor(t, e, o) {
this.tone = t, this.players = [
new T(t, 0, e, o),
new T(t, 1, e, o),
new T(t, 2, e, o),
new T(t, 3, e, o)
//new Player(tone, 4, mainOutput, playComplete)
], this.solfeggioSynth = new w(t, e), this.activeInstrumentNames = [], this.bgLoopID = null, this.playerID_1 = null, this.playerID_2 = null, this.playerID_3 = null, this.playerID_4 = null;
}
start() {
this.solfeggioSynth.start();
}
setFrequency(t) {
this.solfeggioSynth.setFrequency(t);
}
playIntroTone(t) {
t !== 0 && this.solfeggioSynth.play(t);
}
//loads a new set of audio files and data sets into the app
play(t) {
console.log("PLAYERS: Play", t.name, "song"), this.stopAll(), this.bgLoopID = this.tone.getTransport().scheduleOnce((e) => {
console.log("---> PLAYERS: BG LOOP"), this.playBackgroundLoop(t);
}, "+" + this.tone.Time("0")), this.playerID_1 = this.tone.getTransport().scheduleOnce((e) => {
console.log("---> PLAYERS: PLAYER 2"), this.playInstrument(t);
}, "+" + this.tone.Time("2m")), this.playerID_2 = this.tone.getTransport().scheduleOnce((e) => {
console.log("---> PLAYERS: PLAYER 3"), this.playInstrument(t);
}, "+" + this.tone.Time("8m")), this.playerID_3 = this.tone.getTransport().scheduleOnce((e) => {
console.log("---> PLAYERS: PLAYER 4"), this.playInstrument(t);
}, "+" + this.tone.Time("14m")), this.playerID_4 = this.tone.getTransport().scheduleOnce((e) => {
console.log("---> PLAYERS: PLAYER 5");
}, "+" + this.tone.Time("20m"));
}
//PLAY
//bg and instruments
playBackgroundLoop(t) {
const e = t.getBackgroundLoop();
if (!e) {
console.warn("PLAYERS: No background loop found");
return;
}
this._playInstrument(e);
}
playInstrument(t) {
const e = t.getInstruments().filter(
(n) => !this.activeInstrumentNames.includes(n.name)
);
if (e.length === 0) {
console.warn("Players: All available instruments are playing");
return;
}
const o = Math.floor(Math.random() * e.length), i = e[o];
this._playInstrument(i);
}
//RESET
resetPlayer(t) {
for (const e of this.players)
if (e.getInstrumentName() === t) {
console.log("PLAYERS: Player", e.id, "with instrumentName", t, "has been reset."), e.resetInstrument();
const o = this.activeInstrumentNames.indexOf(t);
o > -1 && this.activeInstrumentNames.splice(o, 1), console.log("--- RMV PLAYLIST", t);
break;
}
}
//PLAYBACK
_playInstrument(t) {
this.activeInstrumentNames.push(t.name), console.log("+++ ADD PLAYLIST", this.activeInstrumentNames);
const e = this._getAvailablePlayer();
e ? (console.log("Players: Play", t.name, "on player", e.id), e.playInstrument(t)) : console.warn("Players: All note players are being used");
}
_getAvailablePlayer() {
let t = null;
for (const e of this.players)
if (!e.getInstrumentName()) {
t = e;
break;
}
return t;
}
//loop through all players and stop them
stopAll() {
console.log("PLAYERS: Stop all"), this.tone.getTransport().clear(this.bgLoopID), this.tone.getTransport().clear(this.playerID_1), this.tone.getTransport().clear(this.playerID_2), this.tone.getTransport().clear(this.playerID_3), this.tone.getTransport().clear(this.playerID_4), this.bgLoopID = null, this.playerID_1 = null, this.playerID_2 = null, this.playerID_3 = null, this.playerID_4 = null, this.players.forEach((t) => t.stop()), this.activeInstrumentNames = [];
}
}
class H {
//INIT ENGINE
constructor(t) {
console.log("AUDIO: Init Audio Engine"), this.tone = t, this.songs = [], this.currSong = null, this.mainBusInput = null, this.mainBus = null, this.players = null, this.startSongID = null, this.initComplete = !1;
}
async initAudioEngine() {
console.log("AUDIO: Init Audio Engine with Tone", this.tone), this.initComplete || (this.tone.getContext().state === "suspended" && await this.tone.getContext().resume(), console.log("AUDIO: Tone resumed", this.tone.getContext().state), this.tone.getTransport().bpm.value = 100, this.tone.getContext().lookAhead = 1, console.log("AUDIO: Lookahead time", this.tone.getContext().lookAhead), this.tone.getTransport().state !== "started" ? (console.log("AUDIO: Start transport"), this.tone.getTransport().start()) : console.log("AUDIO: Transport already started"), this.songs = [
new D(this.tone, 0),
new R(this.tone, 1),
new E(this.tone, 2),
new S(this.tone, 3),
new I(this.tone, 4),
new N(this.tone, 5)
], this.mainBusInput = new this.tone.Gain(1), this.mainBus = new v(this.tone, this.mainBusInput), this.players = new B(
this.tone,
//pass in tone
this.mainBusInput,
//pass in main input
this.playComplete
//completion callback
), this.initComplete = !0);
}
//LOAD and PLAY SONG
async playSong(t) {
await this.initAudioEngine(), console.log("AUDIO: Load song", t);
const e = this.songs[t];
if (!e) {
console.error("AUDIO: No song found for ID", t);
return;
}
if (this.currSong && this.currSong.id === t) {
console.warn("AUDIO: Song already playing", this.currSong.name);
return;
} else
this.currSong = e;
console.log("AUDIO: Play intro tone", t), this.players.playIntroTone(t), this.mainBus.fadeIn(1), await this.currSong.load() ? console.log("AUDIO: Song", t, "loaded") : console.error("AUDIO: Failed to load song", t), this.players.setFrequency(P[t]), this.players.start(), this.startSongID = this.tone.getTransport().scheduleOnce((i) => {
console.log("AUDIO: Play Song", t, "at time", i), this.players.play(this.currSong), t === L.INTRO && this.playIntroSound();
}, "+" + this.tone.Time("4n"));
}
playIntroSound() {
console.log("PLAYERS: Play intro");
const t = "./../sounds/intro/intro_H5.mp3", e = new this.tone.Player({
url: t,
autostart: !1,
// set false to manually control
volume: 5,
// db
onload: () => {
console.log("INTRO PLAYER: Loaded, starting now"), e.start();
},
onerror: (o) => {
console.error("INTRO PLAYER: Error loading", o);
}
}).toDestination();
this.tone.Transport.state !== "started" && this.tone.Transport.start(), e.onstop = () => {
e.dispose(), console.log("INTRO PLAYER: Disposed after stop");
};
}
playComplete = (t) => {
console.log("AUDIO: Instrument", t, "complete, play next"), this.players.resetPlayer(t), this.players.playInstrument(this.currSong);
};
stopSong() {
this.tone.getTransport().clear(this.startSongID), this.startSongID = null, this.players.stopAll(), this.mainBus.fadeOut(), this.currSong = null;
}
}
export {
H as default
};