Get the demo code
The code demonstrated during and after the presentation is available on GitHub, in two separate repos:
- VanillaJuce is the basic JUCE-based synthesizer plug-in.
- The master branch is the original plug-in, written as a simple JUCE tutorial example.
- The network branch adds the changes necessary for remote DSP execution.
- VanillaJuceNet is a JUCE-based, standalone, command-line program which wraps only the DSP code from VanillaJuce (the identical code, not a modified version) as a network service.
You will need to clone (or download) both repos. Make sure to put them in sibling folders; the VanillaJuceNet projects point directly to the VanillaJuce DSP code files, assuming they are in a sibling folder called VanillaJuce.
Both repos make use of Projucer files (extension ".jucer"). You will need to open these in the JUCE Projucer and generate whichever target projects you requre, because neither repo contains the JUCE library. The VanillaJuce plug-in can be generated for any supported plug-in target type, e.g. Windows VST[3], Macintosh AU, etc. The standalone VanillaJuceNet program can be generated for Windows, Macintosh, or Linux. (The Linux version was demonstrated at ADC2018.)
Modifying your own JUCE-based plug-ins
By perfoming a diff operation between the two branches of the VanillaJuce repo, you can see exactly what changes are required. You will see that most of them are related to adding GUI components to support the newNetwork tab. The basic changes involved are:
- For the plug-in itself, the existing PluginProcessor-derived class receives a new DSPClient member, and its processBlock() function is modified to allow the option either run locally as usual, or remotely by delegating to the DSPClient's processBlock() function:
- Appropriate controls must be added to the plug-in GUI to allow user entry of the remote server's IP address and port, and to switch between local and remote DSP operation.
- A few other minor changes may also be needed on the plug-in side, to facilitate serialization of parameter updates across the network connection, and to ensure that there are no noticeable changes in the plug-in's operation as it is switched between local to remote DSP modes.
For the server side, the DSP parts of the code are isolated and wrapped as an instance of a new DSPServer class, which contains generic code for accepting incoming network connections, performing per-buffer DSP operations repeatedly, and gracefully shutting down connections.
The DSPClient and DSPServer classes are generic, and as such should work for any plug-in. They are not very sophisticated. All they do is set up and tear down network-socket connections and transport basic MIDI events, parameter-update events, and audio between your plug-in and its remote-DSP counterpart. You will undoubtedly want to extend this code to add more features, but I have deliberately kept it very simple, to avoid obscuring the basic operation.
On working with networks
If you haven't written and debugged networking code before, you will have to learn some new skills. It's not practical for me to provide a complete beginner's guide to network programming here, so you are on your own. Some basic points to be aware of:
- You should probably set up a test network, with just two computers on it. Connect them with a network switch (or even an Ethernet crossover cable), and configure the network interface cards (NICs) on each machine to use fixed IP addresses, e.g. "192.168.1.1" and "192.168.1.2". Every NIC on your network must have a distinct IP address, and should be on the same subnet. (If you don't know what that means, you need to bone up on TCP/IP network technology before you go any further!)
- Use Gigabit Ethernet. Do NOT mix 100-baseT and 1000-baseT (Gigabit) Ethernet NICs. Grief will result.
- Don't even think about using Wi-Fi. Massive grief will result.
- You will need to open at least one network port on whatever software or hardware firewall your server machine uses, or it won't be able to receive incoming socket connections.
- Understand that network protocols generally require that both sides of a connection remain active. Therefore, do not use breakpoints in network code until you know what you're doing. Be prepared to use old-fashioned print statements for debugging.