ghostess and dssi

2009/12/22

Another tutorial, this time on how to use ghostess with DSSI plugins and how to integrate all this into small session scripts.

The Disposable SoftSynth Interface (DSSI) is one of the plugin standards in Linux.

DSSI plugins can be hosted in sequencer applications like MusE, Qtractor or Rosegarden. Due to my bias towards modular systems and since I am using Seq24 for sequencing, my choice was ghostess,

Ghostess is a simple stand-alone DSSI host. It creates one Midi input port and audio I/O ports as specified by the plugins loaded. Those can then be connected to other applications using e.g. qjackctl. Though the code, according to its README file, claims to be ‘sloppy, hurried HACKWARE’ it runs just stable.

I highly recommend to obey to the README file’s name, you might even stop here and go right away to the original source. What follows is more a verbose description of some aspects regarding usage and workflow rather than the reference manual.

ghostess GUI

ghostess GUI

The user interface (UI) lives somewhat in between the worlds of command line interfaces (CLIs) and graphical user interfaces (GUIs).
To start ghostess the first time, a command line needs be assembled, defining the plugins to load and optionally some more properties.
While running, the UI is graphical; loading native plugin GUIs where present or creating generic ones otherwise. Just dynamic loading and removal of plugins is impossible.

A bit surprising at first: The File menu has only an option to ‘Save Configuration…’, no way to load anything. Loading is simply done by executing the saved configuration file.

installation

Many Linux distributions provide a package for ghostess. If this is the case, the best and most simple way of installation is using the distribution’s package management tool.

Ghostess can be built for either Jack-Midi or Alsa-Midi support, so If the packagers choice differs from your preference it becomes necessary to manually compile the source code.

Download it from http://smbolton.com/linux.html

unpack it,

$ tar xvjf ghostess-20100923.tar.bz2

then change to the newly created directory.

$ cd ghostess-20100923

Configure it, omit --with-jackmidi to build for Alsa-Midi,

$ ./configure --with-jackmidi

and build.

$ make

As root, (optionally) install it

$ make install

running ghostess

Start ghostess with fluidsynth-dssi and nekobee simply by this:

$ ghostess fluidsynth-dssi.so nekobee.so

The plugins reside in /usr/lib/dssi or /usr/local/lib/dssi. List all .so (shared object) files in these directories to find the plugin names.

$ ls /usr/lib/dssi/*.so /usr/local/lib/dssi*.so

the lsdssi script

To avoid hand editing too much I wrote a little ‘lsdssi’ script to list all plugins from /usr/lib/dssi in one line, seperated by whitespace.

#!/bin/bash
echo `ls /usr/lib/dssi/*.so | \
sed 's/\/usr\/lib\/dssi\///' | \
tr "\n" " "`

ghostess could then be started with one instance of each installed plugin by typing

$ ghostess `./lsdssi`

However, this will usually not make much sence, except maybe for testing purposes.
In practise, you will more likely type ./lsdssi and copy paste from the output.

more options

An example, for loading more than one instance of each plugin:

$ ghostess \
fluidsynth-dssi.so \
fluidsynth-dssi.so \
fluidsynth-dssi.so \
sineshaper.so \
sineshaper.so

which is just the same as this somewhat more elegant version:

$ ghostess \
-3 fluidsynth-dssi.so \
-2 sineshaper.so

If not specified, ghostess assigns Midi channels counting from zero, following the order the plugins are given on the command line. Accordingly, in the case of the above command, the three instances of fluidsynth-dssi listen on channels zero to two, the sineshapers listen on channel three and four.
Custom Midi channels, deviating from this rule, are specified via the -chan option:

$ ghostess \
-3 -chan 4 fluidsynth-dssi.so \
-2 -chan 10 sineshaper.so

Look at the output of the command to see how the assignment is done.

configuration files

Since the configuration files ghostess saves are human readable Bourne shell scripts, saved plugin configurations can be recombined by hand editing.

The first lines of a saved ghostess configuration file starting with nekobee, fluidsynth-dssi and sineshaper:

#!/bin/sh
DSSI_PATH='/usr/lib/dssi:/home/epikur/.dssi:/usr/local/lib/dssi'
export DSSI_PATH
exec ghostess \
-comment 'nekobee/nekobee/inst00' \
-chan 1 \
-prog 0 0 \
-port 1 1.0001 \
-port 2 1 \
-port 3 26.9828 \
-port 4 0.475025 \
-port 5 0 \
-port 6 0.0005 \
-port 7 0.829218 \
-port 8 1.01 \
'nekobee.so':'nekobee' \
-comment 'fluidsynth-dssi/FluidSynth-DSSI/inst01' \
-chan 2 \
-conf 'load' '/home/epikur/audio/soundfonts/hs_techno_drums.sf2' \
-prog 0 0 \
'fluidsynth-dssi.so':'FluidSynth-DSSI' \
-comment 'sineshaper/ll-sineshaper/inst02' \
-chan 3 \
-conf 'reloadprograms' '' \
-prog 1 2 \
[...]

The sections belonging to each plugin begin with the -comment line, so splitting or combining them is reasonably easy. Make sure you adapt the number following inst and the -chan values.

ghostess in session scripts

Finally, an example of how ghostess can be invoked from within a shell script; extending the last example from this tutorial.


#!/bin/bash
seq24 --manual_alsa_ports \
--priority \
--jack_transport \
--file seq24/seq24.mid &
sleep 2
yoshimi -l yoshimi/yoshimi01.xmz &
sleep 2
## the ghostess startup command initially used:
#ghostess \
# -chan 8 nekobee.so \
# -2 fluidsynth-dssi.so \
# sineshaper.so &
## now invoke the configuration script
./ghostess/ghostess.conf &
sleep 3
ardour ardour/ardoursession/ardoursession.ardour &
sleep 4
jack_snapshot restore jsnap/snapshotfile --noclear

Thanks to Sean Bolton for this smart little application.

This tutorial will lead beginners through the process of writing small scripts that open audio sessions with interconnected applications.

Some familiarity with Linux audio applications and simple use of the command line might be useful, if you lack these and you are still interested, work through the material behind the respective link and use google. Familiarity with shell scripting is not required. I recommend one of the pre-tweaked Linux audio distributions.

general concepts

One common difference between open source and proprietary software is the level of modularity. Commercial solutions more often offer one big application with many features, whereas in the Linux world applications tend to be smaller and more specialized.

Usually these small tools can easily inter-operate and communicate by means of open standards, to solve complex tasks together in modular systems. Much as in good old analog audio, where usually a bunch of devices work together, interconnected by standardised audio and Midi signals via cables.

In the case of Linux audio software there are a number of standards for communication among programs.

Jack for instance does the audio routing between all inputs and outputs provided by the applications and the soundcard. Jack also provides transport synchronisation via Jack Transport.

The case of Midi is a bit more involved, explained here and here.

bash session scripts

This modularity is great, apart from one disadvantage: there is not yet one ‘load session’ button and one ‘save session’ button. This is what the LADCCH, LASH, LADISH and JackSession projects aim(ed) to accomplish. LADCCA is since long discontinued, LASH appears to be dormant but is still supported by a couple of apps, LADISH and JackSession are still alive.

If one of these works for you, use it.

If this is not the case, which might occur at some point due to a lack of support on the applications’ side, scripts are a good option to accomplish the task of restoring a session. They save much time and lead to less errors compared to starting apps manually, by introducing a reproducible procedure.

Ideally, you execute the script, wait a few seconds and continue to play/work, without having to adjust a single knob or fader to regain the previous state. Picture it as writing a new audio application, written in a scripting language.

Ideally, the only practical difference to the monolithic proprietary application is the lack of the single save button. Call it a feature — being able to decide in which apps to save changes after some tweaking can be an advantage.

I am saying ideally above, because this does not always work as easy as with the monolith. It is largely a matter of carefully selecting well behaving applications and plugins that fit your needs.

Depending on what you intend to do, all this might be a little more work than setting up a monolithic app. The upsides are more flexibility and most likely a unique sound. Once you have template scripts for basic tasks it takes little effort to create a new session.

the script I

The Bash scripting language is used for the examples. If Bash is new to you, this might be a good occasion to look into its documentation. If you don’t feel like working through all that, this tutorial will get you to write scripts for simple tasks. However, some background knowledge is helpful, especially when it comes to troubleshooting.

Use an adequate text editor like gedit, scite, vim, emacs or the like to write the script. Do not use anything that does text formatting, such as OpenOffice or Abiword.

For the sake of simplicity I will omit most background information and stick to simple one-command-per-line scripts.

First create a session directory to put everything in, change to that directory and start a text editor.

The first example is a script for starting Aeolus to be played using a Midi Keyboard.

Every bash script begins with the line #!/bin/bash, followed by the instructions.

A script for starting Aeolus.

#!/bin/bash
aeolus

In all examples I will assume that Jack is allready running. To invoke it from within the script, add the content of your ~/.jackdrc file as a first command.

Save that file using any name, e.g. aeolus.sh, to your session directory and make it executable by executing

$ chmod u+x aeolus.sh

To execute the script, type

$ ./aeolus.sh

This just starts Aeolus, so next two kinds of connections need to be made — audio and Midi.

audio connections

The command line tools are jack_connect and jack_disconnect (The latter especially helpful against this nasty behavior of some apps to auto-connect to the soundcard on startup). jack_lsp lists all existing ports. Use the --help or -h option to read all about usage.

The syntax is actually simple:

$ jack_connect <out_port> <in_port>

alsa-midi connections

aconnect works much the same way for Alsa-Midi as jack_connect for Jack-audio. aconnect -io will list all Alsa-Midi input and output ports. See the output of aconnect (without options) and man aconnect for the details.

some remarks on making connections

Each port name consists of two parts seperated by a colon: client:port. In the case of jack_connect, the full client names are required, for aconnect a character string matching a part of the client name is sufficient.

Some clients (e.g. Yoshimi) use the same Alsa-Midi client name for all running instances. aconnect will only connect the first occurrence when fed with an ambiguous client name. Use the client ID instead of a matching string in such a case, e.g. aconnect USBmidi:1 130:0.

Note that all port names used below are just examples, simple copy-pasting may not work. The listing tools will reveal the names on your machine. Assemble and test the commands in a terminal and complete the first example.

#!/bin/bash
aeolus &
sleep 2
jack_connect aeolus:out.R  system:playback_1
jack_connect aeolus:out.L  system:playback_2
aconnect USB\ Device:1 aeolus:0

The script explained:

After Aeolus is started, jack_connect is invoked twice for connecting the two audio outputs of Aeolus to the soundcard. aconnect connects an external USB Midi keyboard to Aeolus.

The backslash in the string USB\ Device:1 is an escape character. When interpreted on execution, the character following the escape character (here whitespace, wich happened to be part of the device name listed by aconnect) will lose its special function as a seperator. An other option would be to use quoting and write

aconnect 'USB Device':1 aeolus:0

Read more about quoting here if you want.

The & symbol in the line aeolus & puts Aeolus in the background so that the terminal is ready for receiving more commands. Without it, the terminal would remain occupied and no further command would be executed as long as Aeolus is running.

The second command, sleep 2, interrupts execution for two seconds to give Aeolus’ ports a little time to come up before attempts are made to connect them.

jack-midi connections

aconnect only connects Alsa-Midi ports. Jack-Midi connections are done with the same tools as Jack audio connections.

In the case of Aeolus, supporting both Midi systems, the aconnect command can be substituted by jack_connect.

#!/bin/bash
aeolus &
sleep 3
jack_connect aeolus:out.R system:playback_1
jack_connect aeolus:out.L system:playback_2
jack_connect system:midi_capture_3 aeolus:Midi/in

Which way to choose depends on the Midi driver in use.

Unless you use ‘Raw’ as the Midi driver in Jack, using the Alsa connection gives a shorter Midi signal path.

Thus, if you have the choice, use aconnect to connect any hardware Midi device to an app, Jack-Midi-only apps are connected via the Jack tools.

If all apps you are using happen to have Jack-Midi support, forget the two paragraphs above. Then you can perfectly use ‘Raw’ as the Midi driver to omit Alsa and do all connections with the Jack tools. For the backgrounds and for methods to bridge between Alsa-Midi and Jack-Midi, (re)read the explanations linked above in the ‘general concepts’ section.

jack_snapshot

jack_snapshot is a command line tool to store and restore Jack connections.

Using jack_snapshot instead of jack_connect, the Aeolus startup script would look like this:

#!/bin/bash
aeolus &
sleep 3
jack_snapshot restore aeolus_snap

The file named ‘aeolus_snap’ then of course needs to exist. To create it, start the applications, establish all required connections manually, then execute

$ jack_snapshot store aeolus_snap

the script II

Now an example for Seq24 synced with Ardour. Seq24 is sending virtual Midi to Yoshimi, Ardour is recording the audio output.

I will proceed in two steps. A first draft of the script starts all applications, maybe with some appropriate options. appname -h or appname --help will usually reveal the secrets.

#!/bin/bash
seq24 --manual_alsa_ports \
--jack_transport &
sleep 2
yoshimi &
sleep 1
ardour &

(The \ character is used to escape (ignore) the line break, just for readability.)

When this script is executed, Ardour will let you create a new session. Select Jack-Sync and add tracks or busses as required, then manually establish all Jack connections.
Do some editing in Seq24 and yoshimi and save the files to the session directory, create a snapshot with jack_snapshot.

Extend the script accordingly, e.g.:

#!/bin/bash
seq24 --manual_alsa_ports \
--priority \
--jack_transport \
--file seq24.mid &
sleep 2
yoshimi -l yoshimi01.xmz &
sleep 2
aconnect seq24:1 yoshimi:0
sleep 1
ardour ardoursession/ardoursession.ardour &
sleep 3
jack_snapshot restore snapshotfile --noclear

The sleep time needed in between the applications can vary, depending on soft- and hardware. Start with plenty of time, since too short intervals might cause problems. Reducing these can be done as a later step of optimisation.

Connections from, to or within Ardour will be done by Ardour itself when loading a session. Redoing them with jack_snapshot doesn’t hurt as long as the --noclear option is used, otherwise Ardour might crash with the message: “critical: event pool out of memory – recompile with larger size!!”. In the above case jack_snapshot is somewhat superfluous, since Ardour is involved in all audio connections.

paths

For running the above script, the files loaded and the Ardour session file all need to be in the same directory together with the script. This is no general necessity, it just makes the script as simple as possible.

Something else might be more convenient. For instance a base directory holding several session scripts and separate subdirectories for each single app to keep its patches and configuration files all in one place.

With slight changes to the paths (the places to look for files) the script could be adapted to that environment.

#!/bin/bash
seq24 --manual_alsa_ports \
--priority \
--jack_transport \
--file seq24/seq24.mid &
sleep 2
yoshimi -l yoshimi/yoshimi01.xmz &
sleep 2
aconnect seq24:1 yoshimi:0
sleep 1
ardour ardour/ardoursession/ardoursession.ardour &

In all cases above, the paths given are relative paths. All files need to be either in the directory where the script is executed or in any (sub…)subdirectory. This is useful for porting the session to a different computer and it makes backups easy.

Instead of relative ones, absolute paths can be used — this might as well be useful in some setups. An absolute path gives the whole path from the root directory like /home/epikur/yoshimi/bass.xmz. If all paths given in a script are given as absolute paths, the script can be located and executed in any directory.

For portability to other users than epikur, the hard coded user can be replaced by the environment variable ${HOME} like this: ${HOME}/yoshimi/bass.xmz

A possible use of an absolute path could be to point to an Ardour session that is stored on a data-partition somwhere outside the session directory.

#!/bin/bash
seq24 --manual_alsa_ports \
--priority \
--jack_transport \
--file seq24/seq24.mid &
sleep 2
yoshimi -l yoshimi/yoshimi01.xmz &
sleep 2
aconnect seq24:1 yoshimi:0
sleep 1
ardour /usr/share/audiodata/ardoursession.ardour &

kill script

It is handy to have a little kill script for terminating the session. An example:

#!/bin/bash
echo === attentione ===
echo "really quit? you have 3 seconds..."
sleep 3
echo "...killing session..."
killall -w seq24
killall -w yoshimi
killall -w ardour-2.8.4
echo "...session dead."

jack_snapshot script

another useful helper:

#!/bin/bash
jack_snapshot store snapshotfile

backup

After some effort is put into developement of scripts and sessions, backup your session directory:
$ tar -cvjf session/ session0910.tar.bz2

Copy the tarball to at least a second storage device, hardware tends to fail sometimes. Sure, the whole backup process can be automated as well, but that would be another posting of its own.

Follow

Get every new post delivered to your Inbox.