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 = '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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:

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

davidesp
  • 3,743
  • 10
  • 39
  • 77

3 Answers3

15

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

context.decodeAudioData(arrayBuffer, (buffer) => { 
          resolve(buffer); 
 }, (e) => { reject(e); });
Bruno Caceiro
  • 7,035
  • 1
  • 26
  • 45
Hans
  • 151
  • 3
  • `promise-decode-audio-data` is not in active development anymore. I find this polyfill even more useful: https://github.com/chrisguttandin/standardized-audio-context – Patrick Hund Sep 02 '19 at 15:47
2

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

KIDdAe
  • 2,714
  • 2
  • 22
  • 29
  • both answers to this question are correct, you need to take care of both to get audio to work on iOS Safari – see https://stackoverflow.com/a/46534088/1253156 – Patrick Hund Sep 03 '19 at 07:08
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.

Shreyas Jadhav
  • 2,363
  • 4
  • 10
  • 23