AudioContext.decodeAudioData(...) not working on iPhone but working everywhere else
Asked Answered
I

3

7

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 = '//NExAAQAEIUANLGJD7ADozTCghwCrpuImJJfsmVhFye+crPy6UZNvdyC3ixx2QbUXKDDlX08m12kIo4WCJRygGQeQkwibDB/ZrHyhc5cQBEFHBAwIxQ5WKqwiN9YbWw//NExBMQwD5EAOIGBMnKxBJ9D0giPOFBPScfvxIpVJq4mK7+A9D5y8Y3LvMyC1DLUJbcEQI6BAGsF2H1DDl7tCB0gNA0YnTME2djADGlXHxJFDYoGQqNS2+JIwq5AuAZ//NExCMQOD5EAOMEBDwo++j0YiFS9EwDXtsa1iuwlUxFVXUeHNuidz1PGD08yRPht+9y+rq5jvqSGkhjZxskqbnQtm7qTjAFJASA5QYkFmJUDrpc/LwOKoYxbigaWtZp//NExDUReMpAAOBEcCtjm+uvaHV6VmbRdCLU6koVI9x4hWKTSqdtcuzs3G4KinsCsLgxNRBEsBhAqKBImFydfRRBZy4rFc7R7C+57/+heawnfqyxESIRR/hRM/z9qyQK//NExEIWoa5MAMpGlH0VrqexaG1vJ0LLtvWfoHg+Bz4OXf6bWIU9FV64lWG5ZG857CW/AsSpWdrnTnVhp4RUaBA6c7l2zrcE+h47DBK9U0IWokqikon47JbNKwvffzum//NExDogskJYAVh4AB+wOD+aDm8/3vT97R2xqt/PJNjwtfFL/HzL/SI/wfixVEOm99K8mvvOKUxEpTFb/13SBeG5v3+93vf31t5wOfJ0oW4l1xybv6mQ6de0xZed7mO1//NExAoUKYqUAZhoAHZqJVt8rF6LxTNy4OEeRsBIDBkubGxmgSpUUDQFIE/HkSJs3N/ZN/67f/UrXWpm9Sv2PaFgyoqKFErSi/0PIssBhDP///yacwVquH+ZI/h+iyDS//NExAwUgWqwAY9oABPiVifA8RtAcEyDdCyAlY4yeE4EvHCAKRfEYC2hIDBMNYiyUhyA3VIKvnlr/////7nE/rPkWNkDLQNbADU3pd0Cns/+n+hTWMwyKDtX3KS3D1Yk//NExA0VGaKgAdmIAQQRsNMUoMxAOad5rRelM6Ho2u6VUydisYwhBwBaC5JFS4Yukxmiy27a+rtr6/7/1UziToJrZNVnro1qRRMPKxRcJZ4QFfXvtW5TcPGISERada+a//NExAsUmY6MANZKlBWv60UAuDg717piGJYFA8fl5VUKFrkXHDX7pYaFypY6KJpEDWxppH+rnf+7//v/v27af/b8+Up2Egc0YQ1TzDw0IxxuXErdKhoknWyCNcEgChWA//NExAsT+aaIANzKlDOAAoE3iGS09mITLZ8j0D1EKmBEALjTNxLQWeiG5A0JByCows4tIJFDSLet++vfrz//6cnM1g1qF71RkGCRGMvfu//rM1KYVCDBQIiRH7bmY6eF//NExA4UcaKMANyKlOhgAwCnyK4gAFCE0wwYO0ri/CjpE4K6CzmBEQEUFySfOCmpmkz1oa277Pl5tf/+uguwmH+ET3EiaXURkQFGoi6P//htebtUdBqh1XHQLXZEyAxN//NExA8R2cqoANSElKUrR7ZIDYGOeTBAAwAWnJUgxbkCBGhPkSFdBtuJzLnWZp6+/ft/f/06asSqai2r1Po2HP9RZ9b9amj5CgrO9i6o+kwQIAoY1aAujzVdwd6sfynK//NExBoQmUq0AHvElavbagjgYT9IYBHngO1fusmsY3T5p0/p//+yMKqBVeGu9ShCB5P/qvyVg6udoaE220TCH8Z0da88j6QHGhqkaSlS3RUZXJ8KBvQ0bQ/0OOYYRi2Z//NExCoQeKK4AH4eTNuU9wMC8CMR1/W1RMVGIUt3a1Rq2jroNkvvcUIXed4O4MRonZCXxDE5GoqYBo7KJDtbcl/Yc/nXiibtNacpr4IAEwCQiAVnkaETH1Z3qnr7f6ez//NExDsRyUK0AH5UcDGkvmutkPOyz+39dNWFd/MgCq/5iCiVrHbdiTlnFEYNYazM2Sb7HOs60myrSpdUmtVRwgroy3JowoliFJJPopdSvfUt+pfVpJHfV4s+/pai//An//NExEYSYT6sAMYacP///pU42IiGnMmVAazJ0ytwUKQNezswUVJpDfsZrLkOVmPohwnK0VAJgSLpE82NV1I+tun7dTeZPrNkV57y3gkPFztfvf/Uh47UPweVYZhiTYXd//NExE8QuUKsAJ5acIboStr2uulWalEp3Vkbw95n6fLgPdTKPZ/lyRMNgUiLWYmoYdcLPtpirazAlE7wK7+oQlwfINZV3o9NjGG3bHjdqyhEGBYbXeFRnMkXaskICgoU//NExF8RqK6sAH4eTLSGyMMJsxp+EXF6aaeIQHEchiNqmSq4aY11Cznv6SCPGDTgeb/WfJB///JKaDj1W1Z1iZQIMGimJoMAzF7DhIEyuTWAgDnJbANNYqoDwBMiRqoA//NExGsQ2KasAMYeTHgT6pPhjcbQI7qt9bx8/T/06c7Iwdkm//+hMXCWjc9BpjNIpKDYpwzIiEeDsUZGf3DWVNk30dncp0GGXRdx2CtxWHA1Wko2qHwdGaKeyxrZgdRd//NExHoRAZKoAMPEleVpvEKyOtAIAR//St///////8rVIg0igUiovLHgijGOmBOEQRkxgZJ4BKA2xAL+xoRNZLSo6yKUkKULukIxCJzqsNWsqTHG7Pf9//7/rzV77at2//NExIkSSJ6gAMYwTGHTnqqbftO27mBv1UezRZ////Fw0mkP+SBBe2KSsmd3ukYyZqtWWBY8xgBiUrpcWlhnoszNCVIo4JQcaZHDq5vU878xZ+vcy/Xf7+sDUNTUzzP5//NExJIU6Y6UANYKlB7P0dHvt0fq6g2N//7f///+li4aUd0VIA/bFhQ05JGav4DanYISz+eDp4+3KVOou1A5rAiBBKvRchYWJABHmZre5kvrvZvegRc91/xF51W3//ps//NExJEUMX6QAN4ElP///8qqEt2+R3POSC2PCBVGhBZdMON0M+w5TGryTOAmkv7q+uRaYiQdsKtdRrSS6tS/gAU245AqXgJpCy1iFqjuVStAS+kwpnRgURlp4TqwzO4F//NExJMRMKKEAM5eTIOjbitISA8ckyo5iKtKVWB2NQpOBeRScYkAo08IFCTFo0ui8sjGzUUaUCgMjlumvtYuBTYjrGGj/7F1DeUS2MFzVes27GtHMINRxPYYbIROEIng//NExKEQQKJ0AM5eTHRZY/pFF5pNhIqhT6GQbMJc9QoOSC5JwxRs8xCIpZNqPSyeE2p2t9tCPmwDibwPs1uxYh+Ug0qyJhUn1MVCoBRz9FFM4KkjVL51UfI0gDAdALAe//NExLMR2OpoAMsMcAULgFrizBZcEn0rERVywUNoTava7HEre+kV+n9FM9kU0iWCvq02JQ9KgqeFRMKhU/JHBWtpqOTpqIKiIGgEFAaaJjyw1BUqAgoeBoRLXhqVcWPE//NExL4QKJ5cAMsSTEsoedOuJS2yr0LVZ+S//1I00MgZGRKgZILFyYIoUp6FgYEAhqXLZUMv7LDJlkNZSNQ0B0KiMBCoZMgsLiojMgsIzIS0AUVFdQsL+zQFBIaBkKkn//NExNARqKJMANJMTPwKKiT1etICF/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:

https://codepen.io/anon/pen/rZgEoo

Isadoraisadore answered 25/9, 2018 at 2:33 Comment(0)
S
16

Safari doesn't know the promise based decodeAudioData. You will have to use callbacks.

context.decodeAudioData(arrayBuffer, (buffer) => { 
          resolve(buffer); 
 }, (e) => { reject(e); });
Solve answered 27/9, 2018 at 12:12 Comment(2)
promise-decode-audio-data is not in active development anymore. I find this polyfill even more useful: github.com/chrisguttandin/standardized-audio-context – Abash
I did the following(using standarized-audio-context): ``` ... if(!isiOS) { decodedAudioData = await decodeAudioData(getContext().rawContext, file); } else { getContext().decodeAudioData(file, buffer => { decodedAudioData = buffer; }); await new Promise(resolve => setTimeout(resolve, 1000)); } ... ``` – Lindseylindsley
U
2

context is in suspended state after creation on iOS. It needs a call to resume in a user interaction to be running

Undulatory answered 15/2, 2019 at 16:22 Comment(1)
πŸ‘πŸ» both answers to this question are correct, you need to take care of both to get audio to work on iOS Safari – see https://mcmap.net/q/576394/-onaudioprocess-not-called-on-ios11 – Abash
U
0

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.

Undergraduate answered 25/2, 2022 at 14:4 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.