mami/src/mami.js/audio/context.js

152 lines
4 KiB
JavaScript

#include utility.js
#include audio/buffer.js
#include audio/source.js
const MamiSRLEEncode = function(input, cutoff) {
let output = '', last = '', repeat = 0;
input = (input || '').toString();
cutoff = cutoff || 1
for(let i = 0; i <= input.length; ++i) {
const chr = input[i];
if(last === chr)
++repeat;
else {
if(repeat > cutoff)
for(const repChr in repeat.toString()) output += ')!@#$%^&*('[parseInt(repChr)];
else
output += last.repeat(repeat);
repeat = 0;
if(chr !== undefined) {
output += chr;
last = chr;
}
}
}
return output;
};
const MamiSRLEDecode = function(input) {
let output = '', repeat = '', chr;
input = (input || '').toString().split('').reverse();
for(;;) {
const chr = input.pop(), num = ')!@#$%^&*('.indexOf(chr);
if(num >= 0) repeat += num;
else {
if(repeat) {
output += output.slice(-1).repeat(parseInt(repeat));
repeat = '';
}
if(chr === undefined) break;
output += chr;
}
}
return output;
};
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,' + MamiSRLEDecode(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 = {};
let volume = null,
isMuted = false;
const ctxArgs = { latencyHint: 'playback' };
let ctx = null,
mainGain = null;
const init = function() {
const audObj = window.AudioContext || window.webkitAudioContext;
try {
ctx = new audObj(ctxArgs);
} catch(ex) {
ctx = new audObj;
}
mainGain = ctx.createGain();
if(volume === null) {
volume = mainGain.gain.defaultValue;
isMuted = false;
} else
mainGain.gain.value = isMuted ? 0 : volume;
mainGain.connect(ctx.destination);
};
init();
pub.getContext = function() { return ctx; };
pub.resetContext = init;
pub.useGain = function(callback) {
callback.call(pub, mainGain.gain);
};
pub.getVolume = function() {
return volume;
};
pub.setVolume = function(vol) {
volume = vol;
if(!isMuted)
mainGain.gain.value = volume;
};
pub.isMuted = function() {
return isMuted;
};
pub.setMuted = function(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));
};
const createSource = function(buffer) {
const gain = ctx.createGain();
gain.connect(mainGain);
const source = ctx.createBufferSource();
source.buffer = buffer;
source.connect(gain);
return new MamiAudioSource(source, gain);
};
pub.createSource = createSource;
return pub;
};