Coders Develop Glorious Stuff
http://forum.cdgs-crew.com/

Some mathematical calculation info for pan, swing and slides
http://forum.cdgs-crew.com/viewtopic.php?f=11&t=15
Page 1 of 1

Author:  BastyCDGS [ 1. June 2005 12:15 ]
Post subject:  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)

Page 1 of 1 Time zone: Europe/Berlin
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/