'AudioContext.decodeAudioData(...) not working on iPhone but working everywhere else
I have the following very basic code which is part of a more complex problem.
My problem here is the function: context.decodeAudioData(arrayBuffer) is not working on iPhone (tried on Safari and Chrome) nor Mac (Safari), but it works everywhere else (Android and Windows 10 (all browsers). Even it works on Mac (Chrome).
On Mac (Safari) I get the following error:
Unhandled Promise Rejection: TypeError: Not enough arguments
Here is the code:
window.AudioContext = window.AudioContext || window.webkitAudioContext;
const context = new AudioContext();
window.addEventListener('load', function() {
const button_option_1 = document.querySelector('.button_option_1');
const button_option_1_play = document.querySelector('.button_option_1_play');
button_option_1_play.disabled = true;
button_option_1.addEventListener('click', async function() {
log('', false);
let buffer;
button_option_1_play.disabled = true;
button_option_1_play.onclick = () => playBuffer(buffer);
let time_start = new Date().getTime();
let b64 = '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TPwKKiT1etICF/6hcjitTEFNRTMuOTkuNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTEFNRTMu//NExNwRaHo0AMJMSDk5LjVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTEFNRTMu//NExOkUKLnAANDGTDk5LjVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTEFNRTMu//NExKwAAANIAAAAADk5LjVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTEFNRTMu//NExKwAAANIAAAAADk5LjVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NExKwAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NExKwAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV';
arrayBuffer = base64ToArrayBuffer(b64);
time_start = new Date().getTime();
let audioBuffer = await context.decodeAudioData(arrayBuffer);
let duration = sprintf('%.2fs', (new Date().getTime() - time_start) / 1000);
log(sprintf('P3. Delay: +%s for decoding.', duration));
button_option_1_play.disabled = false;
buffer = audioBuffer;
button_option_1_play.click();
});
});
function playBuffer(buffer, from, duration) {
const source = context.createBufferSource(); // source: AudioBufferSourceNode
source.buffer = buffer;
source.connect(context.destination);
source.start(context.currentTime, from, duration);
}
function log(text, append = true) {
let log = document.querySelector('.log');
if (!append)
log.innerHTML = '';
let entry = document.createElement('div');
entry.innerHTML = text;
log.appendChild(entry);
}
function base64ToArrayBuffer(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
.log {
display: inline-block;
font-family: "Courier New", Courier, monospace;
font-size: 13px;
margin-top: 10px;
padding: 4px;
background-color: #d4e4ff;
}
.divider {
border-top: 1px solid #ccc;
margin: 10px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/sprintf/1.1.1/sprintf.min.js"></script>
<button class="button_option_1">Option 1</button>
<button class="button_option_1_play">Play</button><br />
<div class="log">[empty]</div>
Here is the corresponding CodePen.io:
Solution 1:[1]
Safari doesn't know the promise based decodeAudioData. You will have to use callbacks.
context.decodeAudioData(arrayBuffer, (buffer) => {
resolve(buffer);
}, (e) => { reject(e); });
Solution 2:[2]
context is in suspended state after creation on iOS. It needs a call to resume in a user interaction to be running
Solution 3:[3]
I had similar problem lately that decodeAudioData failing without much information. After trying lot of things realized,
iOS safari was crashing because decoding large (10-20 MB) mp3 files simultaneously, we had 6 of such files. so we tried to use smaller size and its working now. seems this happens only with iOS, maybe some kind of memory issues or bug.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Bruno Caceiro |
| Solution 2 | KIDdAe |
| Solution 3 |
