Examples

A Simple Player in C: beet.c

This example opens MIDI, initializes the environment using standard maps (16 MIDI channels, 1 route), connects to the interface passed as argument, and finally plays Beethoven's Ninth (4th movement) before closing MIDI again. To avoid "hick-ups" introduced by start-up delays, the timer is reset to zero immediately before output begins. Basic error checking and reporting is done.

#include <stdio.h>
#include "../../include/mi_d.h"

void main(int argc, char* argv[]) {
  int res, i;
  int qtr = 350;		/* quarter note tempo (in ms) */
  unsigned long time = 0;	/* note time stamp */
  int dur;			/* note duration */
  short notes[]			/* the melody */
    = {64, 64, 65, 67, 67, 65, 64, 62, 60, 60, 62, 64, 64, 62, 62};

  /* make sure we've got exactly one argument */
  if (argc != 2) {		
    fprintf(stderr, "Usage: %s interface\n", argv[0]);
    return;
  }

  /* Open MIDI for 16 channels, 1 route and connection, 16+1      */
  /* mapping cells and allocate a small queue of 100 or so events */
  res = mi_dOpen("Hello Mi_D", 16, 1, 1, 17, 100);
  if (res != mi_dNoErr) {
    fprintf(stderr, "Can't open MIDI (%d)\n", res);
  } else {
    /* use standard channel and route maps */
    mi_dStandardMaps();
    /* connect to the given interface */
    res = mi_dConnect(0, argv[1], mi_dOutput);
    if (res 1= mi_dNoErr) {
      fprintf(stderr, "Can't connect to \"%s\" (%d)\n", argv[1], res);
    } else {
      /* reset timer */
      mi_dSetTime(0UL);
      /* play the melody */
      for (i = 0; i < 15; i++) {
	dur = qtr * (i == 12 ? 1.5 : i == 13 ? .5 : i == 14 ? 2 : 1);
	mi_dWriteNote_3c(0, notes[i], 64, 64, dur, time);
	time += dur;
      }
    }
  }

  mi_dClose();
  return;
}

Compile with cc -o beet beet.c -lmi_d or whatever is necessary on your system and call with, for instance, ./beet "Software Synth" on an SGI.

The Same Player in Lisp: beet.lisp

Here the same example in Lisp. In Lisp, we wrap the code in a function beet and call the function instead of writing and executing a stand-alone C application with main entry point.

(defun beet (interface)
  (let (res
	(qtr 350)			; quarter note tempo (in ms)
	(time 0)			; note time stamp
	dur				; note duration
	(notes				; the melody
	 '(64 64 65 67 67 65 64 62 60 60 62 64 64 62 62)))
    ;; Open MIDI for 16 channels, 1 route and connection, 16+1
    ;; mapping cells and allocate a small queue of 100 or so events
    (setf res (mi_d:open-midi "Hello Mi_D" 16 1 1 17 100))
    (if (/= res mi_d:+no-err+)
        (error "Can't open MIDI (~d)" res)
      (progn
	;; use standard channel and route maps
	(mi_d:standard-maps)
	;; connect to the given interface
	(setf res (mi_d:connect 0 interface :mi_d-output))
	(if (/= res mi_d:+no-err+)
            (error "Can't connect to ~s (~d)" interface res)
	  (progn
	    ;; reset timer
	    (mi_d:set-time 0)
	    ;; play the melody
	    (dotimes (i 15)
	      (setf dur (floor
			 (* qtr (case i (12 1.5) (13 .5) (14 2) (t 1)))))
	      (mi_d:write-note_3c 0 (elt notes i) 64 64 dur time)
	      (incf time dur))))))
    (mi_d:close-midi)))

Make sure the Mi_D shared library is loaded or otherwise accessible to the Lisp image, then load mi_d.lisp and whatever implementation-dependent interfaces there are for your Lisp (see the comment at the beginning of beet.lisp). Then call it by evaluating, for example, (beet "Software Synth") on the SGI.