Closed satelllte closed 4 months ago
Have you learned anything new regarding the global context? I'm trying to set latencyHint
to playback
without blowing up the whole app's modularity/treeshaking by importing * as Tone from 'tone
. Everything I try throws an error.
Have you learned anything new regarding the global context? I'm trying to set
latencyHint
toplayback
without blowing up the whole app's modularity/treeshaking by importing* as Tone from 'tone
. Everything I try throws an error.
@FractalHQ no, I didn't have this use-case, maybe you should create a separate issue for this
Hello - I am not very familiar with React so admittedly I don't follow the code in your demo very well (specifically - the order in which code is being executed across the different files). The error is happening because some of the code is referencing an already-closed older context (or audio nodes created with the older context). Some things to note about contexts in Tone.js that should help you work around the problem:
new Tone.Synth({context: myCustomContext1})
). That way you never have to worry about which context is referred to by Tone.context
and Tone.getContext()
, and it's easier to debug.toDestination()
and getTransport()
which assumes use of a single context (instead: synth.connect(myCustomContext1.destination)
, myCustomContext1.transport.start()
).new AudioContext()
then you lose out on the x-browser compatibility benefits of standardized-audio-context
, and you're deeper in edge case territory because Tone expects a standards-conforming audio context which standardized-audio-context
guarantees but not all browsers provide. There are some situations where using a native context might be preferable. But if yours is not one of those, then you should use new Tone.Context()
to instantiate a context wrapped by Tone.js and its bundled standardized-audio-context
.Hi @satelllte,
This is an issue with <StrictMode />
in React and the only solution is not opting in.
If you remove the strict mode wrapper in index.tsx
your issue is solved.
From version 18 the effects are fired twice on load. This is the reason why your context wasn't working, basically it was disposed right after you initialised it.
More Info: StrictMode: Ensuring reusable state
Hi @satelllte, This is an issue with
<StrictMode />
in React and the only solution is not opting in. If you remove the strict mode wrapper inindex.tsx
your issue is solved. From version 18 the effects are fired twice on load. This is the reason why your context wasn't working, basically it was disposed right after you initialised it.More Info: StrictMode: Ensuring reusable state
Hi @andeeplus, you're right! When I turn off the React strict mode it works fine. I've also tried to not dispose the context on unmount, which fixes the issue when strict mode is on.
But my main concern is about the difference between Tone.context
and Tone.getContext()
, why the behaviour is different?
UPD: I see, probably because of this, like @marcelblum described:
Using a new context with Tone is a bit of an edge use case that brings some subtle pitfalls. If you will be creating multiple contexts for use in Tone it's good practice to keep your own global references to those contexts, and always explicitly pass in those references when creating Tone objects (ex: new Tone.Synth({context: myCustomContext1})). That way you never have to worry about which context is referred to by Tone.context and Tone.getContext(), and it's easier to debug.
@satelllte Yes, I think what @marcelblum said is the reason about the difference. I've personally run Tone in a large application and I must admit I never had the need for a different context from the main. Anyway has a practice I always access to the destination and the context using getDestination()
and getContext()
.
About strict mode, this is a bit of a pain in react for those kind of situations. Also if you plan to work with other libraries that had issue with strict mode (i.e. wavesurferjs). I didn't find any other solution than didn't opt in the strict mode for the moment (the alternative would be manually opt in all the components that are not using the library that fails).
Got it, @andeeplus.
Thanks for sharing more about your experience with Tone. And, for sure, that's a good point to use only one way of accessing something at the same project.
Regarding scrict mode, I personally prefer to have it on, so this was one of the reasons to open this issue. But maybe it's really a pain in case the project depends on libraries like Tone, which normally should be instantiated once per session.
Describe the bug
Hi 👋🏻 I'm trying to build some wrapper in my application over the Tone.js for the abstraction. One of the problems I'd like to resolve is to have an ability to instantiate & dispose (i.e. destroy) the core instance of Tone.js.
The weird thing I noticed about Tone.js is the difference between calling
Tone.context
VS callingTone.getContext()
to get the reference to the Context object. In case I'm usingTone.getContext()
I never hear the audio.To Reproduce
The basic demo in the sandbox: https://stackblitz.com/edit/tone-context-issue (see the
private get _context()
method ofCoreAudio.ts
file, if you edit it to returnTone.getContext()
instead ofTone.context
you will not hear audio anymore)Expected behavior
Tone.getContext()
looks like an opposite ofTone.setContext()
which should get me the current context reference and it should be playable.What I've tried
See the sandbox for details. Maybe I did something wrong in my
CoreAudio
wrapper?