Rewrote heavy callback usage in sound backend to use async/await instead.

This commit is contained in:
Pachira 2024-02-09 22:38:57 +00:00
parent 719e03e607
commit 149cdac8ed
13 changed files with 218 additions and 500 deletions

View file

@ -0,0 +1,23 @@
#include srle.js
#include utility.js
const MamiDetectAutoPlaySource = '/+NIxA!!FhpbmcA#PA$wA@fgAV$#q$#/$#A#OUxBTUUzLjEwMAIeA!)UCCQC8CIA@gA@H49wpKWgA!%&/+MYxA$NIA$ExBTUUzLjEwMFV^%/+MYxDsA@NIA$FV&&/+MYxHYA@NIA$FV&&';
const MamiDetectAutoPlay = async () => {
try {
const audio = $e('audio', { src: 'data:audio/mpeg;base64,' + MamiSRLE.decode(MamiDetectAutoPlaySource) });
try {
await audio.play();
} catch(ex) {
if('name' in ex && ex.name !== 'NotAllowedError' && ex.name !== 'AbortError') {
console.error(ex);
throw ex;
}
return false;
}
} catch(ex) {}
return true;
};

View file

@ -1,10 +1,6 @@
const MamiAudioBuffer = function(ctx, buffer) {
return {
getBuffer: function() {
return buffer;
},
createSource: function() {
return ctx.createSource(buffer);
},
getBuffer: () => buffer,
createSource: () => ctx.createSource(buffer),
};
};

View file

@ -1,29 +1,7 @@
#include srle.js
#include utility.js
#include audio/buffer.js
#include audio/source.js
const MamiDetectAutoPlaySource = '/+NIxA!!FhpbmcA#PA$wA@fgAV$#q$#/$#A#OUxBTUUzLjEwMAIeA!)UCCQC8CIA@gA@H49wpKWgA!%&/+MYxA$NIA$ExBTUUzLjEwMFV^%/+MYxDsA@NIA$FV&&/+MYxHYA@NIA$FV&&';
const MamiDetectAutoPlay = async () => {
try {
const audio = $e('audio', { src: 'data:audio/mpeg;base64,' + MamiSRLE.decode(MamiDetectAutoPlaySource) });
try {
await audio.play();
} catch(ex) {
if('name' in ex && ex.name !== 'NotAllowedError' && ex.name !== 'AbortError') {
console.error(ex);
throw ex;
}
return false;
}
} catch(ex) {}
return true;
};
const MamiAudioContext = function() {
const pub = {};
@ -31,9 +9,9 @@ const MamiAudioContext = function() {
isMuted = false;
const ctxArgs = { latencyHint: 'playback' };
let ctx = null,
mainGain = null;
const init = function() {
let ctx = null;
let mainGain = null;
const init = () => {
const audObj = window.AudioContext || window.webkitAudioContext;
try {
ctx = new audObj(ctxArgs);
@ -52,45 +30,27 @@ const MamiAudioContext = function() {
};
init();
pub.getContext = function() { return ctx; };
pub.getContext = () => ctx;
pub.resetContext = init;
pub.useGain = function(callback) {
callback.call(pub, mainGain.gain);
};
pub.getVolume = function() {
return volume;
};
pub.setVolume = function(vol) {
pub.getVolume = () => volume;
pub.setVolume = vol => {
volume = vol;
if(!isMuted)
mainGain.gain.value = volume;
};
pub.isMuted = function() {
return isMuted;
};
pub.setMuted = function(mute) {
pub.isMuted = () => isMuted;
pub.setMuted = mute => {
mainGain.gain.value = (isMuted = mute) ? 0 : volume;
};
pub.createBuffer = function(url, callback) {
$x.get(url, { type: 'arraybuffer' })
.then(resp => {
try {
ctx.decodeAudioData(
resp.body(),
buffer => callback.call(pub, true, new MamiAudioBuffer(pub, buffer)),
error => callback.call(pub, false, error)
);
} catch(ex) {
callback.call(pub, false, ex);
}
})
.catch(err => callback.call(pub, false, err));
pub.createBuffer = async url => {
const result = await $x.get(url, { type: 'arraybuffer' });
const buffer = await ctx.decodeAudioData(result.body());
return new MamiAudioBuffer(pub, buffer);
};
const createSource = function(buffer) {
const createSource = buffer => {
const gain = ctx.createGain();
gain.connect(mainGain);

View file

@ -6,14 +6,17 @@ const MamiAudioSource = function(source, gain, buffer) {
let hasDisconnected = false;
pub.getSource = function() { return source; };
pub.getSource = () => source;
const play = function() {
source.start();
const play = () => {
return new Promise(resolve => {
source.addEventListener('ended', () => resolve());
source.start();
});
};
pub.play = play;
const disconnect = function() {
const disconnect = () => {
if(hasDisconnected)
return;
hasDisconnected = true;
@ -22,26 +25,14 @@ const MamiAudioSource = function(source, gain, buffer) {
source.disconnect();
};
const stop = function() {
const stop = () => {
source.stop();
disconnect();
};
pub.stop = stop;
pub.useGain = function(callback) {
callback.call(pub, gain.gain);
};
pub.usePlaybackRate = function(callback) {
callback.call(pub, source.playbackRate);
};
pub.useDetune = function(callback) {
callback.call(pub, source.detune);
};
pub.getRate = function(rate) {
return source.playbackRate.value;
};
pub.setRate = function(rate) {
pub.getRate = () => source.playbackRate.value;
pub.setRate = rate => {
source.playbackRate.value = Math.min(
source.playbackRate.maxValue,
Math.max(
@ -50,10 +41,8 @@ const MamiAudioSource = function(source, gain, buffer) {
)
);
};
pub.getDetune = function(rate) {
return source.detune.value;
};
pub.setDetune = function(rate) {
pub.getDetune = () => source.detune.value;
pub.setDetune = rate => {
source.detune.value = Math.min(
source.detune.maxValue,
Math.max(
@ -63,44 +52,26 @@ const MamiAudioSource = function(source, gain, buffer) {
);
};
pub.getVolume = function() {
return volume;
};
pub.setVolume = function(vol) {
pub.getVolume = () => volume;
pub.setVolume = vol => {
volume = vol;
if(!isMuted)
gain.gain.value = volume;
};
pub.isMuted = function() {
return isMuted;
};
pub.setMuted = function(mute) {
pub.isMuted = () => isMuted;
pub.setMuted = mute => {
gain.gain.value = (isMuted = mute) ? 0 : volume;
};
pub.setLoop = function(loop) {
if(typeof loop !== 'boolean')
loop = true;
source.loop = loop;
};
pub.setLoopStart = function(start) {
if(typeof start !== 'number')
start = 0;
source.loopStart = start;
};
pub.setLoopEnd = function(end) {
if(typeof end !== 'number')
end = 0;
source.loopEnd = end;
pub.setLoop = (loop, start, end) => {
if(typeof start === 'number')
source.loopStart = start;
if(typeof end === 'number')
source.loopEnd = end;
source.loop = !!loop;
};
pub.whenEnded = function(handler) {
source.addEventListener('ended', handler.bind(pub));
};
source.addEventListener('ended', function() {
disconnect();
});
source.addEventListener('ended', () => disconnect());
return pub;
};

View file

@ -28,7 +28,8 @@ const MamiContext = function(targetBody) {
};
pub.initAudio = initAudio;
let soundMgr = null, sndPckPlay = null;
let soundMgr = null;
let sndPckPlay = null;
const soundLib = new MamiSoundLibrary(),
soundPck = new MamiSoundPacks();
@ -47,102 +48,35 @@ const MamiContext = function(targetBody) {
pub.getSoundPacks = function() { return soundPck; };
pub.getSoundPackPlayer = function() { return sndPckPlay; };
pub.playUrlSound = function(soundSources, complete, volume, rate) {
if(soundMgr === null)
return;
const hasCallback = typeof complete === 'function';
try {
const soundUrl = soundMgr.findSupportedUrl(soundSources);
if(soundUrl === null)
return;
const soundName = 'MamiCtx:' + soundUrl;
if(soundMgr.isLoaded(soundName)) {
const source = soundMgr.get(soundName);
if(hasCallback)
source.whenEnded(function() {
complete();
});
if(typeof volume === 'number')
source.setVolume(volume);
if(typeof rate === 'number')
source.setRate(rate);
source.play();
} else {
soundMgr.load(soundName, soundUrl, function(success, buffer) {
if(success) {
const source = buffer.createSource();
if(hasCallback)
source.whenEnded(function() {
complete();
});
if(typeof volume === 'number')
source.setVolume(volume);
if(typeof rate === 'number')
source.setRate(rate);
source.play();
} else {
console.error(buffer);
if(hasCallback)
complete();
}
});
}
} catch(ex) {
console.error(ex);
if(hasCallback)
complete();
}
const playSoundBuffer = async (buffer, volume, rate) => {
const source = buffer.createSource();
if(typeof volume === 'number')
source.setVolume(volume);
if(typeof rate === 'number')
source.setRate(rate);
await source.play();
};
pub.playLibrarySound = function(soundName, complete, volume, rate) {
pub.playUrlSound = async (sources, volume, rate) => {
if(soundMgr === null)
return;
const hasCallback = typeof complete === 'function';
const url = soundMgr.findSupportedUrl(sources);
if(url === null)
return;
try {
const soundInfo = soundLib.getSound(soundName);
const buffer = await soundMgr.load(`MamiCtx:${url}`, url);
await playSoundBuffer(buffer, volume, rate);
};
if(soundMgr.isLoaded(soundName)) {
const source = soundMgr.get(soundName);
if(hasCallback)
source.whenEnded(function() {
complete();
});
if(typeof volume === 'number')
source.setVolume(volume);
if(typeof rate === 'number')
source.setRate(rate);
source.play();
} else {
soundMgr.load(soundName, soundInfo.getSources(), function(success, buffer) {
if(success) {
const source = buffer.createSource();
if(hasCallback)
source.whenEnded(function() {
complete();
});
if(typeof volume === 'number')
source.setVolume(volume);
if(typeof rate === 'number')
source.setRate(rate);
source.play();
} else {
console.error(buffer);
if(hasCallback)
complete();
}
});
}
} catch(ex) {
console.error(ex);
if(hasCallback)
complete();
}
pub.playLibrarySound = async (name, volume, rate) => {
if(soundMgr === null)
return;
const soundInfo = soundLib.getSound(name);
const buffer = await soundMgr.load(soundInfo.getName(), soundInfo.getSources());
await playSoundBuffer(buffer, volume, rate);
};
const txtTriggers = new MamiTextTriggers;

View file

@ -9,6 +9,7 @@ const Umi = { UI: {} };
#include server.js
#include utility.js
#include weeb.js
#include audio/autoplay.js
#include audio/context.js
#include eeprom/eeprom.js
#include settings/backup.js
@ -248,10 +249,8 @@ const Umi = { UI: {} };
const mcPortalSnd = 'minecraft:nether:enter';
if(settings.get('minecraft') !== 'no' && ctx.hasSound() && sndLib.hasSound(mcPortalSnd))
ctx.getSound().load(mcPortalSnd, sndLib.getSound(mcPortalSnd).getSources(), function(success, buffer) {
if(success)
buffer.createSource().play();
});
ctx.getSound().load(mcPortalSnd, sndLib.getSound(mcPortalSnd).getSources())
.then(buffer => buffer.createSource().play());
settings.watch('minecraft', (v, n, i) => {
if(!i)

View file

@ -107,17 +107,10 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
const urls = {
mp3: '//static.flash.moe/sounds/touhou-death.mp3',
ogg: '//static.flash.moe/sounds/touhou-death.ogg'
ogg: '//static.flash.moe/sounds/touhou-death.ogg',
};
mami.getSound().load('banSFX', urls, function(success, buffer) {
if(!success) {
console.log('Failed to load kick/ban SFX: ' + buffer);
return;
}
buffer.createSource().play();
});
mami.getSound().load('banSFX', urls).then(buffer => buffer.createSource().play());
};
const playBannedBgm = function(preload) {
if(!mami.hasSound())
@ -128,19 +121,13 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
caf: '//static.flash.moe/sounds/players-score.caf'
};
mami.getSound().load('banBGM', urls, function(success, buffer) {
if(!success) {
console.log('Failed to load kick/ban SFX: ' + buffer);
mami.getSound().load('banBGM', urls).then(buffer => {
if(preload)
return;
}
if(!preload) {
const source = buffer.createSource();
source.setLoopStart(10.512);
source.setLoopEnd(38.074);
source.setLoop();
source.play();
}
const source = buffer.createSource();
source.setLoop(true, 10.512, 38.074);
source.play();
});
};
@ -595,7 +582,6 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
sound = '';
mami.playLibrarySound(
trigger.getRandomSoundName(),
null,
trigger.getVolume(),
trigger.getRate()
);

View file

@ -1,72 +1,50 @@
#include rng.js
const OsuKeys = (function() {
const OsuKeys = (() => {
const urlBase = '//static.flash.moe/sounds/';
const rng = new MamiRNG;
let sndRng = false;
const playSound = function(name) {
const playSound = async name => {
if(!mami.hasSound())
return;
const soundMgr = mami.getSound();
const urls = {
ogg: urlBase + name + '.ogg',
mp3: urlBase + name + '.mp3',
};
mami.getSound().load('OsuKeys:' + name, urls, function(success, buffer) {
if(success) {
const source = buffer.createSource();
if(sndRng)
source.setRate(1.8 - (rng.sample() * 1.5));
source.play();
}
});
const buffer = await soundMgr.load('OsuKeys:' + name, urls);
const source = buffer.createSource();
if(sndRng)
source.setRate(1.8 - (rng.sample() * 1.5));
await source.play();
};
const playPress = function() { playSound('key-press-' + rng.next(1, 5).toString()); };
const playCaps = function() { playSound('key-caps'); };
const playConfirm = function() { playSound('key-confirm'); };
const playDelete = function() { playSound('key-delete'); };
const playMove = function() { playSound('key-movement'); };
const keyHandler = ev => {
if(ev.key === 'Control' || ev.key === 'Alt' || ev.key === 'Shift')
return;
const keyHandler = function(ev) {
switch(ev.key) {
case 'Enter':
case 'NumpadEnter':
playConfirm();
break;
case 'Backspace':
case 'Delete':
playDelete();
break;
case 'NumLock':
case 'CapsLock':
case 'ScrollLock':
playCaps();
break;
case 'ArrowUp':
case 'ArrowDown':
case 'ArrowLeft':
case 'ArrowRight':
playMove();
break;
case 'Control':
case 'Alt':
case 'Shift':
break;
default:
playPress();
break;
}
let soundName;
if(ev.key === 'Enter' || ev.key === 'NumpadEnter')
soundName = 'key-confirm';
else if(ev.key === 'Backspace' || ev.key === 'Delete')
soundName = 'key-delete';
else if(ev.key === 'NumLock' || ev.key === 'CapsLock' || ev.key === 'ScrollLock')
soundName = 'key-caps';
else if(ev.key === 'ArrowUp' || ev.key === 'ArrowDown' || ev.key === 'ArrowLeft' || ev.key === 'ArrowRight')
soundName = 'key-movement';
else
soundName = `key-press-${rng.next(1, 5)}`;
playSound(soundName);
};
return {
playConfirm: playConfirm,
playDelete: playDelete,
playCaps: playCaps,
playMove: playMove,
playPress: playPress,
setEnable: function(value) {
if(value)
window.addEventListener('keydown', keyHandler);

View file

@ -5,32 +5,24 @@ const MamiSoundInfo = function(name, isReadOnly, title, sources) {
sources = sources || {};
return {
getName: function() {
return name;
},
isReadOnly: function() {
return isReadOnly;
},
getTitle: function() {
return title;
},
getSources: function() {
return sources;
},
getName: () => name,
isReadOnly: () => isReadOnly,
getTitle: () => title,
getSources: () => sources,
};
};
const MamiSoundLibrary = function() {
const sounds = new Map;
const addSound = function(soundInfo) {
const addSound = soundInfo => {
if(sounds.has(soundInfo.getName()))
throw 'a sound with that name has already been registered';
sounds.set(soundInfo.getName(), soundInfo);
};
const loadSoundFormats = ['opus', 'caf', 'ogg', 'mp3', 'wav'];
const loadSound = function(soundInfo, readOnly) {
const loadSound = (soundInfo, readOnly) => {
if(typeof soundInfo !== 'object')
throw 'soundInfo must be an object';
if(typeof soundInfo.name !== 'string')
@ -56,25 +48,23 @@ const MamiSoundLibrary = function() {
return {
addSound: addSound,
loadSound: loadSound,
loadSounds: function(soundInfos, readOnly) {
loadSounds: (soundInfos, readOnly) => {
for(const soundInfo of soundInfos)
loadSound(soundInfo, readOnly);
},
removeSound: function(name) {
removeSound: name => {
sounds.delete(name);
},
clearSounds: function() {
clearSounds: () => {
sounds.clear();
},
forEachSound: function(body) {
forEachSound: body => {
if(typeof body !== 'function')
return;
sounds.forEach(body);
},
hasSound: function(name) {
return sounds.has(name);
},
getSound: function(name) {
hasSound: name => sounds.has(name),
getSound: name => {
if(!sounds.has(name))
throw 'No sound with this name has been registered.';
return sounds.get(name);

View file

@ -3,156 +3,87 @@
#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 probablySupported = [];
const maybeSupported = [];
const 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);
const format = formats[name];
const support = elem.canPlayType(format);
if(support === 'probably')
supported.push(name);
probablySupported.push(name);
else if(support === 'maybe')
fallback.push(name);
maybeSupported.push(name);
}
})();
const pub = {};
const findSupportedUrl = function(urls) {
const findSupportedUrl = urls => {
if(typeof urls === 'string')
return urls;
// lol we're going backwards again
if(Array.isArray(urls)) {
const tmp = urls;
urls = {};
for(const type of probablySupported)
if(type in urls && typeof urls[type] === 'string')
return urls[type];
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;
}
}
for(const type of maybeSupported)
if(type in urls && typeof urls[type] === 'string')
return urls[type];
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;
return null;
};
pub.findSupportedUrl = findSupportedUrl;
pub.loadAnonymous = function(urls, callback) {
pub.loadAnonymous = async urls => {
const url = findSupportedUrl(urls);
if(url === null) {
callback.call(pub, false, 'No supported audio format could be determined.');
return;
}
if(url === null)
throw 'No supported audio format could be determined.';
context.createBuffer(url, function(success, buffer) {
callback.call(pub, success, buffer);
});
return await context.createBuffer(url);
};
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;
}
pub.load = async (name, urls) => {
if(loaded.has(name))
return loaded.get(name);
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;
}
if(url === null)
throw 'No supported audio format could be determined.';
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;
}
const buffer = await context.createBuffer(url);
loaded.set(name, buffer);
loaded.set(name, buffer);
if(hasCallback)
callback.call(pub, success, buffer);
});
return buffer;
};
pub.unload = function(name) {
pub.unload = name => {
loaded.delete(name);
};
pub.reset = function() {
pub.reset = () => {
loaded.clear();
};
pub.play = function(name) {
pub.play = name => {
if(loaded.has(name))
loaded.get(name).createSource().play();
};
pub.isLoaded = function(name) {
return loaded.has(name);
};
pub.isLoaded = name => loaded.has(name);
pub.get = function(name) {
pub.get = name => {
if(!loaded.has(name))
return null;
return loaded.get(name).createSource();

View file

@ -7,44 +7,34 @@ const MamiSoundPack = function(name, isReadOnly, title, events) {
events = events || new Map;
return {
getName: function() {
return name;
},
isReadOnly: function() {
return isReadOnly;
},
getTitle: function() {
return title;
},
setTitle: function(newTitle) {
getName: () => name,
isReadOnly: () => isReadOnly,
getTitle: () => title,
setTitle: newTitle => {
if(isReadOnly)
throw 'Cannot edit read only sound pack.';
title = (newTitle || '').toString();
},
getEventNames: function() {
return Array.from(events.keys());
},
hasEventSound: function(eventName) {
return events.has(eventName);
},
getEventSound: function(eventName) {
getEventNames: () => Array.from(events.keys()),
hasEventSound: eventName => events.has(eventName),
getEventSound: eventName => {
if(!events.has(eventName))
throw 'event not registered';
return events.get(eventName);
},
setEventSound: function(eventName, soundName) {
setEventSound: (eventName, soundName) => {
events.set(
(eventName || '').toString(),
(soundName || '').toString()
);
},
removeEventSound: function(eventName) {
removeEventSound: eventName => {
events.delete(eventName);
},
clearEventSounds: function() {
clearEventSounds: () => {
events.clear();
},
clone: function(newName, readOnly) {
clone: (newName, readOnly) => {
return new MamiSoundPack(newName, readOnly, 'Clone of ' + title, new Map(events));
},
};
@ -54,40 +44,22 @@ const MamiSoundPackPlayer = function(soundMgr, sndLibrary) {
const pub = {};
let pack = null;
pub.loadPack = function(packInfo) {
pub.loadPack = packInfo => {
if(typeof pack !== 'object' && typeof pack.getEventSound !== 'function')
throw 'pack is not a valid soundpack';
pack = packInfo;
};
pub.unloadPack = function() {
pub.unloadPack = () => {
pack = null;
buffers.clear();
};
pub.hasPack = function() {
return pack !== null;
};
pub.hasPack = () => pack !== null;
const playSource = function(source, hasCallback, callback) {
if(hasCallback)
source.whenEnded(function() {
callback(true);
});
source.play();
};
pub.hasEvent = eventName => pack !== null && pack.hasEventSound(eventName);
const handlePlayError = function(ex, hasCallback, callback) {
console.error(ex);
if(hasCallback)
callback(false, ex);
};
pub.hasEvent = function(eventName) {
return pack !== null && pack.hasEventSound(eventName);
};
pub.playEvent = function(eventName, callback) {
pub.playEvent = async eventName => {
if(pack === null)
return;
@ -107,25 +79,10 @@ const MamiSoundPackPlayer = function(soundMgr, sndLibrary) {
} else if(!pack.hasEventSound(eventName))
return;
const hasCallback = typeof callback === 'function';
const info = sndLibrary.getSound(pack.getEventSound(eventName));
const buffer = await soundMgr.load(info.getName(), info.getSources());
try {
const soundInfo = sndLibrary.getSound(pack.getEventSound(eventName)),
soundName = soundInfo.getName();
if(soundMgr.isLoaded(soundName)) {
playSource(soundMgr.get(soundName), hasCallback, callback);
} else {
soundMgr.load(soundName, soundInfo.getSources(), function(success, buffer) {
if(success)
playSource(buffer.createSource(), hasCallback, callback);
else
handlePlayError(buffer, hasCallback, callback);
});
}
} catch(ex) {
handlePlayError(ex, hasCallback, callback);
}
await buffer.createSource().play();
};
return pub;
@ -134,13 +91,13 @@ const MamiSoundPackPlayer = function(soundMgr, sndLibrary) {
const MamiSoundPacks = function() {
const packs = new Map;
const addPack = function(packInfo) {
const addPack = packInfo => {
if(packs.has(packInfo.getName()))
throw 'a pack with that name has already been registered';
packs.set(packInfo.getName(), packInfo);
};
const loadPack = function(packInfo, readOnly) {
const loadPack = (packInfo, readOnly) => {
if(typeof packInfo !== 'object')
throw 'packInfo must be an object';
if(typeof packInfo.name !== 'string')
@ -169,25 +126,23 @@ const MamiSoundPacks = function() {
return {
addPack: addPack,
loadPack: loadPack,
loadPacks: function(packInfos, readOnly) {
loadPacks: (packInfos, readOnly) => {
for(const packInfo of packInfos)
loadPack(packInfo, readOnly);
},
removePack: function(name) {
removePack: name => {
packs.delete(name);
},
clearPacks: function() {
clearPacks: () => {
packs.clear();
},
forEachPack: function(body) {
forEachPack: body => {
if(typeof body !== 'function')
return;
packs.forEach(body);
},
hasPack: function(name) {
return packs.has(name);
},
getPack: function(name) {
hasPack: name => packs.has(name),
getPack: name => {
if(!packs.has(name))
throw 'No pack with this name has been registered.';
return packs.get(name);

View file

@ -2,9 +2,9 @@
#include sound/sndpacks.js
#include sound/seinfeld.js
Umi.Sound = (function() {
Umi.Sound = (() => {
return {
Play: function(sound) {
Play: sound => {
if(!sound || sound === 'none' || !mami.hasSound())
return;

View file

@ -19,27 +19,22 @@ const MamiYouAreAnIdiot = function() {
const pub = {
getElement: () => html,
onViewPush: () => {
return new Promise(resolve => {
const soundMgr = mami.getSound();
if(soundMgr === undefined || soundMgr === null) {
resolve();
return;
}
onViewPush: async () => {
const soundMgr = mami.getSound();
if(soundMgr === undefined || soundMgr === null)
return;
const soundSrcs = mami.getSoundLibrary().getSound('misc:youare').getSources();
soundMgr.load('youarebgm', soundSrcs, (success, buffer) => {
if(success) {
soundSrc = buffer.createSource();
soundSrc.setMuted(true);
soundSrc.setLoopStart(0.21);
soundSrc.setLoopEnd(5);
soundSrc.setLoop();
soundSrc.play();
resolve();
} else resolve();
});
});
try {
const sources = mami.getSoundLibrary().getSound('misc:youare').getSources();
const buffer = await soundMgr.load('youarebgm', sources);
soundSrc = buffer.createSource();
soundSrc.setMuted(true);
soundSrc.setLoop(true, 0.21, 5);
soundSrc.play();
} catch(ex) {
console.error(ex);
}
},
onViewForeground: async () => {
if(soundSrc !== undefined)