No Audio on Iphone and iPad (including fix)
Posted: 26 June 2021, 21:26
Hi all,
There have been bugs filed about not having iPhone or iPad audio, and they get closed all the time as works for me, where in fact it does not. I think about 30% of the community at least uses these devices, so it is quite bad. So I dug a little into what was going on myself. So the issue is that mobile browsers on iOS need to be activated with a user action like a touch or a hover before it will start playing audio. Outside that it just does not work throwing exceptions; I saw that when I had my iPad on the debug cable. With some experimenting I managed to create a little 'hack', that also uses the AudioBuffer instead of the current way of HTML5 embedding. I could not find any git repo to contribute to so, I decided to put it here, in the hope that someone of the platform will pick it up, and fixes the audio (thank you!).
This will work by the way out of the box when you just include this as js, but i can imagine one would in the end want to improve the SoundManager itself.
There have been bugs filed about not having iPhone or iPad audio, and they get closed all the time as works for me, where in fact it does not. I think about 30% of the community at least uses these devices, so it is quite bad. So I dug a little into what was going on myself. So the issue is that mobile browsers on iOS need to be activated with a user action like a touch or a hover before it will start playing audio. Outside that it just does not work throwing exceptions; I saw that when I had my iPad on the debug cable. With some experimenting I managed to create a little 'hack', that also uses the AudioBuffer instead of the current way of HTML5 embedding. I could not find any git repo to contribute to so, I decided to put it here, in the hope that someone of the platform will pick it up, and fixes the audio (thank you!).
This will work by the way out of the box when you just include this as js, but i can imagine one would in the end want to improve the SoundManager itself.
Code: Select all
/iP(hone|od|ad)/.test(navigator.platform) &&
(function () {
console.log("Init Audio Context");
AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContext();
var audioGain = audioContext.createGain();
var buffers = {};
audioGain.gain.value=1;
window.audioContext = audioContext;
const body = document.getElementsByTagName('body')[0];
var audioUnlocked = false;
function playBuffer(buffer) {
var source = audioContext.createBufferSource();
source.buffer = buffer;
source.connect(audioGain);
audioGain.connect(audioContext.destination);
source.start(0);
}
function setGain( level ) {
audioGain.gain.value=level;
}
function loadAudioFile(key, url, callback) {
var request = new XMLHttpRequest();
request.open ('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function () {
audioContext.decodeAudioData(request.response, function(audiodata) {
buffers[key] = audiodata;
if (typeof callback == "function") callback(buffers[key]);
});
//console.log("Loaded file" + url );
};
request.send();
}
function unlockAudio() {
// Run Once:
if (audioUnlocked) return;
audioUnlocked = true;
body.removeEventListener('click', unlockAudio);
body.removeEventListener('touchstart', unlockAudio);
body.removeEventListener('hover', unlockAudio);
// Unlock audioContext by playing 0-length buffer:
playBuffer(audioContext.createBuffer(1, 1, 22050));
console.log("Unlocked AudioContext.");
}
body.addEventListener('click', unlockAudio);
body.addEventListener('touchstart', unlockAudio);
body.addEventListener('hover', unlockAudio);
// SoundManager stuffing.
soundManager.buffers = buffers;
soundManager.soundBaseUrl = (new DOMParser()).parseFromString(jstpl_audiosrc,"text/xml").children[0].getAttribute('src');
soundManager.loadSound= function(t, callback) {
if (t in buffers) return;
var url = this.soundBaseUrl.replace("${file}", t) + (this.useOgg ? ".ogg" : ".mp3");
loadAudioFile(t, url, callback);
};
soundManager.doPlay = function(t) {
if (this.bMuteSound) return;
soundManager.doPlayFile(soundManager.getSoundIdFromEvent(t.id));
};
soundManager.doPlayFile = function(t) {
if (t in buffers) {
setGain( soundManager.volume );
playBuffer(buffers[t]);
} else {
soundManager.loadSound(t, function(b) {
playBuffer(buffers[t]);
});
}
};
})();