www.pudn.com > midif101.zip > MIDIFile.txt, change:2000-03-16,size:12323b


MIDIFile v.1.01 package for Delphi 4 and 5 contains 
units MIDIRead.dcu, MIDIWrite.dcu that make it very 
easy to read and write standard MIDI files. 
 
The package also contains sample Delphi projects: 
 
 - MIDI File Info 
 - MIDI File Transpose 
 - MIDI File Player 
 - MIDI File Recorder 
 
Copyright 2000: Alexei V. Gretchikha 
        E-mail: ag50@cornell.edu 
 
LEGAL DISCLAIMER 
 
By using this software product, you accept that I am not 
responsible for any consequences of such use. The product 
is provided "as is" and without any explicit or implied 
warranty. 
 
 
 
DESCRIPTION OF THE PRODUCT 
 
MIDIRead and MIDIWrite Delphi units make it easy to read and write 
standard MIDI files. The sample program block below illustrates how 
they work. The program reads MIDI data from an input file, message  
by message, and copies them into an output file: 
         
 ReadSMF(InputSMFName); 
   ReadSMFHeader(SMFType,Tracks,Ticks); 
   WriteSMFHeader(SMFType,Tracks,Ticks); 
   for trk := 1 to Tracks do 
     begin 
      ReadTrackHeader; 
      WriteTrackHeader; 
      repeat //until TrackEmpty// 
       ReadMIDIEvent(Delta,Status,Byte1,Byte2,Meta,MsgString); 
       if (not(Meta=$2F)) //End of track treated separately// 
       then WriteMIDIEvent(Delta,Status,Byte1,Byte2,Meta,MsgString); 
       VerifyEndOfTrack; 
      until TrackEmpty; 
      WriteEndOfTrack; //End of track treated separately// 
     end;  
 VerifyEndOfSMF; 
 WriteSMF(OutputSMFName); 
 
The above short program represents all the interface procedures 
from the units. These procedures provide all the tools one needs 
for efficient reading and writing MIDI files. 
 
To better understand how the procedures work, it is useful to 
recall the structure of a standard MIDI file. 
 
 
            STRUCTURE OF A STANDARD MIDI FILE 
 
 
Standard MIDI file has the following structure: 
 
                   <MIDI file header> 
                   <MIDI track #1> 
                   .... 
                   <MIDI track #n> 
 
  MIDI file header contains the information about the MIDI file type, 
                   the number of MIDI tracks in it and the number of  
                   MIDI ticks per quarternote it uses. (See below for 
                   more details.) 
 
      MIDI tracks, in turn, have the following structure: 
  
                  <MIDI track header> 
                  <Delta time #1> 
                  <MIDI event #1> 
                  .... 
                  <Delta time #k> 
                  <MIDI Event #k> 
                  <End of MIDI track> 
 
       Delta time shows time from the previous MIDI event and is 
                  expressed in MIDI ticks. MIDI ticks are not  
                  milliseconds or metronome clicks, they are just 
                  some integers. To convert them into physical time, 
                  one needs to know two values: 
 
                  - Number of MIDI ticks per quarternote 
 
                  (contained in the MIDI file header).  
  
                  - Tempo expressed in microseconds per quarternote. 
 
                  (provided by the Set Tempo meta events; otherwise, 
                   by default, tempo is assumed to be 125000.) 
 
       MIDI events fall into three categories: 
 
                  - Channel events 
                  - SysEx events 
                  - Meta events 
 
    Channel events are "directly playable", i.e. they can be 
                   sent to or received from a MIDI device and result 
                   in sound being produced or changed. 
                   Channel events have the following structure: 
                  
                   <Status byte> - type of channel event 
                   <Byte 1>      - MIDI event data 
                   [<Byte 2>      - MIDI event data] 
 
                   In three-byte-long events, all three bytes are present. 
                   In two-byte-long events, the Byte 2 is missing. 
 
      SysEx events contain hardware-specific MIDI data that can 
                   be sent to or received from a MIDI device and result 
                   in changing its MIDI characteristics. 
                   SysEx events have the following structure: 
 
                   <Status byte> - normally, $F0 or $F7 
                   <Data length> - length of the following data chunk 
                                   written in the so-called variable 
                                   length format (the field can contain 
                                   one or several bytes, depending on 
                                   how large is this value). 
                   <SysEx data>  - the SysEx data chunk 
 
       Meta events are not supposed to be sent to or received from 
                   MIDI devices. Instead, they contain information about 
                   the MIDI sequence, including the information how the 
                   sequence must be processed. 
                   Meta events have the following structure: 
 
                   <Status byte> - always $FF 
                   <Type byte>   - type of meta event 
                   <Data length> - length of the following data chunk 
                                   written in the variable length format. 
                   <Meta data>   - the meta event data chunk. Can contain 
                                   text and binary data. 
                    
                   The only meta event that directly affects the way 
                   the MIDI sequence sounds is the Set Tempo event: 
 
                   <Status byte> = $FF 
                   <Type byte>   = $51 
                   <Data length> = 3 
                   <Meta data>   = b1 
                                   b2 
                                   b3 
      
                     where Tempo = b3+256*(b2+256*b1) 
 
                   Information contained in all other meta events 
                   does not affect the actual sound of the sequence, 
                   but may be important for other things (scoring, 
                   copyrighting, etc.) 
 
 
Now, we can describe the procedures themselves 
 
 
DESCRIPTION OF THE INTERFACE PROCEDURES 
 
 
******************************************************************** 
 
ReadSMF(InputSMFName:ansistring) 
 
                Reads the contents of a midi file to its raw image 
                in memory. 
 
******************************************************************** 
 
ReadSMFHeader(var SMFType: byte; var Tracks: words; var Ticks: word) 
 
                 Reads MIDI file header and assigns values to the 
                 following three variables: 
 
       SMFType - MIDI File type. (Types 0 and 1 are supported.) 
 
       Tracks  - Number of MIDI tracks in the file. 
 
       Ticks   - Number of MIDI ticks per quarternote. 
                 
******************************************************************** 
 
WriteSMFHeader(SMFType: byte; Tracks,Ticks:word) 
               
                 Writes these three values to the output MIDI 
                 file header. 
 
******************************************************************** 
 
ReadTrackHeader 
 
                 Reads MIDI track header and remembers the track 
                 length value stored in it. 
 
******************************************************************** 
 
WriteTrackHeader  
 
                  Writes a track header template and leaves space 
                  for the track length value. WriteEndOfTrack will 
                  write it later to the reserved space.                  
 
******************************************************************** 
 
ReadMIDIEvent(var Delta: cardinal; var Status: byte; var Byte1: byte; 
              var Byte2: byte; var Meta: byte; var MsgString: ansistring) 
 
                  The central procedure, along with its opposite: 
                  WriteMIDIEvent. Assigns values to the following 
                  six variables: 
 
          Delta - Delta Time in MIDI ticks from the previous event. 
 
         Status - Status Byte of MIDI Event. 
 
          Byte1 - The second and the third bytes of a three-byte-long 
          Byte2 - channel MIDI event. For a two-byte-long channel event, 
                  InByte2 = 0. For non-channel events (metaevents, 
                  system exclusives), Byte1 = Byte2 = 0. 
 
           Meta - Meta event type byte. For other events, Meta = 0; 
 
      MsgString - SysEx or meta event data. For all other events, 
                  MsgString=''; 
 
                  ReadMIDIEvent also verifies the read data. If something 
                  is wrong, it shows an error message with the information 
                  about the problem and aborts the reading. 
 
********************************************************************** 
 
WriteMIDIEvent(Delta: cardinal;Status,Byte1,Byte2,Meta: byte; MsgString: ansistring) 
 
                  Writes delta time Delta followed by a MIDI event 
                  specified by the above values. Depending on the Status 
                  byte, only the relevant variables are processed. For 
                  example, if the Status byte indicates a channel event, 
                  then Meta and MsgString are ignored. Alternatively, 
                  Byte1 and Byte2 are ignored for SysEx and meta events 
                  (Status in [$FF, $F0, $F7]). 
 
*********************************************************************** 
 
VerifyEndOfTrack  
 
                  Makes sure that the number of bytes left in the 
                  MIDI track is not negative, shows an error message 
                  otherwise. 
 
*********************************************************************** 
 
WriteEndOfTrack  
 
                  Closes the track by writing the End of Track meta 
                  event at its end and writing the track length value 
                  to the reserved space in the track header. 
 
*********************************************************************** 
 
TrackEmpty: boolean 
 
                  True if no events are left in the processed MIDI track. 
 
*********************************************************************** 
 
VerifyEndOfSMF 
   
                 Makes sure that the input MIDI file length is equal 
                 to the sum of the bytes read, shows an error message 
                 otherwise. 
 
*********************************************************************** 
 
WriteSMF(InputSMFName:ansistring) 
 
                 Writes the built raw image of the output file to 
                 the file with the specified name. 
 
*********************************************************************** 
 
 
SAMPLE DELPHI PROJECTS 
 
 
For your convenience, I am attaching four sample Delphi projects: 
 
MIDI File Information Project : reads the MIDI file and shows information 
about it. 
 
MIDI File Transposition Project: transposes any MIDI file any number of 
semitones up or down. 
 
MIDI File Player Project: plays MIDI files to MIDI Out. Source is only 
available with purchasing the full version. 
 
MIDI File Recorder Project: records MIDI files from MIDI In. Source is 
only available with purchasing the full version. 
 
 
DEMO VERSION 
 
 
The units MIDIRead and MIDIWrite are shareware. The demo version has 
all the features of the full version, and only one limitation: it  
cannot handle files more than 16K long. 
 
The full version units are contained in password-protected zip archives, 
along with the sources of the projects MIDI Player and MIDI Recorder. 
 
 
PURCHASING FULL VERSION 
 
 
You can purchase the full version for $5.  Send a $5 check payable 
to Alexei Gretchikha to the following address: 
 
                          Alexei Gretchikha, 
                          369 Upson Hall, 
                          Ithaca, NY 14853, 
                          USA 
 
with your e-mail address included, and I will e-mail you the password 
to the password-protected zipfiles. 
 
Because of the low price of the package, I did not arrange the credit 
card payment option. (Transaction costs would have almost doubled the 
price.) Please let me know if this is a problem for you. If it turns  
out that people prefer credit card payment, I will let the price up 
and switch to it.