mami/src/mami.js/sound/sndlibrary.js

94 lines
2.9 KiB
JavaScript

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();
},
};
};