Improve comments and formatting.

This commit is contained in:
Veikko Sariola 2020-05-03 16:34:39 +03:00
parent 212951c75d
commit 3c3fe6caf8

View File

@ -110,9 +110,11 @@ EXPORT MANGLE_DATA(LFO_NORMALIZE)
go4k_groove_pattern dw 0011100111001110b go4k_groove_pattern dw 0011100111001110b
%endif %endif
; //======================================================================================== ;-------------------------------------------------------------------------------
; // .crtemui section (emulates crt functions) ; FloatRandomNumber function
; //======================================================================================== ;-------------------------------------------------------------------------------
; Output: st0 : result
;-------------------------------------------------------------------------------
SECT_TEXT(crtemui) SECT_TEXT(crtemui)
EXPORT MANGLE_FUNC(FloatRandomNumber,0) EXPORT MANGLE_FUNC(FloatRandomNumber,0)
@ -124,58 +126,62 @@ EXPORT MANGLE_FUNC(FloatRandomNumber,0)
pop eax pop eax
ret ret
; //======================================================================================== ;-------------------------------------------------------------------------------
; // .g4kcod* sections (code for go4k) ; Waveshaper function
; //======================================================================================== ;-------------------------------------------------------------------------------
; Input: st0 : a - the shaping coefficient
; //---------------------------------------------------------------------------------------- ; st1 : x - input value
; // Waveshaper function ; Output: st0 : (1+k)*x/(1+k*abs(x)), where k=2*m/(1-m) and m=2*a-1
; //---------------------------------------------------------------------------------------- ; and x is clamped first if GO4K_USE_WAVESHAPER_CLIP
; // Input : st0 : shaping coeff ;-------------------------------------------------------------------------------
; // st1 : input
; // Output: st0 : result
; //----------------------------------------------------------------------------------------
%ifdef INCLUDE_WAVESHAPER %ifdef INCLUDE_WAVESHAPER
SECT_TEXT(g4kcod2) SECT_TEXT(g4kcod2)
go4kWaveshaper: go4kWaveshaper: ; a x
%ifdef GO4K_USE_WAVESHAPER_CLIP %ifdef GO4K_USE_WAVESHAPER_CLIP
fxch fxch ; x a
fld1 ; // 1 val fld1 ; 1 x a
fucomi st1 ; // 1 val fucomi st1 ; if (1 <= x)
jbe short go4kWaveshaper_clip jbe short go4kWaveshaper_clip ; goto go4kWaveshaper_clip
fchs ; // -1 val fchs ; -1 x a
fucomi st1 ; // -1 val fucomi st1 ; if (-1 < x)
fcmovb st0, st1 ; // val -1 (if val > -1) fcmovb st0, st1 ; x x a
go4kWaveshaper_clip: go4kWaveshaper_clip:
fstp st1 ; // newval fstp st1 ; x' a, where x' = clamp(x)
fxch fxch ; a x' (from now on just called x)
%endif %endif
fsub dword [c_0_5] fsub dword [c_0_5] ; a-.5 x
fadd st0 fadd st0 ; 2*a-1 x
fst dword [esp-4] ; // amnt in fst dword [esp-4] ; m=2*a-1 x
fadd st0 ; // 2*amnt in fadd st0 ; 2*m x
fld1 ; // 1 2*amnt in fld1 ; 1 2*m x
fsub dword [esp-4] ; // 1-amnt 2*amnt in fsub dword [esp-4] ; 1-m 2*m x
fdivp st1, st0 ; // k in fdivp st1, st0 ; k=2*m/(1-m) x
fld st1 ; // sin k in fld st1 ; x k x
fabs ; // a(in) k in fabs ; abs(x) k x
fmul st1 ; // k*a(in) k in fmul st1 ; k*abs(x) k x
fld1 fld1 ; 1 k*abs(x) k x
faddp st1, st0 ; // 1+k*a(in) k in faddp st1, st0 ; 1+k*abs(x) k x
fxch st1 ; // k 1+k*a(in) in fxch st1 ; k 1+k*abs(x) x
fld1 fld1 ; 1 k 1+k*abs(x) x
faddp st1, st0 ; // 1+k 1+k*a(in) in faddp st1, st0 ; 1+k 1+k*abs(x) x
fmulp st2 ; // 1+k*a(in) (1+k)*in fmulp st2 ; 1+k*abs(x) (1+k)*x
fdivp st1, st0 ; // out fdivp st1, st0 ; (1+k)*x/(1+k*abs(x))
ret ret
%endif ; INCLUDE_WAVESHAPER %endif ; INCLUDE_WAVESHAPER
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // unit values preparation/transform ; TransformValues function
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; Input: [esp] : number of bytes to transform
; esi : pointer to byte stream
; Output: eax : last transformed byte (zero extended)
; edx : pointer to go4k_transformed_values, containing
; each byte transformed as x/128.0f+modulations
; esi : updated to point after the transformed bytes
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcod3) SECT_TEXT(g4kcod3)
go4kTransformValues: go4kTransformValues:
@ -197,22 +203,27 @@ go4kTransformValues_loop:
pop ecx pop ecx
ret 4 ret 4
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // Envelope param mapping ; ENVMap function
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; Input: eax : envelope parameter (0 = attac, 1 = decay...)
; edx : pointer to go4k_transformed_values
; Output: st0 : 2^(-24*x), where x is the parameter in the range 0-1
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcod4) SECT_TEXT(g4kcod4)
go4kENVMap: go4kENVMap:
fld dword [edx+eax*4] fld dword [edx+eax*4] ; x, where x is the parameter in the range 0-1
fimul dword [c_24] fimul dword [c_24] ; 24*x
fchs fchs ; -24*x
; flow into Power function, which outputs 2^(-24*x)
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // Power function (2^x) ; Power function (2^x)
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // Input : st0 : x ; Input: st0 : x
; // Output: st0 : 2^x ; Output: st0 : 2^x
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
EXPORT MANGLE_FUNC(Power,0) ; x EXPORT MANGLE_FUNC(Power,0) ; x
fld1 ; 1 x fld1 ; 1 x
fld st1 ; x 1 x fld st1 ; x 1 x
@ -225,159 +236,83 @@ EXPORT MANGLE_FUNC(Power,0) ; x
fstp st1 ; 2^x fstp st1 ; 2^x
ret ret
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // ENV Tick ; ENV Tick
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN : WRK = unit workspace ; Input: WRK : pointer to unit workspace
; // IN : VAL = unit values ; VAL : pointer to unit values as bytes
; // IN : ecx = global workspace ; ecx : pointer to global workspace
; // OUT : ; Output: st0 : envelope value, [gain]*level. The slopes of
; // DIRTY : eax ; level is 2^(-24*p) per sample, where p is either
; //---------------------------------------------------------------------------------------- ; attack, decay or release in [0,1] range
; Dirty: eax, edx
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcoda) SECT_TEXT(g4kcoda)
EXPORT MANGLE_FUNC(go4kENV_func,0) EXPORT MANGLE_FUNC(go4kENV_func,0)
TRANSFORM_VALUES go4kENV_val TRANSFORM_VALUES go4kENV_val
%ifdef GO4K_USE_ENV_CHECK %ifdef GO4K_USE_ENV_CHECK
; check if current note still active mov eax, dword [ecx-4] ; eax = go4k_instrument.note
mov eax, dword [ecx-4] test eax, eax ; if (eax != 0) // if current note still active
test eax, eax jne go4kENV_func_do ; goto go4kENV_func_do
jne go4kENV_func_do
fldz fldz
ret ret ; return 0
%endif %endif
go4kENV_func_do: go4kENV_func_do:
mov eax, dword [ecx-8] ; // is the instrument in release mode (note off)? mov eax, dword [ecx-8] ; eax = go4k_instrument.release
test eax, eax test eax, eax ; if (eax == 0)
je go4kENV_func_process je go4kENV_func_process ; goto process
mov dword [WRK+go4kENV_wrk.state], ENV_STATE_RELEASE mov dword [WRK+go4kENV_wrk.state], ENV_STATE_RELEASE ; [state]=RELEASE
go4kENV_func_process: go4kENV_func_process:
mov eax, dword [WRK+go4kENV_wrk.state] mov eax, dword [WRK+go4kENV_wrk.state] ; al=[state]
fld dword [WRK+go4kENV_wrk.level] ; // val - fld dword [WRK+go4kENV_wrk.level] ; x=[level]
; // check for sustain state cmp al, ENV_STATE_SUSTAIN ; if (al==SUSTAIN)
cmp al, ENV_STATE_SUSTAIN je short go4kENV_func_leave2 ; goto leave2
je short go4kENV_func_leave2
go4kENV_func_attac: go4kENV_func_attac:
cmp al, ENV_STATE_ATTAC cmp al, ENV_STATE_ATTAC ; if (al!=ATTAC)
jne short go4kENV_func_decay jne short go4kENV_func_decay ; goto decay
call go4kENVMap ; // newval call go4kENVMap ; a x, where a=attack
faddp st1, st0 faddp st1, st0 ; a+x
; // check for end of attac fld1 ; 1 a+x
fld1 ; // 1 newval fucomi st1 ; if (a+x<=1) // is attack complete?
fucomi st1 ; // 1 newval fcmovnb st0, st1 ; a+x a+x
fcmovnb st0, st1 ; // newval 1 (if newval < 1) jbe short go4kENV_func_statechange ; else goto statechange
jbe short go4kENV_func_statechange
go4kENV_func_decay: go4kENV_func_decay:
cmp al, ENV_STATE_DECAY cmp al, ENV_STATE_DECAY ; if (al!=DECAY)
jne short go4kENV_func_release jne short go4kENV_func_release ; goto release
call go4kENVMap ; // newval call go4kENVMap ; d x, where d=decay
fsubp st1, st0 fsubp st1, st0 ; x-d
; // check for end of decay fld dword [edx+go4kENV_val.sustain] ; s x-d, where s=sustain
fld dword [edx+go4kENV_val.sustain] ; // sustain newval fucomi st1 ; if (x-d>s) // is decay complete?
fucomi st1 ; // sustain newval fcmovb st0, st1 ; x-d x-d
fcmovb st0, st1 ; // newval sustain (if newval > sustain) jnc short go4kENV_func_statechange ; else goto statechange
jnc short go4kENV_func_statechange
go4kENV_func_release: go4kENV_func_release:
; // release state? cmp al, ENV_STATE_RELEASE ; if (al!=RELEASE)
cmp al, ENV_STATE_RELEASE jne short go4kENV_func_leave ; goto leave
jne short go4kENV_func_leave call go4kENVMap ; r x, where r=release
call go4kENVMap ; // newval fsubp st1, st0 ; x-r
fsubp st1, st0 fldz ; 0 x-r
; // check for end of release fucomi st1 ; if (x-r>0) // is release complete?
fldz ; // 0 newval fcmovb st0, st1 ; x-r x-r, then goto leave
fucomi st1 ; // 0 newval
fcmovb st0, st1 ; // newval 0 (if newval > 0)
jc short go4kENV_func_leave jc short go4kENV_func_leave
go4kENV_func_statechange: ; // newval go4kENV_func_statechange:
inc dword [WRK+go4kENV_wrk.state] inc dword [WRK+go4kENV_wrk.state] ; [state]++
go4kENV_func_leave: ; // newval bla go4kENV_func_leave:
fstp st1 fstp st1 ; x', where x' is the new value
; // store new env value fst dword [WRK+go4kENV_wrk.level] ; [level]=x'
fst dword [WRK+go4kENV_wrk.level]
go4kENV_func_leave2: go4kENV_func_leave2:
; // mul by gain fmul dword [edx+go4kENV_val.gain] ; [gain]*x'
fmul dword [edx+go4kENV_val.gain]
ret ret
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // VCO Tick ; VCO Tick
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN : WRK = unit workspace ; Input: WRK : pointer to unit workspace
; // IN : VAL = unit values ; VAL : pointer to unit values as bytes
; // IN : ecx = global workspace ; ecx : pointer to global workspace
; // OUT : ; Output: st0 : oscillator value
; // DIRTY : eax ; Dirty: eax, edx
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
SECT_TEXT(g4kcodp)
go4kVCO_pulse:
fucomi st1 ; // c p
fld1
jnc short go4kVCO_func_pulse_up ; // +1 c p
fchs ; // -1 c p
go4kVCO_func_pulse_up:
fstp st1 ; // +-1 p
fstp st1 ; // +-1
ret
SECT_TEXT(g4kcodt)
go4kVCO_trisaw:
fucomi st1 ; // c p
jnc short go4kVCO_func_trisaw_up
fld1 ; // 1 c p
fsubr st2, st0 ; // 1 c 1-p
fsubrp st1, st0 ; // 1-c 1-p
go4kVCO_func_trisaw_up:
fdivp st1, st0 ; // tp'/tc
fadd st0 ; // 2*''
fld1 ; // 1 2*''
fsubp st1, st0 ; // 2*''-1
ret
SECT_TEXT(g4kcods)
go4kVCO_sine:
fucomi st1 ; // c p
jnc short go4kVCO_func_sine_do
fstp st1
fsub st0, st0 ; // 0
ret
go4kVCO_func_sine_do
fdivp st1, st0 ; // p/c
fldpi ; // pi p
fadd st0 ; // 2*pi p
fmulp st1, st0 ; // 2*pi*p
fsin ; // sin(2*pi*p)
ret
%ifdef GO4K_USE_VCO_GATE
SECT_TEXT(g4kcodq)
go4kVCO_gate:
fxch ; // p c
fstp st1 ; // p
fmul dword [c_16] ; // p'
push eax
push eax
fistp dword [esp] ; // -
fld1 ; // 1
pop eax
and al, 0xf
bt word [VAL-5],ax
jc go4kVCO_gate_bit
fsub st0, st0 ; // 0
go4kVCO_gate_bit:
fld dword [WRK+go4kVCO_wrk.gatestate] ; // f x
fsub st1 ; // f-x x
fmul dword [c_dc_const] ; // c(f-x) x
faddp st1, st0 ; // x'
fst dword [WRK+go4kVCO_wrk.gatestate]
pop eax
ret
%endif
SECT_TEXT(g4kcodb) SECT_TEXT(g4kcodb)
EXPORT MANGLE_FUNC(go4kVCO_func,0) EXPORT MANGLE_FUNC(go4kVCO_func,0)
@ -506,15 +441,86 @@ go4kVCO_func_stereodone:
%endif %endif
ret ret
; //---------------------------------------------------------------------------------------- SECT_TEXT(g4kcodp)
; // VCF Tick
; //---------------------------------------------------------------------------------------- go4kVCO_pulse:
; // IN : WRK = unit workspace fucomi st1 ; // c p
; // IN : VAL = unit values fld1
; // IN : ecx = global workspace jnc short go4kVCO_func_pulse_up ; // +1 c p
; // OUT : fchs ; // -1 c p
; // DIRTY : eax go4kVCO_func_pulse_up:
; //---------------------------------------------------------------------------------------- fstp st1 ; // +-1 p
fstp st1 ; // +-1
ret
SECT_TEXT(g4kcodt)
go4kVCO_trisaw:
fucomi st1 ; // c p
jnc short go4kVCO_func_trisaw_up
fld1 ; // 1 c p
fsubr st2, st0 ; // 1 c 1-p
fsubrp st1, st0 ; // 1-c 1-p
go4kVCO_func_trisaw_up:
fdivp st1, st0 ; // tp'/tc
fadd st0 ; // 2*''
fld1 ; // 1 2*''
fsubp st1, st0 ; // 2*''-1
ret
SECT_TEXT(g4kcods)
go4kVCO_sine:
fucomi st1 ; // c p
jnc short go4kVCO_func_sine_do
fstp st1
fsub st0, st0 ; // 0
ret
go4kVCO_func_sine_do
fdivp st1, st0 ; // p/c
fldpi ; // pi p
fadd st0 ; // 2*pi p
fmulp st1, st0 ; // 2*pi*p
fsin ; // sin(2*pi*p)
ret
%ifdef GO4K_USE_VCO_GATE
SECT_TEXT(g4kcodq)
go4kVCO_gate:
fxch ; // p c
fstp st1 ; // p
fmul dword [c_16] ; // p'
push eax
push eax
fistp dword [esp] ; // -
fld1 ; // 1
pop eax
and al, 0xf
bt word [VAL-5],ax
jc go4kVCO_gate_bit
fsub st0, st0 ; // 0
go4kVCO_gate_bit:
fld dword [WRK+go4kVCO_wrk.gatestate] ; // f x
fsub st1 ; // f-x x
fmul dword [c_dc_const] ; // c(f-x) x
faddp st1, st0 ; // x'
fst dword [WRK+go4kVCO_wrk.gatestate]
pop eax
ret
%endif
;-------------------------------------------------------------------------------
; VCF Tick
;-------------------------------------------------------------------------------
; Input: WRK : pointer to unit workspace
; VAL : pointer to unit values as bytes
; ecx : pointer to global workspace
; st0 : signal
; Output: st0 : filtered signal
; Dirty: eax, edx
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcodc) SECT_TEXT(g4kcodc)
EXPORT MANGLE_FUNC(go4kVCF_func,0) EXPORT MANGLE_FUNC(go4kVCF_func,0)
@ -594,15 +600,16 @@ go4kVCF_func_processdone:
go4kVCF_func_end: ; // value - - - - go4kVCF_func_end: ; // value - - - -
ret ret
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // DST Tick ; DST Tick
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN : WRK = unit workspace ; Input: WRK : pointer to unit workspace
; // IN : VAL = unit values ; VAL : pointer to unit values as bytes
; // IN : ecx = global workspace ; ecx : pointer to global workspace
; // OUT : ; st0 : signal
; // DIRTY : eax ; Output: st0 : distorted signal
; //---------------------------------------------------------------------------------------- ; Dirty: eax, edx
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcodd) SECT_TEXT(g4kcodd)
EXPORT MANGLE_FUNC(go4kDST_func,0) EXPORT MANGLE_FUNC(go4kDST_func,0)
@ -666,15 +673,16 @@ go4kDST_func_monohold:
%endif %endif
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // DLL Tick ; DLL Tick
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN : WRK = unit workspace ; Input: WRK : pointer to unit workspace
; // IN : VAL = unit values ; VAL : pointer to unit values as bytes
; // IN : ecx = global workspace ; ecx : pointer to global workspace
; // OUT : ; st0 : signal
; // DIRTY : eax ; Output: st0 : delayed signal
; //---------------------------------------------------------------------------------------- ; Dirty: eax, edx
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcodf) SECT_TEXT(g4kcodf)
EXPORT MANGLE_FUNC(go4kDLL_func,0) EXPORT MANGLE_FUNC(go4kDLL_func,0)
@ -810,15 +818,16 @@ go4kDLL_func_buffer_nowrap2:
ret ret
%endif %endif
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // GLITCH Tick ; GLITCH Tick
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN : WRK = unit workspace ; Input: WRK : pointer to unit workspace
; // IN : VAL = unit values ; VAL : pointer to unit values as bytes
; // IN : ecx = global workspace ; ecx : pointer to global workspace
; // OUT : ; ?
; // DIRTY : eax ; Output: ?
; //---------------------------------------------------------------------------------------- ; Dirty: eax, edx
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcodu) SECT_TEXT(g4kcodu)
EXPORT MANGLE_FUNC(go4kGLITCH_func,0) EXPORT MANGLE_FUNC(go4kGLITCH_func,0)
@ -924,15 +933,16 @@ go4kGLITCH_func_leave:
ret ret
%endif %endif
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // FOP Tick (various fp stack based operations) ; FOP Tick
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN : WRK = unit workspace ; Input: WRK : pointer to unit workspace
; // IN : VAL = unit values ; VAL : pointer to unit values as bytes
; // IN : ecx = global workspace ; ecx : pointer to global workspace
; // OUT : ; stX : depends on the operation
; // DIRTY : ; Output: stX : depends on the operation
; //---------------------------------------------------------------------------------------- ; Dirty: eax, edx
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcodg) SECT_TEXT(g4kcodg)
EXPORT MANGLE_FUNC(go4kFOP_func,0) EXPORT MANGLE_FUNC(go4kFOP_func,0)
@ -989,15 +999,16 @@ go4kFOP_func_mulp2:
fmulp st2, st0 fmulp st2, st0
ret ret
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // FST Tick (stores a value somewhere in the local workspace) ; FST Tick
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN : WRK = unit workspace ; Input: WRK : pointer to unit workspace
; // IN : VAL = unit values ; VAL : pointer to unit values as bytes
; // IN : ecx = global workspace ; ecx : pointer to global workspace
; // OUT : ; st0 : signal
; // DIRTY : ; Output: (st0) : signal, unless popped
; //---------------------------------------------------------------------------------------- ; Dirty: eax, edx
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcodh) SECT_TEXT(g4kcodh)
EXPORT MANGLE_FUNC(go4kFST_func,0) EXPORT MANGLE_FUNC(go4kFST_func,0)
@ -1019,35 +1030,35 @@ go4kFST_func_set:
go4kFST_func_done: go4kFST_func_done:
ret ret
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // FLD Tick (load a value on stack, optionally add a modulation signal beforehand) ; FLD Tick
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN : WRK = unit workspace ; Input: WRK : pointer to unit workspace
; // IN : VAL = unit values ; VAL : pointer to unit values as bytes
; // IN : ecx = global workspace ; Output: st0 : 2*v-1, where v is the loaded value
; // OUT : signal-signal*pan , signal*pan ; Dirty: eax, edx
; // DIRTY : ;-------------------------------------------------------------------------------
; //----------------------------------------------------------------------------------------
SECT_TEXT(g4kcodm) SECT_TEXT(g4kcodm)
EXPORT MANGLE_FUNC(go4kFLD_func,0) ;// in main env EXPORT MANGLE_FUNC(go4kFLD_func,0)
%ifdef GO4K_USE_FLD %ifdef GO4K_USE_FLD
TRANSFORM_VALUES go4kFLD_val TRANSFORM_VALUES go4kFLD_val
fld dword [edx+go4kFLD_val.value] ;// value in fld dword [edx+go4kFLD_val.value] ; v
fsub dword [c_0_5] fsub dword [c_0_5] ; v-.5
fadd st0 fadd st0 ; 2*v-1
%endif %endif
ret ret
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // FSTG Tick (stores a value anywhere in the synth (and in each voice)) ; FSTG Tick
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN : WRK = unit workspace ; Input: WRK : pointer to unit workspace
; // IN : VAL = unit values ; VAL : pointer to unit values as bytes
; // IN : ecx = global workspace ; ecx : pointer to global workspace
; // OUT : ; st0 : signal
; // DIRTY : ; Output: (st0) : signal, unless popped
; //---------------------------------------------------------------------------------------- ; Dirty: eax, edx
;-------------------------------------------------------------------------------
%ifdef GO4K_USE_FSTG %ifdef GO4K_USE_FSTG
SECT_TEXT(g4kcodi) SECT_TEXT(g4kcodi)
@ -1087,39 +1098,45 @@ go4kFSTG_func_done:
ret ret
%endif %endif
; //----------------------------------------------------------------------------------------
; // PAN Tick (multiplies signal with main envelope and converts to stereo) ;-------------------------------------------------------------------------------
; //---------------------------------------------------------------------------------------- ; PAN Tick
; // IN : WRK = unit workspace ;-------------------------------------------------------------------------------
; // IN : VAL = unit values ; Input: WRK : pointer to unit workspace
; // IN : ecx = global workspace ; VAL : pointer to unit values as bytes
; // OUT : signal-signal*pan , signal*pan ; ecx : pointer to global workspace
; // DIRTY : ; st0 : s, the signal
; //---------------------------------------------------------------------------------------- ; Output: st0 : s*(1-p), where p is the panning in [0,1] range
; st1 : s*p
; Dirty: eax, edx
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcodj) SECT_TEXT(g4kcodj)
EXPORT MANGLE_FUNC(go4kPAN_func,0) ;// in main env EXPORT MANGLE_FUNC(go4kPAN_func,0)
%ifdef GO4K_USE_PAN %ifdef GO4K_USE_PAN
TRANSFORM_VALUES go4kPAN_val TRANSFORM_VALUES go4kPAN_val
fld dword [edx+go4kPAN_val.panning] ;// pan in fld dword [edx+go4kPAN_val.panning] ; p s
fmul st1 ;// r in fmul st1 ; p*s s
fsub st1, st0 ;// r l fsub st1, st0 ; p*s s-p*s
fxch ;// l r ; Equal to
; s*p s*(1-p)
fxch ; s*(1-p) s*p
%else %else
fmul dword [c_0_5] fmul dword [c_0_5] ; s*.5
fld st0 fld st0 ; s*.5 s*.5
%endif %endif
ret ret
; //----------------------------------------------------------------------------------------
; // OUT Tick ( stores stereo signal pair in temp buffers of the instrument) ;-------------------------------------------------------------------------------
; //---------------------------------------------------------------------------------------- ; OUT Tick (stores stereo signal pair in temp buffers of the instrument)
; // IN : WRK = unit workspace ;-------------------------------------------------------------------------------
; // IN : VAL = unit values ; Input: WRK : pointer to unit workspace
; // IN : ecx = global workspace ; VAL : pointer to unit values as bytes
; // OUT : ; ecx : pointer to global workspace
; // DIRTY : ; st0 : l, the left signal
; //---------------------------------------------------------------------------------------- ; st1 : r, the right signal
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcodk) SECT_TEXT(g4kcodk)
EXPORT MANGLE_FUNC(go4kOUT_func,0) ;// l r EXPORT MANGLE_FUNC(go4kOUT_func,0) ;// l r
@ -1157,15 +1174,15 @@ EXPORT MANGLE_FUNC(go4kOUT_func,0) ;// l r
%endif %endif
ret ret
; //----------------------------------------------------------------------------------------
; // ACC Tick (stereo signal accumulation for synth commands only -> dont use in instrument commands) ;-------------------------------------------------------------------------------
; //---------------------------------------------------------------------------------------- ; ACC Tick (stereo signal accumulation)
; // IN : WRK = unit workspace ;-------------------------------------------------------------------------------
; // IN : VAL = unit values ; Input: WRK : pointer to unit workspace
; // IN : ecx = global workspace ; VAL : pointer to unit values as bytes
; // OUT : ; ecx : pointer to global workspace
; // DIRTY : eax ; Dirty: eax,edx
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
SECT_TEXT(g4kcodl) SECT_TEXT(g4kcodl)
EXPORT MANGLE_FUNC(go4kACC_func,0) EXPORT MANGLE_FUNC(go4kACC_func,0)
@ -1188,14 +1205,9 @@ go4kACC_func_loop:
popad popad
ret ret
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // Update Instrument (allocate voices, set voice to release) ; Update Instrument (allocate voices, set voice to release)
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN :
; // IN :
; // OUT :
; // DIRTY :
; //----------------------------------------------------------------------------------------
SECT_TEXT(g4kcodw) SECT_TEXT(g4kcodw)
go4kUpdateInstrument: go4kUpdateInstrument:
@ -1239,14 +1251,9 @@ go4kUpdateInstrument_newNote:
go4kUpdateInstrument_done: go4kUpdateInstrument_done:
ret ret
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // Render Voices ; Render Voices
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN :
; // IN :
; // OUT :
; // DIRTY :
; //----------------------------------------------------------------------------------------
SECT_TEXT(g4kcodx) SECT_TEXT(g4kcodx)
go4kRenderVoices: go4kRenderVoices:
@ -1312,9 +1319,12 @@ go4k_render_instrument_next2:
pop ecx ; // restore instrument counter pop ecx ; // restore instrument counter
ret ret
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // the entry point for the synth ; _4klang_render function: the entry point for the synth
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; Has the signature _4klang_render(void *ptr), where ptr is a pointer to
; the output buffer
;-------------------------------------------------------------------------------
SECT_TEXT(g4kcody) SECT_TEXT(g4kcody)
EXPORT MANGLE_FUNC(_4klang_render,4) EXPORT MANGLE_FUNC(_4klang_render,4)
@ -1457,28 +1467,26 @@ go4k_render_nogroove:
popad popad
ret 4 ret 4
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // the magic behind it :) ; VM_process function (the virtual machine behind the synth)
; //---------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; // IN : edi = instrument pointer ; Input: edi : pointer to the instrument structure
; // IN : esi = instrumet values ; VAL : pointer to unit values as bytes
; // IN : ebx = instrument instructions ; ebx : pointer to instrument instructions
; // OUT : ;-------------------------------------------------------------------------------
; // DIRTY :
; //----------------------------------------------------------------------------------------
SECT_TEXT(g4kcodz) SECT_TEXT(g4kcodz)
go4k_VM_process: go4k_VM_process:
lea WRK, [edi+8] ; // get current workspace pointer lea WRK, [edi+8] ; WRK = workspace start
mov ecx, WRK ; // ecx = workspace start mov ecx, WRK ; ecx = workspace start
go4k_VM_process_loop: go4k_VM_process_loop:
movzx eax, byte [ebx] ; // get command byte movzx eax, byte [ebx] ; eax = command byte
inc ebx inc ebx
test eax, eax test eax, eax ; if (eax == 0)
je go4k_VM_process_done ; // command byte = 0? so done je go4k_VM_process_done ; goto done
call dword [eax*4+go4k_synth_commands] call dword [eax*4+go4k_synth_commands] ; call the function corresponding to command
add WRK, MAX_UNIT_SLOTS*4 ; // go to next workspace slot add WRK, MAX_UNIT_SLOTS*4 ; move WRK to next workspace
jmp short go4k_VM_process_loop jmp short go4k_VM_process_loop
go4k_VM_process_done: go4k_VM_process_done:
add edi, go4k_instrument.size ; // go to next instrument voice add edi, go4k_instrument.size ; move edi to next instrument
ret ret