This commit is contained in:
2024-06-04 21:06:35 +03:00
parent 878e57b057
commit 342f91c6ca
11 changed files with 547 additions and 267 deletions

View File

@ -1,6 +1,6 @@
%define SU_LENGTH_IN_SAMPLES 1550944
%define SU_LENGTH_IN_SAMPLES 2703680
%define SU_SAMPLE_RATE 44100
%define SU_BPM 116.
%define SU_BPM 137.
;-------------------------------------------------------------------------------
; unit struct
@ -61,7 +61,7 @@ endstruc
section .synth_object bss align=256
su_synth_obj:
resb su_synthworkspace.size
resb 20*su_delayline_wrk.size
resb 40*su_delayline_wrk.size
;-------------------------------------------------------------------------------
@ -76,7 +76,7 @@ global _su_render_song@4
_su_render_song@4:
pushad ; Stack: edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
xor eax, eax
push 16 ; Stack: VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
push 20752 ; Stack: VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
push 1 ; Stack: RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
push eax ; Stack: GlobalTick, RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
su_render_rowloop: ; loop through every row in the song
@ -85,8 +85,8 @@ su_render_rowloop: ; loop through every row in the song
xor eax, eax ; ecx is the current sample within row
su_render_sampleloop: ; loop through every sample in the row
push eax ; Stack: Sample, Row, GlobalTick, RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
push 8 ; Stack: PolyphonyBitmask, Sample, Row, GlobalTick, RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr ; does the next voice reuse the current opcodes?
push 8 ; Stack: VoicesRemain, PolyphonyBitmask, Sample, Row, GlobalTick, RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
push 4572 ; Stack: PolyphonyBitmask, Sample, Row, GlobalTick, RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr ; does the next voice reuse the current opcodes?
push 17 ; Stack: VoicesRemain, PolyphonyBitmask, Sample, Row, GlobalTick, RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
mov edx, dword su_synth_obj ; edx points to the synth object
mov ebx, dword su_patch_opcodes ; COM points to vm code
mov esi, dword su_patch_operands ; VAL points to unit params
@ -114,11 +114,11 @@ su_render_sampleloop: ; loop through every sample in the row
pop eax ; eax = Sample, Stack: Row, GlobalTick, RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
inc dword [esp + 4] ; increment global time, used by delays
inc eax
cmp eax, 5702
cmp eax, 4828
jl su_render_sampleloop
pop eax ; eax = Row, Stack: GlobalTick, RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr ; Stack: pushad ptr
inc eax
cmp eax, 272
cmp eax, 560
jl su_render_rowloop
; rewind the stack the entropy of multiple pop eax is probably lower than add
pop eax ; eax = GlobalTick, Stack: RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
@ -183,9 +183,9 @@ su_update_voices_skipreset:
su_update_voices_nexttrack:
pop ebx ; ebx=first voice of next instrument, Stack: ptrnrow
pop edx ; edx=patrnrow
add esi, 17
add esi, 35
inc ebp
cmp ebp,su_synth_obj + 6
cmp ebp,su_synth_obj + 12
jl su_update_voices_trackloop
ret
@ -254,6 +254,16 @@ su_op_advance_finish:
popad ; Popped: eax, ecx = DelayWorkSpace, edx = Synth, ebx = OpcodeStream, esp, ebp = Voice, esi = OperandStream, edi. Stack: retaddr_su_run_vm, VoicesRemain, PolyphonyBitmask, Sample, Row, GlobalTick, RandSeed, VoiceTrackBitmask, edi, esi, ebp, esp, ebx, edx, ecx, eax, retaddr_su_render_song, OutputBufPtr
ret
;-------------------------------------------------------------------------------
; ADD opcode: add the two top most signals on the stack
;-------------------------------------------------------------------------------
; Mono: a b -> a+b b
;-------------------------------------------------------------------------------
section .su_op_add code align=1
su_op_add:
fadd st1
ret
;-------------------------------------------------------------------------------
; ADDP opcode: add the two top most signals on the stack and pop
;-------------------------------------------------------------------------------
; Mono: a b -> a+b
@ -264,6 +274,22 @@ su_op_addp:
faddp st1, st0
ret
;-------------------------------------------------------------------------------
; LOADNOTE opcode: load the current note, scaled to [-1,1]
;-------------------------------------------------------------------------------
; Mono: (empty) -> n, where n is the note
;-------------------------------------------------------------------------------
section .su_op_loadnote code align=1
su_op_loadnote:
fild dword [edx-su_voice.inputs+su_voice.note]
fmul dword [FCONST_0_00781250] ; s=n/128.0
fsub dword [FCONST_0_500000] ; s-.5
fadd st0, st0 ; 2*s-1
ret
;-------------------------------------------------------------------------------
; MULP opcode: multiply the two top most signals on the stack and pop
;-------------------------------------------------------------------------------
@ -425,47 +451,6 @@ su_op_delay_loop:
fst dword [ecx+su_delayline_wrk.dcout] ; o'=s+c*o-i
ret
;-------------------------------------------------------------------------------
; COMPRES opcode: push compressor gain to stack
;-------------------------------------------------------------------------------
; Mono: push g on stack, where g is a suitable gain for the signal
; you can either MULP to compress the signal or SEND it to a GAIN
; somewhere else for compressor side-chaining.
; Stereo: push g g on stack, where g is calculated using l^2 + r^2
;-------------------------------------------------------------------------------
section .su_op_compressor code align=1
su_op_compressor:
fld st0 ; x x
fmul st0, st0 ; x^2 x
fld dword [ebp] ; l x^2 x
fucomi st0, st1
setnb al ; if (st0 >= st1) al = 1; else al = 0;
fsubp st1, st0 ; x^2-l x
call su_nonlinear_map ; c x^2-l x, c is either attack or release parameter mapped in a nonlinear way
fmulp st1, st0 ; c*(x^2-l) x
fadd dword [ebp] ; l+c*(x^2-l) x // we could've kept level in the stack and save a few bytes, but su_env_map uses 3 stack (c + 2 temp), so the stack was getting quite big.
; TODO: make this denormalization optional, if the user wants to save some space
fadd dword [FCONST_0_500000] ; add and sub small offset to prevent denormalization. WARNING: this is highly important, as the damp filters might denormalize and give 100x CPU penalty
fsub dword [FCONST_0_500000] ; See for example: https://stackoverflow.com/questions/36781881/why-denormalized-floats-are-so-much-slower-than-other-floats-from-hardware-arch
fst dword [ebp] ; l'=l+c*(x^2-l), l' x
fld dword [edx + 12] ; t l' x
fmul st0, st0 ; t*t l' x
fxch ; l' t*t x
fucomi st0, st1 ; if l' < t*t
fcmovb st0, st1 ; l'=t*t
fdivp st1, st0 ; t*t/l' x
fld dword [edx + 16] ; r t*t/l' x
fmul dword [FCONST_0_500000] ; p=r/2 t*t/l' x
fxch ; t*t/l' p x
fyl2x ; p*log2(t*t/l') x
call su_power ; 2^(p*log2(t*t/l')) x
; 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
fdiv dword [edx + 8]; this used to be pregain but that ran into problems with getting back up to 0 dB so postgain should be better at that
ret
;-------------------------------------------------------------------------------
@ -665,6 +650,7 @@ su_op_oscillat_normalized:
test al, byte 0x80
jz short su_op_oscillat_not_sample
fst dword [ebp] ; for samples, we store the phase without mod(p,1)
fadd dword [edx + 8]
call su_oscillat_sample
jmp su_op_oscillat_shaping ; skip the rest to avoid color phase normalization and colorloading
su_op_oscillat_not_sample:
@ -674,6 +660,12 @@ su_op_oscillat_not_sample:
fprem ; we actually computed mod(p+1,1) instead of mod(p,1) as the fprem takes mod
fstp st1 ; towards zero
fst dword [ebp] ; store back the updated phase
fadd dword [edx + 8]
fld1 ; this is a bit stupid, but we need to take mod(x,1) again after phase modulations
fadd st1, st0 ; as the actual oscillator functions expect x in [0,1]
fxch
fprem
fstp st1
fld dword [edx + 12] ; // c p
; every oscillator test included if needed
test al, byte 0x40
@ -921,7 +913,8 @@ su_vm_jumptable:
dd su_op_send
dd su_op_distort
dd su_op_delay
dd su_op_compressor
dd su_op_add
dd su_op_loadnote
dd su_op_in
dd su_op_out
@ -941,7 +934,8 @@ su_vm_transformcounts:
db 1
db 1
db 4
db 5
db 0
db 0
db 0
db 1
@ -956,25 +950,90 @@ su_patterns:
db 48,1,1,1,48,1,1,1,48,1,1,1,48,1,48,1
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
db 1,1,1,1,58,1,1,1,1,1,1,1,58,1,1,1
db 0,0,0,0,72,1,1,1,1,1,1,1,72,1,1,1
db 1,1,1,1,72,1,1,1,1,1,1,1,72,1,1,1
db 74,1,0,0,74,1,77,70,1,0,70,1,0,70,1,0
db 74,1,0,0,74,1,77,70,1,0,70,1,0,0,72,1
db 74,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 60,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
db 1,1,53,1,1,1,53,1,1,1,53,1,1,1,53,1
db 0,38,50,38,0,38,50,38,0,38,50,38,0,38,50,50
db 0,46,58,46,0,46,58,46,0,46,58,46,0,46,58,58
db 0,48,60,48,0,48,60,48,0,48,60,48,0,48,60,60
db 0,41,53,41,0,41,53,41,0,41,53,41,0,41,53,53
db 0,48,60,48,0,48,60,48,0,48,60,55,0,53,52,53
db 59,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0
db 0,0,53,1,1,1,53,1,1,1,53,1,1,1,53,53
db 1,1,53,1,1,1,53,1,1,1,53,1,1,1,53,53
db 1,1,53,1,1,1,53,1,1,1,53,1,1,1,53,1
db 1,1,53,1,1,1,53,1,1,1,53,1,1,1,53,52
db 0,0,0,0,0,0,0,0,57,57,57,57,54,54,54,54
db 0,0,0,0,0,0,0,0,0,0,57,57,1,52,52,1
db 50,0,0,50,0,50,50,1,50,1,0,50,0,50,0,50
db 0,0,0,50,0,50,50,1,50,1,0,50,0,50,50,50
db 0,46,46,46,0,46,46,1,46,1,0,46,0,46,46,46
db 0,0,46,46,0,46,46,1,46,1,0,46,0,46,46,46
db 0,0,0,48,0,48,48,1,48,1,0,48,0,48,48,48
db 41,1,0,41,0,41,41,1,41,1,0,41,0,41,41,41
db 0,46,74,74,0,46,72,1,74,1,0,74,0,74,74,74
db 76,76,76,76,0,48,70,1,76,1,0,48,0,48,48,79
db 0,0,50,50,0,50,50,1,50,1,0,50,0,50,50,50
db 48,1,0,48,0,48,48,1,48,1,0,48,0,48,48,48
db 74,0,0,74,0,74,72,1,74,1,0,74,0,74,0,72
db 0,0,0,74,0,74,72,1,74,1,0,74,0,74,74,72
db 0,74,74,74,0,74,72,1,74,1,0,74,0,74,74,72
db 0,0,74,74,0,74,72,1,74,1,0,74,0,74,74,76
db 0,0,0,76,0,76,76,1,76,1,0,76,0,76,76,76
db 77,1,0,77,0,77,77,1,77,1,0,77,0,77,77,67
db 0,74,70,46,0,74,69,1,70,1,0,70,0,70,70,70
db 72,72,72,48,0,72,74,1,72,1,0,76,0,76,74,48
db 0,0,74,74,0,74,72,1,74,1,0,74,0,74,74,72
db 76,1,0,76,0,76,76,1,76,1,0,76,0,76,76,76
db 77,0,0,77,0,77,76,1,77,1,0,77,0,77,0,76
db 0,0,0,77,0,77,76,1,77,1,0,77,0,77,77,76
db 0,77,77,77,0,77,76,1,77,1,0,77,0,77,77,76
db 0,0,77,77,0,77,76,1,77,1,0,77,0,77,77,79
db 0,0,0,79,0,79,79,1,79,1,0,79,0,79,79,79
db 81,1,0,81,0,81,81,1,81,1,0,81,0,81,81,72
db 0,70,46,70,0,70,46,1,46,1,0,46,0,46,46,46
db 48,48,48,72,0,76,48,1,48,1,0,72,0,72,77,76
db 0,0,77,77,0,77,76,1,77,1,0,77,0,77,77,76
db 79,1,0,79,0,79,79,1,79,1,0,79,0,79,79,79
db 0,0,0,0,0,0,0,0,77,0,0,0,64,0,0,0
db 62,0,0,0,0,0,69,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,69,0,0,0,0,0,0,0
db 62,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,64,0,0,0,65,0,0,0
db 79,0,0,0,0,0,0,0,0,0,0,0,0,0,81,0
db 0,0,0,0,0,0,0,0,0,0,60,0,0,0,0,0
db 74,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 65,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
db 79,1,1,1,1,1,1,1,0,0,0,0,0,0,84,0
db 0,0,0,0,0,0,0,0,70,0,0,0,69,0,0,0
db 74,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,65,0,0,0,76,0,0,0
db 74,0,0,0,0,0,81,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,81,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,76,0,0,0,77,0,0,0
db 67,0,0,0,0,0,0,0,0,0,0,0,0,0,69,0
db 0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0
db 62,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 77,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
db 67,1,1,1,1,1,1,1,0,0,0,0,0,0,72,0
db 0,0,0,0,0,0,0,0,82,0,0,0,81,0,0,0
;-------------------------------------------------------------------------------
; Tracks
;-------------------------------------------------------------------------------
section .su_tracks data align=1
su_tracks:
db 0,0,0,0,1,2,1,2,1,2,1,2,1,2,1,2,3
db 0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,3
db 0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,3
db 6,7,6,7,6,7,6,7,6,7,6,7,6,7,6,7,8
db 0,0,0,0,9,3,3,3,9,3,3,3,3,3,3,3,3
db 0,0,0,0,10,11,10,10,10,10,10,10,10,10,10,10,3
db 0,0,0,0,0,0,0,0,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,3,3,3
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3
db 5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,3,3,3
db 0,0,0,0,0,0,0,0,7,7,8,8,9,10,8,9,7,7,8,8,9,10,8,11,7,7,8,8,9,10,8,9,0,0,0
db 0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0
db 13,14,14,14,14,14,14,14,14,14,14,15,15,14,15,15,16,15,15,15,16,15,15,15,16,15,15,15,16,15,15,15,3,3,3
db 0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 19,20,21,22,23,24,25,26,19,27,21,22,28,24,25,26,19,27,21,22,28,24,25,26,19,27,21,22,28,24,25,26,0,0,0
db 29,30,31,32,33,34,35,36,29,37,31,32,38,34,35,36,29,37,31,32,38,34,35,36,29,37,31,32,38,34,35,36,0,0,0
db 39,40,41,42,43,44,45,46,39,47,41,42,48,44,45,46,39,47,41,42,48,44,45,46,39,47,41,42,48,44,45,46,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,49,50,51,52,53,54,55,56,49,50,51,57,53,58,59,60,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,61,62,63,60,64,65,66,67,61,62,63,68,64,69,70,52,0,0,0,0
;-------------------------------------------------------------------------------
; Sample offsets
;-------------------------------------------------------------------------------
@ -992,13 +1051,19 @@ su_sample_offsets:
dd 367477
dw 1343
dw 1
dd 1543725
dw 831
dw 104
dd 557335
dw 2374
dw 821
;-------------------------------------------------------------------------------
; Delay times
;-------------------------------------------------------------------------------
section .su_delay_times data align=1
su_delay_times:
dw 1395,350,1744,1744,1116,1188,1276,1356,1422,1492,1556,1618,1140,1212,1300,1380,1446,1516,1580,1642
dw 1395,350,1744,1744,69,12550,24402,21265,32419,1116,1188,1276,1356,1422,1492,1556,1618,1140,1212,1300,1380,1446,1516,1580,1642
;-------------------------------------------------------------------------------
@ -1006,14 +1071,14 @@ su_delay_times:
;-------------------------------------------------------------------------------
section .su_patch_opcodes data align=1
su_patch_opcodes:
db 2,4,6,2,8,10,10,6,12,10,10,10,10,14,17,2,2,6,18,0,2,4,20,6,2,8,6,10,10,12,14,17,2,18,2,18,0,2,22,8,6,2,22,8,6,12,2,4,6,12,10,20,14,17,0,2,4,4,12,6,10,10,20,2,8,6,10,12,24,6,20,14,17,2,18,0,3,3,7,5,7,15,17,0,3,5,7,11,11,15,17,0,27,23,29,0
db 2,4,6,2,8,10,10,6,12,10,10,14,17,2,18,0,2,4,20,6,2,8,6,10,10,12,14,17,2,18,2,18,0,2,22,8,6,2,22,8,6,12,2,4,6,12,10,20,14,17,0,2,18,18,2,4,4,6,4,12,6,10,10,14,17,0,3,3,7,5,7,15,17,0,3,5,7,11,11,15,17,0,2,4,6,14,17,2,18,0,2,4,4,12,8,12,6,2,4,4,12,8,12,6,22,15,11,11,17,0,2,2,6,4,24,4,12,4,12,6,10,10,14,23,17,26,18,0,29,23,31,0
;-------------------------------------------------------------------------------
; The parameters / inputs to each opcode
;-------------------------------------------------------------------------------
section .su_patch_operands data align=1
su_patch_operands:
db 18,65,0,0,60,94,57,0,128,63,79,66,0,43,0,0,128,67,81,87,35,68,100,62,64,9,75,68,53,128,80,10,85,16,10,49,16,64,57,0,62,128,0,0,128,39,61,34,0,128,0,40,0,0,76,0,0,96,86,116,0,0,114,37,130,95,0,68,0,0,83,3,107,57,67,68,128,78,64,71,84,10,47,54,0,0,128,19,136,0,54,68,70,0,128,26,255,255,0,53,0,0,128,64,128,0,0,0,3,97,0,0,54,0,0,128,64,6,0,0,2,3,79,128,0,62,0,0,42,64,64,0,1,64,125,128,39,76,68,114,70,50,12,46,74,36,39,77,40,48,0,84,50,128,35,71,64,0,64,64,64,16,3,128,64,94,128,64,83,32,53,0,0,64,52,59,91,102,72,37,65,87,47,102,59,64,98,23,0,72,47,45,76,128,104,0,8,90,0,0,128,21,78,0,85,64,77,64,0,2,64,111,128,73,49,78,50,60,0,0,128,82,64,0,3,64,127,128,78,128,76,109,128,64,57,84,0,2,40,128,120,42,4,15,128
db 0,70,0,0,76,88,69,0,128,63,79,66,0,43,0,0,128,43,79,84,82,68,100,62,64,12,69,68,12,48,16,64,50,0,62,76,0,0,128,46,40,0,0,76,0,0,96,86,116,0,0,114,37,130,95,0,68,0,0,83,3,107,57,67,68,128,78,64,64,42,26,47,54,0,0,128,19,136,0,54,68,70,0,128,26,255,255,0,53,0,0,128,64,128,0,0,0,3,97,0,0,54,0,0,128,64,6,0,0,2,3,79,128,0,62,0,0,42,64,64,0,1,64,125,128,39,76,68,114,60,39,19,39,73,62,74,128,94,176,0,47,91,0,42,65,86,71,83,88,66,91,49,100,89,34,64,74,64,42,70,17,17,64,78,13,128,88,128,66,22,46,68,10,116,16,64,40,0,8,90,0,0,128,21,78,0,85,64,77,54,0,2,87,111,128,64,128,97,50,60,0,0,128,82,64,0,3,64,127,128,78,128,76,109,128,64,67,128,11,1,74,0,0,64,64,67,0,4,64,99,129,64,89,43,1,78,36,74,64,83,40,0,40,0,63,51,54,64,94,0,128,64,128,35,76,28,52,128,64,102,35,114,67,20,0,48,64,64,64,46,78,128,64,128,35,76,99,54,128,64,128,35,128,80,128,0,0,0,4,1,65,122,128,72,103,128,64,20,6,40,102,47,78,68,0,84,25,84,127,76,52,128,91,48,128,67,88,73,0,57,37,56,35,55,64,0,5,58,128,129,30,128,80,53,128,24,61,69,103,84,12,5,3,27,14,82,200,0,2,61,113,122,97,9,15,128
;-------------------------------------------------------------------------------
; Constants