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