Chrome error: The AudioContext was not allowed to start. It must be resume (or created) after a user gesture on the page.
trelive opened this issue · comments
I've had MIDI.js installed on my site for several years, working just nicely. Then today, I started getting messages from users that the sound wasn't working. And it isn't!
I am getting error: The AudioContext was not allowed to start. It must be resume (or created) after a user gesture on the page.
On my website, users always have to click a button to start the sound, so I can insert code to resume. Although it will need to play nicely with all browser types.
I am not using the midi player feature of MIDI.js I am playing back an array of notes.
This is the code that gets run on page load:
MIDI.loader = new sketch.ui.Timer;
MIDI.loadPlugin({
soundfontUrl: "./soundfont/",
instrument: [countinId, playbackId],
onprogress: function (state, progress) {
MIDI.loader.setValue(progress * 100);
},
onsuccess: function () {
MIDI.programChange(0, MIDI.GM.byName[countinId].number);
MIDI.programChange(1, MIDI.GM.byName[playbackId].number);
}
});
When user clicks the button, the core MIDI.js part of the code is:
setTimeout(function () {
MIDI.setVolume(1, 127);
MIDI.noteOn(1, note, velocity, 0);
MIDI.noteOff(1, note, delayoff);
}, delay);
I am hoping that someone with a more intimate knowledge of MIDI.js than me might have a simple fix.
Many thanks
You need to call MIDI.WebAudio.getContext().resume() from your button click event. Something like
MIDI.WebAudio.getContext().resume().then(() => {
setTimeout(function () {
MIDI.setVolume(1, 127);
MIDI.noteOn(1, note, velocity, 0);
MIDI.noteOff(1, note, delayoff);
}, delay);
}
perhaps. Possibly check which plugin MIDI.js is actualling using if you care about the non-webaudio methods (audio tag, WebMidi).
@hmoffatt, thanks for your answer. MIDI.WebAudio.getContext() is what I needed to get right.
This is working nicely with the start button:
if (MIDI.WebAudio.getContext() && MIDI.WebAudio.getContext().state === 'suspended') {
MIDI.WebAudio.getContext().resume().then(function() {
console.log('audioContext was suspended, now resumed');
playerControl();
});
} else { // either not using webAudio or audioContext already running
playerControl();
}
This is tricky to test as after a few uses the audioContext stays running, so to test I added to the stop button:
if (MIDI.WebAudio.getContext() && MIDI.WebAudio.getContext().state === 'running') {
MIDI.WebAudio.getContext().suspend().then(function() {
console.log('audioContext has been suspended');
});
}