Tonejs / Tone.js

A Web Audio framework for making interactive music in the browser.
https://tonejs.github.io
MIT License
13.24k stars 964 forks source link

AudioContext "not allowed to start" #341

Closed Enteleform closed 5 years ago

Enteleform commented 6 years ago

System:     Windows 10.0.16299 Pro x64     Chrome 66.0.3359.139     Tone.js @ https://unpkg.com/tone@latest/build/Tone.js

  I wrote a Tone.js test in CodePen the other day. It was fully functional, but when I checked it out today it was no longer producing audio.

This message shows up in the console, even after commenting all of my JS code, so it seems that the issue is occuring while Tone.js loads:

The AudioContext was not allowed to start.
It must be resume (or created) after a user gesture on the page.
https://goo.gl/7K7WLu

Tone.Context @ Tone.js:1277
(anonymous) @ Tone.js:1760
Module @ Tone.js:25
(anonymous) @ Tone.js:1267
(anonymous) @ Tone.js:11
(anonymous) @ Tone.js:14

I also checked out the official Tone.js examples and found that the embedded JSFiddle examples work as expected. However, the same examples exhibit the issue mentioned above when accesed via their direct JSFiddle addresses. They do not work upon the initial load and produce the AudioContext error message. After clicking on the Run button to reload the Results panel, they then work as expected.

tambien commented 6 years ago

I haven't done much investigation into this, but i think something like StartAudioContext should fix this. This has been a restriction on iOS for years and now most desktop browsers are adopting this same restriction.

Not sure yet what needs to happen on the Tone.js side of things, if anything. but the examples will definitely need to be updated to use StartAudioContext not just on mobile browsers.

datramt commented 6 years ago

a simple solution is to add this:

    if (Tone.context.state !== 'running') {
        Tone.context.resume();
    }

inside your "mousedown" listener

document.documentElement.addEventListener(
  "mousedown", function(){
    mouse_IsDown = true;
    if (Tone.context.state !== 'running') {
    Tone.context.resume();
  }})
Enteleform commented 6 years ago

@tambien

Adding StartAudioContext(Tone.context) resolved the issue in the mentioned CodePen.

Could StartAudioContext be implemented directly in Tone.js? It seems like a breaking change (on the browser side?) & an unknown issue to developers. I just checked out the first 12 examples on https://tonejs.github.io/demos, and 8 of them exhibited the AudioContext issue.

tambien commented 6 years ago

@Enteleform there may be a few simple things that can be implemented directly in Tone.js that would help people with this issue. Good documentation of this would probably help the most. The underlying change that Chrome made which requires a person to explicitly start the audio needs to be taken care of by the developer.

CarloCattano commented 6 years ago

Having the same issues here . Only safari doesnt seem affected by this recent change . I cant run examples online neither on my own .

Andrparsons commented 6 years ago

It's probably because of this:

https://developers.google.com/web/updates/2017/09/autoplay-policy-changes

Google made the change without telling anyone and it has broken a ton of audio.

CarloCattano commented 6 years ago

yep , I solved it like @datramt said . Just need to keep in in mind for the future.

Enteleform commented 6 years ago

@CarloCattano

I ran into a caveat when testing @datramt's mousedown listener solution. It doesn't work until after the first mousedown. So in the example I posted with an interactive piano, if the first user interaction is to press one of the piano keys - the audio will not be played. After the first click, however, the audio will play as expected.

@tambien's solution of using StartAudioContext(Tone.context) (@GitHub, @NPM) does not have that caveat, and allows immediate initialization of audio before any user events are fired.

datramt commented 6 years ago

oh interesting, i didn't have that problem with my proposed solution on your interactive piano although maybe it could be fixed by swapping the order of operations in the callback. Anyway, I agree it's probably smart to use something like StartAudioContext when you can so that you can really bake it into the different listener types on the page. Not sure I'm going to want to include it on every single web audio project project I pursue though.

nightshining commented 6 years ago

Having the same issue. Added in the code you recommended. Now Tone.Players play back files but all the audio is extremely degraded. Works totally fine on multiple android devices and on mac laptop in chrome and safari. Just happening on ios Chrome and Safari.

harking commented 6 years ago

HowlerJS has implemented this solution: https://github.com/goldfire/howler.js/blob/master/src/howler.core.js#L278

tambien commented 6 years ago

@harking @nightshining you can find a similar solution to the iOS sampling rate issue here

tambien commented 5 years ago

Made an unmute button which hopefully addresses all of these issues. moving further discussion over to that repo if necessary

dkozar commented 5 years ago

Confirming that the solution to this issue is to call:

Tone.context.resume();

... upon first user action in the app, just before starting to play any sounds.

For me this solved a "microphone with no sound" issue with another library (https://github.com/alemangui/pizzicato/issues/115).

johnmarinelli commented 3 years ago

I was having this error on my iOS device (iPhone 6) and it didn't work for the longest time, even with the Tone.context.resume. Long story short...make sure to turn the mute button side switch "off" 😂

vincerubinetti commented 1 year ago

For me everything is working fine because I'm only triggering notes via a user interaction. But still, it seems that just creating a synth without playing anything causes a few of these warnings to show up in the dev tools. Seems like some of the constructors in the library are trying to access the audio context or something.