Get access to RNBO Device in Javascript

seejayjames's icon

Got everything set up and successfully exported a RNBO patch to my local web server. It (mostly) makes sense and now I'm itching to play :)

My patch is simple: one param that opens a gate~, allowing a sine wave to play when the param is 1. The web page (see screenshot) has all the template sections, plus the one parameter named "tog", and it does work when it slides all the way to 1...hallelujah! I also added "Hello World" just to get my bearings in the HTML.

Now what I don't know is: the slider/parameter is NOT in the HTML, it's just a placeholder, so apparently params/sliders are added dynamically. No problem. The issue, though, is now I want access to that parameter. So I need to get the "Device" via JS.

I have this code from the docs that will list all parameters:

device.parameters.forEach(parameter => { console.log(parameter.id); console.log(parameter.name); });

But I have to get access to the Device object first and store it in a variable....how do I do that?

I tried

const device = await RNBO.createDevice({ audioContext, patcher });

got error message about "await":

await is only valid in async functions and the top level bodies of modules

tried it without "await", then I got

RNBO is not defined

Any ideas? Thanks!

seejayjames's icon

It has been pretty complicated to get all the parts working for RNBO to JS/Web. I ran into a lot of issues and still am battling with a number of them, like I change the app.js file and the changes aren't showing up in the browser....I commented out everything in it, but the page still worked. What?? Yes I connected the dev tools, but no matter what I change in app.js, including breaking it horribly, nothing changes on the page. If I comment out the link to app.js in the index.html, then yeah, there's a change because it wasn't found. Is something overriding the app.js file? I can't think of any other explanation, given that I can break it and the page still functions. Cached version? I'M SO CONFUSED!!

Would love for C74 to make a video about how to get access to RNBO parameters in the index.html page. Ideally nothing would have to change in the exported app.js file, is that correct?

I saw this video, where he creates the app.js file from scratch. Seems like we shouldn't have to do that....Help!!

Florian Demmer's icon

Hi there,

first off - glad to hear you got something working and the itch to play further is there. I'll try to address some of your questions / concerns.

First off - the current web export is not designed as a "one-click" solution in terms of making your patch and then getting a fully running, hosted website / URL to share and potentially further customize. I can see that introducing an additional hurdle in getting started, which is why we provide the generic template on Github to allow users to see their patches work on a website without having to take a deep dive into Web programming first.

However, once you have more custom ideas there is some programming necessary and you might need to adjust or only use portions of the template to suit your needs. Looking at the issues you describe here a few tips that can hopefully make this a bit easier.

Caching when running a local dev-server

  • disabling "caching" entirely can help to make sure that you always see the latest - if you are using Chrome there is a toggle "Disable Cache" at the top of the Network tab in the devtools

  • if you are using npx http-server to serve up the static site, pass -c-1 to disable caching headers as described here

Understanding the app.js

The app.js contains comment to help understand what it is doing. While it mean seem like a lot of code at first, really a lot of it comes down to it having to be generic and support a wider feature palette of exported RNBO patchers. I recommend focusing on the setup function as means to understand the basic principle of what it's doing. Additionally the Working with JavaScript series in the RNBO docs can be helpful as it goes through each of the features one-by-one and shows the relevant code.

Rolling your own

If the template / example is too wordy and noisy, maybe rolling your own version of it to get started can be helpful and allow you to focus on learning how to use the features you are interested in one at a time rather than trying to customize the more generic code?

To help here a very slimmed down Codepen Project that only shows the mandatory steps to load an exported patch, create the Device and connect it to the AudioContext.

Maybe this helps as a starting point for further exploration and learning using the docs or additional videos linked to above? The only additional things here are a gain slider for controlling the overall volume and a button to start / resume the AudioContext. In return this doesn't magically expose parameter control as sliders on the page, add MIDI control or anything else.

seejayjames's icon

You are my new personal superhero!!

Your post is incredibly helpful, I know it took awhile and it is MUCH appreciated.

Caching was the reload issue...not sure why I didn't figure that out on my own, gah. One note, if you Disable Cache in the browser Dev tools, once you close the tools it will go back to caching. Using

npx http-server -c-1

does the trick to keep it disabled, as you said.

The Codepen snippet was really helpful too. Took awhile to get all the pieces together, but I successfully created a button in HTML with two states and it controls the RNBO gate by setting the value of its internal parameter. Hallelujah!

One note about the Codepen snippet: there's this line:

outputNode.gain.setValueAtTime(0, context.currentTime);

Works fine in that example because the slider is setting the volume. In mine I just had the gate, so it was actually working but the volume had been set to 0. More head scratching...but then commented out that line, voila.

Am quite familiar with Max and pretty good with JS, so should be able to experiment a lot. It was just getting everything connected and figuring out how things communicate that was a struggle.

Again, I can't thank you enough for your clear and detailed explanations!