Linux MIDI: A Brief Survey, Part 4
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.
/* import Q-Midi functions */ include midi; /* read in MIDI files from a directory named "midi" */ def M = map load (glob "midi/*.mid"); /* create a map for file selection via the dice */ /* the numbers are the MIDI file fragments, */ /* i.e., 70.mid, 10.mid, 42.mid, etc. */ def T = map (map pred) [// part A [ 70, 10, 42, 62, 44, 72], [ 34, 24, 6, 8, 56, 30], [ 68, 50, 60, 36, 40, 4], [ 18, 46, 2, 12, 79, 28], [ 32, 14, 52, 16, 48, 22], [ 58, 26, 66, 38, 54, 64], // part B [ 80, 20, 82, 43, 78, 69], [ 11, 77, 3, 41, 84, 63], [ 59, 65, 9, 45, 29, 7], [ 35, 5, 83, 17, 76, 47], [ 74, 27, 67, 37, 61, 19], [ 13, 71, 1, 49, 57, 31], [ 21, 15, 53, 73, 51, 81], [ 33, 39, 25, 23, 75, 55]]; /* define and roll the dice */ dice N = listof die (I in nums 1 N); die = random div 1000 mod 6; /* make selections from map table */ polonaise D = foldl seq  (A++A++B++A1) where P = map (M!) (zipwith (!) T D), A = take 6 P, B = drop 6 P, A1 = drop 2 A; /* create sequences */ seq S1 S2 = S2 if null S1; = S1++map (shift DT) S2 where (DT,_) = last S1; shift DT (T,MSG) = (T+DT,MSG); /* play the results of 14 throws */ kirnberger = play (polonaise (dice 14));
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.
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 :
;;; 8. Defining a recursive process (sierpinski) with five input args. ;;; sprout's second arg is the time to start the sprouted object. ;;; (define (sierpinski knum ints dur amp depth) (let ((len (length ints))) (process for i in ints for k = (transpose knum i) output (new midi :time (now) :duration dur :amplitude amp :keynum k) when (> depth 1) ;; sprout a process on output note sprout (sierpinski (transpose k 12) ints (/ dur len) amp (- depth 1)) wait dur))) (events (sierpinski 'a0 '(0 7 5 ) 3 .5 4) "test.mid")
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.
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.
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.
Similis sum folio de quo ludunt venti.
- High-Availability Storage with HA-LVM
- Localhost DNS Cache
- DNSMasq, the Pint-Sized Super Dæmon!
- Real-Time Rogue Wireless Access Point Detection with the Raspberry Pi
- Days Between Dates: the Counting
- You're the Boss with UBOS
- Multitenant Sites
- PostgreSQL, the NoSQL Database
- The Usability of GNOME
- Linux for Astronomers