问题
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
回答1:
Safari doesn't know the promise based decodeAudioData. You will have to use callbacks.
context.decodeAudioData(arrayBuffer, (buffer) => {
resolve(buffer);
}, (e) => { reject(e); });
回答2:
context is in suspended state after creation on iOS. It needs a call to resume in a user interaction to be running
来源:https://stackoverflow.com/questions/52489787/audiocontext-decodeaudiodata-not-working-on-iphone-but-working-everywhere-e