mirror of
https://github.com/vsariola/sointu.git
synced 2025-12-02 07:23:24 -05:00
Implement compressor.
This commit is contained in:
@ -419,3 +419,56 @@ SECT_DATA(suconst)
|
||||
%endif
|
||||
|
||||
%endif ; DELAY_ID > -1
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; Compressor Tick
|
||||
;-------------------------------------------------------------------------------
|
||||
%if COMPRES_ID > -1
|
||||
|
||||
SECT_TEXT(sucompr)
|
||||
|
||||
EXPORT MANGLE_FUNC(su_op_compressor,0)
|
||||
fld st0 ; x x
|
||||
fmul st0, st0 ; x^2 x
|
||||
%ifdef INCLUDE_STEREO_COMPRES
|
||||
jnc su_op_compressor_mono
|
||||
fld st2 ; r l^2 l r
|
||||
fmul st0, st0 ; r^2 l^2 l r
|
||||
faddp st1, st0 ; r^2+l^2 l r
|
||||
call su_op_compressor_mono ; So, for stereo, we square both left & right and add them up
|
||||
fld st0 ; and return the computed gain two times, ready for MULP STEREO
|
||||
ret
|
||||
su_op_compressor_mono:
|
||||
%endif
|
||||
fld dword [WRK+su_compres_wrk.level] ; l x^2 x
|
||||
mov al,1 ; high bits are zero so this is ok. eax = 1 => release
|
||||
fucomi st0, st1 ; if l > x^2 // we're releasing
|
||||
jnb su_op_compressor_releasing
|
||||
xor eax, eax ; eax = 0 => attacking
|
||||
su_op_compressor_releasing:
|
||||
fsub st1, st0 ; l x^2-l x
|
||||
call su_env_map ; c l x^2-l x, c is either attack or release parameter mapped in a nonlinear way
|
||||
fmulp st2, st0 ; l c*(x^2-l) x
|
||||
faddp st1, st0 ; l+c*(x^2-l) x
|
||||
fst dword [WRK+su_compres_wrk.level] ; l'=l+c*(x^2-l), l' x
|
||||
fld dword [edx+su_compres_ports.threshold] ; t l' x
|
||||
fmul st0, st0 ; t*t
|
||||
fucomi st0, st1 ; if threshold < l'
|
||||
jb su_op_compressor_compress ; then we actually do compression
|
||||
fstp st0 ; l' x
|
||||
fstp st0 ; x
|
||||
fld1 ; 1 x
|
||||
ret ; return unity gain when we are below threshold
|
||||
su_op_compressor_compress: ; l' x
|
||||
fdivrp st1, st0 ; t*t/l' x
|
||||
fld dword [edx+su_compres_ports.ratio] ; r t*t/l' x
|
||||
fmul dword [c_0_5] ; p=r/2 t*t/l' x
|
||||
fxch ; t*t/l' p x
|
||||
fyl2x ; p*log2(t*t/l') x
|
||||
jmp MANGLE_FUNC(su_power,0) ; 2^(p*log2(t*t/l')) x
|
||||
; tail call ; Equal to:
|
||||
; (t*t/l')^p x
|
||||
; if ratio is at minimum => p=0 => 1 x
|
||||
; if ratio is at maximum => p=0.5 => t/x => t/x*x=t
|
||||
|
||||
%endif ; COMPRES_ID > -1
|
||||
@ -344,3 +344,47 @@ struc su_delayline_wrk
|
||||
.buffer resd MAX_DELAY
|
||||
.size
|
||||
endstruc
|
||||
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; COMPRES effect related defines
|
||||
;-------------------------------------------------------------------------------
|
||||
%assign COMPRES_ID -1
|
||||
|
||||
%macro USE_COMPRES 0
|
||||
%if COMPRES_ID == -1
|
||||
%assign COMPRES_ID CUR_ID
|
||||
%assign CUR_ID CUR_ID + 2
|
||||
%xdefine OPCODES OPCODES MANGLE_FUNC(su_op_compressor,0),
|
||||
%xdefine NUMPARAMS NUMPARAMS 4,
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro SU_COMPRES 5
|
||||
db %2
|
||||
db %3
|
||||
db %4
|
||||
db %5
|
||||
USE_COMPRES
|
||||
%xdefine CMDS CMDS COMPRES_ID + %1,
|
||||
%if %1 == STEREO
|
||||
%define INCLUDE_STEREO_COMPRES
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%define ATTAC(val) val
|
||||
%define RELEASE(val) val
|
||||
%define THRESHOLD(val) val
|
||||
%define RATIO(val) val
|
||||
|
||||
struc su_compres_ports
|
||||
.attack resd 1
|
||||
.release resd 1
|
||||
.threshold resd 1
|
||||
.ratio resd 1
|
||||
.ports
|
||||
endstruc
|
||||
|
||||
struc su_compres_wrk
|
||||
.level resd 1
|
||||
endstruc
|
||||
@ -152,7 +152,7 @@ su_transform_values_out:
|
||||
;-------------------------------------------------------------------------------
|
||||
SECT_TEXT(supower)
|
||||
|
||||
%if ENVELOPE_ID > -1
|
||||
%if ENVELOPE_ID > -1 ; TODO: compressor also uses this, so should be compiled if either
|
||||
su_env_map:
|
||||
fld dword [edx+eax*4] ; x, where x is the parameter in the range 0-1
|
||||
fimul dword [c_24] ; 24*x
|
||||
|
||||
Reference in New Issue
Block a user