presently the ENGINEs are written in supercollider.
with 3.0 we want to facilitate ENGINEs in many environments such as pd, chuck, and custom DSP.
ENGINEs were actually never the main focus in my initial design of norns— i was (and continue to be) highly focussed on the incredible combination of lua + softcut. softcut was first implemented in supercollider. and the availability of supercollider meant we could create additional DSP easily, and we did, and called them engines. then @zebra did a massive rewrite and now softcut is standalone. now it feels like engines should be extended to a more general idea of external DSP applications.
there are a few major components to this goal:
standardizing the OSC exchange to establish what constitutes and “engine” (right now some of this is abstracted within supercollider)
engines will use a lua metadata file rather than the existing query/report process (which will simplify management of engines)
start/stop procedures for different engine environments (likely systemd) and details therein
@jah has written up details on the norns github wiki which includes a how-it-works-now section and links to some example engine lua metadata.
i’m posting this to promote discussion about this direction forward and also invite code contributors. norns is a very interesting, diverse codebase (i’ve learned a ton working with everyone on it) and with the prospects of pi-shields and desktop version (ie, run norns on your mac/linux) this ecosystem has the opportunity to be used by many more people— we’re looking to make it more expansive rather than have various forks. while i don’t expect it can be (or needs to be) everything to everyone, i do feel like the norns ecosystem could facilitate/accommodate a growing number of use cases (for example pd/orac and custom dsp, both of which the community here has vocalized interest).
i can’t promise a timeframe for 3.0, and we’ll certainly be releasing smaller updates in the coming months. (for example, i am enthusiastic to overhaul the PARAM system menu along with some way overdue fixes).
One thought that comes to mind with universal engines: one thing that I’m super impressed by is the effect support in SuperDirt (the TidalCycles sound engine in SC). There are a ton of effects in there, and they’re only activated as needed on a per-orbit basis.
Right now, one of the key norns features is that softcut is always available to every lua script. I think it would be really cool if we extend that to treat other C++ effects like plugins. We’re sort of there with the main output reverb and delay. What I imagine is something like SuperDirt, where there are a large host of effects and each script can summon them as needed. That way, we can have three different reverbs and use the most relevant one on each script (instead of one size fits all), or quickly access a library of saturation functions to add tape vibe to the output, etc.
abstracting the AUX and INSERT fx is certainly an interesting side-proposal… for example, making matron an LV2 host. if this is something you’d like to pursue and discuss i might suggest we start another thread. (edit: proceed below!)
this doesn’t need to be hard - also imho not necessarily unrelated to the thread. it has been at the back of our minds for a while.
at present the AUX and INS effect parameters are hardcoded into multiple layers of the norns ecosystem. so it would be easy to add a light abstraction layer to the processing, and switch out different DSP implementations using the same parameter sets.
the compressor and reverb algos are basically off-the-shelf Faust programs, so if people wanted to use Faust to roll their own implementations then that is trivial to provide a general Faust build script, and a means of switching between any number of static instances of AuxEffectChain and InsertEffectChain or whatever. (i suppose we could even make all the parameters work with abstract unit ranges, or something.) (same applies of course if people want to implement algos in C/C++.)
on the other hand, allowing crone to instance arbitrary FX chains with arbitrary parameters, is a different proposition. still doesn’t need to be very hard on the crone side - a simple stereo chain is easy to manage, and the OSC/IPC interface [*] can be dynamically regenerated without too much trouble.
but requiring dynamic parameter management means that these arbitrary AUX and INS chains start to look exactly like engines. and in that case i suppose i would simply implement them as such - two additional “engine slots” that take the aux and output busses as their inputs, instead of the ADC bus, but otherwise function identically to other engines in 3.0 proposal: correspond to arbitrary DSP processes and present their parameter metadata as lua files. doesn’t matter if they are supercollider patches, pd patches, mod-host instances, or something else.
[*] side note: i’ve been meaning to replace OSC as the matron -> crone IPC layer, for many reasons. assuming this can get done, the resulting efficiency improvement might be an argument for keeping the effect chain DSP within the crone process.
i’m nervous about the complexity of treating AUX/INS like extra “engines” regarding the param exchange and additional application loading.
but i do like the idea of adding the possibility to switch between instances of built-in crone/faust FX. this seems like a great place for DSP extensibility in crone with minimal overall system complexity, if we give some thought to param management.
Is there enough horsepower in Norns at this time to handle the sort of computational complexity being discussed here in a live environment? I’m all for ambitious software roadmaps but overall platform stability and hardware capacity are the other two legs of the stool. I could be way off so thanks for humoring me.
i don’t believe anything in this proposal implies increased computational complexity per se.
(well, obvs if we add arbitrary FX algos then the cost of computing those is also arbitrary.)
we remove some architectural complexity by using static metadata files to describe parameters, rather than a dynamic descriptor table that matron and the engine environment (supercollider) have to collaborate in building at runtime over OSC. (the present situation - it’s scary and complex. has worked so far, but i’ll be happy to tear it out.)
we add some architectural complexity with the requirement to manage different DSP processes instead of just supercollider. this is minimized if we only have one process at a time and completely tear it down when switching engines.
as far as horsepower specifically, the nice thing about the architecture is that matron (lua), crone client (mixer, fx), softcut client, and the DSP engine(s) are each in separate processes, and we have 4 CPU cores. generally they are not gonna compete for cycles,
so, yes, arbitrary DSP engines need to be computationally efficient enough to run on one core without underruns, which is the same limitation presently applying to supercollider-based engines.
on mac, CLOCK_MONOTONIC is missing from the POSIX implementation, so metro.c won’t compile or function. it needs a platform-specific shim using mach_time or something. (this SO post has some hints but is not a complete solution.)
My thought was more that the Lua level would have easy access to an expanded collection of baked-in effects instead of them being automatically part of the parameter menu, kind of like how softcut is now instead of the master effects.
That way, the script author can determine what gets exposed to the user on the parameter menu, and what is managed by the script itself, if that makes sense.
For the initial 3.0, I’m thinking that these could just be some C++ files that are baked-in like softcut instead of a quickly-expanding plugin library. The focus could be on well-curated effects so that we could have a flexible reverb, or a tape saturation buddy for softcut, etc.
Design of how we’re to support multiple engine backends is well underway. There is quite some work to implement and test this thoroughly. To clarify, though, right now there’s no initiative taken to support running multiple engines (as in engine instances) at the same time. One script, one engine what we’re working on for 3.0… well, at least for now.
Arbitrary effects as discussed here I consider to be a new feature request, which obviously would be super-awesome to have. This can be solved in various ways, but IMO has not been planned or prioritized for 3.0… yet. The only thing close to this right now is the R engine.
One thing not yet mentioned in this thread is that we in 3.0 also will try to address a couple of serious issues with SuperCollider engines that happened as a consequence of breaking up the monolithic monome/dust repo - namely the class duplication problem. The idea we’re exploring for 3.0 is to move away from implementing engines as SuperCollider classes to implementing engines in interpreted sclang. This way, creating engines would be more like working in the SuperCollider REPL, so to speak, without recompilation of the SCClassLibrary and all the issues that it brings (… has anyone used Quarks? ). Interpreted sclang is also more similar to working with lua scripts. There are implications to this, of course, and we do not know if it will fly on the rpi (I’m wary of sclang performance). But if we can use interpreted sclang the big win is we will get away from a lot of engine installation issues and hassle users have been dealing with.
I’ve been an advocate for smoothing the rough edges of products my entire career, so it made my morning to read this. However you accomplish it, making the process of loading, using, updating and managing scripts a simpler and less-prone-to-badness one is a big win for the entire community. Thanks again.
Super cool, and hopefully I’m understanding the intent of engines correctly but I mean it’s a linux box too so! I’d be excited to try to port astrid/pippi to a norns platform. The intention being for it to run asynchronously in the background and push buffers to a realtime thread.
Astrid, which is the interactive front end to pippi I use for performance etc already works like this and uses JACK so from the little I have read about norns it shouldn’t be too crazy to integrate directly?
Selfishly if astrid/pippi ran on norns and I can just run norns on a laptop or NUC or whatever if I don’t care about the GUI or I/O this would be even more fun to me.
Anyway, I’m excited about these developments which I am late to the party on!
just voicing some vague interest in these since I don’t think anyone else has yet - I would love a way to write sample-level DSP on norns (C++ or faust would be fine) and I feel like it would be the best platform for building larger modular-type engines.