Reply to topic  [ 1 post ] 
Some mathematical calculation info for pan, swing and slides 
Author Message
Administrator

Joined: 31. May 2005 05:23
Posts: 70
Location: Liège
Post Some mathematical calculation info for pan, swing and slides
Code:
All effects marked with * completed 1oo% ! All marked with a ! instead need
a change later, and all marked with a ? aren't tested yet but should work.
But you never know: Bug rulez ! :-)))))

Volume formula (I use 64-bit multiply and divide for them)
----------------------------------------------------------
For 8-bit, use:
          Vol * TVol * RVol * VEnv * Fde * GVol
OutVol =  -------------------------------------
           255 * 255 * 255 * 255 * 65535 * 255


SUB VOLUMES ARE USED ONLY BY SLIDES ! DO NOT USE IT IN FINAL CALCULATION !

OutVol = Output volume to mixing device (0 - 255)
Vol = Volume, TVol = Track volume, RVol = Random volume (look below)
VEnv = Volume envelope volume, Fde = Fadeout count (set to 65535 on new note),
IVol = Instrument volume, SVol = Sample volume, VSw = Volume swing
GVol = Global volume

Random volume variation formula (looks little complicated but can be easily
                                 implemented on an assembler):
          RVol = ((IVol * SVol) - (IVol * SVol * VSw / 256))
                 + Rnd(((IVol * SVol * VSw / 256) * 2) + 1)

       Clip values < 0 to 0 and values greater than 255*255 to 255*255
       (this assumes that e.g. Rnd(10) returns a random value from 0 - 9)

The following QUITE VERY SIMPLE routine is used for the final volume
calculation by the player in the tucomposer.library (for Asm-coders)
D7 points to current host channel, A2 points to virtual channel structure,
A3 points to host channel structure and A6 to the tucomposer.library base
Code (c) by Basty/TuC in 1997:
        moveq   #0,d0                           ; Clear for MULU
        move.b  pc_Volume(a2),d0                ; Vol (Note volume)
        tst.b   pc_Flags(a2)                    ; Running backgrnd channel ?
        bmi.s   RunBackChan                     ; No -> Jump
        cmp.w   phc_VirtualChannel(a3),d7       ; Virtual channel - Host ch ?
        bne.s   RunBackChan                     ; No -> Jump
        btst    #PHCB_TremorExec-8,phc_Flags+2(a3) ; Tremor running ?
        beq.s   RunBackChan                     ; No -> Jump
        btst    #PHCB_TremorOff-8,phc_Flags+2(a3) ; Tremor off currently ?
        beq.s   RunBackChan                     ; No -> Jump
        moveq   #0,d0                           ; Set volume to zero
RunBackChan: moveq      #0,d2                   ; Clear D2 for MULU
        move.b  phc_TrackVolume(a3),d2          ; TVol (Track volume)
        mulu.w  d2,d0                           ; Multiple
        mulu.w  pc_InstrVolume(a2),d0           ; * RVol (look code below)
        move.w  pc_VolEnvelopeVolume(a2),d2     ; Volume envelope volume
        lsr.w   #8,d2                           ; scale down to 0-255
        moveq   #0,d1                           ; Clear D1 for MULU
        move.b  pc_GlobalVolume(a2),d1          ; * GVol (Global volume)
        mulu.w  d1,d2                           ; Multiple them
        mulu.w  pc_FadeOutCount(a2),d2          ; * Fde (Fadeout count)
        mulu.l  d2,d1:d0                        ; Final multiply (64 bit)
        divu.l  #255*255*255*255,d1:d0          ; Divide to scale to 255
        divu.l  #65535*255,d0                   ; 2 steps needed (no 64/64)...
        move.b  d0,pc_FinalVolume(a2)           ; Store OutVol
        move.b  d0,ms_Volume(a2)                ; Output volume for mixer
        ...                                     ; Other code (panning & co.)

Here the routine I use for calculating the random volume variation:
        moveq   #0,d0                           ; Clear D0 for MULU
        move.b  tcs_GlobalVolume(a1),d0         ; SVol (Global sample volume)
        moveq   #0,d4                           ; Same for D4
        move.b  tci_GlobalVolume(a0),d4         ; IVol (Global instr volume)
        mulu.w  d0,d4                           ; SVol * IVol
        move.l  d4,d2                           ; Store for later use
        mulu.w  tci_VolumeSwing(a0),d4          ; * VSw (Volume swing)
        lsr.l   #8,d4                           ; / 256
        move.l  d4,d5                           ; Store again for Rnd
        add.l   d5,d5                           ; * 2
        addq.l  #1,d5                           ; + 1
        move.l  tcb_RandomSeed(a6),d0           ; Randomize seed
        move.l  d0,d1                           ; Store
        swap    d0                              ; Swap words for OR
        clr.w   d0                              ; Clear to remove trash
        or.l    d0,d1                           ; OR them for new value
        muls.l  #-1153374675,d1                 ; Multiply (68020+ !!!)
        addq.l  #1,d1                           ; Add one for case of 0
        move.l  d1,tcb_RandomSeed(a6)           ; Store new seed
        mulu.l  d5,d0:d1                        ; Scale seed for rnd value
        sub.l   d4,d2                           ; Subtract VSwing scale
        add.l   d2,d0                           ; Add to volume
        bpl.s   VolSwingLowValOk                ; Is positive ?
        moveq   #0,d0                           ; No -> set to zero
VolSwingLowValOk: move.l #255*255,d1            ; May not exceed 255*255
        cmp.l   d1,d0                           ; Compare random result
        bls.s   VolSwingHiValOk                 ; Less or same ?
        move.l  d1,d0                           ; No -> set to 255*255
VolSwingHiValOk: move.w d0,pc_InstrVolume(a2)   ; Store RVol
        ...                                     ; Other routines (I don't
                                                ; print the whole play routine
                                                ; here :-)))

You see, actually quite a simple process. Similar routine is used for
pitch swing, except that it's limited to 1 to 2^32-1 and is a little bit
faster due to / 65536 which can be written with SWAP which is faster as LSR...

Panning formula
---------------
Set any panning values of 255 to 256 (i.e. Pan = Pan * 256 / 255) !

FinalPan = (PEnv - 128) * (128 - Abs(Pan - 128)) / 128
If Stereo Then
  If Surround Or Track Surround Or Global Surround Then
    OutPan = Surround (or 128 when not supported)
  Else
    ChPan = (((128 - FinalPan) * (TPan - 128)) / 128) + 128
    OutPan = (((128 - ChPan) * (GPan - 128)) / 128) + 128
    If OutPan = 256 Then OutPan = 255 (I used this one due to byte-pan var)
  End If
Else
  OutPan = 128 (central pan)
End If

Note that 128 = 2^7 so that arithmetic (ASL, ASR) bit shifting can be done...

SUB PANNING IS ONLY USED BY SLIDES ! DO NOT USE IT IN FINAL CALCULATION !

OutPan = Output panning to mixing device (0 - 255)
Pan = Panning or Track panning, TPan = Track panning, GPan = Global panning
ChPan = Channel panning, FinalPan = Final panning (pan with envelope)

Frequency formula
-----------------
Frequency = (8363*1712*4) / Period
ST3Period = Period / 4 (also for FT2 & IT)
AmigaPeriod = ST3Period / 4 (MOD, MED, etc.)

Linear frequence formula:
NewFrequency = OldFrequency*2^(FineSlide/3072)
DownFineSlide = -FineSlide
NormalSlide = FineSlide * 16

NTSC Note frequencies (in Hz), used by FT2, ST3 and IT:
    C-4   C#4   D-4   D#4   E-4   F-4   F#4   G-4   G#4   A-4   A#4   B-4
   8363  8860  9395  9943 10559 11186 11852 12559 13306 14092 14914 15786

Final note formula:
Frequency = (NoteFreq[Note] * 2^Octave) / 2^4 (base is C-4)


1. June 2005 12:15
Profile ICQ WWW
Display posts from previous:  Sort by  
Reply to topic   [ 1 post ] 

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by STSoftware for PTF.