Creating a new Zynthian Synth Engine
1 Creating a Zynthian engine
1.1 Prerequirements
Before starting to build your own engine you have to satify some facts:
- You need to know how to program in Python3.
- Some ideas about Git, GitHub (including an account) and how to clone, branch, pull, creating push requests are very useful.
- You should have some experience with using Zynthian to understand the workflow.
- You should have some ideas about working with Linux/Unix.
Before you start, check if your desired software for the engine would work with Zynthian:
- You need a binary/LV2-plugin compiled for the Raspberry (ARM Cortex-A architecture - NOT i386 or AMD64 (Intel/AMD CPUs)!!!)
- If you can get the source-code: nice! You have to write an installation script for compiling and installing, so you also need knowledge about shell-programing and compiler-tools (gcc, make, ...)
- Take a look at the license!!! It makes no sense if you write lots of code and don't find a way to license the software for working with Zynthian. Perhaps you also have to think about a way to get a license-key for your software into the system.
- Your software does not need a GUI. The controlling of your software should completely done via command-line/config-files/MIDI/OSC. If there is only a GUI control it may be impossible to write an engine.
- VST instruments are currently not supported! The only plugin format you can use is currently LV2 (inside MOD-UI engine).
- If you don't use a LV2 plugin, your software has to use JACK as audio-server.
- Think about that a Raspberry Pi is not a high tuned PC! It's really markable what a Raspberry Pi 3 is able to do with Zynthians engines - but the CPU is limited - so you should try to start your software without Zynthian for a first try. Check if you get audio-drops or not. Perhaps some tweaking of the compiler options can help - but this is not the topic of this article.
Ok, if you have read until this line and you are not already shocked from the prerequirements, it's time to share your idea with the Zynthian-Forum. You are not alone - and don't forget: Don't panic!. Perhaps some more hints and spoilers from others can help for your project.
1.1.1 LV2 plugins
If you plan to integrate a software which is a LV2 plugin, you only need to copy the data into '/zynthian/zynthian-plugins/lv2' and if you like you can create a nice MODGUI.
1.2 Write the engine
1.2.1 The filesystem structure
1.2.2 Files to touch/create
1.2.2.1 Engine XXX class file: zyngine/zynthian_engine_XXX.py
Implementing a new engine is not too difficult, but the details are a little bit tricky. Try studing the setBfree implementation. Probably it's the most simple. ZynAddSubFX is quite straightforward too.
- If you need to start the engine after knowing the MIDI channel, you should implement the add_layer function and "start" the engine there. In that case, don't call the "start" function from the constructor.
- If you want the layer can be moved to a different channel, you should implement the set_midi_chan. If your synth engine must be started with a fixed MIDI channel, you should restart the engine in the specified MIDI channel.
- For getting the presets, implement the get_preset_list function. It should return a list of "sets". Every preset "set" have this format:
(preset_file_path, (bank_msb, bank_lsb, program), title, extra)
The file path is a string that will be used by set_preset for loading the preset. No need to be a real file path. The second element is a set that can be used by set_preset for loading the preset using MIDI messages (bank, program). If not used, it should be None. The title is the preset name as shown by the UI. The 4th parameter is optional. Use it for storing whatever you need, related with the preset.
- If there is no banks, you should return an empty list in the **get_bank_list** function. The UI will ignore the bank screen and go directly to the presets screen.
1.2.2.2 zyngui/zynthian_gui_engine.py
For getting the new engine listed in the engine selection screen, you need to add some lines to zyngui/zynthian_gui_engine.py.
- Probably you also want (in a first approach) to avoid the possibility of starting more than one Pianoteq layer. For getting this, you would need to tune the zyngui/zynthian_gui_engine::fill_list function.
1.2.2.3 zyngui/zynthian_gui_layer.py
If you prefer to remove the option of "moving a layer to a differet channel" from the UI, you should add some dirty code in the zyngui/zynthian_gui_layer::add_layer function.
1.2.3 How to test
For testing your development, you should install your forked development version into your zynthian box. Something like this could do the job:
systemctl stop zynthian cd /zynthian mv zynthian-ui zynthian-ui.orig git clone https://github.com/#your_github_account#/zynthian-ui.git cd zynthian-ui git checkout #your_development_branch# /zynthian/zynthian-sys/sbin/zynthian.sh
For better debugging, i recommend to edit "/zynthian/zynthian-sys/sbin/zynthian.sh" and enable exception raising, like that:
ZYNTHIN_RAISE_EXCEPTIONS=1
For avoiding adding/commiting every time you change/fix something, i recommend copying the files directly to your zynthian box. This will avoid polluting the git history and simplify the development/test cycle. Once your changes are tested and your code stable, you can add/commit and sync your zynthian box from your development repo, like this:
cd /zynthian/zynthian-ui git checkout . git pull
This will overwrite your local changes and will take the latest changes from the repo.
1.2.4 How to get the software into Zynthian(-master)
If it's your first development for zynthian, you should get familiar with git and github. I recommend start "forking" in github the repository you want to work in (zynthian-ui) and creating a "branch" for your development. When you have a stable version of your work, you should make a "pull request" from your forked github repository.