PTMFORM v1.17, 26 October 1996 1) Introduction ~~~~~~~~~~~~~~~ Poly Tracker is a Scream Tracker 3 like tracker written by Lone Ranger of= AcmE and thoroughly tested by ViC / AcmE and The REW / Nostalgia. The original intent was to release the tracker as a shareware product, but after the r= elease of Fast Tracker 2, Lone Ranger decided the tracker would need a major fac= e-lift before a 'commercial' release. ViC and The REW compose all of their music= in Poly Tracker, and because they are rather succesful in doing so (they are= the two best musicians in the Netherlands) more and more people ask for the f= ormat of the PTM (Poly Tracker Module) files Poly Tracker produces. As is normal with coders, Lone Ranger did not have the PTM file format (l= ike Otto Chrons of DMP still does not have a description of the AMF format), = but because the Nostalgia products use PTM files I got some source code and h= eader descriptions and stuff from Lone Ranger so I could draw up a simple forma= t description. This description did not really suffice for a scene release (although a number of people already have this document), so here I am ty= ping a less concise description allowing other scene members to support the PTM = format in their players. This is a description of version 2.03 of the PTM format. Early formats ar= e no longer used or supported by the current version of Poly Tracker (it still= says "version 1.0=E1", but I think there have been about a dozen different ver= sions, including some customized test versions), and therefor I stick to version= 2.03 here. When writing Poly Tracker, Lone Ranger needed a simple, straight forward = module format. Since Poly Tracker was to become a better Scream Tracker (both Vi= C and The REW liked the Scream Tracker 3 interface but the program itself did n= ot meet their requirements) Lone Ranger took a quick look at the S3M format = and decided to adept it to the needs of Poly Tracker. This means that the PTM format has many similiarities with the S3M format, leaving out some typic= al ST3 fields and putting in some extra Poly Tracker specific stuff. This may ca= use the format to look a little awkard, but remember that it was never the intention to release a Poly Tracker using this specification - it was mer= ely a convenient beta-version format. This document is divided into several parts. First, I give a concise description of the PTM lay-out, followed by a more thorough and detailed explanation. The next section covers the effects used by Poly Tracker, fo= llowed by the last chapter, written for those who already include S3M support in= to their player, comparing the two formats. Well, that's enough introduction chat, I hope you find this a useful docu= ment. Any questions regarding this format can be sent to me by e-mail. Momentar= ely my address is jal@hacom.nl. You can also check the Nostalgia home page: http://pitel_lnx.ibk.fnt.hvu.nl/~therew/Nostalgia.html, where any updates of this document can also be found. Version 1.1 of this document covers one additional subject: the volume ta= ble used in Poly Tracker. It is covered in section 6. JAL / Nostalgia, 27 May / 12 September 1995 2) Concise description of the PTM format / PTM format reference ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is a concise description of the PTM format. Four columns are used: o= ffset, name, type and description. (rel.)offset is the (relative) offset of the = field, name is the field's name, type the field's type and description a short description (a more detailed description can be found in the next section= ). The field type descriptions used are: a =3D ascii character (8 bits) b =3D byte (8 bits) w =3D word (16 bits) l =3D long (32 bits) A number after the type indicates an array of that size (in elements). 'l= 4' would mean an array of 4 longs. All 'reserved' fields are currently not i= n use, neither internally nor externally. I: header offset name type description 0 SongName a28 name of song, asciiz string 28 EofMark a eof mark, #26 29 FileVersion w version of file, currently 0203h 31 Reserved1 b reserved, set to 0 32 nOrders w number of orders (0..256) 34 nInstr w number of instruments (1..255) 36 nPatterns w number of patterns (1..128) 38 nChannels w number of channels (voices) used (1..32) 40 FileFlags w set to 0 42 Reserved2 w reserved, set to 0 44 SongID a4/l song identification, 'PTMF' or 464d5450h 48 Reserved3 b16 reserved, set to 0 64 ChSet b32 channel panning settings, 0..15, 0 =3D left= , 7 =3D middle, 15 =3D right 96 Orders b256 order list, valid entries 0..nOrders-1 352 PatSeg w128 pattern segments (segment =3D 16 bytes) 608 (size) II: instruments The instrument data directly follows the header. It is an array of 0..nIn= str-1 of the following structure: rel.offset name type description 0 SampleType b sample type (bit array) 1 DOSName a12 name of external sample file 13 Volume b default volume 14 C4Spd w C4 speed 16 SampleSeg w sample segment (*) 18 FileOfs l offset of sample data 22 Length l sample size (in bytes) 26 LoopBeg l start of loop 30 LoopEnd l end of loop 34 GUSBegin l GUS begin address (*) 38 GUSLStart l GUS loop start address (*) 42 GUSLEnd l GUS loop end address (*) 46 GUSLoop b GUS loop flags (*) 47 Reserved b reserved, set to 0 48 SampleName a28 name of sample, asciiz 76 SampleID a4/l sample identification, 'PTMS' or 534d5450h 80 (size) SampleType bit flags: bits 0 and 1: 0 =3D no sample (instrument info only) 1 =3D normal sample (FileOfs / Length fields are valid) 2 =3D OPL2 / OPL3 instrument (not used) 3 =3D MIDI instrument (not used) bit 2: sample loop (0 =3D no loop, 1 =3D loop) bit 3: loop type (0 =3D unidirectional, 1 =3D bidirectional) bit 4: sample resolution (0 =3D 8 bits, 1 =3D 16 bits) bit 5: tonable sample (0 =3D tonable, 1 =3D non-tonable) (*) these are used internally only, and set to 0 in the file III: patterns The patterns are stored after the instrument information. Each pattern st= arts at a 16-byte aligned position. The size of each pattern is calculated by subtracting the next offset from the current. The next offset for the las= t pattern is the offset of the first sample (retrieved from the first intru= ment's FileOfs field). This is a little akward and was due for improvement, but = Lone Ranger never came around to doing it. Data byte reference: 0 - next row else: venc.cccc ccccc - channel (0..31) n - read note (1 byte, 254 (note off), 0 (no note), 1..120 (c-0..b-9)) = and sample number (1 byte, 0 (no sample), 1..255) e - read effect (1 byte, 0..22 (0..N)) and parameter(s) (1 byte (2 nibb= les)) v - read volume (1 byte, 0..64) IV: samples The sample data follows the pattern data. Each sample starts at the offse= t as described in the FileOfs field of the instrument structure and has a leng= th as described in the Length field. 3) Detailed description of the PTM format ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ I: header The first 28 bytes are an asciiz string containing the name of the song, followed by a end-of-file mark, thus making the file typable. Next comes = the file version (currently 2.03). All older versions are not compatible with= the current format and players / trackers should not attempt to load them. Af= ter a reserved byte follow the number of entries in the order list (0..256), th= e number of instruments (1..255), the number of patterns (1..128), and the = number of channels (voices) used (1..32). To detect whether the file is a Poly Tracker module, check the longint at offset 44. The 4 characters here should contain the value 'PTMF'. ChSet contains the panning settings for the channels (0..15, 0 =3D left, 7 =3D = middle, 15 =3D right), Orders is the order list containing the pattern numbers to pl= ay. PatSeg needs some further explanation. Poly Tracker loads a PTM file at o= ffset 0 of the file's memory segment. All patterns are also paragraph aligned (= i.e. at 16 byte (segment) bounderies), both in the memory as in the file (maki= ng it possible to load the header and the patterns in one read). The PatSeg arr= ay contains the absolute file offsets divided by 16. Thus, the first pattern= has file offset PatSeg[0] * 16, the second PatSet[1] * 16 and so on. When PolyTracker loads the file, the PatSeg array is adjusted to contain the absolute segment numbers, by adding the file's segment to all PatSeg arra= y elements. (Poly Tracker has some more tricks for internal pattern storage= as it is capable of using EMS, but that's of no concern for this document.) II: instruments The instrument structure starts with a byte denoting the sample type. It = is a bitarray, individual bits are used to store information. The first two bi= ts either contain 0 (unused) or 1 (used). Other values are currently not in = use. If a sample is unused the FileOfs and Length fields should be ignored (th= ere is no sample data for this instrument in the file). Bit 2 indicates whether = or not the sample should loop. 0 means no loop, 1 means looping is enabled. Bit = 3 is only valid if bit 2 is set to 1. If bit 3 is set to 1, the sample loop sh= ould be played bi-directional, otherwise it is uni-directional. Bit 4 defines = the sample resolution. If set to 1, the sample is a 16 bit sample, 8 bit othe= rwise. Bit 5 is the last bit defined. If set, the instrument is "non-tonable", i= .e. an effect or a percussion instrument. This bit should be ignored during play= -back. Following the sample type is the DOS file name of the original sample (si= nce Poly Tracker cannot sample or create samples, all samples are loaded from disk). It has the usual format: filename, dot, extension. If the name con= tains less than 12 characters it should be zero-extended. Volume is the sample's default volume, and has a value from 0 up to 64. N= ote that, as with most trackers, this is not a relative, but an absolute valu= e. Thus, it should be regarded as a first 'volume set' command. The C4Spd is= the frequency of the sample when a C-4 is played. In older MOD formats this i= s also called C2 speed. SampleSeg is the internal memory segment of the sample data and currently= not used by Poly Tracker. FileOfs is the absolute offset of the sample data i= n the PTM file, Length the size of the sample in bytes. LoopBeg and LoopEnd are= the looping values (used only when SampleType bit 2 is set). When bit 4 of th= e sample type field is set (the sample is 16 bit), LoopBeg and LoopEnd shou= ld have an even value. Since Poly Tracker loads the instruments directly into memory, there are = some fields used only internally. The four GUS fields are used for internal management of the GUS heap and other GUS related variables, and should be= set to 0 when on disk. SampleName is an asciiz string containing the sample/instrument name (or = some comment if the first two bits of sample type are set to 0). SampleID is t= he sample identification, containing the four characters 'PTMS'. III: patterns Patterns are stored row by row, each row containing none, one, or multipl= e voices. The patterns contain compressed information, as opposed to the one-position-one-byte approach of most trackers. In essence, patterns are= a byte stream. The compression scheme is similar to the ST3 approach. Patte= rns always contain 64 rows. The decoding scheme is as follows: repeat read byte if (byte =3D 0) then next row else channel =3D bits 0..4 if (bit 5 is set) then read note (1 byte) read sample number (1 byte) endif if (bit 6 is set) then read effect (1 byte) read effect parameter (1 byte) endif if (bit 7 is set) then read volume (1 byte) endif endif until 64 rows read If the data byte is 0 it means that the current row contains no (more) information. If not, bit 5 is checked to see whether a note and sample information are stored. If so, they are read. Next, bit 6 is checked to s= ee whether an effect and its parameter are stored. If so, they are read. Fin= ally, bit 7 is checked. If bit 7 is set, this means that a volume byte is store= d, and it is read. The patterns has been completely read when all 64 rows have b= een read (the current file format does not allow for any other number of rows= ). The channel number is a number from 0 to 31 (or nChannels - 1 if less tha= n 32 channels are used). Note values are 254 (note off), 0 (no note, not used = in compressed patterns) or between 1 and 120: 1 =3D C-0, 120 =3D B-9. Sample= number is 0 (no sample) or a value between 1 and 255 (or nInstr if less than 255 instruments). The effect byte can have a value between 0 and 23. 0 throug= h 9 are effects 0 through 9, 10 through 23 are effects A through N (see next chapter for a description of the effects used). The last value, volume, c= an have a value between 0 and 64. IV: samples The samples are stored in a signed delta format, allowing a high compress= ion rate with 8 bit samples. 16 bit samples are also stored this way, althoug= h they do not have the 8 bit compression advantage. The following piece of C code shows how to convert the signed delta forma= t to straight format: n =3D 0; for (i =3D 0; i < size; i++) { n =3D (data[i] +=3D n); data[i] ^=3D 0x80; /* only when converting to unsigned */ } In Pascal: N :=3D 0; for I :=3D 0 to Size-1 do begin Inc (Data^[I], N); N :=3D Data^[I]; Data^[I] :=3D Data^[I] xor $80; {only when converting to unsigned} end; In assembly (es:di points to start of sample buffer): mov ah, 0 mov cx, Size @@1: mov al, es:[di] add al, ah mov ah, al xor al, 80h ; only when converting to unsigned stosb loop @@1 The current version does not allow for compressed samples, but when ZIPpe= d or ARJed 8 bit delta samples compress considerably better than normally stor= ed samples. 4) Poly Tracker Effects ~~~~~~~~~~~~~~~~~~~~~~~ Poly Tracer uses 24 effects, numbered 0 through 9 and A through N. Since = I am no musician I do not know the precise meaning of the commands, but I trus= t most people *do* know, so I excluded a description of the commands. cmd# meaning 0xy arpeggio 1xx slide down 1fx fine slide down 1ex extra fine slide down 2xx slide up 2fx fine slide up 2ex extra fine slide up 3xx tone portamento 4xy vibrato (x =3D speed, y =3D depth) 5xy tone portamento + volume slide 6xy vibrato + volume slide 7xy tremolo (x =3D speed, y =3D depth) 8xx - (not used) 9xx set sample offset (to xx00h) ax0 volume slide up a0x volume slide down axf fine volume slide up afx fine volume slide down bxx set song position cxx set volume (for MTM/MOD compatibility only) dxx set break position e0x - (not used) e1x fine slide down (for MTM/MOD compatibility only, use 1fx) e2x fine slide up (for MTM/MOD compatibility only, use 2fx) e3x - (not used) e4x set vibrato wave form (see table 4.1) e5x set sample fine tune value (see table 4.3) e60 set loop start e6x loop to start e7x set tremolo wave form (see table 4.1) e8x set pan position (0 =3D left, 7 =3D middle, 15 =3D right) e9x retrigger note (for MTM/MOD compatibility only, use h0x or h8x) eax fine volume slide up (for MTM/MOD compatibility only, use axf) ebx fine volume slide down (for MTM/MOD compatibility only, use afx) ecx note cut (x =3D count) edx note delay (x =3D count) eex pattern delay (x =3D number of rows) efx - (not used) dxx break to next pattern (xx =3D position in next pattern) fxx set speed (xx <=3D 20h) or tempo (xx > 20h) gxx set global volume hxy retrigger note + volume changes (x =3D volume (see table 4.2), y = =3D count) ixy fine vibrato (x =3D speed, y =3D depth) jxy note slide down (x =3D speed, y =3D note count) kxy note slide up (x =3D speed, y =3D note count) lxy note slide down + note retrigger (x =3D speed, y =3D note count) mxy note slide up + note retrigger (x =3D speed, y =3D note count) nxx reverse sample + offset (start with offset 256 * xx bytes) (note:= this command is not supported correctly by the current version of the player) table 4.1 - vibrato and tremolo wave forms 0: sine wave 1: ramp down 2: square wave 3: random table 4.2 - retrigger note volume changes 0: no changes 1: volume - 1 2: volume - 2 3: volume - 4 4: volume - 8 5: volume - 16 6: volume * 2/3 7: volume * 1/2 8: no changes 9: volume + 1 a: volume + 2 b: volume + 4 c: volume + 8 d: volume + 16 e: volume * 3/2 f: volume * 2 table 4.3 - fine tune values to C4 speed values 0: 7895 Hz 1: 7941 Hz 2: 7985 Hz 3: 8046 Hz 4: 8107 Hz 5: 8169 Hz 6: 8232 Hz 7: 8280 Hz 8: 8363 Hz (no fine tune) 9: 8413 Hz a: 8463 Hz b: 8529 Hz c: 8581 Hz d: 8651 Hz e: 8723 Hz f: 8757 Hz =20 5) Comparison of S3M and PTM Formats ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The S3M format was chosen as a start for the PTM format because of the similarities between Poly Tracker and Scream Tracker. The current version= of the PTM format (2.03) was never ment to be released, but as time caught u= p with the planned improvements, and more and more people asked for the PTM form= at, Lone Ranger decided to release it anyway. This section is a brief coverag= e of the differences between the two formats, intended as a quick guide for programmers who already have a S3M loader and want to write a PTM loader = as well. The information is very concise, as it is taken directly from some = info I wrote when writing a PTM to S3M converter. I: header PTM: S3M: 0 SongName a28 0 SongName a28 28 EofMark a 28 EofMark a 29 FileVersion w 29 FileType b 31 Reserved1 b 30 Reserved1 w 32 nOrders w 32 nOrders w 34 nInstr w 34 nInstr w 36 nPatterns w 36 nPatterns w 38 nChannels w 38 Flags w 40 FileFlags w 40 TrackVer w 42 Reserved2 w 42 FileVer w 44 SongID a4/l 44 FileID a4/l 48 Reserved3 b16 48 GlobalVol b 49 InitSpeed b 50 InitTempo b 51 MasterVol b 52 Reserved2 b10 62 SpecialPtr w 64 ChSet b32 64 ChanSet b32 96 Orders b256 96 Orders b(nOrders) 352 PatSeg w128 xxx InsPtr w(nInstr) 608 (size) xxx PatternPtr w(nPatterns) II: instruments PTM: S3M: 0 SampleType b 0 SampleType b 1 DOSName a12 1 DosName a12 13 Volume b 13 MemSeg b3/w 14 C4Spd w 16 Length l 16 SampleSeg w 20 LoopBegin l 18 FileOfs l 24 LoopEnd l 22 Length l 28 Volume b 26 LoopBeg l 29 Reserved1 b 30 LoopEnd l 30 Packing b 34 GUSBegin l 31 Flags b 38 GUSLStart l 32 C2Spd l 42 GUSLEnd l 36 Reserved2 l 46 GUSLoop b 40 Internal1 w 47 Reserved b 42 Internal2 w 44 Internal3 l 48 SampleName a28 48 SampleName a28 76 SampleID a4/l 76 SampleID a4/l 80 (size) 80 (size) PTM sample type: bit 0, 1 (0 =3D no sample, 1 =3D sample, 2 =3D adlib, 3 =3D midi) 2 (0 =3D no loop, 1 =3D loop) 3 (0 =3D uni, 1 =3D bi) 4 (0 =3D 8, 1 =3D 16) S3M sample type: 0 =3D sample not used 1 =3D sample 2 =3D adlib melody 3+ =3D adlib drum S3M sample flags: bit 0 =3D loop on 1 =3D stereo (not supported!) 2 =3D 16-bit sample (not supported!) Storage format: PTM stores samples in a signed delta format (start =3D 0), S3M in unsigne= d raw. III: patterns Both packed scheme: 0 =3D end of row, always 64 rows, else low nibble =3D= channel, high-nibble =3D flags bit: 567 PTM: nev S3M: nve n: after this byte follows note and instrument (1+1 bytes) e: after this byte follows effect and parameter (1+1 bytes) v: after this byte follows volume (1 byte) If the bit is set the bytes follow, in order of bits. IV: notes PTM: 0 =3D empty, 1 =3D C-0, 2 =3D C#0, 3 =3D D-0, etc. (12 steps within= octave) S3M: hi =3D octave, lo =3D note, 255 =3D empty (12+4 steps within= octave) both: 254 =3D ^^^ =3D key off V: commands Note: PTM commands start with 0 up to 9, a =3D 10 etc., S3M commands star= t with a =3D 0, b =3D 1 etc. command PTM S3M arpeggio 0 j slide down 1 e fine sd 1f ef extra fsd 1e ee slide up 2 f fine su 2f ff extra fsu 2e fe tone porta 3 g vibrato 4 h tp+vol sl 5 l vib+vol sl 6 k tremolo 7 r samp ofs 9 o vol sl up a.0 d.0 vol sl down a0. d0. fine vsd af. df. fine vsu a.f d.f songpos b b volume c - breakpos d c speed f (<20h) a tempo f (>=3D20h) t global vol g v retrig h q fine vib i u note sl down j - note sl up k - note sld+retr l - note slu+retr m - rev smp + ofs n - fine sd e1 (=3D 1f) ef fine su e2 (=3D 2f) ff vib wave e4 s3 fine tune e5 s2 loop e6 sb trem wave e7 s4 set pan pos e8 s8 retrig e9 (=3D h8) q8 fine vsu ea (=3D a.f) d.f fine vsd eb (=3D af.) df. note cut ec sc note delay ed sd patt delay ee se 6) Poly Tracker Volume Table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ After the first release of this document a number of players started supp= orting the PTM format in their new releases. When writing the original document,= I forgot to include one thing: description of the volume table used by Poly Tracker. Since the volume table Poly Tracker uses is different from most players, the many volume slides used by The REW in his PTMs do not sound = right. Only Mr. Logic's / Weird Magic PlayMate player currently supports the rig= ht volume table for PTM play-back, but for example Cubic Player and Digi Tra= kker (by Proton / N-Factor), still play most PTMs erroneous. vol value 0 20000 1 40496 2 43858 3 45883 4 47337 5 48472 6 49403 7 50192 8 50878 9 51483 10 52025 11 52516 12 52965 13 53378 14 53760 15 54116 16 54450 17 54763 18 55059 19 55338 20 55604 21 55856 22 56097 23 56327 24 56548 25 56759 26 56962 27 57158 28 57346 29 57528 30 57704 31 57873 32 58038 33 58198 34 58352 35 58503 36 58649 37 58791 38 58929 39 59064 40 59195 41 59323 42 59448 43 59570 44 59690 45 59806 46 59920 47 60032 48 60141 49 60248 50 60353 51 60456 52 60556 53 60655 54 60752 55 60848 56 60941 57 61033 58 61123 59 61212 60 61299 61 61385 62 61469 63 61553 64 61634 7) Closing Words ~~~~~~~~~~~~~~~~ Well, that's over 650 lines of information, I don't think any format has = ever been covered so thoroughly. I hope I didn't forget any crucial informatio= n, if you need anymore info just write me (see introduction for my e-mail addre= ss). JAL / Nostalgia, 28 May / 13 September 1995