͸
Ĵ
                                                                            
   DIGITRAKKER FILE-FORMAT INFORMATION                 by proton/n-Factor   
                                                                            
Ĵ
;


This file contains information about the songmodule-format "MDL" and the
sample-format "SPL". If you have some problems or if you have questions about
these formats, which are not answered in here, just contact me.


ͻ
                        THE SONGMODULE-FORMAT  (MDL)                   V000 
ͼ

Offset Lenght Description

 000    004     "DMDL"; the four letters mark the mdl-format
 004    001     version; the current version is 0
 005    ???     the different data-blocks are stored at this position

The MDL-songmodule-format is subivided into the following blocks:

"IN" - infoblock; contains most songparameters, like speed, length etc.
"PN" - patternnames; contains the names of the pattern
"ME" - songmessage; contains the songinformation from the composer
"PA" - pattern; contains the tracklists for every pattern
"TR" - tracks; contains the different tracks for the pattern
"IS" - instruments; contains information for every used sample
"SA" - samples; contains the sample-datas

The sequence of the blocks in a file is not fixed so they can be stored in any
way. Digitrakker uses the descripted sequence.

The structure for every block is the same:

Offset Lenght Description

 000    002     "xx"; block-ID (example: "IN" for infoblock)
 002    004     blocklength; this dword contains the length of the following
		datas.
 006 <blocklen> datas for this block...

The next block will be at offset (006 + <blocklength>).

Ŀ
                             The Infoblock (IN)                             


Offset Lenght Description

 000    002     "IN"; infoblock-ID
 002    004     blocklenght
 006    032     songname; name of the songmodule (filled with spaces [32])
 038    020     composername; name of the song-composer
 058    002     songlength; Digitrakker supports up to 255 songpositions
 060    002     songrepeat
 062    001     mainvolume (001-255)
 063    001     song-speed (001-255)
 064    001     beats per minute (004-255)
 065    032     channel-information: bit 0-6 - panposition (0=left,127=right)
				     bit 7   - 0=channel on, 1=channel off
 097  <snglen>  sequencer; contains the number of the pattern for every
		songposition
 ???  <chnnam>  the names for every channel (8 chars for one name).
		<chnnam> = 8 * <number of channels>

Ŀ
                           The Patternnames  (PN)                           


Offset Lenght Description

 000    002     "PN"; patternnames-ID
 002    004     blocklenght
 006  <patnam>  the names for every pattern (16 chars for one name).
		<patnam> = 16 * <number of patterns>

Ŀ
                            The Songmessage (ME)                            


Offset Lenght Description

 000    002     "ME"; songmessage-ID
 002    004     blocklenght
 006    ???     songmessage; every line is closed with the CR-char (13). A
		0-byte stands at the end of the whole text.

Ŀ
                           The Patterndatas  (PA)                           


Offset Lenght Description

 000    002     "PA"; patterndata-ID
 002    004     blocklenght
 006    001     number of pattern; values from 1 to 255 are possible
 007  <patlar>  tracksequencing-data for the used patterns;

These sequencer-lists descripe which track is used as which voice in each
saved pattern. Every pattern consists of 32 channels. The first word in this
list is the number of the track at pattern 0, voice 0. The second is track for
pattern 0, voice 1 and so on... As every pattern consists of 32 voices
(channels), the tracksequencing-list needs 32 words = 64 bytes.
<patlar> = 64 * <number of patterns>.
As every track is saved independend, it is possible to save some discspace by
this methode: If the song contains equal tracks at several positions in
the patterns, these double tracks will only saved one time.
Track 0 is not saved and represents an empty track.

Ŀ
                            The Trackdatas  (TR)                            


Offset Lenght Description

 000    002     "TR"; trackdata-ID
 002    004     blocklenght
 006    002     number of tracks
 008    ???     track-datablocks; every trackdatablock is stored in this way:
		Ofs.000 Len.002         length of the trackdatas
		    002 <trackdatalen>  datas for this track

Every track consists of 64 notepositions and every notposition contains 6
bytes:

byte 0              - note-value; 1=C-0,2=C#0,...,120=B-9,0=nothing,255=stopper
byte 1              - sample-number; 1-255; 0=nothing
byte 2              - volume; 1-255; 0=no volume change
byte 3, low nibble  - number of the first effect-command
byte 3, high nibble - number of the second effect-command
byte 4              - databyte for the first effect-command
byte 5              - databyte for the second effect-command

So one track needs 6 * 64 = 384 bytes in the memory. Digitrakker stores the
tracks in a packed way. The structure of this (very effective!) packformat is
the following:

     bit 76543210
byte 0 - xxxxxxyy

if yy = 00 -> <xxxxxx>+1 is the number of the empty notepositions which are
	      following.
if yy = 01 -> the last noteposition will be repeated <xxxxxx>+1 times.
if yy = 10 -> the noteslot from position <xxxxxx> is copied to the actual
	      position.
if yy = 11 -> the following datas will be put in the actual noteslot:
		bit 2 = 1 -> note
		bit 3 = 1 -> sample
		bit 4 = 1 -> volume
		bit 5 = 1 -> effectcommand numbers
		bit 6 = 1 -> databyte for effect 1
		bit 7 = 1 -> databyte for effect 1

Ŀ
                       The Instrument-Infoblock  (IS)                       


Offset Lenght Description

 000    002     "IS"; intrumentinfo-ID
 002    004     blocklenght
 006    001     number of samples; vales from 0 to 255 are possible
 007  <inslar>  instrument-datas; the datablock for an instrument contains
		57 bytes, so <inslar> = 57 * number of saved samples

The structure of one instrument-datablock:

 000    001     sample-number; (1-255)
 001    032     sample-name; the name of the sample (filled with [32])
 033    008     filename of the sample
 041    002     C-4 sample-frequence in hz (00000-65535)
 043    004     sample-length
 047    004     sample-repeatstart
 051    004     sample-repeatlength; if this value is set to 0, the sample
		will not loop
 055    001     sample-volume (001-255)
 056    001     infobyte:
		bit 0   -> 0=8 bit sample, 1=16 bit sample
		bit 1   -> 0=forward looping, 1=bidirectional looping
		bit 2,3 -> packmethode (0=not packed, methodes 2 and 3 doesn't
			   exist in this version)
		bit 4-7 -> not used (should be set to 0)

Ŀ
                            The Sampledatas (SA)                            


Offset Lenght Description

 000    002     "SA"; sampledata-ID
 002    004     blocklenght
 006    ???     sampledatas; samples are stored in numeric sequence

Unpacked samples are stored in signed form. Packmethode (1) only works with
8 bit samples, so 16 bit samples will always be unpacked.

The description of the sample-packmethode (1):...

This methode is based on the huffman-algorithm. It's an easy form, but very
fast and effective on samples. The packed sample is a bit-data-stream:

    Byte 0    Byte 1    Byte 2    Byte 3
Bit 76543210  fedcba98  nmlkjihg  ....rqpo

A packed byte is stored in the following form:

xxxx10..0s => byte = <xxxx> + (number of <0>-bits between s and 1) * 16 - 8 ;
	      if s=1 then byte = byte xor 255

If there are no <0>-bits between the first bit (sign) and the <1>-bit, you
have the following form:

xxx1s => byte = <xxx> ; if s=1 then byte = byte xor 255

To depack one byte, you have to use the following algorithm:
Ŀ
       read bit                                                             
       sign = bit                                                           
       read bit                                                             
       if bit = 1                                                           
               then    read [3bits]                                         
                       byte = [3bits]                                       
                       goto next                                            
               else    byte = 8                                             
loop:  read bit                                                             
       if bit = 0                                                           
               then    byte = byte + 16                                     
                       goto loop                                            
               else    read [4bits]                                         
                       byte = byte + [4bits]                                
next:   if sign = 1                                                         
               then byte = byte xor 255                                     


Two examples:

xxxx  s
1001101 = ( 9 + 1 * 16 - 8 ) xor 255 = 238

xxx s
01010 = 2

Note that the depacked bytes are delta values. To convert them to real data
use this algorithm:

oldbyte = 0
for sampleposition = 1 to samplelength
	newbyte = byte [sampleposition] + oldbyte
	byte [sampleposition] = newbyte
	oldbyte = newbyte
next sampleposition


ͻ
                          THE SAMPLE-FORMAT  (SPL)                     V000 
ͼ

Offset Lenght Description

 000    004     "DSPL"; the four letters mark the spl-format
 004    001     version; the current version is 0
 005    032     sample-name; the name of the sample (filled with [32])
 037    008     filename of the sample
 045    002     C-4 sample-frequence in hz (00000-65535)
 047    004     sample-length
 051    004     sample-repeatstart
 055    004     sample-repeatlength; if this value is set to 0, the sample
		will not loop
 059    001     sample-volume (001-255)
 060    001     infobyte:
		bit 0   -> 0=8 bit sample, 1=16 bit sample
		bit 1   -> 0=forward looping, 1=bidirectional looping
		bit 2,3 -> packmethode (0=not packed, methodes 2 and 3 doesn't
			   exist in this version)
		bit 4-7 -> not used (should be set to 0)
 061    ???     sampledatas... (see above)
