AdLib MIDI Format

From ModdingWiki
Jump to navigation Jump to search
AdLib MIDI Format
Format typeMusic
Notation typeMIDI
InstrumentsOPL
Max channel count9 or 11
Max track count1
Max pattern count1
Max order count0
Tags?Title
Games

The AdLib MIDI Format is an Ad Lib music format, based on the standard MIDI format. It is derived from ROL Format and have compatible specification for playback. The format has a custom header, but the actual music data mostly in standard MIDI notation. Despite this, it appears that it was never intended to be played on a MIDI device, as the patch numbers refer to indices into a companion OPL instrument bank in AdLib Timbre Bank Format.

In this respect it is similar to the CMF Format, which also stores OPL music in MIDI notation, but unlike CMF this format keeps the instruments in a separate file.

File format

The file is arranged like this:

Data type Name Description
UINT8 majorVersion Major version number (usually 1)
UINT8 minorVersion Minor version number (usually 0)
INT32LE tuneId Song identification number
char[30] tuneName Song title, null terminated
UINT8 tickBeat Number of ticks per beat
UINT8 beatMeasure Number of beats per measure
INT32LE totalTick Length of song, in ticks
INT32LE dataSize Length of MIDI data block, in bytes
INT32LE nrCommand Total number of MIDI events in song, including final 0xFC "stop"
BYTE[8] filler Padding, set to zero
UINT8 soundMode OPL rhythm mode: 0=melodic (off), 1=percussive (on)
UINT8 pitchBRange Pitchbend range (1-12)
UINT16 basicTempo Song tempo, in beats-per-minute.
BYTE[8] filler2 Padding, set to zero
BYTE[dataSize] data Song data in standard MIDI format (same content as a MIDI MTrk block, almost)

The only known version of this format is 1.0.

Timing

The MIDI delay bytes in the song data are in units of "ticks", as per normal. Timing bytes vary from 0 to 0xFE and precede every command. A timing byte of 0xF8 means timing overflow with a value of 240. An overflow byte is always followed by another overflow byte or timing byte.

The fields tickBeat and beatMeasure can be used to convert ticks into beats and measures if desired, for example when drawing a musical staff.

The basicTempo field controls the song playback speed and is measured in beats per minute. The playback frequency can be calculated as follows:

frequency = (basicTempo / 60) * tickBeat

For a song that plays at 120BPM and with 10 ticks per beat, this works out as:

 frequency = (120 / 60) * 10
           = 20 Hz

Therefore playback should happen at 20 ticks per second to be at the correct tempo.

Also the song speed can be controlled during playback, see #Tempo multiplier event.

Rhythm mode

If soundMode is 0, then rhythm mode is off. Valid MIDI channels are 0 to 8 inclusive.

When soundMode is 1, then rhythm mode is on. Valid MIDI channels are 0 to 10, with 0 to 5 being melodic and 6 to 10 being percussive (see table below.) The official code actually treats any nonzero value as enabling rhythm mode, however only the values 0 and 1 should be used.

Both the top cymbal and the snare drum only use the OPL carrier registers, but the values for these registers are actually stored in the file's modulator fields. The carrier fields for these instruments appear to be unused. In other words, percussive instruments always have their settings loaded from the instrument's modulator fields, even when the values are loaded into the OPL chip's carrier registers.

MIDI channel Percussive instrument Operator used in file OPL cell
0-5 Melodic Modulator
Carrier
Modulator
Carrier
6 Bass drum Modulator
Carrier
13 - Channel 7 Modulator
16 - Channel 7 Carrier
7 Snare drum Modulator 17 - Channel 8 Carrier
8 Tom tom Modulator 15 - Channel 9 Modulator
9 Top cymbal Modulator 18 - Channel 9 Carrier
10 Hi-hat Modulator 14 - Channel 8 Modulator

There is no indicator whether a patch is percussive or melodic, so this is controlled entirely by which MIDI channel it is used on. It is possible to use the same patch for both percussive and melodic channels.

In percussive mode, the pitch of the single-operator percussive instruments is handled specially (that is, the snare drum, tom tom, top cymbal and hi-hat. The bass drum is not considered here.) When a note is played on MIDI channel 8 (tom-tom), the pitch on the other instruments is changed also. The changes are:

MIDI channel Percussive instrument Note pitch
7 Snare drum 7 semitones higher than the last tom-tom note on MIDI channel 8
8 Tom tom Use pitch as indicated in the MIDI note-on event
9 Top cymbal Use pitch from last tom-tom note on MIDI channel 8
10 Hi-hat 7 semitones higher than the last tom-tom note on MIDI channel 8

The initial frequency for the tom-tom is supposed to be two octaves below middle-C according to comments in the official adlib.c, however ! this doesn't seem to be the case.

Differences to MIDI

Polyphonic key pressure

According to MIDI specification, event 0xA# should have two byte parameters (the key/note and the pressure for that note), however this format provides only one byte parameter.

It is used to control channel volume. It frequently appears in the beginning of MIDI stream. Also it may be used for dynamic volume control of currently played note (for example: fade in, fade out, or tremolo effects).

Velocity parameter

This parameter goes with Note On and Note Off events. Since the format is inherited from ROL, it doesn't have note velocity specification.

It also changes current channel volume, same as event previously described.

If "Note On" event has velocity parameter equal to 0, it is treated as "Note Off" event, and channel volume is not changed.

Tempo multiplier

This event is structured like System Exclusive event, beginning with bytes 0xF0 0x7F and ending with 0xF7 byte.

By default, it does have fixed length of 6 bytes (including status bytes), and is used to change song speed during playback. It consists of an integer and a fractional part, in 1/128.

Byte Description
0xF0 SysEx Status Byte
0x7F Universal Realtime Command
0x00 Reserved
XX Integer part
YY Fractional part 1/128
0xF7 End of SysEx

So the actual frequency calculated like this:

multiplier = XX + YY / 128
frequency = (basicTempo / 60) * tickBeat * multiplier

Tools

The following tools are able to work with files in this format.

Name PlatformPlay? Create new? Modify? Convert/export to other? Import from other? Access hidden data? Edit metadata? Notes
AdLib play.exe DOSYesNoNoNoNoNoNo Part of AdLib Programmer's Guide
AdLib convert.exe DOSNoNoNoNoYes; .rolNoNo Part of AdLib Programmer's Guide
Camoto Linux/WinYesNoNoYes; manyNoNoYes
Vinyl2CMF Windows CLINoNoNoYes; .cmfNoNoNo

See also

Credits

This file format was originally reverse engineered by Malvineous as the Vinyl Goddess From Mars music format, until binarymaster discovered it was the same as an early AdLib music format, and supplied the documentation on which this article is now based. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)