UNPKG

thetascape-sound-engine

Version:
586 lines (585 loc) 27.1 kB
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 };