XM
From GPWikiThis page is far from complete, go ahead and write some more!
You can extend this page by editing it. 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.
Uword is an "short" Dword is an "unsigned long" Ubyte is and "unsigned char" Sbyte is an "signed char"
[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 useRead 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. :) |


