OctaMED v2.10 module (MED4)

File Format
This draft documentation has been created by means of MED v3.00 to create MED4 files, and a Hex Editor to look at them. The names given to things are not from a specification, and many details may be incorrect.

Signature
The files starts with the file type signature, common among well-designed file formats. For a MED4 file, this is the ASCII characters MED followed by a byte with a value of 4, i.e.

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 4D 45 44 04                                      MED.

Sample Index
Immediately following the header is the list of all the samples that are either included in the file, or are referenced by the file. MED has two options when saving songs in MED4 format, "SONG" which saves only the song data and includes filenames for the samples so that the player can load them separately, or "SNG+SAMPLES" which includes the song and sample data into one file. Song-only files are commonly used when the file is being composed so that multiple copies of samples are not consuming drive space, and combined Song and Samples files are created for distribution.

Sample Index Bitmap
The Sample index begins with one of many "two-level bitmaps" that appear in the file. The first byte after the file signature contains the "coarse" bitmap, where each bit corresponds to a set of eight sample indices, and the bit is set if at least one of those indices contains a sample. For each bit in the "coarse" bitmap that is set, there will be a byte following which contains the "fine" bitmap representing each sample index within that set. The fine bitmap indicates which of the sample indices are populated. This structure means that a file can contain up to 64 samples (8 bits of coarse bitmap representing 8 samples each) without wasting much space.

To work out the length of the complete bitmap, read the first byte (the "coarse" bitmap) then read one further byte for each bit in the coarse bitmap that is set. Note also that sample indices are one-based.

For example, imagine a file contains 10 samples, in indices 1 to 10, the complete bitmap will contain 0xC0, 0xFF, 0xC0

The coarse bitmap value of 0xC0 means that at least one sample exists in the range 1 to 8, and at least one sample exists in the range 9 to 16. It also means that as two bits are set, we should expect two bytes of "fine" bitmap following this. The first byte of fine bitmap corresponds to sample indices 1 to 8, and as all the bits are set, all those indices are populated with samples. The second byte of fine bitmap corresponds to sample indices 9 to 16, and as only the first two bits are set, indices 9 and 10 contain samples.

For a more complicated example, imagine the complete bitmap is as follows: 0x43, 0xAA, 0x0F, 0x94

Here, we read the coarse bitmap, find that three bits are set, and read three more bytes for the fine bitmaps. The coarse bitmap tells us that at least one sample exists in each of the blocks 9-16, 49-56, and 57-64. This is because the second bit is set (0x40) corresponding to the second set of 8 samples (9-16), the seventh bit is set (0x20) corresponding to the seventh set of 8 samples (49-56), and the eighth bit is set (0x01) corresponding to the eighth set of eight samples (57-64). The fine bitmap then tells us that in set 9-16 the specific samples are at 9 (the first sample in the set because bit 0x80 is set), 11 (the third sample), 13 (the fifth sample), and 15 (the seventh sample).

The complete list of used sample indices is 9, 11, 13, 15, 53, 54, 55, 56, 57, 60, and 62. As this is 11 samples, we expect to now find 11 samples in the sample list.

Samples Index List
Having identified how many samples we are to read, and where they begin (immediately after the last "fine" bitmap byte), we read the sample entries.

Each entry begins with a byte of flags which indicates various properties about the sample as well as what other values we should expect to find in the sample entry.

These flags are: 0x01 - Set if the Sample has a Repeat Start of 0 (repeat from the beginning) 0x02 - Set if the Sample has a Repeat Length of 0 (no repeat) 0x04 - Unknown. I have seen this set using a sample >64KB. 0x08 - Unknown. I have seen this set using a sample >64KB. 0x10 - Set if the Sample has a Volume value of 0 (silent) 0x20 - Set if the Sample has a Volume value of 64 (maximum) 0x40 - Set if the Sample has a Transpose value of 0 (default) 0x80 - Unknown

(I would imagine that bits 0x10 (silent) and 0x20 (maximum volume) are mutually exclusive, but I have never tested this to see how MED behaves. I would guess that one takes precedence.) After the Flags byte is the sample name, starting with a byte indicating the number of characters in the sample name, followed by that number of ASCII characters for the name.

Following the filename is up to seven bytes of parameter data about the sample. The number of these bytes present depends on the flags in the flags byte of the sample. - If Flag 0x01 has not been set, then the sample has a non-zero Repeat Start value which follows the filename as a 16-bit Big-endian integer (all multi-byte integers are Big-endian in this file). - Similarly, if Flag 0x02 is clear then a 16-bit Repeat Length will follow. - Flag 0x04 has a (currently) unknown function, but if clear it corresponds to a single byte value which follows next. - Similarly, Flag 0x08's function is unknown, and if clear indicates a single byte value next. - If both 0x10 and 0x20 are clear, the sample Volume is neither maximum nor silent, so is specified by a single byte which follows. - If flag 0x40 is clear, a byte value will follow (specifically a signed 8-bit integer) which indicates the Transpose value of the sample. - Flag 0x80 has an unknown function, and does not appear to include any parameter data.

A typical flags value for a sample is 0x6F, indicating no repeat, maximum volume, and no transpose. Such a sample will have no data following the filename.

Song Play Sequence
Next is a 16-bit integer containing the number of blocks in the file.

Following the samples is the song play sequence. This is a list of block numbers in the sequence that the player is to play them, so that blocks can be repeated as required. This starts with a 16-bit integer indicating the number of entries in the play sequence in the range 0x01 to 0x100 (1 to 256), followed by that many bytes with each byte indicating the number of the block to play at that point.

Following the Play sequence are six bytes with song parameters. The first two are a 16-bit integer of the Primary Tempo, the third byte is a song transposition value, the fourth is song flags, and the fifth and sixth are a 16-bit integer of the Secondary Tempo.

In the Song Flags, 0x08 appears to be set if samples are included in the file. 0x10 appear to be set if Hex Volumes are used in the display (doesn't affect the file format).

Other data
After the Secondary tempo are 20 bytes of data which have non-zero values.

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000020             00 00 00 00 00 00 0C CC 06 67 09 9A      .......Ì.g.š 00000030 0F 00 0F 88 0F AA 0F CC                          ...ˆ.ª.Ì

The first four bytes are unknown.

The remaining 16 bytes are the screen colours, encoded into the file. This is a palette of 8 colours, each colour taking two bytes as "0R GB"

Track Volumes
There are a set of 16 track volumes that are between 0 and 64. Most of these will be 64, which is easy enough to spot in the hex view. This gives you a visual way of working out where the blocks start. After the 16 byte of track volume is a single byte of master volume.

Block Data
Following the Track Volumes will be the data for each of the blocks. Each block has a block header, and then the data for that block.

Block Header
The block header contains a single byte which indicates the length of the block header, this is followed by a byte indicating the number of channels in that block, then a byte for the number of lines in that block. Then follows an int16 indicating the number of bytes that make up the block data for this block.

Following this is another two-level bitmap that indicates if each of the lines in this block are populated or not.

Firstly is the coarse bitmap. This contains one nibble (four bits) for each set of 32 lines in the block. The length of the coarse bitmap is therefore calculated from the number of lines in the block. If there are only 32 lines in the block (or fewer than 32 lines), there will be one nibble (padded out to a byte). If there are 33 to 64 lines (inclusive), there will be two nibbles, etc. Each nibble for a set of 32-lines contains four bits (obviously), whose values are as follows: The most significant bit (0x8) is set if the set contains at least one note on every line (the set of lines is full of notes). The next bit (0x4) is set if the set of lines contains no notes in any position (the set of lines is empty of notes). 0x4 and 0x8 should mutually exclusive. The next bit (0x2) is set if the lines contain at least one command value on every line. The last bit (0x1) is set if the lines contain no command values on any line.

Command values are the three values which follow the note in the block editor, and allow various effects to be played on a note. These command values are stored apart from the notes in the data block as explained below.

For each two-bits in the nibble with the value 0 (indicating that the block is neither completely full or completely empty), a 32-bit "fine" bitmap will exist following the "coarse" bitmap indicating exactly which lines within that block contain values. To clarify, a nibble with the value 0xA will have no fine bitmaps as at least one note (0x8) and at least one command value (0x2) exists on each line. Similarly, nibbles with the values 0x9, 0x6, or 0x5 will have no fine bitmap as they represent various combinations of completely full or completely empty notes and commands.

Complete list of nibble values.

0x0 - Notes and Values are partially filled on lines in the set. Two 32-bit fine bitmaps will follow, one for the notes, and one for the commands. 0x1 - Notes are partially filled in the set, but no command values exist in the set. One 32-bit fine bitmap will follow indicating which lines have notes. 0x2 - Notes are partially filled in the set, and command values exist on every line in the set. One 32-bit fine bitmap will follow indicating which lines have notes. 0x3 - This is invalid as it indicates that command values exist on all lines and no lines. I would imagine that one or other of these took precedence and it behaved as 0x1 or 0x2. 0x4 - No notes exist in the set, and command values are partially filled. One 32-bit fine bitmap will follow indicating which lines have commands. 0x5 - No notes or command values exist anywhere in the set. The set of 32-lines is empty. No fine bitmaps follow. 0x6 - No notes exist in the set, and command values exist on every line. No fine bitmaps follow. 0x7 - This is invalid as it indicates that command values exist on all lines and no lines. 0x8 - Notes exist on every line of the set, and command values are partially filled. One 32-bit fine bitmap will follow indicating which lines have commands. 0x9 - Notes exist on every line of the set, but no command values exist in the set. No fine bitmaps follow. 0xA - Notes and command values exist on every line of the set. No fine bitmaps follow. 0xB - This is invalid as it indicates that command values exist on all lines and no lines. 0xC to 0xF are all invalid.

Following the two-level bitmap appears to be a single byte, the meaning of which is unknown.

Block Data
Following the Block Header is the Block data, with the length as indicated in the Block Header.

For four channel blocks, the data is read as a stream of nibbles. The first nibble is a bitmap indicating which channels on this line have data, then three nibbles for each channel follow, indicating either the note values or command values for that channel.

It is likely that channels with more than four channels use more than one nibble for the channel bitmap. It is also possible that tracks with samples at index 10 or above will use four nibbles to represent the note.

In order to correctly interpret the data, it must be read along with the bitmap of which lines contain note values and which contain command values as they are interleaved in the data. If the first populated line has command values but no notes, the first part of the data block will contain command values. If a line contains both notes and commands, it will have the note data followed by the command data in the data block.

Sample Data
If the file has been saved as a "SONG+SAMPLES" file, it will contain the actual data for the samples toward the end. The structure of this is currently unknown.

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000070       80 00 00 00 00 00 00 01 00 01 31 22 00 00    €.........1"..    00000080  FF FE FF 00 05 05                                ÿþÿ...

"MEDV" Tag
Don't know what this is, but it looks interesting.

The MEDV tag starts with the ASCII text "MEDV", then the byte values 0, 0, 0, 4. This is followed by the version of MED which made the module. 0, 0, 3, 0 indicates MED 3.

The MEDV tag may also contiain TLV data in a form similar to IFF so thar arbitrary data can be added to the file. For example, the ANNO tag is used for annotation and adding an arbitrary string. This is the ASCII text 'ANNO' followed by a four-byte length, followed by that length of data.