UNPKG

live2d-motionsync

Version:

Live2D Motionsync, a lip-sync library for Live2D models.

134 lines (133 loc) 4.82 kB
var h = Object.defineProperty; var f = (s, t, o) => t in s ? h(s, t, { enumerable: !0, configurable: !0, writable: !0, value: o }) : s[t] = o; var n = (s, t, o) => f(s, typeof t != "symbol" ? t + "" : t, o); import { c, C as u, M as m, f as S } from "./fallback.motionsync3-1oooNFSa.js"; let a; function p() { const s = ["click", "keydown", "touchstart", "mousedown", "pointerdown"]; a = new AudioContext(); const t = () => { a.state === "suspended" && a.resume().then(() => { console.log("Audio context resumed"); }); }; s.forEach((o) => { window.addEventListener(o, t, { capture: !0 }); }); } function y() { return a; } p(); const d = 48e3; class x { constructor(t) { n(this, "audioBuffer", null); n(this, "audioSource", null); n(this, "previousSamplePosition", 0); n(this, "audioElapsedTime", 0); n(this, "audioContextPreviousTime", 0); n(this, "_motionSync", null); n(this, "_internalModel"); n(this, "_model"); n(this, "soundBuffer", new c()); this._internalModel = t, this._model = t.coreModel, u.startUp(new m()), u.initialize(); } get audioContext() { return y(); } async loadAudio(t) { const e = await (await fetch(t)).arrayBuffer(); this.reset(), this.audioBuffer = await this.audioContext.decodeAudioData(e); } async loadAudioBuffer(t) { this.reset(), this.audioBuffer = t; } resetMouthStatus() { try { if (!this._motionSync) return; const t = this._motionSync.getData().getSetting(0); if (!t) return; const o = t.cubismParameterList; if (!o) return; const e = o._ptr.map( (i) => i.parameterIndex ); for (const i of e) this._model.setParameterValueByIndex(i, 0); } catch (t) { console.error(t); } } reset() { this.resetMouthStatus(), this.audioSource && (this.audioSource.stop(), this.audioSource.disconnect(), this.audioSource = null), this.audioContextPreviousTime = 0, this.previousSamplePosition = 0, this.audioElapsedTime = 0, this.soundBuffer.clear(), this.soundBuffer = new c(); } async play(t) { return new Promise(async (o, e) => { typeof t == "string" ? await this.loadAudio(t) : await this.loadAudioBuffer(t), this.audioBuffer ? (this.audioSource = this.audioContext.createBufferSource(), this.audioSource.buffer = this.audioBuffer, this.audioSource.connect(this.audioContext.destination), this.audioSource.start(0), this.audioSource.onended = () => { o(); }, this.audioContextPreviousTime = this.audioContext.currentTime) : e(new Error("audioBuffer is null")); }); } updateMotionSync() { if (!this.audioBuffer || !this.audioSource) return; const t = this.audioContext.currentTime; t <= this.audioContextPreviousTime && (this.audioContextPreviousTime = t); const o = t - this.audioContextPreviousTime; this.audioElapsedTime += o; const e = Math.floor( this.audioElapsedTime * this.audioBuffer.sampleRate ); if (this.previousSamplePosition <= this.audioBuffer.length) { const i = this.audioBuffer.getChannelData(0).slice(this.previousSamplePosition, e); for (let r = 0; r < i.length; r++) this.soundBuffer.pushBack(i[r]); if (!this._motionSync) return; this._motionSync.setSoundBuffer(0, this.soundBuffer, 0), this._motionSync.updateParameters(this._model, o); const l = this._motionSync.getLastTotalProcessedCount(0); this.removeProcessedData(l), this.audioContextPreviousTime = t, this.previousSamplePosition = e; } } modelUpdateWithMotionSync() { if (!this._motionSync) return; const o = this._internalModel, e = o.motionManager.update; o.motionManager.update = (...i) => { e.apply(this._internalModel.motionManager, i), this.updateMotionSync(); }; } removeProcessedData(t) { const o = this.soundBuffer; if (t < o.getSize()) return !(o != null && o.begin()) || (o == null ? void 0 : o._size) <= t || (o._ptr.splice(0, t), o._size -= t), o; } loadMotionSync(t, o = d) { if (t == null || t.byteLength == 0) { console.warn("Failed to loadMotionSync()."); return; } this._motionSync = u.create( this._model, t, t.byteLength, o ), this.modelUpdateWithMotionSync(); } async loadDefaultMotionSync(t = d) { const e = await new Blob([S], { type: "application/json" }).arrayBuffer(); this.loadMotionSync(e, t); } async loadMotionSyncFromUrl(t, o = d) { try { const i = await (await fetch(t)).arrayBuffer(); this.loadMotionSync(i, o); } catch { console.warn("Failed to loadMotionSync(). Use default fallback."), await this.loadDefaultMotionSync(o); } } } export { x as MotionSync, y as getAudioContext, p as initAudioContext };