const MamiSoundInfo = function(name, isReadOnly, title, sources) { name = (name || '').toString(); isReadOnly = !!isReadOnly; title = (title || ('Nameless Sound (' + name + ')')).toString(); sources = sources || {}; return { getName: () => name, isReadOnly: () => isReadOnly, getTitle: () => title, getSources: () => sources, }; }; const MamiSoundLibrary = function(soundMgr) { if(typeof soundMgr !== 'object' && typeof soundMgr.loadSource !== 'function') throw 'soundMgr must be an instance of MamiSoundManager'; const sounds = new Map; const soundFormats = ['opus', 'caf', 'ogg', 'mp3', 'wav']; const registerSound = (soundInfo, readOnly) => { if(Array.isArray(soundInfo)) { for(const info of soundInfo) registerSound(info, readOnly); return; } if(typeof soundInfo !== 'object') throw 'soundInfo must be an object'; if(typeof soundInfo.name !== 'string') throw 'soundInfo must contain a name field'; if(typeof soundInfo.sources !== 'object') throw 'soundInfo must contain a sources field'; let sources = {}, sCount = 0; for(const fmt of soundFormats) { if(typeof soundInfo.sources[fmt] !== 'string') continue; sources[fmt] = soundInfo.sources[fmt]; ++sCount; } if(sCount < 1) throw 'soundInfo does not contain any valid sources'; soundInfo = new MamiSoundInfo(soundInfo.name, readOnly, soundInfo.title, sources); sounds.set(soundInfo.getName(), soundInfo); return soundInfo; }; const getSound = name => { if(!sounds.has(name)) throw 'No sound with this name has been registered.'; return sounds.get(name); }; const getSoundSources = name => getSound(name).getSources(); const loadSoundSource = async name => await soundMgr.loadSource(getSoundSources(name)); return { register: registerSound, unregister: name => { sounds.delete(name); }, clear: () => { sounds.clear(); }, info: name => getSound(name), names: () => Array.from(sounds.keys()), has: name => sounds.has(name), get: getSound, getSources: getSoundSources, loadBuffer: async name => await soundMgr.loadBuffer(getSoundSources(name)), loadSource: loadSoundSource, play: async (name, volume, rate) => { if(typeof name !== 'string') return; const source = await loadSoundSource(name); if(typeof volume === 'number') source.setVolume(volume); if(typeof rate === 'number') source.setRate(rate); await source.play(); }, }; };