Zynthian Engine Preset Structure
The relationship between a zynthian it's engines and how settings are stored has grown over the years and like much of the project ever growing.
Suffice to say You need an engine to make things happen. Which is where most of us would start . .
The zynth starts up with nothing loaded, althou' it should quickly build up your last state as you start to do things. . .
But it's really all engines as this stage and you want to load one up to use it.
The Synth Layer is the first to consider this will allow selection of a range of synthesizer like devices that get automatically connected to a MIDI channel (more on this later, hopefully) and the default audio available outputs, which will outside of a few crazed individual connections will be the left and right output of the zynthian, available as two audio sockets for further abuse in other kit.
There are several available.
Now some of these are sound sampler base (Fluidsynth, Linuxsampler, SFizz . . . ), others are genuine synthesizers (ZynaddSubFx, Dexed, Helm,) still others are specific models of existing instruments (Pianoteq, Aeleous,) and others are strange weird, wonderful and possibly untested, collected from the more fetid areas of the Internet, So be aware.
The Zynthian simply serves up engines from elsewhere. It isn't responsible for those engines, offering only a standardized approach to handling them.
But mindful of this warning, things start to look very good, because an awful lot of people have got together over this and within the Linux based world in which the Zynthian lives, constructed some standards to define these sorts of things.
This is an agreement to produce a set of software rules about how audio devices interact within the linux audio world, and allows description of such objects via a Grammar framework on the Internet (https://www.w3.org/RDF/).
This is very helpful because one can describe pretty complex ideas like A 'filter control', or a 'MIDI note' or a 'sound file' and allow these ideas to be understood by machines as well as people. This is all laid out in TTL files (Turtle; computer humour... :-( ) , https://www.w3.org/TR/turtle/)
Luckily the zynthian is here to present all this to you in a nice easy to operate device . . .
Now ( sometime in 2021) not all engines are implemented as LV2 or even if they exist outside of the zynthian's LV2 world, but these are probably exceptions rather than the rule so the code is still a bit of a hybrid in this area. . . :-D
The Traditional elements are still populated manually, Pianoteq is a bit of an exception but the LV2 based components already can be treated programmatically.
They all get an Character ID in the engine_info dictionary with JV/ jammed on the front if they have emerged from the LV2 world scan...
So we have an ordered dictionary of short Codes with a tuple of meta data:-
"ZY", ("ZynAddSubFX", "ZynAddSubFX - Synthesizer", "MIDI Synth", None, zynthian_engine_zynaddsubfx, True)],
and a zynengine import * takes care of presenting these engines from the zynengine directory to the code. So in this case the class instance for zynthian_engine_zynaddsubfx is extracted from the file /zynthian-ui//zyngine/zynthian_engine_zynaddsubfx.py
A you can see we start with some CC definitions applicable to a specific engine, by in large a lot of these are similar: For example:
But once you get onto something like Aeolus things ,obviously, get a little more complicated. But already the zynthian is specifiying Context for Engines and maintaining that environment for the specific engine assumptions.
It's just a big mapping !
That's how it works for the explicitly defined Engines, but for going forward LV2 offers a much for implicit path, which allows lists to be populated from information derived from the LV2 TTL files.
JALV starts to help
So we come to the python component that handles the LV2 bundles.
The list of engines visible came from a call to get_jalv_plugins()
There is a bit of defensive programmiing to prevent damaged files structures from stopping anything happening but the call is then handed up to
zynthian_lv2.get_plugins()in zynthian_lv2.py to do the gory stuff. . .
This is where the lv2 namespace is maintained from and acts as the conduit from the zynthian to the lv2 namespaces.
So what is this JALV business then? Why don't we just go straight to thr LV2 componenets that actually does the heavy lifting?
JALV is the software container that the LV2 component runs in that presents the LV2 objects defined in TTL files to the zynthian.
Well it's time to meet that most Linux based concept Jack.
Jack is the Audio server that runs under the control of the Zynthian.
Jack takes the hardware devices presented by ALSA and allows connections to be established in a highly consistent and connected way. It's jack that takes the data from an input audio port be that a Zynthian input on an Card or a USB connected Mixer, and passes it throu' an Audio Device defined by the Zynthian ( the next section after Synths :-) ) and presents it to the output connectors and also sending it to other places like the Audio Meters on the Zynthian GUI. It also does all this magic for MIDI as well, because MIDI & Audio in the Zynthian World are rather important concepts!. Jack deals with all this stuff and the zynthian is defining the relationships in the Jack Audio world. So as Engines ain't our concern as far as how they do what they do, the actual audio environment we are running isn't processed by us. But Jack has been around for a while and seems to work pretty well and is also rugged :-D.
The World of MIDI is slower than audio but a little more involved, as we can do some manipulation in this space to really aid the performer. Transpose a keyboard by an octave? Play a chord when one note is pressed ( Bontempi Mode :-) ). By using an LV2 component to do this sort of manipulation and get all the definitions from the declared namespaces means we can make solid assumptions about precisely what effects on the sound environment we are controlling.
But there needs to be an important component in the zynthian world to handle the MIDI as it moves in and out of the zynthian, and this is the zynrouter. This engine is a C component and does magic :-D. This allows the zynth to manage several seperate MIDI environments that might well involve all kinds of complicated shenanigans. Oh there's a sequencer down there as well . . .
And all from the zynthians setting up a few electronic conversations.
Jack does this on our behalf and is probably the single most important component around which the zynth is built. Certainly from following this evolutionary path it's possible to see the advantages of an open source environment at their most visible ! :-D
Where it gets stored
So once an engine has been started up what else does it need to know?, given it's MIDI components, parameters and Audio in's and outs have been nicely presented to the user. How do we store all this state we are generating?
In the Pre LV2 age it was all explicitly defined in the code, but we can now do better. We want to be able to add,enable and disable these lv2 components that we could get hold of from 'sources' or indeed write ourselves and offer to others...
What maintains the LV2 zynthian universe?
Well there are three basic places lv2 bundles live.