Search

Linux MIDI: A Brief Survey, Part 4

In this installment of our tour of Linux MIDI software, we look at some
experimental MIDI music-making environments. I've divided this class of
software into command-line and GUI-based applications. Regardless of
interface, the user is expected to employ a more than average amount
of brainpower to get the best results from this software. With that
warning in mind, let's first look at some language-based environments
designed for the experimental MIDI musician.

Improv

Craig Stuart Sapp's Improv is designed for an interactive
performance-oriented environment for experimentally minded MIDI
musicians. The system currently is available as a package that includes
a library of C++ classes optimized for MIDI I/O and a set of examples
demonstrating the functions and capabilities of those classes.

Improv controls real-time MIDI communication between a host
computer and an external synthesizer. In a typical program, the computer
receives MIDI input from the synthesizer, immediately alters that input
in some preprogrammed manner and sends the altered data stream to the
specified MIDI output port. Some Improv examples have the computer
produce a MIDI output stream that can be altered by the external
keyboard, creating interesting possibilities for a musical "dialog"
with the program.

The following small program inverts the note-numbers of a MIDI keyboard,
0-127. Thus, if a player plays the series of pitches C-D-E, two whole
steps upwards, the Improv program converts the series to C-Bb-Ab, two
whole steps downwards, at the same time. With MIDI Thru enabled,
the normal and altered lines produce sound simultaneously. The code is
from the set of examples provided in the Improv package. For brevity's
sake, I've edited Craig's comments, but the entire listing is available on-line
here.

// An Improv program that inverts the incoming MIDI note numbers.
//
// Header for synthesizer I/O programming
#include "synthImprov.h"
/*------------- beginning of improvization algorithms ------------*/
/*- ------------- maintenance algorithms ------------------------*/
// description -- Put a description of the program and how to use it here.
void description(void) {
cout << "plays music backwards" << endl;
}
// initialization -- Put items here which need to be initialized at the
// beginning of the program.
void initialization(void) { }
// finishup -- Put items here which need to be taken care of when the
// program is finished.
void finishup(void) { }
/*-------------------- main loop algorithms -----------------------------*/
// mainloopalgorithms -- this function is called by the improv interface
// continuously while the program is running. The global variable t_time
// which stores the current time is set just before this function is
// called and remains constant while in this functions.
MidiMessage m;
void mainloopalgorithms(void) {
while (synth.getNoteCount() > 0) {
m = synth.extractNote();
synth.send(m.p0(), 127 - m.p1(), m.p2());
}
}
/*-------------------- triggered algorithms -----------------------------*/
// keyboardchar -- Put commands here which will be executed when a key is
// pressed on the computer keyboard.
void keyboardchar(int key) { }
/*------------------ end improvization algorithms -----------------------*/

The main loop of this example performs a simple inversion of the incoming
MIDI note number and sends the result to the MIDI output port. The example
is fairly trivial, but its significance lies in its real-time action, by
which the inversion occurs at apparently the same time as the input.

The henontune example is one of my favorite demonstrations of
Improv's capabilities. When henontune is run, it produces a melody
generated by the Henon chaos mapping function. Incoming MIDI note-on
and velocity values control the parameters of the mapping function,
resulting in a new note stream that becomes cyclic, enters a
chaotic sequence or simply stops. The code listing for henontune
is too lengthy to print here, but it can be read on-line
here.

Improv can be used to create your own MIDI programming environment,
including non-real-time applications. The program's author has provided
control processes not only for typical MIDI synthesizers but also for
the Radio Baton and the Adams Stick. The package's documentation is
excellent and tells you all you need to know in order to create your
own Improv programs.

jMusic

One of these days, I will dedicate a column to the numerous interesting
music applications made with the Java programming language, one of which
is the excellent jMusic audio/MIDI programming environment. Like Improv,
the jMusic package provides a library of classes as well as
a set of useful examples to demonstrate the library functions and
capabilities. jMusic's API also lends the graphics power of Java to its
resources, giving the programmer the opportunity to create attractive
GUIs for his music coding endeavors.

An impressive amount of work has gone into jMusic development. The
resulting environment is a powerful cross-platform resource for music
composition, analysis and non-real-time performance. jMusic can be used
to create real-time MIDI note streams or it can produce standard MIDI
files. You can employ JavaSound for conversion to audio output, or you can
use the MidiShare environment to provide jMusic with flexible MIDI
I/O for routing output to external synthesizers, including softsynths.

The following example from the jMusic on-line tutorial demonstrates a
basic program that creates a standard MIDI file as its output. The
example is trivial, containing exactly one note, but it does indicate
how a typical jMusic program is organized.

// First, access the jMusic classes:
import jm.JMC;
import jm.music.data.*;
import jm.util.*;
/*
* This is the simplest jMusic program of all.
* The equivalent to a programming language's 'Hello World'
*/
public final class Bing implements JMC{
public static void main(String[] args){
//create a middle C minim (half note)
Note n = new Note(C4, MINIM);
//create a phrase
Phrase phr = new Phrase();
//put the note inside the phrase
phr.addNote(n);
//pack the phrase into a part
Part p = new Part();
p.addPhrase(phr);
//pack the part into a score titled 'Bing'
Score s = new Score("Bing");
s.addPart(p);
//write the score as a MIDI file to disk
Write.midi(s, "Bing.mid");
}
}

Compiling this code with javac Bing.java results in a file named
Bing.class. Running java Bing produces a Type 1
standard MIDI file that then can be played by any MIDI player or
sequencer, including TiMidity, playmidi, MusE and Rosegarden4. The jMusic tutorial includes the following
version of this program prepared for eventual output to an audio file
in Sun's AU format. jMusic applications typically first create a MIDI
stream that either is output as a standard MIDI file or is handed
off to JavaSound for translation to audio.

Compiling this code with javac SonOfBing.java produces the
SonOfBing.class file. Running java SonOfBing
opens dialogs for saving first the MIDI output and then the AU file.

The next example is a more elaborate program written by jMusic developer
Andrew Brown. The program is called NIAM--N Is After M--named in
homage to the famous M music software written by David Zicarelli. Again,
the code listing is too lengthy for inclusion here, but the source
may be obtained from the Applications page of the jMusic Web site (see
Resources). The screenshot in Figure 1 nicely shows off jMusic's GUI capabilities.

Figure 1. NIAM at Play

Up to four parts may be defined with separate settings for all parameters
seen in Figure 1. Output can be saved as a MIDI file, and despite its
non-real-time nature and its simple appearance. NIAM is a powerful little
program. Many other jMusic-based applications can be found on the jMusic
Web site, showing off capabilities such as melody generation by way of cellular
automata, music theory assistance and converting standard music notation
to a MIDI file.

jMusic's developers have gone to some pains to provide copious
documentation and tutorial material for the new user. The jMusic Web site
also provides pointers to general information about Java and its music
and sound features, and it offers guidance to other relevant materials
on computer music and related topics. If you already know Java, you
should be able to jump right in to using jMusic, but with the excellent help
available from its Web site even Java novices quickly will be
write their own jMusic tools and applications.

Q-Midi

Dr. Albert Graef describes his Q programming language as "a functional
programming language based on term rewriting". According to the
documentation, a Q program is "a collection of equations...used as
rewriting rules to simplify expressions". If this description is a bit
opaque for you, have no fear, the good doctor has supplied excellent
documentation and many practical examples through which you quickly
learn and appreciate the power of the Q language.

The Q package itself includes some basic MIDI routines, but the addition
of the Q-Midi module greatly expands those capabilities. In the Q-Midi
module, MIDI events are represented as symbolic data that should ease the
formulation of programs for manipulating and processing MIDI messages and
sequences. Q-Midi supports real-time MIDI I/O and the loading, editing
and playing of standard MIDI files, thanks to it being based on the GRAME
team's MidiShare, an excellent C library for cross-platform portable
MIDI programming.

The following code is taken from Dr. Graef's PDF introduction to
Q-Midi. It is an example of Q-Midi's use in algorithmic composition
based on a method of composing with dice, devised by the 18th century
composer Johann Kirnberger. Such methods were not new with Kirnberger,
but his technique lends itself nicely to expression through Q-Midi.

Kirnberger's method used the roll of the dice to determine which of 84
melodic fragments--the files in the midi directory--would be combined
to create the phrases for a dance form called a polonaise. Fragments
A are 6 measures long, fragments B are 8 bars long. The dice decide
which fragments are combined, and the final line of the code plays
the results.

At this time there is no GUI for the Kirnberger code, but Figure 2
illustrates the possibilities of Q combined with KDE/Qt. The basic
MIDI file player code is included as an example with the Q sources,
but QMidiPlayer is a separate source package that requires a full
installation of Q, the Q-Midi module and a recent version of KDE/Qt.

Figure 2. The QMidiPlayer GUI

Common Music

Its home page tells us that Common Music (CM) is:

an object-oriented music composition environment. It produces sound by transforming
a high-level representation of musical structure into a variety of
control protocols for sound synthesis and display. Common Music defines
an extensive library of compositional tools and an API through which
the composer can easily modify and extend the system.

Common Music's output types include scores formatted for the Csound and Common Lisp
Music sound synthesis languages, for the Common Music Notation system
and for MIDI as a file. It also can be rendered in real-time by way of MidiShare.

The following code creates a texture of self-similar motifs in an aural
simulation of the well-known Sierpinski triangle :

This fragment is located in the etc/examples/intro.cm file, a compendium of brief
CM programs that introduce many useful basic features of the language. By
utilizing the MidiShare system, you can render the fragment in real-time
simply by changing test.mid to
midi.port. Of course, you need
a MidiShare-aware synthesizer to connect with, such as the Fluidsynth
soundfont player launched with the following options :

fluidsynth --midi-driver=midishare --audio-driver=jack 8mbgmsfx.sf2

You also need to hook CM to the synthesizer. Figure 3 shows off CM
connected to QSynth (a GUI for Fluidsynth) by way of the MidiShare msconnect
utility. In this arrangement Fluidsynth is seen running with the JACK
audio driver, hence the appearance of QJackCtl.

Figure 3. Common Music, MidiShare and QSynth

As a language-based environment, Common Music development is most at
home in a Lisp-aware text editor, such as Emacs or X/Emacs. Users of
Common Music for the Macintosh have long enjoyed the use of a graphic
tool called the Plotter, which recently was ported to Linux. A new
rendering GUI (Figure 4) has been added to the Common Music CVS sources
that should make it easier to direct CM output to its various targets,
including the Plotter and, of course, MIDI.

Figure 4. Emacs, Common Music and the cmio Panel

Common Music has been in development for many years, and its author, Rick
Taube, has provided excellent documentation and tutorials for new and
experienced users. Recently, Rick published an outstanding book about
music composition with the computer, Notes From The
Metalevel (see
Resources below). His demonstration language of choice naturally is
Common Music. The system is included on the book's accompanying CD, so new
users can jump immediately into developing and testing their own CM code.

Csound

The venerable Csound music and sound programming language has long
supported MIDI input as MIDI files for play by Csound instruments or
by a MIDI device for playing a Csound instrument by way of external
hardware--keyboard, sequencer, wind controller. Thanks primarily to the work of
developer Gabriel Maldonado, Csound also is a useful programming language
for real-time MIDI output.

Playing a Csound instrument, an orc in Csound-speak, through an external MIDI
device is a fairly simple procedure. The following orc file prepares a
MIDI-sensitive instrument :

where -o determines the output target, -M selects a MIDI input device
and -dm6 sets the graphics and messaging levels. Instrument, score
and launch options all can be rolled into a single CSD file, a format
that unifies Csound's necessary components into one handy form.

Designing a Csound instrument involves the definition and connection
of components called opcodes. A Csound opcode could be an oscillator
(oscil), an envelope generator (linenr, linseg), a mathematic operator
(=), a MIDI capture function (ampmid, cpsmidib) or any of the hundreds
of other functions and capabilities available as Csound opcodes.

The following CSD-formatted Csound code demonstrates the moscil opcode, a
MIDI output function. The instrument, instr 1, transmits a major scale
as a series of MIDI note messages starting from a given note-number, 48,
and rising according to the envelope curve described by the linseg opcode.

The linseg envelope generator creates a multistage envelope in which each
step corresponds to a scale degree. When this file is run with
csound moscil-test.csd, a C major scale is played by whatever instrument
is receiving data on the MIDI interface selected by the -Q option.

Csound has many opcodes dedicated to the reception, transmission
and alteration of MIDI messages. The possibilities are intriguing:
simultaneous MIDI input/output, given two physical ports; MIDI control
of synthesis parameters; instruments with combined audio/MIDI output;
and even MIDI control by way of Csound's FLTK-based GUI opcodes. With
Csound, your imagination is the limit.

Output

In my next column, I'll finish this MIDI tour with a look at some GUI-based
experimental MIDI applications, including Tim Thompson's KeyKit, Jeffrey
Putnam's Grammidity and Elody from GRAME, the MidiShare people. See
you next month!

Dave Phillips is a musician, teacher and writer living in Findlay,
Ohio. He has been an active member of the Linux audio community since
his first contact with Linux in 1995. He is the author of The Book of
Linux Music & Sound, as well as numerous articles in
Linux Journal.