
                  Velvet Studio. AMS Format v2.2 
                           Advanced Module System

                                Revision 1.0

Offs   Byte(s)	Desc

[Header]
0       7       Header: "AMShdr",1ah
7       1       Length of ModName (max 30 bytes)
8       x       ModName
?       2       Version of format (Hi = MainVer, Low = SubVer e.g. 0202 = 2.2)
+2      1       Nr of Instruments (0-255)
+3      2       Nr of Patterns (1-1024)
+5      2       Nr of Positions (1-65535)
+7      2       Initial BPM (High byte=Integer part, Low byte=Fraction)
+9      1       Initial Speed
+10	1	Default Channels (1-32)
+11	1	Default Commands (1-7)
+12	1	Default	Rows (0-255)
+13     2       Flags:uuuuuuuumfsuuuuu
                       Unused
                      	1=Stereo,0=Mono
                       Use Linear freq table.
                       MIDI channels are used in tune.
		       Unused


[Instrument]
        1       Length of InstrumentName (max 30 bytes)
        x       Instrument name
        1       Number of samples in instrument (0-16) (if 0, skip this inst.)

      120       Inst number for all notes

        1       Volume Env. Speed
        1       Volume sustain point
        1       Volume loop start point
        1       Volume loop end point
        1       Number of volume points    (0-63)
        x*3     Volume envelope info.
                uuuuuttx xxxxxxxx yyyyyyyy
                   Volume (0-7f)
                 Delta X
                 Curve (0=Line,1=sine 1, 2=sine 2)
                 Reserved for future use.

        1       Panning Env. Speed
        1       Panning sustain point
        1       Panning loop start point
        1       Panning loop end point
        1       Number of panning points   (0-63)
        x*3     Points for panning envelope
                uuuuuttx xxxxxxxx yyyyyyyy
                   Pan value (0-ff)
                 Delta X
                 Curve (0=Line,1=sine 1, 2=sine 2)
                 Reserved for future use.

        1       Vibrato Env. Speed
        1       Vibrato sustain point
        1       Vibrato loop start point
        1       Vibrato loop end point
        1       Number of vibrato points   (0-63)
        x*3     Points for vibrato envelope
                uuuuuttx xxxxxxxx yyyyyyyy
                   Vibrato depth (0-ff)
                 Delta X
                 Curve (0=Line,1=sine 1, 2=sine 2)
                 Reserved for future use.

        1       Shadow Instrument. If non-zero, the value=the shadowed inst.
        2       Vib.Amplify+Volume fadeout
                fedcba9876543210
                 Volume Fadeout.
                 Vibrato Amplify
                 Reserved

        2       Envelope flags:
                fedcba9876543210
                 Volume :Loop on
                 Volume :Sustain on
                 Volume :Envelope on
                 Panning:Loop on
                 Panning:Sustain on
                 Panning:Envelope on
                 Vibrato:Loop on
                 Vibrato:Sustain on
                 Vibrato:Envelope on
                 Volume :Break Loop
                 Panning:Break Loop
                 Vibrato:Break Loop
                 Reserved

[Sample]       (repeated for each sample in the Instrument)
        1       Length of SampName (max 22 bytes)
        x       SampName
        4       Length Of Sample (in samples) (if 0, skip rest of the sample.)
	4	Repeat Start for sample (in samples)
	4	Repeat End for sample (in samples)
        2       Sampled rate (the rate the sample is sampled in)
	1	Hi Nibble=PanPosition, Lo Nibble=FineTuneValue
        2       SampleRate for C-4 (normally 8363Hz)
        1       Relative note (signed byte)
        1       Volume (0-127)
        1       Info Byte 76543210
                           Pack Method
                           16 bit sample
                           Looped sample
                           PingPong loop
                           Reserved
                           Direction (1=Reversed)
                           Reserved

 Data for rest of Instruments are exactly the same!

[Text]
        1       Length of Composer name (max 30 bytes)
        x       Composer Name
      >1       Length of ChannelName (max 11 bytes)
      x       ChannelName
        4       Length of Description (packed, inclusive header)
         4       Length of Description (unpacked)
         1       Version of packroutine (currently 01h)
         1       PreProcessing type (currently none)
         1       Packing method (Currently RLE with #255 as packbyte)
         x       Description of Module

 The Number of ChannelNames are always 32.

[PatternOrder]
	x	PatternNr. Holds number (0-65535) to tell the tracker what
                pattern to play at that position (x=Nr of Positions)

[PatternData]
	4	PatternSize (packed)
        1       PatternLength-1 (0-255)
        1       cccsssss
                c = Nr of Commands used in pattern
                s = Nr of Channels-1 used in pattern (0-31)
        1       Length of PatternName (max 10 bytes)
        x       PatternName
        x       PatternData

        fp0aaaaa ennnnnnn iiiiiiii [rgcccccc bbbbbbbb...]

		Legend:
                f       1=Last data chunk on the row.
                p       0=Read Note+InstNr 1=Don't Read Note+Instnr
                a       Channel (0-31)
                e       1=Read one command
                n       Note. 2-121 (C-0 to B-9), 1=Key off note.
                i       InstrumentNr (0-255)
                r       1=Read one more command
                g       1=Low 6 bits are volume/2
                c       Command-nr
                b       Command-byte

                If first byte = -1 then this row is empty

		If g is set, the command only consist of that byte and
		the low 6 bits are assumed to be a volume command. You
		have to multiply the volume by 2 to get the proper value
                (Volume will only be stored this way if it's even)

[Samples]
        All samples stored after eachother, packed with a special packing
        method not described here since we're so lazy! You've got a routine
        that does the unpacking instead. (You can also save the samples
        unpacked, and it that case they are in twos complement form.)
        16 Bits Samples are usually not packed, since we don't have a special
        16 bits pack-routine. However, you better check the Pack Method
        Bit to be sure.


Header for packed samples. Stored as the first bytes in the sample data.

Offset	Desc
0	4	Unpacked size
4	4	Packed size
8	1	Packcharacter
9	x	Packed data...


  ** MIDI not yet supported. If MIDI Bit=0 then skip this section **


[MIDI Section]
        4       MIDI Section Size







                  Velvet Studio. AIS Format v1.0 
                         Advanced Instrument System


The only that differs the AIS format from the Instrument used in the AMS is
the following header before the other info:

Offset  bytes   Desc

0       7       Header: "AIShdr",1ah
7       1       Type: 0aah=new version, <1fh=old version (Only new versions
                should exist, so don't bother with this flag)
8       2       Version of format (Hi = MainVer, Low = SubVer e.g. 0100 = 1.0)


The actual sampledata is stored right after the Instrument data.


                  Velvet Studio ASE Format v1.0 
                           Advanced Sample System

Offset  Bytes   Desc
0	7       Header: "ASEhdr",1ah
7	2       Version of format (Hi = MainVer, Low = SubVer e.g. 0100 = 1.0)
9	1	Length of SampName (max 22 bytes)
10	x	SampName
	4	Length Of Sample
	4	Repeat Start for sample
	4	Repeat End for sample
	2	Sampled rate (the rate the sample is sampled in)
	1	Hi Nibble=PanPosition, Lo Nibble=FineTuneValue
	2	SampleRate for C-4 (normally 8363Hz)
	1	Relative note (signed byte)
	1	Volume (0-127)
	1	Info Byte 76543210
                           Pack Method
                           16 bit sample
                           Looped sample
                           PingPong loop
                           Reserved
                           Direction (1=Reversed)
                           Reserved
	x	Sample data. Maybe packed.










                   == Velvet Studio Misc Info ==


* The BPM Fraction value is multiplied with 26 to be able to do some
  optimizations. (9*26255) Values can range from 0*26 to 9*26.

* The Default Channels/Command/Rows can be ignored since they are only used
  internally in VS.

* If a Shadow sample is encountered, DON'T read any sample data for that
  sample, instead use the same sample data as it's shadowed to.

* Each pattern can have different number of commands/rows/channels
  therefore you must use a variable patternwidth and length.

* Up to 7 commands/note is possible

* When allocating the needed amount of channels, check through the
  song to see which pattern that uses most channels.




                        Volume 

To calculate the final volume of a channel, use the following formula:

(SampleVol*MasterVol*GlobalVol*ChannelMasterVol*EnvelopeVol/127^4)*FadeOut/65536



                        PanPot 

Sample panposition ranges from 0 to 15, where 0 means CH(annel). If it is set
to CH, then use the default channel panpot instead of the sample panpot.

Sample Panposition 8 is middle, 7 is skipped since 7 and 8 is the same on a GUS,
and with an even number of panpositions you won't get a symmetric pan.

If ChannelPan<=7 Then ChannelPan=ChannelPan-1
   Pan=EnvelopePan/16-8+ChannelPan
If Pan<0 Then Pan=0
If Pan>15 Then Pan=15

An 8xx command sets the ChannelPanpot, and if Sample Panpot is set to CH(annel)
the ChannelPanpot will be used on the channel. If SamplePanpot is set to
some value, that value is used instead, unless a 8xx is inserted on the same
row as the note... Confusing? well, read it again...


                        Freq 

Notes ranges from 0 to 119 (C-0 - B-9)

AmigaFreq:

PeriodTable: 109568,103418,97614,92135,86964,82083,77476,73128,69024,65150,61493,58042

Period=((Note MOD 12 [PeriodTable])/2^Note DIV 12)
Freq=(16*428*C2rate)/Period+PerAdd

Linear Freq:

Freq = C4Rate*2 ^ ((Note+FreqAdd) / 12 - 4)

(Actually the same as FT2, but with some minor modifications)

                        FineTune 
AmigaFreq:

If FineTune>7 Then FineTune=ABS(FineTune-16)
        PerAdd=((Period-1)-(Period))*FineTune/8
If FineTune<=7 Then PerAdd=ABS(((Period)-(Period+1))*FineTune/8)

(Period +/- 1 here means the Period for the note being finetuned +/- one note)

Linear Freq:

If FineTune>7 Then FreqAdd=NEG((FineTune-16)/8) Else FreqAdd=NEG(FineTune/8)
(one note equals to 1 FreqAdd)


                       Envelopes 

The envelope speed for each envelope is determined by the "Envelope Speed
byte". This value is actually the "BPM" of the envelope speed, since a value
of 125 means "update the envelope 50 times/second."

The Sinecurve for the envelope.
(The 4:th part of the Sinecurve only. We calculate the other parts using this
curve.)

It has got 512 values since the maximum distance between 2 poins can be 512.

EnvSine         db 0,1,2,2,3,4,5,5,6,7,8,8,9,10,11,12,12,13,14,15,16,16,17,18,19,19,20,21,22,22,23,24,25,26,26,27,28,29,30,30,31,32,33,33,34,35,36,36,37,38,39,39,40,41,42,43,43,44,45,46,46,47,48,49,49,50,51,52,52,53,54,55,55,56,57,58,58,59,60,61,61,62,63,64,64,65,66,67,67,68,69,70,70,71,72,73,74,74,75,76,76,77,78,79,79,80,81,82,82,83,84,84,85,86,87,87,88,89,90,90,91,92,93,93,94,95,96,96,97,98,98,99,100,100,101,102,103,103,104,105,106,106,107,108,108,109,110,110,111,112,113,113,114,115,115,116,117,117,118
                db 119,119,120,121,121,122,123,123,124,125,126,126,127,127,128,129,130,130,131,132,132,133,134,134,135,136,136,137,138,138,139,139,140,141,141,142,143,143,144,145,145,146,146,147,148,148,149,150,150,151,152,152,153,153,154,155,155,156,156,157,158,158,159,160,160,161,161,162,163,163,164,164,165,166,166,167,167,168,168,169,170,170,171,171,172,173,173,174,174,175,175,176,177,177,178,178,179,179,180,180,181,181,182,182,183,184,184,185,185,186,186,187,187,188,188,189,190,190,191,191,192,192,193
                db 193,194,194,195,195,196,196,197,197,198,198,199,199,200,200,201,201,201,202,202,203,203,204,204,205,205,206,206,207,207,207,208,208,209,209,210,210,211,211,211,212,212,213,213,214,214,214,215,215,216,216,216,217,217,218,218,219,219,219,220,220,221,221,221,222,222,223,223,223,224,224,224,225,225,225,226,226,227,227,227,228,228,228,229,229,229,230,230,230,231,231,231,232,232,232,233,233,233,234,234,234,234,235,235,235,236,236,236,237,237,237,237,238,238,238,239,239,239,239,240,240,240,240
                db 241,241,241,241,242,242,242,242,243,243,243,243,244,244,244,244,244,245,245,245,245,246,246,246,246,246,247,247,247,247,247,248,248,248,248,248,248,249,249,249,249,249,249,250,250,250,250,250,250,250,251,251,251,251,251,251,251,252,252,252,252,252,252,252,252,253,253,253,253,253,253,253,253,253,253,253,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255

Envelope Types:

0=Line.  A straight line, as in FT2
1=Sine1. 3:d or 4:th Part of the sinecurve depending on the locations
         of the points between
2=Sine2. 1:d or 2:d Part of the sinecurve depending on the locations
         of the points between

  ---
 / | \
| 4|1 |
|-----|
| 3|2 |
 \ | /
  ---

The Break flag in the Envelope is used to stop looping the envelope when
a keyoff is detected.

Calculating the Vibrato Envelope:
Using a sinecurve with full amplitude (80h) and Vibrato Amplify set to 3
equals the command 4xf played on C-5 (or using Linear Freq)
Changing the Vib Amplify is just a matter of doubling/halving the amplitude.
0=No amplify
1=2*Amplitude
2=4*Amplitude
3=8*Amplitude

A simple but clear "formula":
Amp 80h, Ampf 0 = Amp 40h, Ampf 1 = Amp 20h, Ampf 2 = Amp 10h, Ampf 3




The following routine is used to unpack samples. If the Pack Method bits is
set to 01, then use this routine.

;
;                             UnPack sample method 1
;
; Input:
;         esi = input offset
;         edi = dest offset
;         ecx = input size
; Output:
;         ecx = output size
;
UnPackMethod1   Proc    Near
        pushad
        mov     inputoffset,esi
        mov     outputoffset,edi
        mov     inputsize,ecx

                                          ;unpacking
        mov     esi,inputoffset
        mov     edi,outputoffset
        mov     ecx,dword ptr [esi]
        mov     inputsize,ecx
        mov     ecx,dword ptr [esi+4]
        mov     al,byte ptr [esi+8]
        mov     packcharacter,al
        add     esi,9
unpackloop:
        lodsb
        cmp     al,packcharacter
        jz      unpacka
        stosb
        loop    unpackloop
        jmp     endofunpack
unpacka:
        lodsb
        dec     ecx
        cmp     al,0
        jz      putpackcharacter
        push    ecx
        movzx   ecx,al
        lodsb
        rep     stosb
        pop     ecx
        dec     ecx
        loop    unpackloop
        jmp     endofunpack
putpackcharacter:
        mov     al,packcharacter
        stosb
        loop    unpackloop
endofunpack:

        mov     edi,inputoffset         ;clear
        mov     ecx,inputsize
        xor     eax,eax
        mov     edx,ecx
        shr     ecx,2
        rep     stosd
        mov     ecx,edx
        and     ecx,3
        rep     stosb

        mov     edi,inputoffset                 ;unpack bit split
        mov     esi,outputoffset
        mov     ebp,edi
        mov     ecx,inputsize
        add     ebp,ecx
        mov     dl,10000000b
bitunpackloop:
        push    ecx

        xor     dh,dh
        lodsb
        mov     ecx,8
bitunpack2:
        mov     bl,al
        and     bl,dl
        add     cl,dh
        ror     bl,cl
        sub     cl,dh
        ror     dl,1
        or      byte ptr [edi],bl
        inc     edi
        cmp     edi,ebp
        jnz     notsettaback
        mov     edi,inputoffset
        inc     dh
notsettaback:
        loop    bitunpack2
        mov     cl,dh
        ror     dl,cl

        pop     ecx
        loop    bitunpackloop

                                                ;delta unpack
        mov     esi,inputoffset
        mov     edi,outputoffset
        mov     ecx,inputsize
        xor     bl,bl
deltaunpack:
        lodsb
        cmp     al,128
        jz      notnegative
        test    al,10000000b
        jz      notnegative
        and     al,01111111b
        neg     al
notnegative:
        sub     bl,al
        mov     byte ptr [edi],bl
        inc     edi
        loop    deltaunpack

        sub     edi,outputoffset
        mov     inputoffset,edi
        popad
        mov     ecx,inputoffset
        ret
UnPackMethod1   Endp


           New commands
           ------------


 8 0x    PanPosition (0-f)
 E 80    Break SampleLoop
10 00    Play Sample Forwards
10 01    Play Sample BackWards
10 02    Enable Bidirectional Loop
         (only on looped samples)
11 xx    Extra Fine Slide Up (4 times finer than normal)
12 xx    Extra Fine Slide Down (4times finer than normal)
13 xy    Retrig with volslide (compare with E9)
         The x value tells if there should be a
         volumeslide between the retrigs.
           0: 0    (No volslide)    8: 0 (No volslide)
           1: -1                    9: +1
           2: -2                    A: +2
           3: -4                    B: +4
           4: -8                    C: +8
           5: -16                   D: +16
           6: 2/3 * the orig. vol.  E: 3/2 * the orig vol
           7: 1/2 * the orig. vol.  F: 2 * the orig.vol.
15 xx   Just Like 5, but with 2 times finer volslide.
16 xx   Just Like 6, but with 2 times finer volslide.
1A xx   2 times finer volslide than A.
1C xx   Channel MasterVolume (0-7fh)
1D xx   Long PatternBreak (use instead of 0D when using
        long patterns). xx is in Hex
1E 1x   Just like E1, but this uses all octaves.
1E 2x   Just like E2, but this uses all octaves.
1E Ax   2 times Finer volslide than EA.
1E Bx   2 times Finer volslide than EB.
1F 0x   Set BPM Decimal value. (0-9)
18 xy   PanSlide x=left speed, y=right speed.
20 xx   Key Off at tic xx
21 xx   Just like 1, but this uses all octaves.
22 xx   Just like 2, but this uses all octaves.
2A xx   Global VolumeSlide
2C xx   Global Volume (0-7fh)




Well, that's about it. There are probably alot of questions left so go ahead
and ask us if there's something you wanna know.
BTW, we don't take any responsibilities for faulty info in this doc :)
(especially the formulas)...


                                                               Velvet staff

