ui icon indicating copy to clipboard operation
ui copied to clipboard

Oscilloscope not connecting to Tone.js audio context

Open jonahvsweb opened this issue 6 years ago • 5 comments

I've tried to set the source two different ways based on what the documentation is showing and looking at the library itself.

First attempt

var oscilloscope = new Nexus.Oscilloscope('#scope');
oscilloscope.connect(Tone.Master);

throws this error:

Uncaught Error: error connecting to node: [object AnalyserNode] InvalidAccessError: Failed to execute 'connect' on 'AudioNode': cannot connect to a destination belonging to a different audio context.

Second attempt

I dug into the library a little and also tried:

var oscilloscope = new Nexus.Oscilloscope('#scope', {
  connect: Tone.Master
});

This didn't produce any errors, but it also didn't work.

I'm kind of at a loss, and would appreciate any help or if this something that needs to get fixed or if I'm misunderstanding how to use this feature. I attached a simple example using the snippets I pasted above to a Pen: https://codepen.io/jonahvsweb/pen/gxREQE?editors=1010

jonahvsweb avatar Aug 11 '17 10:08 jonahvsweb

Great question, yes there is an easy remedy. Tell NexusUI to use Tone's AudioContext:

Nexus.context = Tone.context

You'll want to put that line of code towards the beginning of your script (before you create any NexusUI components).

Fuller explanation: the error is that NexusUI has its own AudioContext (Nexus.context) which it uses for timing and to run the audio analysis for components such as the oscilloscope. Tone also has its own audio context (Tone.context). Web audio doesn't allow you to make audio connections across different contexts.

By setting them equal ( Nexus.context = Tone.context ), we are basically telling NexusUI to use Tone's context for everything. Therefore, any audiocontext-dependent code that NexusUI creates will be compatible (connectable) to any of your Tone audio nodes, because they are all created from the same audiocontext (Tone's audiocontext).

The full working JS for your codepen would be:

Nexus.context = Tone.context

var mute = new Nexus.Toggle('#mute'), 
    oscilloscope = {}, 
    
    synth = new Tone.Oscillator(110, 'square'), 
    vol = new Tone.Volume(-15);

synth.chain(vol, Tone.Master);
Tone.Master.mute = true;

oscilloscope = new Nexus.Oscilloscope('#scope');
oscilloscope.connect(Tone.Master);

mute.on('change', function(v) {
  
  if(v) Tone.Master.mute = false;
  else Tone.Master.mute = true;
});

synth.start();

I'll be sure to add this to the documentation.

taylorbf avatar Aug 11 '17 18:08 taylorbf

@taylorbf Thanks so much! 👏

jonahvsweb avatar Aug 11 '17 18:08 jonahvsweb

Hey, thought I'd put this out there since I just spent several very confused hours troubleshooting this exact issue. For some reason including Nexus.context = Tone.context; threw the TypeError Failed to execute 'connect' on 'AudioNode': No function was found that matched the signature provided. Perhaps this is because Tone.context doesn't seem to return an object formatted as the AudioContext that Nexus is looking for.

Instead, I noticed a properly formatted AudioContext object hanging out in the hidden variable Tone.context._context, and when I used Nexus.context = Tone.context._context the error went away, and my code actually started working (I too was trying to hook up an oscilloscope to a Tone oscillator). Maybe this should be reopened as a separate issue if other people are having the same problem.

I've put my marked-up code here incase anyone's curious—it also includes a function that uses promises to load libraries that deal with AudioContexts upon a user interaction, so that you don't run into problems with modern browsers trying to disable automatic audio.

anselbobrow avatar Jun 19 '20 04:06 anselbobrow

Seems to be, that latest versions provide new API in tone.js, that produce errors during assigning context to nexusui NexusUI.js:9116 Uncaught TypeError: this.context.createScriptProcessor is not a function at module.exports.WAAClock.start (NexusUI.js:9116) at NexusUI.set (NexusUI.js:195)

doubledare704 avatar Aug 07 '20 12:08 doubledare704

Hi @mscottnelson

To solve this specific issue, should I submit a PR that changes the following?:

  • Update main.js so that the setter for Context does a type-check.
  • Update the currently used tone9.js files to the latest version of the Tone library.
  • Update the Nexus examples and documentation for the integration with Tone (to access their internal context correctly).

I already have PR #190 that I can modify to do this.

Regards Andy

pendragon-andyh avatar Aug 08 '20 06:08 pendragon-andyh