mirror of
https://github.com/vsariola/sointu.git
synced 2025-06-04 01:28:45 -04:00
Implement compressor.
This commit is contained in:
parent
71a5a18257
commit
fc0ad4c011
11
README.md
11
README.md
@ -57,8 +57,8 @@ New features since fork
|
|||||||
the first thing actually implemented was a set of regression tests to avoid
|
the first thing actually implemented was a set of regression tests to avoid
|
||||||
breaking everything beyond any hope of repair. Done, using CTest.
|
breaking everything beyond any hope of repair. Done, using CTest.
|
||||||
- **New units**. Bit-crusher, gain, inverse gain, clip, modulate bpm
|
- **New units**. Bit-crusher, gain, inverse gain, clip, modulate bpm
|
||||||
(proper triplets!)... As always, if you don't use them, they won't be
|
(proper triplets!), compressor (can be used for side-chaining)... As
|
||||||
compiled into the code.
|
always, if you don't use them, they won't be compiled into the code.
|
||||||
- **Pattern length does not have to be a power of 2**.
|
- **Pattern length does not have to be a power of 2**.
|
||||||
|
|
||||||
Future goals
|
Future goals
|
||||||
@ -68,8 +68,11 @@ Future goals
|
|||||||
on CMake and compiles on Windows. Cross-platform NASM/YASM macros have been
|
on CMake and compiles on Windows. Cross-platform NASM/YASM macros have been
|
||||||
drafted and remain to be tested. Once the project is more mature, I will
|
drafted and remain to be tested. Once the project is more mature, I will
|
||||||
try compiling on other platforms.
|
try compiling on other platforms.
|
||||||
- **Even more opcodes**. At least: compressor (with side-chaining). Maybe
|
- **Find a more general solution for skipping opcodes / early outs**. It's
|
||||||
also equalizer.
|
probably a new opcode "skip" that skips from the opcode to the next out in
|
||||||
|
case the signal entering skip and the signal leaving out are both close to
|
||||||
|
zero.
|
||||||
|
- **Even more opcodes**. Maybe an equalizer? DC-offset removal?
|
||||||
- **Support for 64-bit targets**.
|
- **Support for 64-bit targets**.
|
||||||
- **Browser-based GUI and MIDI instrument**. Modern browsers support WebMIDI,
|
- **Browser-based GUI and MIDI instrument**. Modern browsers support WebMIDI,
|
||||||
WebAudio and, most importantly, they are cross-platform and come installed
|
WebAudio and, most importantly, they are cross-platform and come installed
|
||||||
|
@ -419,3 +419,56 @@ SECT_DATA(suconst)
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%endif ; DELAY_ID > -1
|
%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
|
.buffer resd MAX_DELAY
|
||||||
.size
|
.size
|
||||||
endstruc
|
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)
|
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:
|
su_env_map:
|
||||||
fld dword [edx+eax*4] ; x, where x is the parameter in the range 0-1
|
fld dword [edx+eax*4] ; x, where x is the parameter in the range 0-1
|
||||||
fimul dword [c_24] ; 24*x
|
fimul dword [c_24] ; 24*x
|
||||||
|
@ -100,6 +100,9 @@ regression_test(test_clip_stereo CLIP)
|
|||||||
regression_test(test_crush "VCO_SINE;ENVELOPE;FOP_MULP;INVGAIN" CRUSH)
|
regression_test(test_crush "VCO_SINE;ENVELOPE;FOP_MULP;INVGAIN" CRUSH)
|
||||||
regression_test(test_crush_stereo CRUSH)
|
regression_test(test_crush_stereo CRUSH)
|
||||||
|
|
||||||
|
regression_test(test_compressor "" COMPRESSOR)
|
||||||
|
regression_test(test_compressor_stereo COMPRESSOR)
|
||||||
|
|
||||||
regression_test(test_filter_band "VCO_SINE;ENVELOPE;FOP_MULP")
|
regression_test(test_filter_band "VCO_SINE;ENVELOPE;FOP_MULP")
|
||||||
regression_test(test_filter_low "VCO_SINE;ENVELOPE;FOP_MULP")
|
regression_test(test_filter_low "VCO_SINE;ENVELOPE;FOP_MULP")
|
||||||
regression_test(test_filter_high "VCO_SINE;ENVELOPE;FOP_MULP")
|
regression_test(test_filter_high "VCO_SINE;ENVELOPE;FOP_MULP")
|
||||||
|
BIN
tests/expected_output/test_compressor.raw
Normal file
BIN
tests/expected_output/test_compressor.raw
Normal file
Binary file not shown.
BIN
tests/expected_output/test_compressor_stereo.raw
Normal file
BIN
tests/expected_output/test_compressor_stereo.raw
Normal file
Binary file not shown.
43
tests/test_compressor.asm
Normal file
43
tests/test_compressor.asm
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
%define BPM 100
|
||||||
|
%define USE_SECTIONS
|
||||||
|
|
||||||
|
%include "../src/sointu.inc"
|
||||||
|
|
||||||
|
SU_BEGIN_PATTERNS
|
||||||
|
PATTERN 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65,
|
||||||
|
PATTERN 76, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
SU_END_PATTERNS
|
||||||
|
|
||||||
|
SU_BEGIN_TRACKS
|
||||||
|
TRACK VOICES(1),0 ; a very silent voice
|
||||||
|
TRACK VOICES(1),1 ; a loud one
|
||||||
|
SU_END_TRACKS
|
||||||
|
|
||||||
|
SU_BEGIN_PATCH
|
||||||
|
SU_BEGIN_INSTRUMENT VOICES(1) ; Instrument0
|
||||||
|
SU_ENVELOPE MONO,ATTAC(64),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(16)
|
||||||
|
SU_ENVELOPE MONO,ATTAC(64),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(16)
|
||||||
|
SU_OSCILLAT MONO,TRANSPOSE(88),DETUNE(64),PHASE(0),COLOR(128),SHAPE(64),GAIN(128),FLAGS(TRISAW)
|
||||||
|
SU_OSCILLAT MONO,TRANSPOSE(88),DETUNE(64),PHASE(0),COLOR(128),SHAPE(64),GAIN(128),FLAGS(TRISAW)
|
||||||
|
SU_MULP STEREO
|
||||||
|
SU_SEND MONO,AMOUNT(128),GLOBALPORT(2,0,receive,left) + SEND_POP
|
||||||
|
SU_SEND MONO,AMOUNT(128),GLOBALPORT(2,0,receive,right) + SEND_POP
|
||||||
|
SU_END_INSTRUMENT
|
||||||
|
SU_BEGIN_INSTRUMENT VOICES(1) ; Instrument0
|
||||||
|
SU_ENVELOPE MONO,ATTAC(64),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(128)
|
||||||
|
SU_ENVELOPE MONO,ATTAC(64),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(128)
|
||||||
|
SU_OSCILLAT MONO,TRANSPOSE(88),DETUNE(64),PHASE(0),COLOR(128),SHAPE(64),GAIN(128),FLAGS(SINE)
|
||||||
|
SU_OSCILLAT MONO,TRANSPOSE(88),DETUNE(64),PHASE(0),COLOR(128),SHAPE(64),GAIN(128),FLAGS(SINE)
|
||||||
|
SU_MULP STEREO
|
||||||
|
SU_SEND MONO,AMOUNT(128),GLOBALPORT(2,0,receive,left) + SEND_POP
|
||||||
|
SU_SEND MONO,AMOUNT(128),GLOBALPORT(2,0,receive,right) + SEND_POP
|
||||||
|
SU_END_INSTRUMENT
|
||||||
|
SU_BEGIN_INSTRUMENT VOICES(1) ; Global compressor effect
|
||||||
|
SU_RECEIVE STEREO
|
||||||
|
SU_COMPRES MONO,ATTAC(32),RELEASE(80),THRESHOLD(32),RATIO(64)
|
||||||
|
SU_MULP MONO
|
||||||
|
SU_OUT STEREO, GAIN(128)
|
||||||
|
SU_END_INSTRUMENT
|
||||||
|
SU_END_PATCH
|
||||||
|
|
||||||
|
%include "../src/sointu.asm"
|
43
tests/test_compressor_stereo.asm
Normal file
43
tests/test_compressor_stereo.asm
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
%define BPM 100
|
||||||
|
%define USE_SECTIONS
|
||||||
|
|
||||||
|
%include "../src/sointu.inc"
|
||||||
|
|
||||||
|
SU_BEGIN_PATTERNS
|
||||||
|
PATTERN 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65,
|
||||||
|
PATTERN 76, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
SU_END_PATTERNS
|
||||||
|
|
||||||
|
SU_BEGIN_TRACKS
|
||||||
|
TRACK VOICES(1),0 ; a very silent voice
|
||||||
|
TRACK VOICES(1),1 ; a loud one
|
||||||
|
SU_END_TRACKS
|
||||||
|
|
||||||
|
SU_BEGIN_PATCH
|
||||||
|
SU_BEGIN_INSTRUMENT VOICES(1) ; Instrument0
|
||||||
|
SU_ENVELOPE MONO,ATTAC(64),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(16)
|
||||||
|
SU_ENVELOPE MONO,ATTAC(64),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(16)
|
||||||
|
SU_OSCILLAT MONO,TRANSPOSE(88),DETUNE(64),PHASE(0),COLOR(128),SHAPE(64),GAIN(128),FLAGS(TRISAW)
|
||||||
|
SU_OSCILLAT MONO,TRANSPOSE(88),DETUNE(64),PHASE(0),COLOR(128),SHAPE(64),GAIN(128),FLAGS(TRISAW)
|
||||||
|
SU_MULP STEREO
|
||||||
|
SU_SEND MONO,AMOUNT(128),GLOBALPORT(2,0,receive,left) + SEND_POP
|
||||||
|
SU_SEND MONO,AMOUNT(128),GLOBALPORT(2,0,receive,right) + SEND_POP
|
||||||
|
SU_END_INSTRUMENT
|
||||||
|
SU_BEGIN_INSTRUMENT VOICES(1) ; Instrument0
|
||||||
|
SU_ENVELOPE MONO,ATTAC(64),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(128)
|
||||||
|
SU_ENVELOPE MONO,ATTAC(64),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(128)
|
||||||
|
SU_OSCILLAT MONO,TRANSPOSE(88),DETUNE(64),PHASE(0),COLOR(128),SHAPE(64),GAIN(128),FLAGS(SINE)
|
||||||
|
SU_OSCILLAT MONO,TRANSPOSE(88),DETUNE(64),PHASE(0),COLOR(128),SHAPE(64),GAIN(128),FLAGS(SINE)
|
||||||
|
SU_MULP STEREO
|
||||||
|
SU_SEND MONO,AMOUNT(128),GLOBALPORT(2,0,receive,left) + SEND_POP
|
||||||
|
SU_SEND MONO,AMOUNT(128),GLOBALPORT(2,0,receive,right) + SEND_POP
|
||||||
|
SU_END_INSTRUMENT
|
||||||
|
SU_BEGIN_INSTRUMENT VOICES(1) ; Global compressor effect
|
||||||
|
SU_RECEIVE STEREO
|
||||||
|
SU_COMPRES STEREO,ATTAC(32),RELEASE(80),THRESHOLD(32),RATIO(64)
|
||||||
|
SU_MULP STEREO
|
||||||
|
SU_OUT STEREO, GAIN(128)
|
||||||
|
SU_END_INSTRUMENT
|
||||||
|
SU_END_PATCH
|
||||||
|
|
||||||
|
%include "../src/sointu.asm"
|
Loading…
x
Reference in New Issue
Block a user