DixShtix

com.dixshtix.midi
Class EventType

java.lang.Object
  |
  +--java.lang.Number
        |
        +--com.dixshtix.midi.MidiNumber
              |
              +--com.dixshtix.midi.EventType
All Implemented Interfaces:
java.lang.Cloneable, java.io.Serializable

public class EventType
extends MidiNumber

All the primary types of MIDI file content.

These are internal programmatic representations of this data.

MESSAGE TYPES

Messages are divided into two main categories: Channel and System.

Channel
Channel messages contain a four-bit number in the Status byte which address the message specifically to one of sixteen channels. These messages are thereby intended for any units in a system whose channel number matches the channel number encoded into the Status byte.

There are two types of Channel messages: Voice and Mode.

Voice
To control the instrument's voices, Voice messages are sent over the Voice Channels.
Mode
To define the instrument's response to Voice messages, Mode messages are sent over the instrument's Basic Channel.
System
System messages are not encoded with channel numbers.

There are three types of System messages: Common, Real-Time, and Exclusive.

Common
Common messages are intended for all units in a system.
Real-Time
Real-Time messages are intended for all units in a system. They contain Status bytes only -- no Data bytes. Real-Time messages may be sent at any time -- even between bytes of a message which has a different status. In such cases the Real-Time message is either ignored or acted upon, after which the receiving process resumes under the previous status.
Exclusive
Exclusive messages can contain any number of Data bytes, and are terminated by an End of Exclusive (EOX) or any other Status byte. These messages include a Manufacturer's Identification (ID) code. If the receiver does not recognize the ID code, it should ignore the ensuing data.

So that other users can fully access MIDI instruments, manufacturers should publish the format of data following their ID code. Only the manufacturer can update the format following their ID.

DATA TYPES

Status Bytes
Status bytes are eight-bit binary numbers in which the Most Significant Bit (MSB) is set (binary 1). Status bytes serve to identify the message type, that is, the purpose of the Data bytes which follow the Status byte.

Except for Real-Time messages, new Status bytes will always command the receiver to adopt their status, even if the new Status is received before the last message was completed.

Running Status
For Voice and Mode messages only, when a Status byte is received and processed, the receiver will remain in that status until a different Status byte is received. Therefore, if the same Status byte would be repeated, it may (optionally) be omitted so that only the correct number of Data bytes need be sent. Under Running Status, then, a complete message need only consist of specified Data bytes sent in the specified order.

The Running Status feature is especially useful for communicating long strings of Note On/Off messages, where "Note On with Velocity of 0" is used for Note Off. (A separate Note Off Status byte is also available.)

Running Status will be stopped when any other Status byte intervenes, except that Real-Time messages will only interrupt the Running Status temporarily.

Unimplemented Status
Any status bytes received for functions which the receiver has not implemented should be ignored, and subsequent data bytes ignored.
Undefined Status
Undefined Status bytes must not be used. Care should be taken to prevent illegal messages from being sent during power-up or power-down. If undefined Status bytes are received, they should be ignored, as should subsequent Data bytes.
Data Bytes
Following the Status byte, there are (except for Real-Time messages) one or two Data bytes which carry the content of the message. Data bytes are eight-bit binary numbers in which the MSB is reset (binary 0). The number and range of Data bytes which must follow each Status byte are specified in the tables which follow. For each Status byte the correct number of Data bytes must always be sent. Inside the receiver, action on the message should wait until all Data bytes required under the current status are received. Receivers should ignore Data bytes which have not been properly preceded by a valid Status byte (with the exception of "Running Status," above).

Version:
0.1
Author:
Richard C. Penner II
See Also:
Serialized Form

Field Summary
static int kChannelAfterTouch
          Voice message, change pressure/velocity on all notes.
static int kChannelPrefix
          MIDI Channel Prefix MetaEvent.
static int kControlChange
          Voice message, change a control.
static int kCopyrightTextEvent
          Copyright Notice MetaEvent.
static int kCuePoint
          Cue Point MetaEvent.
static int kEndTrack
          End of Track MetaEvent.
static int kInstrumentName
          Instrument Name MetaEvent.
static int kKeyAfterTouch
          Voice message, alters playback on a particular channel and note at a specific velocity.
static int kKeySignature
          Key Signature MetaEvent.
static int kLyric
          Lyric MetaEvent.
static int kMarker
          Marker MetaEvent.
static int kMidiPortPrefix
          MIDI Port Prefix MetaEvent.
static int kNoteOff
          Voice message, ends playback on a particular channel and note, at a speed given by the velocity.
static int kNoteOn
          Voice message, starts playback on a particular channel, note, and velocity.
static int kPatchChange
          Voice message, change a patch/program.
static int kPitchWheelChange
          Voice message, change The Pitch Wheel setting.
static int kRawData
          Anything Else.
static int kRawMetaEvent
          Uncataloged Meta-Event.
static int kRT_ActiveSensing
          Real Time Message.
static int kRT_Continue
          Real Time Message.
static int kRT_Start
          Real Time Message.
static int kRT_Stop
          Real Time Message.
static int kRT_SystemReset
          Real Time Message.
static int kRT_TimingClock
          Real Time Message.
static int kSequencerSpecific
          Sequencer Specific Meta-Event.
static int kSetSequenceNumber
          Sequence Number MetaEvent.
static int kSetTempo
          Set Tempo MetaEvent.
static int kSmpteOffset
          SMPTE Offset MetaEvent.
static int kSongPosition
          System Common Message.
static int kSongSelect
          System Common Message.
static int kSysexF0
          System Exclusive Message.
static int kSysexF7
          System Exclusive Message.
static int kTextEvent
          Text MetaEvent.
static int kTextEvent08
          Undefined Text MetaEvent.
static int kTextEvent09
          Undefined Text MetaEvent.
static int kTextEvent0a
          Undefined Text MetaEvent.
static int kTextEvent0b
          Undefined Text MetaEvent.
static int kTextEvent0c
          Undefined Text MetaEvent.
static int kTextEvent0d
          Undefined Text MetaEvent.
static int kTextEvent0e
          Undefined Text MetaEvent.
static int kTextEvent0f
          Undefined Text MetaEvent.
static int kTimeSignature
          Time Signature MetaEvent.
static int kTrackName
          Sequence/Track Name MetaEvent.
static int kTuneRequest
          System Common Message.
static java.lang.String[] names
          English names of all the 44 original EventTypes.
private static ReverseLookup rev_names
          A type of lookup hash.
 
Fields inherited from class com.dixshtix.midi.MidiNumber
number
 
Fields inherited from class java.lang.Number
serialVersionUID
 
Constructor Summary
EventType(int evntNumber)
          Creator method.
EventType(java.lang.String name)
          Creator method from string.
 
Method Summary
static int getNumberNames()
          Returns the number of predefined EventTypes.
 boolean isMetaEvent()
          Accessor method.
static boolean isMetaEvent(int evntNumber)
          Conversion utility.
 boolean isMidiEvent()
          Accessor method.
static boolean isMidiEvent(int evntNumber)
          Conversion utility.
 boolean isNonTextMetaEvent()
          Accessor method.
static boolean isNonTextMetaEvent(int evntNumber)
          Conversion utility.
 boolean isTextEvent()
          Accessor method.
static boolean isTextEvent(int evntNumber)
          Conversion utility.
(package private) static int lookupByName(java.lang.String name)
          Conversion utility that converts a string into a integer in the range 0-43.
static java.lang.String toName(int evntNumber)
          Conversion utility.
 java.lang.String toString()
          Accessor method.
 
Methods inherited from class com.dixshtix.midi.MidiNumber
byteValue, doubleValue, equals, floatValue, hashCode, intValue, longValue, shortValue
 
Methods inherited from class java.lang.Object
, clone, finalize, getClass, notify, notifyAll, registerNatives, wait, wait, wait
 

Field Detail

kNoteOff

public static final int kNoteOff
Voice message, ends playback on a particular channel and note, at a speed given by the velocity.

8X nn vv

This is often replaced with a 0-velocity Note On message to take advantage of "Running Status." A Velocity of 64 is a good default for most Note Offs.

See Also:
Note

kNoteOn

public static final int kNoteOn
Voice message, starts playback on a particular channel, note, and velocity.

9X nn vv

A 64 velocity is default. A zero velocity is a disguised NoteOff.

See Also:
Note, Velocity

kKeyAfterTouch

public static final int kKeyAfterTouch
Voice message, alters playback on a particular channel and note at a specific velocity.

AX nn vv

This is called Polyphonic Key Pressure or Aftertouch.

See Also:
Note, Velocity

kControlChange

public static final int kControlChange
Voice message, change a control.

BX cc vv

There are a lot of different controls defined. This is also used to change the Channel Mode.

See Also:
Controller, Value

kPatchChange

public static final int kPatchChange
Voice message, change a patch/program.

CX pp

The instrument may define many different patches.

See Also:
Patch, GeneralMidi, RolandGS

kChannelAfterTouch

public static final int kChannelAfterTouch
Voice message, change pressure/velocity on all notes.

DX vv

This is Channel Aftertouch.

See Also:
Velocity

kPitchWheelChange

public static final int kPitchWheelChange
Voice message, change The Pitch Wheel setting.

EX value

Value is defined to be 14 bits of data. It is encoded as two 7-bit bytes. The least significant seven bits come first. Sensitivity of the pitch bender is selected in the receiver. Center position value (no pitch change) is 0x2000, which would be transmitted En 00 40.


kSetSequenceNumber

public static final int kSetSequenceNumber
Sequence Number MetaEvent.

FF 00 02 ss ss
or
FF 00 00
This optional event which must occur at the beginning of a MTrk (ie, before any non-zero delta-times and before any midi events) specifies the number of a sequence. The two data bytes ss ss, are that number which corresponds to the MIDI Cue message. In a format 2 MIDI file, this number identifies each "pattern" (ie, Mtrk) so that a "song" sequence can use the MIDI Cue message to refer to patterns. If the ss ss numbers are omitted (ie, Length byte = 0 instead of 2), then the MTrk's location in the file is used (ie, the first MTrk chunk is the first pattern). In format 0 or 1, which contain only one "pattern" (even though format 1 contains several MTrks), this event is placed in only the first MTrk. So, a group of format 1 files with different sequence numbers can comprise a "song collection".

There can be only one of these events per MTrk chunk in a Format 2. There can be only one of these events in a Format 0 or 1, and it must be in the first MTrk.


kTextEvent

public static final int kTextEvent
Text MetaEvent.

FF 01 len text

Any amount of text (amount of bytes = len) for any purpose. It's best to put this event at the beginning of an MTrk. Although this text could be used for any purpose, there are other text-based Meta-Events for such things as orchestration, lyrics, track name, etc. This event is primarily used to add "comments" to a MIDI file which a program would be expected to ignore when loading that file.

The text in this event should be printable ASCII characters for maximum interchange. However, other characters codes using the high-order bit may be used for interchange of files between different programs on the same computer which supports an extended character set. Programs on a computer which does not support non-ASCII characters should ignore those characters.

Note that len could be a series of bytes since it is expressed as a variable length quantity.

Meta-event types 01 through 0F are reserved for various types of text events, each of which meets the specification of text events (above) but is used for a different purpose:


kCopyrightTextEvent

public static final int kCopyrightTextEvent
Copyright Notice MetaEvent.
FF 02 len text

Contains a copyright notice as printable ASCII text. The notice should contain the characters (C), the year of the copyright, and the owner of the copyright. If several pieces of music are in the same MIDI File, all of the copyright notices should be placed together in this event so that it will be at the beginning of the file. This event should be the first event in the track chunk, at time 0.

Note that len could be a series of bytes since it is expressed as a variable length quantity.


kTrackName

public static final int kTrackName
Sequence/Track Name MetaEvent.
FF 03 len text

If in a format 0 track, or the first track in a format 1 file, the name of the sequence. Otherwise, the name of the track.

Note that len could be a series of bytes since it is expressed as a variable length quantity.


kInstrumentName

public static final int kInstrumentName
Instrument Name MetaEvent.
FF 04 len text

A description of the type of instrumentation to be used in that track. May be used with the MIDI Prefix meta-event to specify which MIDI channel the description applies to, or the channel may be specified as text in the event itself.

The named instrument might be different than the Sequence/Track Name. For example, maybe the name of your sequence (ie, Mtrk) is "Butterfly", but since the track is played on a piano, you might also include an Instrument Name of "Piano".

It's best to put one (or more) of this event at the beginning of an MTrk to provide the user with identification of what instrument(s) is playing the track. Usually, the instruments (ie, patches, tones, banks, etc) are setup on the audio devices via MIDI Program Change events within the MTrk, particularly in MIDI files that are intended for General MIDI Sound Modules. So, this event exists merely to provide the user with visual feedback of the instrumentation for a track.

Note that len could be a series of bytes since it is expressed as a variable length quantity.


kLyric

public static final int kLyric
Lyric MetaEvent.
FF 05 len text

A lyric to be sung. Generally, each syllable will be a separate lyric event which begins at the event's time.

Note that len could be a series of bytes since it is expressed as a variable length quantity.


kMarker

public static final int kMarker
Marker MetaEvent.
FF 06 len text

Normally in a format 0 track, or the first track in a format 1 file. The name of that point in the sequence, such as a rehearsal letter or section name ("First Verse", etc.)

Marker events might be used to denote a loop start and loop end (ie, where the sequence loops back to a previous event).

Note that len could be a series of bytes since it is expressed as a variable length quantity.


kCuePoint

public static final int kCuePoint
Cue Point MetaEvent.
FF 07 len text

A description of something happening on a film or video screen or stage at that point in the musical score ("Car crashes into house", "curtain opens", "she slaps his face", etc.)

A Cue Point might be used to denote where a WAVE (ie, sampled sound) file starts playing, where the text would be the WAVE's filename.

Note that len could be a series of bytes since it is expressed as a variable length quantity.


kTextEvent08

public static final int kTextEvent08
Undefined Text MetaEvent.
FF 08 len text

Meta-event types 01 through 0F are reserved for various types of text events, each of which meets the specification of text events (above) but is used for a different purpose:


kTextEvent09

public static final int kTextEvent09
Undefined Text MetaEvent.
FF 09 len text

Meta-event types 01 through 0F are reserved for various types of text events, each of which meets the specification of text events (above) but is used for a different purpose:


kTextEvent0a

public static final int kTextEvent0a
Undefined Text MetaEvent.
FF 0A len text

Meta-event types 01 through 0F are reserved for various types of text events, each of which meets the specification of text events (above) but is used for a different purpose:


kTextEvent0b

public static final int kTextEvent0b
Undefined Text MetaEvent.
FF 0B len text

Meta-event types 01 through 0F are reserved for various types of text events, each of which meets the specification of text events (above) but is used for a different purpose:


kTextEvent0c

public static final int kTextEvent0c
Undefined Text MetaEvent.
FF 0C len text

Meta-event types 01 through 0F are reserved for various types of text events, each of which meets the specification of text events (above) but is used for a different purpose:


kTextEvent0d

public static final int kTextEvent0d
Undefined Text MetaEvent.
FF 0D len text

Meta-event types 01 through 0F are reserved for various types of text events, each of which meets the specification of text events (above) but is used for a different purpose:


kTextEvent0e

public static final int kTextEvent0e
Undefined Text MetaEvent.
FF 0E len text

Meta-event types 01 through 0F are reserved for various types of text events, each of which meets the specification of text events (above) but is used for a different purpose:


kTextEvent0f

public static final int kTextEvent0f
Undefined Text MetaEvent.
FF 0F len text

Meta-event types 01 through 0F are reserved for various types of text events, each of which meets the specification of text events (above) but is used for a different purpose:


kChannelPrefix

public static final int kChannelPrefix
MIDI Channel Prefix MetaEvent.
FF 20 01 channel

The MIDI channel (0-15) contained in this event may be used to associate a MIDI channel with all events which follow, including System exclusive and meta-events. This channel is "effective" until the next normal MIDI event (which contains a channel) or the next MIDI Channel Prefix meta-event. If MIDI channels refer to "tracks", this message may into a format 0 file, keeping their non-MIDI data associated with a track. This capability is also present in Yamaha's ESEQ file format.

In a Format 1 file, this optional event which normally occurs at the beginning of an MTrk (ie, before any non-zero delta-times and before any MetaEvents except Sequence Number) specifies to which MIDI Channel any subsequent MetaEvent or System Exclusive events are associated. The data byte channel, is the MIDI channel, where 0 would be the first channel.

The MIDI spec does not give a MIDI channel to System Exclusive events. Nor do MetaEvents have an embedded channel. When creating a Format 0 MIDI file, all of the System Exclusive and MetaEvents go into one track, so its hard to associate these events with respective MIDI Voice messages. (ie, For example, if you wanted to name the musical part on MIDI channel 1 "Flute Solo", and the part on MIDI Channel 2 "Trumpet Solo", you'd need to use 2 Track Name MetaEvents. Since both events would be in the one track of a Format 0 file, in order to distinguish which track name was associated with which MIDI channel, you would place a MIDI Channel MetaEvent with a channel number of 0 before the "Flute Solo" Track Name MetaEvent, and then place another MIDI Channel MetaEvent with a channel number of 1 before the "Trumpet Solo" Track Name MetaEvent.

It is acceptable to have more than one MIDI channel event in a given track, if that track needs to associate various events with various channels.


kMidiPortPrefix

public static final int kMidiPortPrefix
MIDI Port Prefix MetaEvent.
FF 21 01 port

This optional event which normally occurs at the beginning of an MTrk (ie, before any non-zero delta-times and before any midi events) specifies out of which MIDI Port (ie, buss) the MIDI events in the MTrk go. The data byte port, is the port number, where 0 would be the first MIDI buss in the system.

The MIDI spec has a limit of 16 MIDI channels per MIDI input/output (ie, port, buss, jack, or whatever terminology you use to describe the hardware for a single MIDI input/output). The MIDI channel number for a given event is encoded into the lowest 4 bits of the event's Status byte. Therefore, the channel number is always 0 to 15. Many MIDI interfaces have multiple MIDI input/output busses in order to work around limitations in the MIDI bandwidth (ie, allow the MIDI data to be sent/received more efficiently to/from several external modules), and to give the musician more than 16 MIDI Channels. Also, some sequencers support more than one MIDI interface used for simultaneous input/output. Unfortunately, there is no way to encode more than 16 MIDI channels into a MIDI status byte, so a method was needed to identify events that would be output on, for example, channel 1 of the second MIDI port versus channel 1 of the first MIDI port. This MetaEvent allows a sequencer to identify which MTrk events get sent out of which MIDI port. The MIDI events following a MIDI Port MetaEvent get sent out that specified port.

It is acceptable to have more than one Port event in a given track, if that track needs to output to another port at some point in the track.


kEndTrack

public static final int kEndTrack
End of Track MetaEvent.
FF 2F 00

This event is not optional. It is included so that an exact ending point may be specified for the track, so that an exact length, which is necessary for tracks which are looped or concatenated.

Only 1 of these per MTrk.


kSetTempo

public static final int kSetTempo
Set Tempo MetaEvent.
FF 51 03 tt tt tt

(in microseconds per MIDI quarter-note)

This event indicates a tempo change. Another way of putting "microseconds per quarter-note" is "24ths of a microsecond per MIDI clock". Representing tempos as time per beat instead of beat per time allows absolutely exact long-term synchronization with a time-based sync protocol such as SMPTE time code or MIDI time code. This amount of accuracy provided by this tempo resolution allows a four-minute piece at 120 beats per minute to be accurate within 500 microseconds at the end of the piece. Ideally, these events should only occur where MIDI clocks would be located -- this convention is intended to guarantee, or at least increase the likelihood, of compatibility with other synchronization devices so that a time signature/tempo map stored in this format may easily be transfered to another device.

The 3 data bytes of tt tt tt are the tempo in microseconds per quarter note. In other words, the microsecond tempo value tells you how long each one of your sequencer's "quarter notes" should be. For example, if you have the 3 bytes of 07 A1 20, then each quarter note should be 0x07A120 (or 500,000) microseconds long.

So, the MIDI file format expresses tempo as "the amount of time (ie, microseconds) per quarter note". As you recall, the time signature specifies pulses per quarter note, which all ties in.

BPM

Normally, musicians express tempo as "the amount of quarter notes in every minute (ie, time period)". This is the opposite of the way that the MIDI file format expresses it.

When musicians refer to a "beat" in terms of tempo, they are referring to a quarter note (ie, a quarter note is always 1 beat when talking about tempo, regardless of the time signature. Yes, it's a bit confusing to non-musicians that the time signature's "beat" may not be the same thing as the tempo's "beat" -- it won't be unless the time signature's beat also happens to be a quarter note. But that's the traditional definition of BPM tempo). To a musician, tempo is therefore always "how many quarter notes happen during every minute". Musicians refer to this measurement as BPM (ie, Beats Per Minute). So a tempo of 100 BPM means that a musician must be able to play 100 steady quarter notes, one right after the other, in one minute. That's how "fast" the "musical tempo" is at 100 BPM. It's very important that you understand the concept of how a musician expresses "musical tempo" (ie, BPM) in order to properly present tempo settings to a musician, and yet be able to relate it to how the MIDI file format expresses tempo.

To convert the MIDI file format's tempo (ie, the 3 bytes that specify the amount of microseconds per quarter note) to BPM:

BPM = 60,000,000/(tt tt tt)

For example, a tempo of 120 BPM = 07 A1 20.

So why does the MIDI file format use "time per quarter note" instead of "quarter notes per time" to specify its tempo? Well, its easier to specify more precise tempos with the former. With BPM, sometimes you have to deal with fractional tempos (for example, 100.3 BPM) if you want to allow a finer resolution to the tempo. Using microseconds to express tempo offers plenty of resolution.

Also, SMPTE is a time-based protocol (ie, it's based upon seconds, minutes, and hours, rather than a musical tempo). Therefore it's easier to relate the MIDI file's tempo to SMPTE timing if you express it as microseconds. Many musical devices now use SMPTE to sync their playback.

PPQN Clock

A sequencer typically uses some internal hardware timer counting off steady time (ie, microseconds perhaps) to generate a software "PPQN clock" that counts off the timebase (Division) "ticks". In this way, the time upon which an event occurs can be expressed to the musician in terms of a musical bar:beat:PPQN-tick rather than how many microseconds from the start of the playback. Remember that musicians always think in terms of a beat, not the passage of seconds, minutes, etc.

As mentioned, the microsecond tempo value tells you how long each one of your sequencer's "quarter notes" should be. From here, you can figure out how long each one of your sequencer's PPQN clocks should be by dividing that microsecond value by your MIDI file's Division. For example, if your MIDI file's Division is 96 PPQN, then that means that each of your sequencer's PPQN clock ticks at the above tempo should be 500,000 / 96 (or 5,208.3) microseconds long (ie, there should be 5,208.3 microseconds in between each PPQN clock tick in order to yield a tempo of 120 BPM at 96 PPQN. And there should always be 96 of these clock ticks in each quarter note, 48 ticks in each eighth note, 24 ticks in each sixteenth, etc).

Note that you can have any timebase at any tempo. For example, you can have a 96 PPQN file playing at 100 BPM just as you can have a 192 PPQN file playing at 100 BPM. You can also have a 96 PPQN file playing at either 100 BPM or 120 BPM. Timebase and tempo are two entirely separate quantities. Of course, they both are needed when you setup your hardware timer (ie, when you set how many microseconds are in each PPQN tick). And of course, at slower tempos, your PPQN clock tick is going to be longer than at faster tempos.

MIDI Clock

MIDI clock bytes are sent over MIDI, in order to sync the playback of 2 devices (ie, one device is generating MIDI clocks at its current tempo which it internally counts off, and the other device is syncing its playback to the receipt of these bytes). Unlike with SMPTE frames, MIDI clock bytes are sent at a rate related to the musical tempo.

Since there are 24 MIDI Clocks in every quarter note, the length of a MIDI Clock (ie, time in-between each MIDI Clock message) is the microsecond tempo divided by 24. In the above example, that would be 500,000/24, or 20,833.3 microseconds in every MIDI Clock. Alternately, you can relate this to your timebase (ie, PPQN clock). If you have 96 PPQN, then that means that a MIDI Clock byte must occur every 96 / 24 (ie, 4) PPQN clocks.

SMPTE

SMPTE counts off the passage of time in terms of seconds, minutes, and hours (ie, the way that non-musicians count time). It also breaks down the seconds into smaller units called "frames". The movie industry created SMPTE, and they adopted 4 different frame rates. You can divide a second into 24, 25, 29, or 30 frames. Later on, even finer resolution was needed by musical devices, and so each frame was broken down into "subframes".

So, SMPTE is not directly related to musical tempo. SMPTE time doesn't vary with "musical tempo".

Many devices use SMPTE to sync their playback. If you need to synchronize with such a device, then you may need to deal with SMPTE timing. Of course, you're probably still going to have to maintain some sort of PPQN clock, based upon the passing SMPTE subframes, so that the user can adjust the tempo of the playback in terms of BPM, and can consider the time of each event in terms of bar:beat:tick. But since SMPTE doesn't directly relate to musical tempo, you have to interpolate (ie, calculate) your PPQN clocks from the passing of subframes/frames/seconds/minutes/hours (just as we previously calculated the PPQN clock from a hardware timer counting off microseconds).

Let's take the easy example of 25 Frames and 40 SubFrames. As previously mentioned in the discussion of Division, this is analogous to millisecond based timing because you have 1,000 SMPTE subframes per second. (You have 25 frames per second. Each second is divided up into 40 subframes, and you therefore have 25 * 40 subframes per second. And remember that 1,000 milliseconds are also in every second). Every millisecond therefore means that another subframe has passed (and vice versa). Every time you count off 40 subframes, a SMPTE frame has passed (and vice versa). Etc.

Let's assume you desire 96 PPQN and a tempo of 500,000 microseconds. Considering that with 25-40 Frame-SubFrame SMPTE timing 1 millisecond = 1 subframe (and remember that 1 millisecond = 1,000 microseconds), there should be 500,000 / 1,000 (ie, 500) subframes per quarter note. Since you have 96 PPQN in every quarter note, then every PPQN ends up being 500 / 96 subframes long, or 5.2083 milliseconds (ie, there's how we end up with that 5,208.3 microseconds PPQN clock tick just as we did above in discussing PPQN clock). And since 1 millisecond = 1 subframe, every PPQN clock tick also equals 5.2083 subframes at the above tempo and timebase.

Conclusions

BPM= 60,000,000/MicroTempo
MicrosPerPPQN= MicroTempo/TimeBase
MicrosPerMIDIClock= MicroTempo/24
PPQNPerMIDIClock= TimeBase/24
MicrosPerSubFrame= 1000000 * Frames * SubFrames
SubFramesPerQuarterNote= MicroTempo/(Frames * SubFrames)
SubFramesPerPPQN= SubFramesPerQuarterNote/TimeBase
MicrosPerPPQN= SubFramesPerPPQN * Frames * SubFrames

Errata

In a format 0 file, the tempo and time signature changes are scattered throughout the one MTrk. In format 1, the very first MTrk should consist of just the tempo and time signature events so that it could be read by some device capable of generating a "tempo map". In format 2, each MTrk should begin with at least one initial tempo and time signature event.

NOTE: If there are no tempo and time signature events in a MIDI file, assume 120 BPM and 4/4.


kSmpteOffset

public static final int kSmpteOffset
SMPTE Offset MetaEvent.
FF 54 05 hr mn se fr ff

This event, if present, designates the SMPTE time at which the track chunk is supposed to start. It should be present at the beginning of the track, that is, before any nonzero delta-times, and before any transmittable MIDI events. the hour must be (or Should Not be) encoded with the SMPTE format, just as it is in MIDI Time Code. In a format 1 file, the SMPTE Offset must be stored with the tempo map, and has no meaning in any of the other tracks. The ff field contains fractional frames, in 100ths of a frame, even in SMPTE-based tracks which specify a different frame subdivision for delta-times.


kTimeSignature

public static final int kTimeSignature
Time Signature MetaEvent.
FF 58 04 nn dd cc bb

The time signature is expressed as four numbers. nn and dd represent the numerator and denominator of the time signature as it would be notated. The denominator is a negative power of two: 2 represents a quarter-note, 3 represents an eighth-note, etc. The cc parameter expresses the number of MIDI clocks in a metronome click. The bb parameter expresses the number of notated 32nd-notes in a MIDI quarter-note (24 MIDI clocks). This was added because there are already multiple programs which allow a user to specify that what MIDI thinks of as a quarter-note (24 clocks) is to be notated as, or related to in terms of, something else.

Therefore, the complete event for 6/8 time, where the metronome clicks every three eighth-notes, but there are 24 clocks per quarter-note, 72 to the bar, would be (in hex):

FF 58 04 06 03 18 08

That is, 6/8 time (8 is 2 to the 3rd power, so this is 06 03), 24 MIDI clocks per dotted-quarter (0x18 hex!), and eight notated 32nd-notes per quarter-note.

Errata

In a format 0 file, the tempo and time signature changes are scattered throughout the one MTrk. In format 1, the very first MTrk should consist of just the tempo and time signature events so that it could be read by some device capable of generating a "tempo map". In format 2, each MTrk should begin with at least one initial tempo and time signature event.

NOTE: If there are no tempo and time signature events in a MIDI file, assume 120 BPM and 4/4.


kKeySignature

public static final int kKeySignature
Key Signature MetaEvent.

FF 59 02 sf mi

sf = -7:7 flats
sf = -1:1 flat
sf = 0:key of C
sf = 1:1 sharp
sf = 7:7 sharps
mi = 0:major key
mi = 1:minor key


kSequencerSpecific

public static final int kSequencerSpecific
Sequencer Specific Meta-Event.

FF 7F len data

Special requirements for particular sequencers may use this event type: the first byte or bytes of data is a manufacturer ID (these are one byte, or if the first byte is 00, three bytes). As with MIDI System Exclusive, manufacturers who define something using this meta-event should publish it so that others may be used by a sequencer which elects to use this as its only file format; sequencers with their established feature-specific formats should probably stick to the standard features when using this format.

This can be used by a program to store proprietary data. The first byte(s) should be a unique ID of some sort so that a program can identity whether the event belongs to it, or to some other program. A 4 character (ie, ASCII) ID is recommended for such.

Note that len could be a series of bytes since it is expressed as a variable length quantity.


kRawMetaEvent

public static final int kRawMetaEvent
Uncataloged Meta-Event.

FF XX len data

For XX in the range, 10-1F, 22-2E, 30-50, 52-53, 55-57, 5A-7E, applications and sequencers can define special sequences.


kSysexF0

public static final int kSysexF0
System Exclusive Message.

On the wire:

F0 id type bytes F7

In the file:

F0 length id type bytes F7

In a file, a F0 System event can be split. The remained will be in F7 events. The only restriction on the bytes is that they must be in the range 0-127.

In no case should other Status or Data bytes (except Real-Time) be interleaved with System Exclusive, regardless of whether or not the ID code is recognized.

EOX or any other Status byte, except Real-Time, will terminate a System Exclusive message, and should be sent immediately at its conclusion.


kSysexF7

public static final int kSysexF7
System Exclusive Message.

On the wire:

bytes

In the file:

F7 length bytes

In a file, a F0 System event can be split. The remained will be in F7 events. The final byte of F7 in the byte-stream ends the original F0 System exclusive message.


kSongPosition

public static final int kSongPosition
System Common Message. Cue up to this position in the song.

F2 LSB HSB

Song Position Pointer: Is an internal register which holds the number of MIDI beats (1 beat = 6 MIDI clocks) since the start of the song. Normally it is set to 0 when the START switch is pressed, which starts sequence playback. It then increments with every sixth MIDI clock receipt, until STOP is pressed. If CONTINUE is pressed, it continues to increment. It can be arbitrarily preset (to a resolution of 1 beat) by the SONG POSITION POINTER message.


kSongSelect

public static final int kSongSelect
System Common Message. Cue up to this song.

F3 Song

Song is in the range 0-127. Specifies which song or sequence is to be played upon receipt of a Start (Real-Time) message.


kTuneRequest

public static final int kTuneRequest
System Common Message. Tune Analog Synthesizers.

F6

Used with analog synthesizers to request them to tune their oscillators.


kRawData

public static final int kRawData
Anything Else. This should not be depended on.

kRT_TimingClock

public static final int kRT_TimingClock
Real Time Message. Timing Clock.

F8

The system is synchronized with this clock, which is sent at a rate of 24 clocks/quarter note.


kRT_Start

public static final int kRT_Start
Real Time Message. Start.

FA

This byte is immediately sent when the PLAY switch on the master (e.g. sequencer or rhythm unit) is pressed.


kRT_Continue

public static final int kRT_Continue
Real Time Message. Continue.

FB

This is sent when the CONTINUE switch is hit. A sequence will continue at the time of the next clock.


kRT_Stop

public static final int kRT_Stop
Real Time Message. Stop.

FC

This byte is immediately sent when the STOP switch is hit. It will stop the sequence.


kRT_ActiveSensing

public static final int kRT_ActiveSensing
Real Time Message. Active Sensing.

FE

Use of this message is optional, for either receivers or transmitters. This is a "dummy" Status byte that is sent every 300 ms (max), whenever there is no other activity on MIDI. The receiver will operate normally if it never receives 0xFE. Otherwise, if 0xFE is ever received, the receiver will expect to receive 0xFE or a transmission of any type every 300 ms (max). If a period of 300 ms passes with no activity, the receiver will turn off the voices and return to normal operation.


kRT_SystemReset

public static final int kRT_SystemReset
Real Time Message. System Reset.

FF

This message initializes all of the system to the condition of just having turned on power. The system Reset message should be used sparingly, preferably under manual command only. In particular, it should not be sent automatically on power up.


rev_names

private static ReverseLookup rev_names
A type of lookup hash. Do not access directly.
See Also:
lookupByName(String)

names

public static final java.lang.String[] names
English names of all the 44 original EventTypes.
Constructor Detail

EventType

public EventType(int evntNumber)
Creator method.
Parameters:
evntNumber - in the range 0-43.

EventType

public EventType(java.lang.String name)
Creator method from string.
Parameters:
evntName - is one of the previously-defined parameter names.
Method Detail

isMidiEvent

public static boolean isMidiEvent(int evntNumber)
Conversion utility.
Parameters:
evntNumber - is in the range 0-43.

isMidiEvent

public boolean isMidiEvent()
Accessor method.

isTextEvent

public static boolean isTextEvent(int evntNumber)
Conversion utility.
Parameters:
evntNumber - is in the range 0-43.

isTextEvent

public boolean isTextEvent()
Accessor method.

isNonTextMetaEvent

public static boolean isNonTextMetaEvent(int evntNumber)
Conversion utility.
Parameters:
evntNumber - is in the range 0-43.

isNonTextMetaEvent

public boolean isNonTextMetaEvent()
Accessor method.

isMetaEvent

public static boolean isMetaEvent(int evntNumber)
Conversion utility.
Parameters:
evntNumber - is in the range 0-43.

isMetaEvent

public boolean isMetaEvent()
Accessor method.

toName

public static java.lang.String toName(int evntNumber)
Conversion utility.
Parameters:
evntNumber - is in the range 0-43.

toString

public java.lang.String toString()
Accessor method.
Overrides:
toString in class MidiNumber

lookupByName

static int lookupByName(java.lang.String name)
Conversion utility that converts a string into a integer in the range 0-43.

getNumberNames

public static int getNumberNames()
Returns the number of predefined EventTypes. Originally 44 types are defined. More may be added in future.

DixShtix