Difference between revisions of "HERAD"
(→MIDI notation) |
(→Header) |
||
Line 90: | Line 90: | ||
| <tt>UINT16</tt> || <tt>wLoopCount</tt> || Number of times the selected measures will play (0 = loop forever; >0 - play N times) | | <tt>UINT16</tt> || <tt>wLoopCount</tt> || Number of times the selected measures will play (0 = loop forever; >0 - play N times) | ||
|- | |- | ||
− | | <tt>UINT16</tt> || <tt>wSpeed</tt> || | + | | <tt>UINT16</tt> || <tt>wSpeed</tt> || Fixed point value that controls music speed. Value range is 0x0100 - 0x8100 |
|- | |- | ||
| <tt>UINT8[32]</tt> || <tt>bUnknown5</tt> || Unknown array of bytes only in '''AGD''' files (settings for Adlib Gold surround module?) | | <tt>UINT8[32]</tt> || <tt>bUnknown5</tt> || Unknown array of bytes only in '''AGD''' files (settings for Adlib Gold surround module?) | ||
|} | |} | ||
+ | |||
+ | ====Speed / Tempo==== | ||
+ | The default tempo is 500 BPM with the MIDI data at 24 ticks per quarter note. To slow down the music, a fixed-point value must be entered into the <tt>wSpeed</tt> field. To calculate the tempo of the song, take 500 and divide it by the value. Since this is a fixed-point value, some BPM will be at odd values. | ||
A measure is 96 MIDI ticks in duration. | A measure is 96 MIDI ticks in duration. |
Revision as of 01:57, 1 May 2016
HERAD System | |||||
Developer: | Rémi Herbulot | ||||
Header: | Custom | ||||
Content: | Notational | ||||
Instruments: | Optional | ||||
Target Output
| |||||
Released: | 1992-??-?? | ||||
First Game: | ? | ||||
Extensions |
|
Herbulot AdLib (HERAD) System was created by Rémi Herbulot, one of Cryo Interactive Entertainment co-founders and lead programmers. Stéphane Picq, Cryo's first music composer also helped design HERAD with Herbulot. There are two versions of HERAD that are known to exist.
Contents
Players
- RdosPlay - DOS - only version 1 (OPL2/OPL3 music)
Converters
HERAD to ?
? to HERAD
Games
Released | Title | Sample |
---|---|---|
1992-??-?? | Dune (DOS) | |
1992-??-?? | KGB (DOS) | |
1993-??-?? | MegaRace (DOS) |
Technical
- File extensions stands for different sound devices:
- ADL, SDB - AdLib/Sound Blaster (OPL2)
- AGD - AdLib Gold (OPL3)
- M32 - Roland MT-32 (LA32)
- HSQ are compressed files with the Herbulot Sequencer algorithm, which is similar to LZ** dictionary algorithms.
- The internal music notation is very similar to MIDI, however Pitch Bend and Meta events do differ.
- M32 files usually contain one multi-channel track, while ADL/SDB/AGD files may contain multiple tracks.
Version Compatibility
The format has two known versions, which have several differences; however, neither version has any FourCC or header data denoting which version it is. In order to detect the proper version, each music file needs to be inspected.
The first version was used in Dune (DOS) and KGB (DOS), and the second version was used in MegaRace (DOS).
File structure
There are three chunks to HERAD files: the header, the MIDI data, and the AdLib Instrument chunk. Note that the Instrument chunk is absent in M32 files.
Header
All values in the header are in little endian format.
Data type | Name | Description |
---|---|---|
UINT16 | wFileSize | Size of uncompressed file (different between versions) |
UINT16[21] | wOffsets | Array of relative offsets to the MIDI tracks (0 = track doesn't exist) |
UINT16 | wLoopStart | Loop starts at this measure (0 = don't loop) |
UINT16 | wLoopEnd | Loop ends at this measure (0 = don't loop) |
UINT16 | wLoopCount | Number of times the selected measures will play (0 = loop forever; >0 - play N times) |
UINT16 | wSpeed | Fixed point value that controls music speed. Value range is 0x0100 - 0x8100 |
UINT8[32] | bUnknown5 | Unknown array of bytes only in AGD files (settings for Adlib Gold surround module?) |
Speed / Tempo
The default tempo is 500 BPM with the MIDI data at 24 ticks per quarter note. To slow down the music, a fixed-point value must be entered into the wSpeed field. To calculate the tempo of the song, take 500 and divide it by the value. Since this is a fixed-point value, some BPM will be at odd values.
A measure is 96 MIDI ticks in duration.
For the 1st version wFileSize value represents total file size, for the 2nd version it represents file size without instruments data block. Also there are differences in MIDI notation, which is described below.
Looping
Looping a song works by specifying the start and end points with the wLoopStart and wLoopEnd bytes, and denoting how many times the loop should play with the wLoopCount byte. This can be used to either play a song forever, or to play a song that doesn't repeat but has a short segment that loops instead (like a repeating melody or phrase). For example, to loop first two measures of the song, the wLoopStart byte will be 01 and the wLoopEnd byte will be 03.
For version 1 songs, in order for music to repeat, this loop data must be in place. Version 2 songs that are being played back in MegaRace's sound engine will automatically repeat forever even if the wLoopCount field specifies that the song should only be played once. If there are no loop points in the file, the version 2 song will automatically repeat from beginning to end. As a result, several tracks in MegaRace (NewSan, Maeva and Terminal City) have short loops that are only a few measures long. Because those loop points are being used, the music continues to loop the song from beginning to end due to the sound engine. The other remaining tracks from MegaRace (Factory Land, Skyholder and Fractalian Space) have intros to them that are not repeated so their loop points start at the end of the intro and finish when the song is over.
MIDI notation
- The most of status bytes are compatible with MIDI standard.
- It looks like that running status is not supported as all known songs programmed in HERAD never use it.
- All MIDI data for Cryo's games uses 24 ticks per quarter note.
MIDI message | Description | MIDI compatible |
---|---|---|
8# xx xx | Note Off (version 1) | Yes |
8# xx | Note Off (version 2) | No |
9# xx xx | Note On | Yes |
A# ?? ?? | Poly Aftertouch (unused) | Unknown |
B# ?? ?? | Control Change (unused) | Unknown |
C# xx | Program Change (uses internal instruments for AGD and SDB) | Yes |
D# xx | Channel Aftertouch | Yes |
E# xx | Pitch Bend | No |
FF | Track End |
For the Note Off command in version 2 songs, the velocity byte has been removed. The Pitch Bend command has only the MSB byte available. Like the MIDI Standard dictates, 0x40 is the "center" of the pitch bend range. Sending this data byte after the Pitch Bend status byte will result in no change to the pitch. Anything higher than 0x40, the pitch will go up, whereas any value less than 0x40 produces a lower pitch. In the MegaRace music files, Channel Aftertouch only occurs one time in one song (Fractalian Space).
Instrument Data
The instrument chunk contains all the OPL register values needed for each instrument, along with some macros that control various parameters of the instrument during playback. Each instrument is 0x28 bytes long. Version 2 of HERAD introduced a keymap instrument that can be used for linking several instruments into one; this allows for some very complex drum sequencing.
To use an instrument, the MIDI notation must use the "Program Change" message and specify a number for the instrument to be used. All instruments are listed sequentially and the first instrument is always number #0. Let's say we want to play the 13th instrument in the chunk. We tell the MIDI data to Program Change to instrument number #12 (C0 0C) and the notation after that will play using that instrument until the end of the track or another Program Change message is sent.
It seems that the OPL register values are almost in the exact same layout as the BNK format (technical). Thanks to Malvineous for his documentation on the BNK file format.
These offsets are still a work in progress and need more research.
Offset | Size | Name | Description | OPL base register | Notes |
---|---|---|---|---|---|
0x0 | 1 | |
Denotes if this is an instrument or a version 2 keymap. 0x0 in version 1 songs, 0x1 in version 2 songs Changing this value in Version 1 songs seems to have no effect. | ||
0x1 | 1 | |
Most likely a meta identifier (changing this value has no effect in any song) | ||
0x2 | 1 | ksl | |
0x40 (bits 6-7) | |
0x3 | 1 | multiple | |
0x20 (bits 0-3) | |
0x4 | 1 | feedback | |
0xC0 (bits 1-3) | |
0x5 | 1 | attack | |
0x60 (upper four bits) | |
0x6 | 1 | sustain | |
0x80 (upper four bits) | |
0x7 | 1 | eg | |
0x20 (bit 5) | nonzero value is on |
0x8 | 1 | decay | |
0x60 (lower four bits) | |
0x9 | 1 | releaseRate | |
0x80 (lower four bits) | |
0xA | 1 | totalLevel | |
0x40 (bit 0-5) | uses all bits; output level can still be modified by output level byte 0x1E |
0xB | 1 | am | 0x20 (bit 7) | ||
0xC | 1 | vib | 0x20 (bit 6) | ||
0xD | 1 | ksr | |
0x20 (bit 4) | |
0xE | 1 | con | |
0xC0 (bit 0, inverted) | 0: OPL bit set to 1 other: OPL bit set to 0 |
0xF | 1 | ksl | |
0x40 (bits 6-7) | |
0x10 | 1 | multiple | |
0x20 (bits 0-3) | |
0x11 | 1 | feedback | |
0xC0 (bits 1-3) | This byte seems to have garbage data in it and is not used |
0x12 | 1 | attack | |
0x60 (upper four bits) | |
0x13 | 1 | sustain | |
0x80 (upper four bits) | |
0x14 | 1 | eg | |
0x20 (bit 5) | nonzero value is on |
0x15 | 1 | decay | |
0x60 (lower four bits) | |
0x16 | 1 | releaseRate | |
0x80 (lower four bits) | |
0x17 | 1 | totalLevel | |
0x40 (bit 0-5) | uses all bits; output level can still be modified by output level byte 0x1F |
0x18 | 1 | am | 0x20 (bit 7) | ||
0x19 | 1 | vib | 0x20 (bit 6) | ||
0x1A | 1 | ksr | |
0x20 (bit 4) | |
0x1B | 1 | con | |
0xC0 (bit 0, inverted) | So far, this seems to be always set at zero. |
0x1C | 1 | |
0xE0 (bits 0-1) | ||
0x1D | 1 | |
0xE0 (bits 0-1) | ||
0x1E | 1 | |
Uses the MIDI NoteOn velocity to control the Modulator Output level (goes from 0 to 4; 0 = no velocity change, 4 = softest velocity change) | ||
0x1F | 1 | |
Same as previous macro, only this affects the Carrier operator. Seems to multiply the velocity value; as a result some notes that are too loud or quiet will not be affected since the sum will be out of range for the OPL chip. | ||
0x20 | 1 | |
0xC0 (bits 1-3) | This byte seems to be a duplicate control for Feedback, need to do more research. | |
0x21 | 1 | |
Increases pitch bend range (Fine tune = 0, Coarse tune = 1) | ||
0x22 | 1 | |
Normally set at 0x0, 0xC = an octave higher | ||
0x23 | 1 | Duration of the pitch bend in ticks | |||
0x24 | 1 | |
Setting to 0x18, while the coarse flag is enabled produces semi-tone intervals, however they start to go out of tune after several notes. | ||
0x25 | 1 | |
|||
0x26 | 1 | |
In version 1 songs, this is set to 0x0, whereas in version 2 songs, this is always set to 0x1 | ||
0x27 | 1 | |
Always set to zero |
Keymap
Introduced in version 2 songs, a keymap control was added into the instrument chunk. All 6 songs in MegaRace use this keymapping for their drum sequencing. Like the other separate instruments in this chunk, it is also 0x28 bytes long, but differs greatly from the other instruments since it doesn't contain any OPL register values.
It is essentially an array of instruments that are mapped to different MIDI notes. Instead of having to send a Program Change MIDI message every time a different drum instrument is used, this keymap greatly reduces the amount of MIDI messages being sent since all the drum sounds are located in one instrument.
Offset | Description | Notes |
---|---|---|
0x0 | |
Must always be 0xFF; this denotes that this is a keymap |
0x1 | |
Most likely a meta identifier (so far, changing this value results in no effect) |
0x2 | |
Must always be 0x18; changing this will offset the instruments sounds. Leaving this at 0x18 will have the keymap start at MIDI pitch #48 (aka C4). Decreasing the value will start the keymap at a lower pitch. For example, if you change the value to 0x11, the keymap will start at MIDI pitch #41 (aka F3) |
0x3 | |
So far, changing this value results in no effect to any instruments inside the keymap range. Some instruments outside the keymap range may be affected, but these aren't suppose to be heard anyway. |
0x4-0x28 | |
List of instruments |
The keymap starts at MIDI pitch #48 (aka C4) and continues with each consecutive pitch (48, 49, 50, ..., etc).
Sometimes in the instrument array, there will be an instrument that covers several MIDI pitches, instead of just a single instance (for example, a tom-tom drum that requires different pitches). This is done by specifying the instrument's number (i.e. 0x10) and then for every repeating instrument, the keymap instrument's number itself is referenced. For example, let's say our keymap instrument is number "0xC" and we want to repeat the instrument "0x10" 8 times. We do this like so: 10 0C 0C 0C 0C 0C 0C 0C.
Again, all instruments in the instrument chunk must be 0x28 bytes long, so when all the instruments in the array are specified, the remaining bytes are to be padded out by the keymap instrument number.
Links
- File:MegaRace - DOS - Credits.png - HERAD system is mentioned in the credits of MegaRace (DOS).
- mobygames.com/developer/sheet/view/developerId,1760/ - HERAD System mentioned on MobyGames.
- sourceforge.net/p/adplug/feature-requests/18/ - Format support request on AdPlug repository.