It has come to my attention that there is a C++ framework to build audio plugins called JUCE. It is GPL licensed (sort of) and I’m working with it for a different project.
I noticed quite a while ago, MOD’s very own @falkTX added LV2 as a plugin output destination to the JUCE framework. Unfortunately, it appears the JUCE release manager never merged the code, which is a rather depressing end to this seven year long forum thread.
Is it unreasonable to fork JUCE since the authors don’t seem to care about LV2? I’m new to the framework and I don’t completely understand all its features.
AFAIK juce plugins have been problematic to bring onto the mod. There are several synths that were attempted to be brought to MOD by falktx (notably Tal Noiz3M4k3r and Helm) and were not successful. I don’t know the details of why, probably because juce had required dependencies that don’t make sense on a headless system and therefore aren’t installed on MOD.
juce based plugins are working for MOD now, and are already on the non-stable part of the store.
My juce fork contains LV2 and non-X11 support for events.
In my juce fork, if JUCE_AUDIOPROCESSOR_NO_GUI C++ macro is defined, GUI stuff (that relies on X11) does not get built.
So the result is a juce static lib that makes no calls to X11, freetype or any kind of graphics stuff.
Your own plugin code will need the same treatment. The createEditor() call needs to return null.
Almost all plugins in my distrho-ports project can build for MOD.
Since it was mostly a test, I skipped the plugins that would need a lot of work.
mod-plugin-builder already contains the build-stuff that makes part of the magic happen.
Now, if you want to do this yourself… make sure you know juce and making your own project files well (makefiles, waf, cmake or similar). Since the official juce does not support LV2 or MOD, you have to make the plugin build rules yourself - which is what I do in the distrho-ports.
EDIT: @ssj71 noisemaker already runs on the MOD, though you need 256 as buffer size to stop the huge amount of xruns.
ah I’m behind the times. Sorry!
Thanks for the clarification falktx.
HA! You already forked it. Right on. The thread I found was quite disappointing. I gathered some traditional FLOSS flame wars between the LV2 guy and the JUCE guy. I commend your resolve not to engage and keep making great work!
I was looking at your fork of Juce and noticed that you have worked on v7 with JUCE_AUDIOPROCESSOR_NO_GUI.
I have cloned your repo and am trying to build a basic plugin with nothing but trouble
Is this version working? Or is there another version I could try?
It works yes, if you have old juce7 branch get rid of it and use the main one. Still same repo, that is https://github.com/DISTRHO/JUCE/
But for dealing with this for MOD it is best to use the packaged juce7.
Which I realize now I never pushed… So this part is unfinished, I think I was meant to do some final validation
Best to use juce6 for now, you can follow these 2 project files as initial setup.
Then replace the juce local subfolder setup for a find-package, like so:
Super thanks for the info.
I got the v7 one building and deploying to mod-host, there was one ifdef missing in
#if ! JUCE_AUDIOPROCESSOR_NO_GUI
I’m going to try to get it onto the dwarf now, if I have issues I will have a look at the juce6…
I’m in no end of confusion here!
The issue I am getting with v7 is it flagging up missing includes for Moddwarf, x11 etc.
If I take the Crypt example and build it via the build script everything is fine, if I take the source and build after
source local.env moddwarf then I am back to the same issue I have with v7 but it is using
[ 13%] Building CXX object CMakeFiles/CryptSynthPlugin.dir/home/andrewcapon/mod-workdir/moddwarf/host/usr/include/JUCE-6.0.7/modules/juce_audio_processors/juce_audio_processors.cpp.o
In file included from /home/andrewcapon/mod-workdir/moddwarf/host/usr/include/JUCE-6.0.7/modules/juce_audio_processors/juce_audio_processors.h:56:0,
/home/andrewcapon/mod-workdir/moddwarf/host/usr/include/JUCE-6.0.7/modules/juce_gui_basics/juce_gui_basics.h:299:12: fatal error: X11/Xlib.h: No such file or directory
I must be missing something simple here?
I guess it is being patched somehow, I changed CMakeLists to add the JUCE_AUDIOPROCESSOR_NO_GUI define in and it gets further.
How is this patching being done?
For crypt the UI code is being put inside that
ifdef block so it is never used Changes for MOD build · moddevices/crypt@6dce4dd · GitHub
It is very important to remove
The mod-plugin-builder package includes extra patches that cannot go into the “generic” DISTRHO/JUCE one. see mod-plugin-builder/plugins-dep/package/juce6 at master · moddevices/mod-plugin-builder · GitHub
I had gone back to v7 and managed to get a juce example plugin built and running on the Dwarf.
Need a change to
juce_gui_basics.h line 322:
#if JUCE_GUI_BASICS_INCLUDE_XHEADERS && !JUCE_AUDIOPROCESSOR_NO_GUI
The main issue with it being plug and play is that they build a helper that loads the .so and creates the ttl files.
Its a bit of a catch 22, if you are cross compiling the tool will be able to read the cross compiled .so but you can’t run the tool.
If you build the tool for native you can run it but it can’t open the cross compiled .so.
I put in a PR#22 for those two JUCE_AUDIOPROCESSOR_NO_GUI changes.
I have removed that PR.
I have changed everything far beyond what you would probably want to merge as I guess it doesn’t fit in with the way you guys do things, useful for me though.
Now nothing would need patching to build for mod gear.
I have updated Projucer to add a new “Mod Linux Makefile” Exporter.
I have also changed the cmake stuff and added a flag CMAKE_MOD_DEVICES.
Hi. I’m interested in trying the JUCE approach out…not sure from all this what the current state of things is. Can I use latest JUCE to build mod plugins at this stage?
Yes and no… you can start to develop plugins based on juce, but dont expect to have them work on dwarf as-is at the moment.
Also, JUCE6 has my fork which provides a better experience on MOD though it needs a few extra implementation details on dev/your side; JUCE7 has the official LV2 implementation which, while it works on MOD, won’t allow to map/address parameters to hardware or MIDI CC for the foreseeable future.
Both options require using a patched JUCE, rather than your own custom or the stock version.
Do you already have a plugin you want to port over, or are you starting from scratch?
I’d be starting more or less from scratch. As well as building for Mod devices (my Mod Duo X, particularly), I’m interested in trying to use the JUCE7 LV2 implementation for building plugins for use in FFmpeg of all things (work-related stuff). Not a whole lot of experience in this area, but plenty of general dev experience though. So more would be necessary than adding a new Projucer Exporter? Although it sounds like @AndyCap did that, in some incompatible way, maybe?
So using JUCE7, you could build a plugin, but you wouldn’t be able to change any of its parameters on the device, is that correct? Only in the browser?
Obviously there is a point where JUCE7 becomes more of a hassle than not using it. It would be nice, though, to have a custom workflow (based on JUCE7) in place in the meantime. If and when full support comes (in the unforeseeable future!), I could then just remove the custom parts. Is my thinking.
So I need to examine your fork and then see how those changes could be patched to JUCE7 then, I suppose. I think I’d better get used to the standard non-JUCE workflow in the meantime though.
JUCE7 uses cmake, no Projucer needed any more.
I think if you are starting from scratch then from my experience trying it I wouldn’t use Juce if you are just developing for the Mod.
I wanted to port some Juce code over and in the end just took all the DSP code out and wrapped it up in an LV2.
The most painful thing about LV2 is the way parameters work currently, the nightmare ttl files and making sure all the ports are indexed correctly and match up in the code.
I ended up writing a little utility that read a ttl file without index numbers and wrote one with index numbers, this way if you want to add in a port/parameter you don’t need to re-index manually. Obviously if you only have a few parameters you probably don’t need this.
Also if you have a lot of parameters then come up with some code that makes connecting them up in
ConnectPort() and processing them
Run(). So something like a
Params class that handles a group of parameters, this can connect things, check if params have changed, check all params are correctly mapped etc.
Getting param index mismatches can cause issues that are pretty hard to track down so it is important to get this bit right.