Last active
November 4, 2020 14:05
-
-
Save takumifukasawa/2e8354b8b6dd26fe4ed9897b4080a24c to your computer and use it in GitHub Desktop.
howler: manage audio for play, load, cache...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Howl, HowlOptions } from "howler"; | |
import { map } from "lodash"; | |
const caches = new Map<string | string[], Howl>(); | |
/** | |
* howlオブジェクトを生成してキャッシュする。。キャッシュの中にあったらキャッシュを返す | |
* | |
* @param {HowlOptions} options | |
* @returns {(Howl | null)} | |
*/ | |
function getAudio(options: HowlOptions): Howl | null { | |
if (!options.src) { | |
console.error("[audioActions] howler option has not src"); | |
return null; | |
} | |
const { src } = options; | |
console.log("[audioActions] current cache", caches); | |
if (caches.has(src)) { | |
return caches.get(src) || null; | |
} | |
const obj = new Howl(options); | |
caches.set(src, obj); | |
console.log("[audioActions] new cache", caches); | |
return obj; | |
} | |
/** | |
* 音声をロード | |
* | |
* @export | |
* @param {HowlOptions} options | |
* @returns {Promise<Howl>} | |
*/ | |
export async function loadAudio(options: HowlOptions): Promise<Howl> { | |
return new Promise((resolve, reject) => { | |
if (!options.src) { | |
reject(new Error("[audioActions] howler option has not src")); | |
return; | |
} | |
// for manually loading | |
if (typeof options.preload === "undefined") { | |
options.preload = false; | |
} | |
const obj = getAudio(options); | |
if (!obj) { | |
reject(new Error("[audioActions] has not howler obj")); | |
return; | |
} | |
const loadingState = obj.state(); | |
if (loadingState === "loaded" || loadingState === "loading") { | |
console.log( | |
`[audioActions] already ${loadingState} audio: ${options.src}` | |
); | |
resolve(obj); | |
return; | |
} | |
obj.once("load", () => { | |
console.log(`[audioActions] loaded audio: ${options.src}`); | |
resolve(obj); | |
}); | |
obj.once("loaderror", () => { | |
reject(new Error(`[audioActions] howler load error: ${options.src}`)); | |
}); | |
obj.load(); | |
}); | |
} | |
/** | |
* 音声群をロード | |
* | |
* @export | |
* @param {HowlOptions[]} data | |
* @returns {Promise<Howl[]>} | |
*/ | |
export async function loadAudios(data: HowlOptions[]): Promise<Howl[]> { | |
return Promise.all( | |
map(data, (options) => { | |
return loadAudio(options); | |
}) | |
); | |
} | |
/** | |
* 音声を再生し、howlerオブジェクトがキャッシュされる | |
* | |
* @export | |
* @param {HowlOptions} options | |
* @returns {(Howl | null)} | |
*/ | |
export function playAudio(options: HowlOptions): Howl | null { | |
if (!options.src) { | |
console.error("[audioActions] howler option has not src"); | |
return null; | |
} | |
console.log(`[audioActions] play audio: ${options.src}`); | |
options.preload = true; | |
const obj = getAudio(options); | |
if (!obj) { | |
console.error("[audioActions] has not howler obj"); | |
return null; | |
} | |
obj.seek(0); | |
obj.play(); | |
return obj; | |
} | |
/** | |
* 音声をreleaseし、キャッシュも削除 | |
* | |
* @export | |
* @param {HowlOptions} options | |
* @returns {void} | |
*/ | |
export function unloadAudio(options: HowlOptions): void { | |
if (!options.src) { | |
console.error("[audioActions] howler option has not src"); | |
return; | |
} | |
const { src } = options; | |
console.log(`[audioActions] unload audio: ${src}`); | |
const cachedObj = caches.get(src); | |
if (!cachedObj) { | |
return; | |
} | |
if (cachedObj.state() === "loaded") { | |
cachedObj.unload(); | |
} | |
caches.delete(src); | |
console.log("[audioActions] current audio caches", caches); | |
} | |
/** | |
* 音を一回だけ再生する。キャッシュしないのでただ再生だけしたい時用途 | |
* | |
* @export | |
* @param {HowlOptions} options | |
* @returns {(Howl | null)} | |
*/ | |
export function playOnceAudio(options: HowlOptions): Howl | null { | |
if (!options.src) { | |
console.error("[audioActions] howler option has not src"); | |
return null; | |
} | |
console.log(`[audioActions] play once audio: ${options.src}`); | |
options.preload = true; | |
const obj = new Howl(options); | |
obj.on("end", () => { | |
obj.unload(); | |
}); | |
obj.play(); | |
return obj; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment