XM
From GDWiki
- This article is a stub. You can help out by expanding it.
| To comply with our quality standards, this article may need to be rewritten. Please help improve this article. The discussion page may contain suggestions. |
Okay this is supposed to cover the xm format (Extended Module) created by Triton a swedish demo group. (now commonly known as Starbreeze Studios)
XM (Extended Module) and XI (Extended Instrument). XM was and still is one of the most popular module formats nowadays, because of its compact and well compressible file structure. This document will guide you through the file structure of the XM file format, and hopefully also show you how to open and play it. With this said and done, I think it's time to start coding.
Variable explanation
Uword is an "short"
Dword is an "unsigned long"
Ubyte is and "unsigned char"
Sbyte is an "signed char"
Presumably these types are assuming the usual x86 architecture. More likely Uword is a uint16_t, Dword is a uint32_t, and the assumption is that CHAR_BIT==8.
Contents |
[edit] Headers
[edit] General Header
Offset Length Type EXPLANATION
****** ****** ***** ***********
0 17 char should always contain the string "Extended Module:", Fasttracker reports the file as corrupt if not
17 20 char stores the name of the song
37 1 char dunno what this is or does, thou it seems as it always is 26 ??????? (See note below table)
38 20 char usually stores the name of the tracker used to create the xm file
58 2 Uword version of the file , hi-byte major and low-byte minor. The current format is version $0103
60 4 Dword stores the size of this header
+4 2 Uword the length of the song (in patterns).
+6 2 Uword restart position
+8 2 Uword number of channels (2,4,6,8,10,...,32)
+10 2 Uword number of patterns (max 256)
+12 2 Uword number of instruments (max 128)
+14 2 Uword flags 0 = amiga frequency table, 1 = linear frequency table
+16 2 Uword Default tempo (number of ticks)
+18 2 Uword Default BPM (Beats Per Minute)
+20 256 Ubyte Pattern order table (0,1,5,2,34....)
Char 26: It's an "escape char". If you cat the file on your terminal it will stop after printing "Extended Module:" and the name of the song. Otherwise your terminal will fill up with garbage (works for Windows/Dos at least)
[edit] Pattern Header
? 4 Dword the size of this header (always 9) +4 1 Ubyte the pattern type. always 0 (don't think that xm files contain any other types of patterns) +5 2 Uword number of rows in this pattern +7 2 Uword the size of the pattern
Note that if the size equals 0, then that pattern isn't stored in the actual module and therefore needs to be created. Allocate 64(rows) * (nr of channels) and set them to 128
[edit] Note Header
? 1 Ubyte stores notes from 0-96. 97 is note off +1 1 Ubyte stores the instrument used +2 1 Ubyte volume +3 1 Ubyte effect type (arppegio,porta....) +4 1 Ubyte effect parameter (value)
[edit] Intrument Header
? 4 Dword stores the size of the header +4 22 char instrument name +24 1 Ubyte instrument type. should always be 0 +25 2 Uword number of samples in instrument
[edit] Second Instrument Header
? 4 Dword stores the size of the header +4 95 Ubyte table refering to samples +99 23 Uword volume envelopes, stored as x,y .... x,y +122 23 Uword panning envelopes, stored as x,y .... x,y +145 1 Ubyte number of volume points stored in instrument +146 1 Ubyte number of panning points stored in instrument +147 1 Ubyte volume sustain point +148 1 Ubyte volume loop start point +149 1 Ubyte volume loop end point +150 1 Ubyte panning sustain point +151 1 Ubyte panning loop start point +152 1 Ubyte panning loop end point +153 1 Ubyte volume type: 0 = on ; 1 = sustain ; 2 = loop +154 1 Ubyte panning type:0 = on ; 1 = sustain ; 2 = loop +155 1 Ubyte vibrato type +156 1 Ubyte vibrato sweep +157 1 Ubyte vibrato depth +158 1 Ubyte vibrato rate +159 2 Uword volume fadeout
[edit] Sample Header
? 4 Dword sample length +4 4 Dword loop start +8 4 Dword loop end +12 1 Ubyte volume +13 1 Sbyte finetune signed byte +14 1 Ubyte type 0 = no loop ; 1 = forward loop ; 2 = ping-pong loop ; 16 = 16-bit sampledata +15 1 Ubyte panning +16 1 Sbyte relative note signed byte +17 1 Ubyte reserved +18 22 char sample name
[edit] How to use
Read patterns (pseudo code)
If the pattern size equals zero you have to create the pattern and allocate (rows * (nr of channels)) and set the notes to 128
for(int i=0; i< patterns; i++) { patternsize = OpenDWord; // the size of the pattern. type = OpenByte; // always 0 (atleast should be) Rows = OpenWord; // this is the number of rows in this pattern if (patternsize == 0) { //create a empty pattern Rows = 64; // set rows to 64 by default // Allocate rows * (nr of channels) and set the notes to 128 } for(int y=0; y< rows; y++) for(int x=0; x< channels; x++) { //readnote } }
The notes are stored using a simple packing scheme, just so that the patterns don't become too large. description of the compression technique follows. Since the higher range of the note byte isn't used. it is used for the compression. If the bit is set, then the other bits are interpreted as follows:
bit 0 set: Open Note byte 1 set: Open Instrument byte 2 set: Open Volume byte 3 set: Open Effect byte 4 set: Open Parameter byte
Ubyte first; first = openbyte // open up one byte to perform a little check on it to see if the note is packed or not. if (first & 128) { // the note is packed if (first & 1) note = openbyte; // the note number. Ranges from 0-96, 97 is note-off if (first & 2) instrument = openbyte; // the instrument used if (first & 4) volume = openbyte; // the volume number if (first & 8) effect = openbyte; // the effect number if (first & 16)parameter = openbyte; // the effect parameter } else { // the note isn't packed note = first; instrument = openbyte; volume = openbyte; effect = openbyte; parameter = openbyte; }
this document is not ready yet. More to come. Lars If you notice anything thats wrong, or just isn't clear. Then don't hesitate to drop me a e-mail (lars_akesson_1(at)hotmail.com) or change the wrong part. this is a wiki after all. :)

