Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getting clicks when updating genish graph #25

Open
michaelpalumbo opened this issue Aug 10, 2022 · 11 comments
Open

getting clicks when updating genish graph #25

michaelpalumbo opened this issue Aug 10, 2022 · 11 comments

Comments

@michaelpalumbo
Copy link

I'm making an app which is going to be making a lot of frequent updates to the genish audio graph. I built a simple page to experiment with this and I'm getting clicks whenever I swap in a different string to be evaluated:

https://codepen.io/michaelpalumbo/pen/yLVVKjm?editors=1011

Is there a better way to insert a new genish graph?

@charlieroberts
Copy link
Owner

hmmm. in gibberish i maintain a single worklet and send genish code to run inside of it, but my guess is that’s more complex than what you need. seems like you’d just need a crossfade option, correct? where the new worklet would be gradually introduced and more importantly the old one would fade out…

@michaelpalumbo
Copy link
Author

michaelpalumbo commented Aug 10, 2022

Actually I believe I would be more interested in the first method you mention, using gibberish and sending genish code to run inside. I wasnt able to find doc on how to do this, could you point me in the right direction?

@charlieroberts
Copy link
Owner

OK, the best place to see how this works is in gibber, select the sound design tutorials > creating synths from the pulldown menu. You can find the associated Make function in gibberish here. You won't get the sequencing stuff shown in the gibber demo but everything else should work the same. Or, if you wanted the sequencing, you could step all the way up to gibber.audio.lib

I have no idea where the best place to ask further questions about this would be; I opened up discussions for this repo in case that makes more sense. But I do think there's some useful feature development proposals in this issue, so I'll leave it open for now.

@charlieroberts
Copy link
Owner

one other note, managing the generated worklet is related to #20

@michaelpalumbo
Copy link
Author

michaelpalumbo commented Aug 11, 2022 via email

@michaelpalumbo
Copy link
Author

michaelpalumbo commented Aug 11, 2022

@charlieroberts I played around with the creating synths tutorial (and several others from that page). I'm wondering how one would redefine the Ugen graph sometime after it has been made with Make(), as I was unable to do this. So far I was only able to fully stop playback, modify the graph, and then run it all again.

So essentially I'd like to be able to do something like this:

const gen = Gibberish.genish
def = {
  name:'synth',
  type:'Ugen',
  constructor: function() {
    this.graph = gen // or, null?
    return graph
  }
}

mySynth = Make( def )
ms = mySynth
ms.connect()

// and then say 30 seconds later I instantiate a cycle and want to add it to the gen graph

ms.graph =  new Function(`gen.cycle(440)`)

// maybe 10 seconds later do this

ms.graph =  new Function(`gen.mul(cycle(440), saw(2))`)

The other question I have is, supposing the above were to work, would gibberish run it at the next sample after I apply it, or would it wait until the 1st downbeat to apply the change? (I'm after the former)

@charlieroberts
Copy link
Owner

It's not currently possible to replace the graph although that might be something that could be added... can you tell me the audible effect you're trying to avoid? Trying to figure out the practical limitations of just running the code again.

You can run code immediately in gibber using shift+enter instead of ctrl+enter. In gibberish, there's no real concept of a measure / beat so yes, code would be executed immediately.

@michaelpalumbo
Copy link
Author

Oh I see.

can you tell me the audible effect you're trying to avoid?
Well there's the clicks that I mentioned up top. I suppose the other issue could be that an oscillator's phase would be reset if the graph is replaced, though I'm not sure how to avoid that.

For usage, my app is a modular synth in WebXR. Each module is either a genish op, or a collection of ops (kinda like a max abstraction). So I'm anticipating players instantiating ops into the scene, making cable connections between inlets and outlets, twisting knobs (genish params), that kind of thing. In an earlier version, I was using max scripting to metaprogram Gen~ code from player actions in VR, but every time a new object or cable was instantiated, the Max audio scheduler would hang for ~300ms. The crossfader option in the patcher general settings did not smooth this either.

Another problem we ran into with the Max version, that I'm anticipating here as well, is that Graham had made a simple sequencer that had a randomized sequence, and each time an edit to the scene was made (adding another op, making a patch connection or disconnection, etc) the sequence seed would change and you would just suddenly hear a different melody.

So this metaprogramming approach is what's informing my assumption around wanting to replace (or ideally, modify) the graph in real time. Maybe though, directly changing the graph isn't the right approach. Maybe instead I could write an interface to take changes in VR (adding an op, patching a connection, turning a knob, etc) and translate it into gibber with the equivalent of shift+enter?

@charlieroberts
Copy link
Owner

Maybe instead I could write an interface to take changes in VR (adding an op, patching a connection, turning a knob, etc) and translate it into gibber with the equivalent of shift+enter?

Sure! There's no seeded random function in gibber (or JavaScript more generally) currently, but that wouldn't be hard to add in, plenty of libraries that cover it.

@michaelpalumbo
Copy link
Author

michaelpalumbo commented Aug 18, 2022

@charlieroberts i'm now wondering about trying what you had previously suggested:

seems like you’d just need a crossfade option, correct? where the new worklet would be gradually introduced and more importantly the old one would fade out…

Could you show me how to do this?

@michaelpalumbo
Copy link
Author

Hi @charlieroberts figured I'd follow up, is crossfading between two worklets a possibility? I'd love to try this out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants