GGJ22/Engine/src/shared/audio.ts
2022-01-30 03:23:21 -08:00

117 lines
2.7 KiB
TypeScript

import assets from 'url:../../../Assets/Audio/**/*.ogg'
console.log('audio assets:', assets)
type Entry = { [key: string]: string | Entry }
export const audio: Record<string, string> = {}
function traverse(path: string, entry: Entry|string) {
if (typeof entry === 'string') {
audio[path] = entry
} else if (typeof entry === 'object') {
for (let [key, value] of Object.entries(entry)) {
traverse((path?path+'/':'')+key, value)
}
}
}
traverse('', assets)
export let enabled = true
export function enableSound() {
enabled = true
if (playingSongAudio) {
playingSongAudio.play()
}
}
export function disableSound() {
enabled = false
if (playingSongAudio) {
playingSongAudio.pause()
}
}
// Preload 'em
for (let [key, value] of (Object.entries(audio))) {
let audio = new Audio()
audio.addEventListener('canplaythrough', () => {
console.log('preloaded audio', key)
})
audio.preload = ''
audio.src = value
}
let audioCache: HTMLAudioElement[] = []
let playingSongAudio: HTMLAudioElement
export function playSong(name: string) {
if (!enabled) return
// Replace old audio and start crossfading.
if (playingSongAudio && !playingSongAudio.paused) {
;((playingSongAudio: HTMLAudioElement) => {
let cl = setInterval(() => {
if (Number(playingSongAudio.volume.toFixed(1)) > 0) {
playingSongAudio.volume -= 0.1
} else {
clearInterval(cl)
}
}, 50)
})(playingSongAudio)
}
playingSongAudio = new Audio()
playingSongAudio.autoplay = true
playingSongAudio.preload = ''
playingSongAudio.loop = true
playingSongAudio.volume = 0
// Start fade in.
;((playingSongAudio: HTMLAudioElement) => {
let cl = setInterval(() => {
if (playingSongAudio.paused) {
clearInterval(cl)
return
}
if (Number(playingSongAudio.volume.toFixed(1)) < 1.0) {
playingSongAudio.volume += 0.1
} else {
clearInterval(cl)
}
}, 50)
})(playingSongAudio)
playingSongAudio.src = audio[name]
let promise = playingSongAudio.play()
if (promise !== undefined) {
promise.then(() => {
// ok
}).catch((error: any) => {
//console.error(error)
})
}
}
export function playSound(name: string, volume: number): HTMLAudioElement|undefined {
if (!enabled) return
let s = audioCache.pop()
if (!s) {
s = new Audio()
s.autoplay = true
s.preload = ''
s.addEventListener('ended', () => {
audioCache.push(s as HTMLAudioElement)
})
}
s.src = audio[name]
s.volume = volume
let promise = s.play()
if (promise !== undefined) {
promise.then(() => {
// ok
}).catch((error: any) => {
})
}
return s
}