mudcube / MIDI.js

:musical_keyboard: Making life easy to create a MIDI-app on the web. Includes a library to program synesthesia into your app for memory recognition or for creating trippy effects. Convert soundfonts for Guitar, Bass, Drums, ect. into code that can be read by the browser. Supports multiple simultaneous instruments and perfect timing.

Home Page:http://mudcu.be/midi-js/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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');
        });
    }