import * as dict from 'lib/dict' export type Sounds = Record export enum Sound { Crash, Ride, TomHigh, TomMedium, TomFloor, HitHatOpen, HitHatClosed, Snare, Kick, } export function all(): Array { return dict.values(Sound) } export function record(f: (sound: Sound) => T): Record { let res: any = {} all().forEach(async sound => { res[sound] = f(sound) }) return (res as Record) } export function toString(sound: Sound): string { switch (sound) { case Sound.Kick: return 'Kick' case Sound.Snare: return 'Snare' case Sound.HitHatOpen: return 'Hit-hat open' case Sound.HitHatClosed: return 'Hit-hat closed' case Sound.Ride: return 'Ride' case Sound.Crash: return 'Crash' case Sound.TomFloor: return 'Tom floor' case Sound.TomMedium: return 'Tom medium' case Sound.TomHigh: return 'Tom high' default: throw `Sound ${sound} is unknown.` } } const audioContext = new AudioContext() let lazy: undefined | Sounds = undefined export async function load(): Promise { if (lazy !== undefined) { return lazy } else { let sounds = dict.fromList(await Promise.all(dict.toList(record(fetchSound)).map(async obj => { let value = await obj.value return { key: obj.key, value } }))) as Sounds lazy = sounds return sounds } } async function fetchSound(sound: Sound): Promise { return await fetch(path(sound)) .then(res => res.arrayBuffer()) .then(ArrayBuffer => audioContext.decodeAudioData(ArrayBuffer)) } function path(sound: Sound): string { switch (sound) { case Sound.Kick: return 'sounds/kick.opus' case Sound.Snare: return 'sounds/snare.opus' case Sound.HitHatOpen: return 'sounds/hit-hat-open.opus' case Sound.HitHatClosed: return 'sounds/hit-hat-closed.opus' case Sound.Ride: return 'sounds/ride.opus' case Sound.Crash: return 'sounds/crash.opus' case Sound.TomFloor: return 'sounds/tom-floor.opus' case Sound.TomMedium: return 'sounds/tom-medium.opus' case Sound.TomHigh: return 'sounds/tom-high.opus' default: throw `Sound ${sound} is unknown.` } } export function play(sounds: Sounds, sound: Sound): void { const source = audioContext.createBufferSource() source.buffer = sounds[sound] source.connect(audioContext.destination) source.start() }