Introduction:

Using the SGI MIDI libraries

Using MIDI as a data protocol on an SGI is very simple. There are some good tutorials that come with Irix 6.3 (and later) that are usually stored in /usr/share/src/dmedia/midi. The standard method for getting started is to intitialize the MIDI library, open input and output ports, configure the IO ports, and then start sending and receiving data. The following code fragment will set up basic MIDI IO when given port names like "Software Synth" and "Serial Port 2".

/********************************************************************/
int initMidi(char *inPort, char *outPort)
{
int	num_intfcs;	/* Number of configured interfaces */


	/* Initialize the MIDI subsystem.  mdInit returns the current
	 * number of active interfaces.
	 */ 
	num_intfcs = mdInit();
	if (num_intfcs == 0)
		{
       		fprintf(stderr, "No MIDI interfaces configured.\n");
        	exit(1);
  		}

	iport = mdOpenInPort(inPort);
	if (iport == NULL) {
		printf("open of input port failed\n");
		exit(1);
	}	

	oport = mdOpenOutPort(outPort);
	if (oport == NULL) {
		printf("open of output port failed\n");
		exit(1);
	}
	
	/* We're just sending/receiving data as fast as we can,
	 * so we don't need to timestamp events.
	 */
	mdSetStampMode(iport, MD_NOSTAMP);
	mdSetStampMode(oport, MD_NOSTAMP);

printf("\nfinished midiInit\n");

return 1;
} /* end initMidi */

/* Reads and writes are then trivial: */
MDevent event;
int channel;
int note;

/* send a note to channel 1 */
channel = 1;
note = 60;  /* middle C */
event.msg[0] = MD_NOTEON | channel;
event.msg[1] = note;
event.msg[2] = 100; /* velocity */
mdSend(oport, &event, 1);

/* now turn the note off after a second */
sleep(1);
event.msg[0] = MD_NOTEOFF | channel;
event.msg[1] = note;
event.msg[2] = 0;
mdSend(oport, &event, 1);

/* receive a midi event */
mdReceive(iport, &event, 1);

/********************************************************************/
/* MIDI event structure
 * [0] status -> command & channel (NOTEON, CONTROLCHANGE, PROGRAMCHANGE)
 * [1] additional info  (note number, control number, instrument number)
 * [2] additional info (velocity, control setting)
 * [3] unused
 */

/* Here are some other examples of read/write code */
int status;

mdReceive(iport, &event, 1);
status = (int)event.msg[0] & MD_STATUSMASK;
channel = (int)event.msg[0] & MD_CHANNELMASK;

/* in this example we expect status to equal
 *MD_CONTROLCHANGE.  Others are...
 *MD_PROGRAMCHANGE - for changing instruments
 *MD_SYSEXMSG - for system exclusive messages
 */

switch channel
	{
	case 1:
		if (event.msg[1] == MD_GENERALPURPOSE1) /* 0x10 */
			{
			/* do something with the value in
			event.msg[2] which ranges from 0->127. */
			}
		/* other event types may also be present -
		 * when getting data from the I-Cube, you'll know
		 * what to expect.
		 */
		break;
	case 2:
		/* do something with the event on channel two */
		break;
	}


/* change the MIDI instrument type on channel one */
channel = 1;
event.stamp = stamp; stamp++; /* use only if you need time stamping! */
event.msg[0] = MD_PROGRAMCHANGE|channel;
event.msg[1] = 9; /* glockenspiel - instrument #10 (numbering starts at 0)*/
mdSend(port, &event, 1);

There are other midi libraries out there besides the ones from SGI though I have not tried them.


kcscott@cc.gatech.edu
© 1998 Georgia Institute of Technology