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

dual scsynth instances #630

Closed
catfact opened this issue Nov 1, 2018 · 3 comments
Closed

dual scsynth instances #630

catfact opened this issue Nov 1, 2018 · 3 comments
Assignees

Comments

@catfact
Copy link
Collaborator

@catfact catfact commented Nov 1, 2018

while supernova is great for polysynths, it actually has poor performance with:

  • single heavy synthdefs / ugens (e.g. zita reverb)
  • polys that have audio connections / process dependencies between voices (e.g. softcut)

(at least, this is what we're seeing with 3.9, 3.10-beta versions on ARM/NEON.)

so alternatively we should try two (or more?) instances of scsynth connected through jack.

this is pretty straightforward. the big drawback is doubling the process latency by running through a jack connection.

opening this issue mostly to discuss and document requirements and a few gotchas discovered in initial tests. apologies for its length and rambling nature...


details could change, but overall the scheme could go something like this:

in bash / matron:

  • run scsynth process for engines (call this instance engine), say on port 57111
  • run scsynth process for effects. (call this instance fx), say on port 57112

note that these have to be created with extra arguments to increase audio I/O channel count (see below.)

in sclang:

  • create remote servers:
server_engine = Server.remote("engine", NetAddr("127.0.0.1", 57111));
server_engine.doWhenBooted { server_engine.initTree; }
// create AudioContext on server_engine, pass it to engine classes

server_fx = Server.remote("fx", NetAddr("127.0.0.1", 57112));
server_fx.doWhenBooted { server_fx.initTree; }
// initialize CroneEffects with server_fx 

CroneEffects will need minor refactor to use SoundIn instead of AudioContext busses.

(NB: .doWhenBooted is the equivalent of .waitForBoot for remote servers; .initTree is necessary, or there is no root node and you can't create more nodes. this was non-obvious to me.)

somewhere (matron?):

  • use jack API to connect scsynth processes to each other, and to the ADC/DAC. (non-obviously, this doesn't appear to happen automatically unless the servers are created from sclang - when launched directly, either SC_JackDriver::ConnectPorts() isn't being called, or is failing silently.)

open questions:

  • not clear to me how the jack client names are assigned. in this case they always seem to be SuperCollider and SuperCollider-01.

  • need to dig into jack API to see how to list clients / ports. this seems like a simple project to look at: https://sourceforge.net/projects/njconnect/

  • there are different options for routing:

    1. engine can have 4 output channels; 2 connected to DAC, 2 to fx. change engine->FX routing by modulating the send levels here.
    2. engine can just have 2 outputs and always go through fx server; change engine->FX routing by modulating mix levels on fx server.

in either case i think it makes sense for fx server to grab ADC inputs directly for monitoring and processing, minimizing latency there. so fx server needs 4 input channels, 2 outputs.

option 1 minimizes latency for engine output without fx. but option 2 makes it simpler to monitor levels; it would also prevent comb-filtering artifacts from blending dry and wet engine signal. so, i dunno.


in future, matron could run its own audio process as a jack client, and take over routing / metering / recording duties.

@samdoshi
Copy link

@samdoshi samdoshi commented Nov 6, 2018

One suggestion regarding the Faust based effects. Could you not recompile them as Jack clients and then run them outside of SuperCollider.

I can't say I'm an expert on anything Faust related, but there are some faust2jack* binaries listed in the documentation (as well as other targets for LV2 and LADSPA).

Might be an alternative route to spreading the CPU load, and it would also allow reverb tails to survive scserver restarts (which might make that viable thing to do on engine changes).

(Also, would it be a good idea to add the Faust source for the 3 effects into the repo?)

edit:

For a socket controllable LV2 host see: https://github.com/moddevices/mod-host

@catfact
Copy link
Collaborator Author

@catfact catfact commented Nov 7, 2018

thanks sam. we are actually looking at those very things right now. in the short term it's not any easier to run mod-host or jalv than it is to run another scsynth, but we will likely support those things in the future.

embarassingly, i actually lost the .dsp files for FaustZitaRev and FaustCompressor somehow. i think they were on a norns that got wiped before they were checked in. they are pretty trivial though, basically one-liners from the standard lib and easy to recreate if needed. (the reverb is the zita-rev1 reverb from the faust stdlib, with regalia-mitra peaking EQs on the output. the compressor is the stdlib compressor, unmodified.)

(BTW: for our purposes it might be best to make a minimal architecture file instead of relying on the faust2foo scripts, which tend to be, i dunno... opinionated.)

@catfact
Copy link
Collaborator Author

@catfact catfact commented Nov 25, 2018

we're moving forward on our plan to take effects and routing out of SC entirely. currently this is a simple custom jack client with hardcoded effect blocks, but in future maybe we will end up forking mod-host.

PR #650 tracking progress on that.

closing this since it is basically covered by issue #296

@catfact catfact closed this Nov 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants