mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	
		
			
	
	
		
			337 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Groff
		
	
	
	
	
	
		
		
			
		
	
	
			337 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Groff
		
	
	
	
	
	
| 
								 | 
							
								.TH MIDIFILE 3
							 | 
						||
| 
								 | 
							
								.SH NAME
							 | 
						||
| 
								 | 
							
								mfread,mfwrite - read and write a standard MIDI file
							 | 
						||
| 
								 | 
							
								.SH SYNOPSIS
							 | 
						||
| 
								 | 
							
								\fC#include "mfread.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mfread ()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.nf
							 | 
						||
| 
								 | 
							
								int (*Mf_getc) ();
							 | 
						||
| 
								 | 
							
								int (*Mf_putc) ();
							 | 
						||
| 
								 | 
							
								int (*Mf_error) (char *msg);
							 | 
						||
| 
								 | 
							
								int (*Mf_header) (int format, int ntrks, int division);
							 | 
						||
| 
								 | 
							
								int (*Mf_trackstart) ();
							 | 
						||
| 
								 | 
							
								int (*Mf_trackend) ();
							 | 
						||
| 
								 | 
							
								int (*Mf_noteon) (int chan, int pitch, int vol);
							 | 
						||
| 
								 | 
							
								int (*Mf_noteoff) (int chan, int pitch, int vol);
							 | 
						||
| 
								 | 
							
								int (*Mf_pressure) (int chan, int pitch, int pressure);
							 | 
						||
| 
								 | 
							
								int (*Mf_parameter) (int chan, int control, int value);
							 | 
						||
| 
								 | 
							
								int (*Mf_pitchbend) (int chan, int msb, int lsb);
							 | 
						||
| 
								 | 
							
								int (*Mf_program) (int chan, int program);
							 | 
						||
| 
								 | 
							
								int (*Mf_chanpressure) (int chan, int pressure);
							 | 
						||
| 
								 | 
							
								int (*Mf_sysex) (int leng, char *msg);
							 | 
						||
| 
								 | 
							
								int (*Mf_metamisc) (int type, int leng, int msg);
							 | 
						||
| 
								 | 
							
								int (*Mf_seqspecific) (int type, int leng, int msg);
							 | 
						||
| 
								 | 
							
								int (*Mf_seqnum) (int num);
							 | 
						||
| 
								 | 
							
								int (*Mf_text) (int type, int leng, int msg);
							 | 
						||
| 
								 | 
							
								int (*Mf_eot) ();
							 | 
						||
| 
								 | 
							
								int (*Mf_timesig) (int numer, int denom, int clocks, int qnotes);
							 | 
						||
| 
								 | 
							
								int (*Mf_smpte) (int hour, int min, int sec, int frame, int fract);
							 | 
						||
| 
								 | 
							
								int (*Mf_tempo) (int microsecs);
							 | 
						||
| 
								 | 
							
								int (*Mf_keysig) (int sharpflat, int minor);
							 | 
						||
| 
								 | 
							
								int (*Mf_arbitrary) (int leng, int msg);
							 | 
						||
| 
								 | 
							
								int Mf_nomerge;
							 | 
						||
| 
								 | 
							
								long Mf_currtime;
							 | 
						||
| 
								 | 
							
								.fi
							 | 
						||
| 
								 | 
							
								.sp 1
							 | 
						||
| 
								 | 
							
								mfwrite(int format, int ntracks, int division, FILE *fp)
							 | 
						||
| 
								 | 
							
								.sp 1
							 | 
						||
| 
								 | 
							
								.nf
							 | 
						||
| 
								 | 
							
								int (*Mf_writetrack)(int track);
							 | 
						||
| 
								 | 
							
								int (*Mf_writetempotrack)();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mf_write_midi_event(delta, type, chan, data, size)
							 | 
						||
| 
								 | 
							
								unsigned long delta;
							 | 
						||
| 
								 | 
							
								unsigned int type,chan,size;
							 | 
						||
| 
								 | 
							
								char *data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mf_write_meta_event(delta, type, data, size)
							 | 
						||
| 
								 | 
							
								unsigned long delta;
							 | 
						||
| 
								 | 
							
								unsigned int type,chan,size;
							 | 
						||
| 
								 | 
							
								char *data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mf_write_tempo(tempo)
							 | 
						||
| 
								 | 
							
								unsigned long tempo;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								unsigned long mf_sec2ticks(float seconds, int division, int tempo)
							 | 
						||
| 
								 | 
							
								float seconds;
							 | 
						||
| 
								 | 
							
								int division;
							 | 
						||
| 
								 | 
							
								unsigned int tempo;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float mf_ticks2sec(ticks, division, tempo)
							 | 
						||
| 
								 | 
							
								unsigned long ticks;
							 | 
						||
| 
								 | 
							
								int division;
							 | 
						||
| 
								 | 
							
								unsigned int tempo;
							 | 
						||
| 
								 | 
							
								.fi
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.SH DESCRIPTION
							 | 
						||
| 
								 | 
							
								The \fCmfread\fR function reads and inteprets a standard MIDI file.
							 | 
						||
| 
								 | 
							
								To use it you need to understand the general form of a
							 | 
						||
| 
								 | 
							
								MIDI file and the type of information it contains, but you don't
							 | 
						||
| 
								 | 
							
								need to know much, if anything, about the detailed format of the file
							 | 
						||
| 
								 | 
							
								and the mechanics of reading it reliably and portably.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The \fCmfwrite\fR function writes a standard MIDI file making
							 | 
						||
| 
								 | 
							
								use of user-defined functions that access the program's
							 | 
						||
| 
								 | 
							
								data structure.  To use it you need to define your own Mf_writetrack
							 | 
						||
| 
								 | 
							
								routine and then make use of the write_* family of routines to
							 | 
						||
| 
								 | 
							
								write out the MIDI data.  The \fCmfwrite\fR routine takes
							 | 
						||
| 
								 | 
							
								care of the file format and writing the file and track chunk headers. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.SH READING STANDARD MIDI FILES
							 | 
						||
| 
								 | 
							
								A single call to \fCmfread\fR will read an entire MIDI file.
							 | 
						||
| 
								 | 
							
								The interface to \fCmfread\fR is a set of external variables
							 | 
						||
| 
								 | 
							
								named \fCMf_*\fR, most of which are function pointers to be called
							 | 
						||
| 
								 | 
							
								from within \fCmfread\fR during the process of parsing the MIDI file.
							 | 
						||
| 
								 | 
							
								Before calling \fCmfread\fR, the only
							 | 
						||
| 
								 | 
							
								requirement is that you assign a value
							 | 
						||
| 
								 | 
							
								to \fCMf_getc\fR - a pointer to a function that will return
							 | 
						||
| 
								 | 
							
								characters from the MIDI file, using -1 to indicate EOF.
							 | 
						||
| 
								 | 
							
								All the rest of the function
							 | 
						||
| 
								 | 
							
								pointers are initialized to NULL, and the default action for each
							 | 
						||
| 
								 | 
							
								is to do nothing.  The following is a complete program using \fCmfread\fR
							 | 
						||
| 
								 | 
							
								that could serve as a 'syntax checker' for MIDI files:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.in +1i
							 | 
						||
| 
								 | 
							
								.ft C
							 | 
						||
| 
								 | 
							
								.nf
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include "midifile.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mygetc()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									/* use standard input */
							 | 
						||
| 
								 | 
							
									return(getchar());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								main()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									Mf_getc = mygetc;
							 | 
						||
| 
								 | 
							
									mfread();
							 | 
						||
| 
								 | 
							
									exit(0);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								.fi
							 | 
						||
| 
								 | 
							
								.ft R
							 | 
						||
| 
								 | 
							
								.in -1i
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This takes advantage of the default action when an error is detected, which
							 | 
						||
| 
								 | 
							
								is to exit silently with a return code of 1.  An error function of your
							 | 
						||
| 
								 | 
							
								own can be used by giving a value to \fCMf_error\fR; the function will be
							 | 
						||
| 
								 | 
							
								called with the error message as an argument.
							 | 
						||
| 
								 | 
							
								The other \fCMf_* variables can similarly be used to call arbitrary
							 | 
						||
| 
								 | 
							
								functions while parsing the MIDI file.  The descriptions below
							 | 
						||
| 
								 | 
							
								of the information passed to these functions is sparse; refer to
							 | 
						||
| 
								 | 
							
								the MIDI file standard for the complete descriptions.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\fCMf_header\fR is the first function to be called, and its arguments
							 | 
						||
| 
								 | 
							
								contain information from the MIDI file's header; the format (0,1, or 2),
							 | 
						||
| 
								 | 
							
								the number of tracks, and the division of a quarter-note that defines
							 | 
						||
| 
								 | 
							
								the times units.
							 | 
						||
| 
								 | 
							
								\fCMf_trackstart\fR and
							 | 
						||
| 
								 | 
							
								\fCMf_trackend\fR are called at the beginning and end of each track.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Once inside a track, each separate message causes a function to be called.
							 | 
						||
| 
								 | 
							
								For example, each note-on message causes \fCMf_noteon\fR to be called
							 | 
						||
| 
								 | 
							
								with the channel, pitch, and volume as arguments.  The time at which
							 | 
						||
| 
								 | 
							
								the message occurred is stored in \fCMf_currtime\fR - one of the few
							 | 
						||
| 
								 | 
							
								external variables that isn't a function pointer.  The other channel messages
							 | 
						||
| 
								 | 
							
								are handled in a similar and obvious fashion -
							 | 
						||
| 
								 | 
							
								\fCMf_noteoff\fR,
							 | 
						||
| 
								 | 
							
								\fCMf_pressure\fR,
							 | 
						||
| 
								 | 
							
								\fCMf_parameter\fR,
							 | 
						||
| 
								 | 
							
								\fCMf_pitchbend\fR,
							 | 
						||
| 
								 | 
							
								\fCMf_program\fR,
							 | 
						||
| 
								 | 
							
								and \fCMf_chanpressure\fR.  See the declarations above for the arguments
							 | 
						||
| 
								 | 
							
								that are passed to each.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								System exclusive messages are handled by calling \fCMf_sysex\fR, passing
							 | 
						||
| 
								 | 
							
								as arguments the message length and a pointer to a static buffer containing
							 | 
						||
| 
								 | 
							
								the entire message.
							 | 
						||
| 
								 | 
							
								The buffer is expanded when necessary; memory availability is the only limit
							 | 
						||
| 
								 | 
							
								to its size.  Normally, 'continued' system exclusives are automatically
							 | 
						||
| 
								 | 
							
								merged, and \fCMf_sysex\fR is only called once.  It you want to disable this
							 | 
						||
| 
								 | 
							
								you can set \fCMf_nomerge\fR to 1, causing \fCMf_sysex\fR to be called
							 | 
						||
| 
								 | 
							
								once for each part of the message.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\fCMf_seqnum\fR is called by the \fImeta\fR message that provides
							 | 
						||
| 
								 | 
							
								a sequence number,
							 | 
						||
| 
								 | 
							
								which if present must appear at the beginning of a track.
							 | 
						||
| 
								 | 
							
								The tempo \fImeta\fR message causes \fCMf_tempo\fR to be called; its
							 | 
						||
| 
								 | 
							
								argument is the number of microseconds per MIDI quarter-note (24 MIDI clocks).
							 | 
						||
| 
								 | 
							
								The end-of-track \fImeta\fR message causes \fCMf_eot\fR to be called.
							 | 
						||
| 
								 | 
							
								The key signature \fImeta\fR message causes \fCMf_keysig\fR to be called;
							 | 
						||
| 
								 | 
							
								the first argument conveys the number of sharps or flats, the second
							 | 
						||
| 
								 | 
							
								argument is 1 if the key is minor.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The \fCMf_timesig\fR and \fCMf_smpte\fR functions are called when the
							 | 
						||
| 
								 | 
							
								corresponding \fImeta\fR messages are seen.  See the MIDI file standard
							 | 
						||
| 
								 | 
							
								for a description of their arguments.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The \fItext\fR messages in the MIDI file standard are of the following
							 | 
						||
| 
								 | 
							
								types:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.in +1i
							 | 
						||
| 
								 | 
							
								.nf
							 | 
						||
| 
								 | 
							
								0x01		Text Event
							 | 
						||
| 
								 | 
							
								0x02		Copyright
							 | 
						||
| 
								 | 
							
								0x03		Sequence/Track Name
							 | 
						||
| 
								 | 
							
								0x04		Instrument
							 | 
						||
| 
								 | 
							
								0x05		Lyric
							 | 
						||
| 
								 | 
							
								0x06		Marker
							 | 
						||
| 
								 | 
							
								0x07		Cue Point
							 | 
						||
| 
								 | 
							
								0x08-0x0F	Reserverd but Undefined
							 | 
						||
| 
								 | 
							
								.fi
							 | 
						||
| 
								 | 
							
								.in -1i
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\fCMf_text\fR is called for each of these; the arguments are
							 | 
						||
| 
								 | 
							
								the type number, the message length, and a pointer to the message buffer.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Misceallaneous \fImeta\fR messages are handled by \fCMf_metamisc\fR,
							 | 
						||
| 
								 | 
							
								sequencer-specific messages are handled by \fCMf_seqspecific\fR, and
							 | 
						||
| 
								 | 
							
								arbitrary "escape" messages (started with 0xF7) are handled by
							 | 
						||
| 
								 | 
							
								\fCMf_arbitrary\fR.
							 | 
						||
| 
								 | 
							
								.SH READING EXAMPLE
							 | 
						||
| 
								 | 
							
								The following is a \fCstrings\fR-like program for MIDI files:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.in +1i
							 | 
						||
| 
								 | 
							
								.ft C
							 | 
						||
| 
								 | 
							
								.nf
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <ctype.h>
							 | 
						||
| 
								 | 
							
								#include "midifile.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								FILE *F;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mygetc() { return(getc(F)); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mytext(type,leng,msg)
							 | 
						||
| 
								 | 
							
								char *msg;
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									char *p;
							 | 
						||
| 
								 | 
							
									char *ep = msg + leng;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for ( p=msg; p<ep ; p++ )
							 | 
						||
| 
								 | 
							
										putchar( isprint(*p) ? *p : '?' );
							 | 
						||
| 
								 | 
							
									putchar('\n');
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								main(argc,argv)
							 | 
						||
| 
								 | 
							
								char **argv;
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if ( argc > 1 )
							 | 
						||
| 
								 | 
							
										F = fopen(argv[1],"r");
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
										F = stdin;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Mf_getc = mygetc;
							 | 
						||
| 
								 | 
							
									Mf_text = mytext;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									mfread();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									exit(0);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								.fi
							 | 
						||
| 
								 | 
							
								.ft R
							 | 
						||
| 
								 | 
							
								.in -1i
							 | 
						||
| 
								 | 
							
								.sp
							 | 
						||
| 
								 | 
							
								.SH WRITING STANDARD MIDI FILES
							 | 
						||
| 
								 | 
							
								A single call to \fCmfwrite\fR will write an entire MIDI file.  Before
							 | 
						||
| 
								 | 
							
								calling \fCmfwrite\fR, you must assign values to function pointers
							 | 
						||
| 
								 | 
							
								\fCMf_writetrack\fR and \fCMf_putc\fR.  The first is a routine to
							 | 
						||
| 
								 | 
							
								access your MIDI data structure, which can make use of other library
							 | 
						||
| 
								 | 
							
								routines to write the actual MIDI data.  The routine
							 | 
						||
| 
								 | 
							
								\fCMf_writetrack\fR will be passed a single parameter which is the
							 | 
						||
| 
								 | 
							
								number of the track to be written.  The pointer \fCMf_putc\fR should be
							 | 
						||
| 
								 | 
							
								set to point to a routine that accepts a charcter as input, writes that
							 | 
						||
| 
								 | 
							
								character to a file, and returns the value that was written.  In the
							 | 
						||
| 
								 | 
							
								case of a format 1 file, a routine has to be written to write a tempo
							 | 
						||
| 
								 | 
							
								map, and assigned to the function pointer \fCMf_writetempotrack\fR.
							 | 
						||
| 
								 | 
							
								This is because format 1 files assume the first track written is a
							 | 
						||
| 
								 | 
							
								tempo track.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\fCmf_write_midi_event\fR and \fCmf_write_meta_event\fR are routines
							 | 
						||
| 
								 | 
							
								that should be called from your \fCMf_writetrack\fR routine to write
							 | 
						||
| 
								 | 
							
								out MIDI events.  The delta time param is the number of ticks since the
							 | 
						||
| 
								 | 
							
								last event.  The int "type" is the type of MIDI message. The int "chan"
							 | 
						||
| 
								 | 
							
								is the MIDI channel, which can be between 1 and 16.  The char pointer
							 | 
						||
| 
								 | 
							
								"data" points to an array containing the data bytes, if any exist. The
							 | 
						||
| 
								 | 
							
								int "size" is the number of data bytes.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\fCmf_sec2ticks\fR and \fCmf_ticks2sec\fR are utility routines
							 | 
						||
| 
								 | 
							
								to help you convert between the MIDI file parameter of ticks
							 | 
						||
| 
								 | 
							
								and the more standard seconds. The int "division" is the same
							 | 
						||
| 
								 | 
							
								division parameter from the file header, and tempo is expressed
							 | 
						||
| 
								 | 
							
								in microseconds per MIDI quarter-note, or "24ths of a microsecond
							 | 
						||
| 
								 | 
							
								per MIDI clock". The division has two meanings, depending on
							 | 
						||
| 
								 | 
							
								whether bit 15 is set or not.  If bit 15 of division is zero,
							 | 
						||
| 
								 | 
							
								bits 14 through 0 represent the number of delta-time "ticks"
							 | 
						||
| 
								 | 
							
								which make up a quarter note.  If bit 15 of division is a one,
							 | 
						||
| 
								 | 
							
								delta-times in a file correspond to subdivisions of a second
							 | 
						||
| 
								 | 
							
								similiar to SMPTE and MIDI time code. In this format bits
							 | 
						||
| 
								 | 
							
								14 through 8 contain one of four values - 24, -25, -29, or -30,
							 | 
						||
| 
								 | 
							
								corresponding to the four standard SMPTE and MIDI time code
							 | 
						||
| 
								 | 
							
								frame per second formats, where -29 represents 30 drop frame.
							 | 
						||
| 
								 | 
							
								The second byte consisting of bits 7 through 0 corresponds
							 | 
						||
| 
								 | 
							
								the the resolution within a frame.  Refer the Standard MIDI Files 
							 | 
						||
| 
								 | 
							
								1.0 spec for more details.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.SH WRITING EXAMPLE
							 | 
						||
| 
								 | 
							
								The following is a simple program to demonstrate writing MIDI files.
							 | 
						||
| 
								 | 
							
								The track would consist of a series of quarter notes from lowest to
							 | 
						||
| 
								 | 
							
								highest in pitch at constant velocity, each separted by a quarter-note
							 | 
						||
| 
								 | 
							
								rest.
							 | 
						||
| 
								 | 
							
								.sp
							 | 
						||
| 
								 | 
							
								.in +1i
							 | 
						||
| 
								 | 
							
								.ft C
							 | 
						||
| 
								 | 
							
								.nf
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <ctype.h>
							 | 
						||
| 
								 | 
							
								#include "midifile.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								FILE *fp;
							 | 
						||
| 
								 | 
							
								myputc(c) { return(putc(c,fp));}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int mywritetrack(track)
							 | 
						||
| 
								 | 
							
								int track;
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int i;
							 | 
						||
| 
								 | 
							
								    char data[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* 120 beats/per/second */
							 | 
						||
| 
								 | 
							
								    mf_write_tempo((long)500000); 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for(i = 1 ; i < 128; i++){
							 | 
						||
| 
								 | 
							
								       data[0] = i; /* note number */
							 | 
						||
| 
								 | 
							
								       data[1] = 64; /* velocity */
							 | 
						||
| 
								 | 
							
								       if(!mf_write_midi_event(480,note_on,1,data,2)) 
							 | 
						||
| 
								 | 
							
									   return(-1);
							 | 
						||
| 
								 | 
							
								       if(!mf_write_midi_event(480,note_off,1,data,2)) 
							 | 
						||
| 
								 | 
							
								           return(-1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return(1);
							 | 
						||
| 
								 | 
							
								} /* end of write_track() */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								main(argc,argv)
							 | 
						||
| 
								 | 
							
								char **argv;
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if((fp = fopen(argv[1],"w")) == 0L)
							 | 
						||
| 
								 | 
							
									exit(1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Mf_putc = myputc;
							 | 
						||
| 
								 | 
							
								    Mf_writetrack = mywritetrack;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* write a single track */
							 | 
						||
| 
								 | 
							
								    mfwrite(0,1,480,fp);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								.sp
							 | 
						||
| 
								 | 
							
								.fi
							 | 
						||
| 
								 | 
							
								.ft R
							 | 
						||
| 
								 | 
							
								.in -1i
							 | 
						||
| 
								 | 
							
								.sp
							 | 
						||
| 
								 | 
							
								.SH AUTHOR
							 | 
						||
| 
								 | 
							
								Tim Thompson (att!twitch!glimmer!tjt)
							 | 
						||
| 
								 | 
							
								.SH CONTRIBUTORS
							 | 
						||
| 
								 | 
							
								Michael Czeiszperger (mike@pan.com)
							 |