Implement compressor.

This commit is contained in:
Veikko Sariola
2020-05-17 16:37:08 +03:00
parent 71a5a18257
commit fc0ad4c011
9 changed files with 194 additions and 5 deletions

View File

@ -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

View File

@ -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

View File

@ -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