The Cabbage Standalone Host.The main Cabbage application that launches when you open Cabbage is known as the standalone host. This simple application 'hosts' Cabbage plugins in the same way any DAW hosts a plugin, but is restricted to one plugin at a time. The host also features a source code editor for editing your code, and a lets users activate a GUI designer so they can design interfaces using a simple drag-and-drop system. The host also takes cares of audio settings, allowing users to quickly change both MIDI and audio settings through Cabbage's options. If a user wishes to run an instrument as a plugin they can use the 'Export' option which will prompt them to export their instrument as an audio plugin. The plugin formats are currently restricted to VST and Linux Native VST. While the main purpose of the Cabbage standalone host is for prototyping and development, it can also be used as a fully blown production environment depending on the complexity of the hosted instrument.
An example of the GUI and source code editor.
Cabbage Instruments.Cabbage instruments are nothing more than Csound instruments with an extra <Cabbage></Cabbage> section that exists outside of the <CsoundSyntheszier> tags. Each line of text in this section defines a GUI widget. Special identifiers can be used to control the look and behavior of the widget. This text ultimately defines how the graphical interface will look. Instruments can be exported as either effects or synths. Effects process incoming audio, while synths won't produce any sound until they are triggered via the MIDI widget, or a MIDI keyboard. Cabbage makes no differentiation between synths and effects, but VST hosts do, so one must be careful when exporting instruments. A full list of available widgets, identifiers and parameters can be found in the Cabbage reference manual that comes with all Cabbage binaries.
A Basic Cabbage SynthesiserCode to create the most basic of Cabbage synthesisers is presented below. This instrument uses the MIDI interop command line flags to pipe MIDI data directly to p-fields in instrument 1. In this case all MIDI pitch data is sent directly to p4, and all MIDI amplitude data is sent to p5. MIDI data sent on channel 1 will cause instrument 1 to play. Data sent on channel 2 will cause instrument 2 to play. If one prefers they may use the massign opcode rather than the MIDI interop flags, but regardless of what mechanism is used, they still need to declare "-+RTMIDI=NULL -M0" in the CsOptions.
<Cabbage> form size(400, 120), caption("Simple Synth"), pluginID("plu1") keyboard bounds(0, 0, 380, 100) </Cabbage> <CsoundSynthesizer> <CsOptions> -n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5 </CsOptions> <CsInstruments> sr = 44100 ksmps = 64 nchnls = 2 0dbfs=1 instr 1 kenv linenr p5, 0.1, .25, 0.01 a1 oscil kenv*k1, p4, 1 outs a1, a1 endin </CsInstruments> <CsScore> f1 0 1024 10 1 f0 3600 </CsScore> </CsoundSynthesizer>
You will notice that a -n and -d are passed to Csound in the CsOptions section. -n stops Csound from writing audio to disk. This must be used when Cabbage is managing audio. If users wish to use Csound audio IO modules they need to disable Cabbage audio from the settings menu. The -d prevents any FLTK widgets from displaying. You will also notice that our instrument is stereo. ALL Cabbage instruments operate in stereo.
Controlling Your Instrument
The most obvious limitation to the above instrument is that users cannot interact directly with Csound. In order to do this one can use a Csound channel opcode and a Cabbage control such as a slider. Any control that is to interact with Csound must have a channel identifier.
When one supplies a channel name to the channel() identifier Csound will listen for data being sent on that channel through the use of the named channel opcodes. In order to retrieve data from the named channel bus in Csound one can use the chnget opcode. It is defined in the Csound reference manual as:
kval chnget Sname
Sname is the name of the channel. This same name must be passed to the channel() identifier in the corresponding <Cabbage> section. Cabbage only works with the chnget/chnset method of sending and receiving channel data. The invalue and outvalue opcodes are not supported.
The previous example can be modified so that a slider now controls the volume of our oscillator.
<Cabbage> form size(400, 170), caption("Simple Synth"), pluginID("plu1") hslider bounds(0, 110, 380, 50), channel("gain"), range(0, 1, .5), textBox(1) keyboard bounds(0, 0, 380, 100) </Cabbage> <CsoundSynthesizer> <CsOptions> -n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5 </CsOptions> <CsInstruments> sr = 44100 ksmps = 64 nchnls = 2 0dbfs=1 instr 1 k1 chnget "gain" kenv linenr p5, 0.1, 1, 0.1 a1 oscil kenv*k1, p4, 1 outs a1, a1 endin </CsInstruments> <CsScore> f1 0 1024 10 1 f0 3600 </CsScore> </CsoundSynthesizer>
In the example above we use a hslider control which is a horizontal slider. The bounds() identifier sets up the position and size of the widget. The most important identifier is channel(). It is passed a string "gain". This is the same string we pass to chnget in our Csound code. When a user moves the slider, the current position of the slider is sent to Csound on a channel named "gain". Without the channel() identifier no communication would take place between the Cabbage control and Csound. The keyboard widget can be used en lieu of a real MIDI keyboard when testing plugins.
A basic Cabbage effect
Cabbage effects are used to process incoming audio. To do so one must make sure they can access the incoming audio stream. Any of Csound's signal input opcodes can be used for this. The examples that come with Cabbage use both the ins and inch opcodes to retreive the incoming audio signal. The following code is for a simple reverb unit. It accepts a stereo input and outputs a stereo signal.
<Cabbage> form caption("Reverb") size(230, 130) groupbox text("Stereo Reverb"), bounds(0, 0, 200, 100) rslider channel("size"), bounds(10, 25, 70, 70), text("Size"), range(0, 2, 0.2) rslider channel("fco"), bounds(70, 25, 70, 70), text("Cut-off"), range(0, 22000, 10000) rslider channel("gain"), bounds(130, 25, 70, 70), text("Gain"), range(0, 1, 0.5) </Cabbage> <CsoundSynthesizer> <CsOptions> -d -n </CsOptions> <CsInstruments> ; Initialize the global variables. sr = 44100 ksmps = 32 nchnls = 2 instr 1 kfdback chnget "size" kfco chnget "fco" kgain chnget "gain" ainL inch 1 ainR inch 2 aoutL, aoutR reverbsc ainL, ainR, kfdback, kfco outs aoutL*kgain, aoutR*kgain endin </CsInstruments> <CsScore> f1 0 4096 10 1 i1 0 1000 </CsScore> </CsoundSynthesizer>
The above instrument uses 3 sliders to control the reverb size, the cut-off frequency for the internal low-pass filters, and the overall gain. The range() identifier is used with each slider to specify the min, max and starting value of the sliders. If you compare the two score sections in the above instruments you’ll notice that the synth instrument doesn't use any i-statement. Instead it uses an f0 3600. This tells Csound to wait for 3600 seconds before exiting. Because synth instruments are controlled via MIDI we don’t need to use an i-statement in the score. In the audio effect example we use an i-statement with a long duration so that the effect runs without stopping for a long time, typically longer than a user session in a DAW.
Where can I Download Cabbage?
Cabbage is hosted on GitHub, and pre-compiled binaries for Windows and OSX can be found at:
If you run Linux you will need to build Cabbage yourself, but instructions are included with the source code. You will need to have Csound installed.