Adlib sound effect

From ModdingWiki
Jump to navigation Jump to search
Adlib sound effect
Format typeSound
HardwareOPL
Number of sounds1
Sampling rateN/A
Channel count1
Bits per sampleN/A
Compressed?No
Tags?None
Games

The Adlib sound effect format is used to store sound effects for the OPL chip on Adlib and SoundBlaster sound cards. The sound data is normally packaged up inside an AudioT file.

File format

Ignoring the various headers that are found inside the AudioT file, the actual sound data is in the following format.

Data type Name Description
UINT8[16] instrument The OPL register settings for the instrument
UINT8 octave Octave to play notes at
BYTE[...] notes Pitch data

The instrument data is loaded into the registers below, which are for OPL channel #0. Any of the nine channels will work, however games using this format use channel #0, since the background music is written such that channel #0 is left free and will not interfere with the music.

The octave value is written into the block field of OPL register 0xB0. Since this register also holds other important fields (including the note on/off bit) care must be taken to ensure any writes to this register don't interfere with the other fields stored there. To calculate where the octave value should be written, the following formula can be used:

block = (octave & 7) << 2
regB0 = block | other_fields

Since bit 5 (0x20) of this register is the keyon field, whenever notes are played the value must be combined with the block or the octave will unexpectedly change.

regB0 = 0x20            // note on, and set octave to zero!
regB0 = block | 0x20    // note on
regB0 = block           // note off (0x20 not set)

Instrument data

The data in the instrument field is arranged as follows.

Data type Name OPL register Description
UINT8 mChar 0x20 Modulator characteristics
UINT8 cChar 0x23 Carrier characteristics
UINT8 mScale 0x40 Modulator scale
UINT8 cScale 0x43 Carrier scale
UINT8 mAttack 0x60 Modulator attack/decay rate
UINT8 cAttack 0x63 Carrier attack/decay rate
UINT8 mSust 0x80 Modulator sustain
UINT8 cSust 0x83 Carrier sustain
UINT8 mWave 0xE0 Modulator waveform
UINT8 cWave 0xE3 Carrier waveform
UINT8 nConn 0xC0 Feedback/connection (usually ignored and set to 0)
UINT8 voice - unknown (Muse-only)
UINT8 mode - unknown (Muse-only)
UINT8[3] padding - Pad instrument definition up to 16 bytes

Note:

The structure if the instrument data is identical to the instrument data structures in CMF Format, IBK Format and SBI Format files, except for the voice and mode settings, which are just unused padding in those files.

Pitch data

Each byte in the pitch data contains a single value to write to OPL register 0xA0. The data runs at a constant rate of 140 Hz, therefore the IMF music rate usually is a multiple of 140 Hz (known IMF rates are 280, 560 and 700 Hz), so that the adlib sound data can be sent to the OPL chip every two, four or five IMF cycles.

If a byte in the pitch data is zero, the note should be turned off, by disabling the keyon bit (bit 5, 0x20, in OPL register 0xB0. The other bits in register 0xB0 should be left unchanged, especially the block/octave.) When the next non-zero byte is read, the keyon bit should be set again (but probably after the byte has been written into register 0xA0 as per normal.)

In pseudocode it may look like this:

block = (octave & 7) << 2
note = off
while (more data) {
  get next byte
  if next byte is 0x00 {
    setRegister(0xB0, block)
    note = off
  } else {
    setRegister(0xA0, next byte)
    if note is off {
      setRegister(0xB0, block | 0x20)
      note = on
    }
  }
  wait for next 140 Hz tick
}

Note: This pseudocode is not entirely true to the playback routines used in the games! The games usually only update the OPL chip if the current byte value differs from the previous byte value, so that one long note is played instead of many short notes.