[comp.music] Need help With MIDI interface S/W Ideas.

chena1@ese.essex.ac.uk (Chengodan A) (10/21/89)

***************
A.Chengodan,
ESE,
Essex University,
Colchester,CO4 3SQ,
Essex, UK.

					21/10/89.

Hi,
	I have got more problems to solve with MIDI.
I'm trying to interface an IBM-AT with a keyboard
via MIDI. Now I`m not sure the actual DATA structure 
I need to use on READING THE MIDI MESSAGES; especially
the timing information of each MIDI MESSAGES 

i.e:
In storing the MIDI MESSAGE ( key on/off ..), how do I
include the time field indicating when each note/event 
( key on/off ..) has occurred (relatively/ ??). This is to
make sure the MIDI MESSAGES are sent at a right time on 
playback. 

	How to incorporate this timing in the MIDI 
MESSAGE structure? 

	So far I could only think of these, using:

(1).	hardware:	Reading a Real-Time clock
			with high resolution. 
			
			or

			A special timer set after each
			key is pressed and reset it as
			it's released. ( not sure this is
			that simple when 16 keys are
			pressed simultaneously ....)

(2).	software:	Reading a computers Real-Time 
			clock and calculate the time 
			interval between each event.
			( this might eat-up a lot of 
			CPU's time and miss reading
			the incoming data..).

			The structure which I think suitable
			in C is:

			struc MIDIMSG
			{
				int status;	/* 8 bit integer */
				int data;	/* to make a full */
				int speed;	/* use of memory */
				int time;
			};

(3).	SYSTEM REAL-TIME MESSAGES:
			Using the System Real-Time MIDI Messages
			which provide a TIMING-CLOCK at a rate of
			24 beats per quarter notes.
			If I could use this, what sort of calculations
			or steps I should take to make it work?


	I hope to get some comments and ideas of how I can go around 
solving this problem. I wish you will be able to send some Email for me.

Thank You Very Much.

***************
***************
Email:	chena1@ese.essex.ac.uk.

***************

maverick@oak.Berkeley.EDU (Vance Maverick) (10/22/89)

I failed sending mail, so I'll post this as a followup.

> I`m not sure the actual DATA structure
> I need to use on READING THE MIDI MESSAGES; especially
> the timing information of each MIDI MESSAGES

> In storing the MIDI MESSAGE ( key on/off ..), how do I
> include the time field indicating when each note/event
> ( key on/off ..) has occurred (relatively/ ??). This is to
> make sure the MIDI MESSAGES are sent at a right time on
> playback.

For notes I recommend a structure like this:

typedef struct {
        long time;              /* Attack time from start of track */
        unsigned int length;    /* Length in same time units */
        char pitch,             /* MIDI information: pitch 0-127 */
            channel,            /* channel 0-15 (low nibble of status) */
            velocity,           /* Attack velocity (from note-on) */
            release;            /* Release velocity (from note-off) */
    } note;

(Assuming long = 32 bits, int = 16, char = 8.)

In writing a MIDI sequencer three years ago, my partner and I committed
ourselves early on to a track format where ons and offs were stored
separately.  This became a real pain when we started implementing edit
operations.  Also, I think you want to store the time as absolute, i.e.
from the start of the track, rather than with respect to the previous note:
again, the advantage becomes most apparent with edit operations.

For timing on the PC, there are a couple of options.  The Roland MPU
interface and its clones will do timing for you, in 120ths of a quarter
note (and other resolutions);  this is quite adequate for a sequencer.  If
you don't have one, or don't want to deal with the eccentricities of the
MPU command set and timing scheme, you can do the timing yourself with the
PC's system timer.  You'll need to speed up the timer, divert the interrupt
to a handler of your own, and call the old handler at the right (old)
speed.  This is not "hard", but tricky to get right.  I don't have the demo

scott@bbxsda.UUCP (Scott Amspoker) (10/24/89)

In article <2211@servax0.essex.ac.uk> chena1@ese.UUCP (Chengodan A) writes:
>Hi,
>	I have got more problems to solve with MIDI.
>I'm trying to interface an IBM-AT with a keyboard
>via MIDI. Now I`m not sure the actual DATA structure 
>I need to use on READING THE MIDI MESSAGES; especially
>the timing information of each MIDI MESSAGES 
>[...]

Here are a couple of suggestions based on what I have done
with my own software:

Use one of the programmable interval timers on your PC.  They
can be set to interrupt at ranges from 2 microseconds to 
many milliseconds.  Make your timer interrupt handle increment
a tick counter in memory.  This will be your "clock".  I use
a Yamaha C1 which has an additional timer just for music
applications.

Your midi receive interrupt handler should remember the current
clock upon receiving a status byte (or implied running status).
When the entire midi message had been recieved it is then
stuffed (along with the clock value) into a quick and dirty
circular queue (don't spend too much time in the interrupt routine).
A higher level routine may retrieve these time-stamped messages at
its leasure and place them into a more complex and permanent data
structure.  (Be sure to disable interrupts when setting/retrieving
the clock value as well as when accessing the circular queue).
My recieve interrupt handler is also responsible for echoing
incoming MIDI messages to the appropriate output port.

There are several ways to handle playback of MIDI data.  It depends
on how you chose to represent your "tracks" in memory.  If absolute
timing accuracy is important (as it is for me) than you can prepare
a "dispatch" queue containing data indicating time delays between the
MIDI messages.  Your clock tick interrupt may then take the
responsibility of dispatching the data precisely on schedule (including
the timely dispatch of MIDI sync messages).  Once again, keep it
simple.  Don't spend too much time in an interrupt handler.  Your
higher level logic can take all the time it wants preparing output
data, updating the screen, etc. as long as it doesn't allow the dispatch
queue to become empty.  The actual MIDI output ports are also
interrupt driven.  If the port is busy then place output data
in a queue so that the output interrupt handler can take care of it
when it's ready.

This is a rather oversimplified description of one of *many* ways
of doing things.  I hope it gave you some ideas.

-- 
Scott Amspoker
Basis International, Albuquerque, NM
(505) 345-5232
unmvax.cs.unm.edu!bbx!bbxsda!scott

scott@bbxsda.UUCP (Scott Amspoker) (10/24/89)

In article <18642@pasteur.Berkeley.EDU> maverick@oak.Berkeley.EDU (Vance Maverick) writes:
>[about designing a sequencer]
>For notes I recommend a structure like this:
>
>typedef struct {
>        long time;              /* Attack time from start of track */
>        unsigned int length;    /* Length in same time units */
>        char pitch,             /* MIDI information: pitch 0-127 */
>            channel,            /* channel 0-15 (low nibble of status) */
>            velocity,           /* Attack velocity (from note-on) */
>            release;            /* Release velocity (from note-off) */
>    } note;
>
>(Assuming long = 32 bits, int = 16, char = 8.)
>
>In writing a MIDI sequencer three years ago, my partner and I committed
>ourselves early on to a track format where ons and offs were stored
>separately.  This became a real pain when we started implementing edit
>operations.

Good advice!  I "discovered" that myself after getting halfway through
the project.  It was significant enough to warrant rewriting a lot
of code.  It gets a little trickier during record and playback but
makes a lot of other features a lot easier.

>For timing on the PC, there are a couple of options.  The Roland MPU
>interface and its clones will do timing for you, in 120ths of a quarter
>note (and other resolutions);  this is quite adequate for a sequencer.

This is not a flame but I'm not entirely sure that 120 ppq is enough.
I use 480 ppq and admit that it might be an overkill but I do a lot
of "free-form" sequencing (without a click).  When I do use a click
and drum machine I almost never quantize except maybe the bass part.
Since I use a Yamaha C1 I don't know much about the Roland MPU.  The
C1 provides an additional interval timer for applications.  There
are 2 input and 8 output ports that contain on-chip FIFOs (about 16
bytes) so the main application is not overburdened with interrrupt 
handling.

-- 
Scott Amspoker
Basis International, Albuquerque, NM
(505) 345-5232
unmvax.cs.unm.edu!bbx!bbxsda!scott

ear@wpi.wpi.edu (Eric A Rasmussen) (10/25/89)

My father's company is considering developing a IBM PC midi card and
sequencing software to accompany it.  As an informal marketing survey, I would
like to ask your opinions on several points:

1)  How important is MPU401 compatibility?

2)  How important is price?

3)  How important would the inclusion of the source code (in C) be so that
    users could modify the software to suit personal tastes/needs?  (or how
    foolish would it be to include the source code?)

4)  Would you be willing to buy a PC midi card and software if it was not
    MPU401 compatible but cost altogether less than $100.  (and possibly
    included the source code?)

5)  What is the best deal you have seen on a midi card (with or without
    software) for a PC, and do you think it's a good deal?

6)  What is your favorite sequencer software for the PC?


Thanks for your time.

 _                _                                         +-=-=-=-=-=-=-=-=-+
|_  ,_  .   _    |_}   _    _  ,_ _         _   _   _   ,_  | ear@wpi.wpi.edu |
|_  |   |  |_    | \  |_\  _>  | | |  |_|  _>  _>  |_'  | | | ear%wpi@wpi.edu |
--< A real engineer never reads the instructions first! >-- +-=-=-=-=-=-=-=-=-+