mami/src/mami.js/sound/sndmgr.js

163 lines
4.3 KiB
JavaScript

#include utility.js
#include sound/sndlibrary.js
#include sound/sndpacks.js
const MamiSoundManager = function(context) {
const supported = [], fallback = [],
formats = {
opus: 'audio/ogg;codecs=opus',
ogg: 'audio/ogg;codecs=vorbis',
mp3: 'audio/mpeg;codecs=mp3',
caf: 'audio/x-caf;codecs=opus',
wav: 'audio/wav',
};
const loaded = new Map;
(function() {
const elem = $e('audio');
for(const name in formats) {
const format = formats[name], support = elem.canPlayType(format);
if(support === 'probably')
supported.push(name);
else if(support === 'maybe')
fallback.push(name);
}
})();
const pub = {};
const findSupportedUrl = function(urls) {
if(typeof urls === 'string')
return urls;
// lol we're going backwards again
if(Array.isArray(urls)) {
const tmp = urls;
urls = {};
for(const item of tmp) {
let type = null;
if(item.type)
type = item.type;
else {
switch(item.format) {
case 'audio/mpeg':
case 'audio/mp3':
type = 'mp3';
break;
case 'audio/ogg': // could also be opus, oops!
type = 'ogg';
break;
case 'audio/opus': // isn't real lol
type = 'opus';
break;
case 'audio/x-caf':
type = 'caf';
break;
}
}
if(type === null || type === undefined)
continue;
urls[type] = item.url;
}
}
// check "probably" formats
let url = null;
for(const type of supported) {
if(type in urls) {
url = urls[type];
break;
}
}
// check "maybe" formats
if(url === null)
for(const type of fallback) {
if(type in urls) {
url = urls[type];
break;
}
}
return url;
};
pub.findSupportedUrl = findSupportedUrl;
pub.loadAnonymous = function(urls, callback) {
const url = findSupportedUrl(urls);
if(url === null) {
callback.call(pub, false, 'No supported audio format could be determined.');
return;
}
context.createBuffer(url, function(success, buffer) {
callback.call(pub, success, buffer);
});
};
pub.load = function(name, urls, callback) {
const hasCallback = typeof callback === 'function';
if(loaded.has(name)) {
if(hasCallback)
callback.call(pub, true, loaded.get(name));
return;
}
const url = findSupportedUrl(urls);
if(url === null) {
const msg = 'No supported audio format could be determined.';
if(hasCallback)
callback.call(pub, false, msg);
else
throw msg;
return;
}
context.createBuffer(url, function(success, buffer) {
if(!success) {
if(hasCallback)
callback.call(pub, success, buffer);
else // not actually sure if this will do anything but maybe it'll show in the console
throw buffer;
return;
}
loaded.set(name, buffer);
if(hasCallback)
callback.call(pub, success, buffer);
});
};
pub.unload = function(name) {
loaded.delete(name);
};
pub.reset = function() {
loaded.clear();
};
pub.play = function(name) {
if(loaded.has(name))
loaded.get(name).createSource().play();
};
pub.isLoaded = function(name) {
return loaded.has(name);
};
pub.get = function(name) {
if(!loaded.has(name))
return null;
return loaded.get(name).createSource();
};
return pub;
};