mirror of
https://github.com/vsariola/sointu.git
synced 2025-06-04 01:28:45 -04:00
195 lines
7.9 KiB
NASM
195 lines
7.9 KiB
NASM
%define WRK ebp ; // alias for unit workspace
|
|
%define VAL esi ; // alias for unit values (transformed/untransformed)
|
|
%define COM ebx ; // alias for instrument opcodes
|
|
|
|
;===============================================================================
|
|
; Uninitialized data: The one and only synth object
|
|
;===============================================================================
|
|
SECT_BSS(susynth)
|
|
|
|
su_synth_obj resb su_synth.size
|
|
su_transformed_values resd 16
|
|
|
|
;===============================================================================
|
|
; The opcode table jump table. This is constructed to only include the opcodes
|
|
; that are used so that the jump table is as small as possible.
|
|
;===============================================================================
|
|
SECT_DATA(suoptabl)
|
|
|
|
su_synth_commands
|
|
dd OPCODES
|
|
|
|
;===============================================================================
|
|
; The number of transformed parameters each opcode takes
|
|
;===============================================================================
|
|
SECT_DATA(suparcnt)
|
|
|
|
su_opcode_numparams
|
|
db NUMPARAMS
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; Constants used by the common functions
|
|
;-------------------------------------------------------------------------------
|
|
SECT_DATA(suconst)
|
|
|
|
c_i128 dd 0.0078125
|
|
c_RandDiv dd 65536*32768
|
|
c_0_5 dd 0.5
|
|
EXPORT MANGLE_DATA(RandSeed)
|
|
dd 1
|
|
c_24 dd 24
|
|
c_i12 dd 0x3DAAAAAA
|
|
EXPORT MANGLE_DATA(LFO_NORMALIZE)
|
|
dd DEF_LFO_NORMALIZE
|
|
|
|
%ifdef INCLUDE_POLYPHONY
|
|
su_polyphony_bitmask dd POLYPHONY_BITMASK ; does the next voice reuse the current opcodes?
|
|
%endif
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; su_run_vm function: runs the entire virtual machine once, creating 1 sample
|
|
;-------------------------------------------------------------------------------
|
|
; Input: su_synth_obj.left : Set to 0 before calling
|
|
; su_synth_obj.right : Set to 0 before calling
|
|
; Output: su_synth_obj.left : left sample
|
|
; su_synth_obj.right : right sample
|
|
; Dirty: everything
|
|
;-------------------------------------------------------------------------------
|
|
SECT_TEXT(surunvm)
|
|
|
|
EXPORT MANGLE_FUNC(su_run_vm,0)
|
|
mov COM, MANGLE_DATA(su_commands) ; COM points to vm code
|
|
mov VAL, MANGLE_DATA(su_params) ; VAL points to unit params
|
|
; su_unit.size will be added back before WRK is used
|
|
mov WRK, su_synth_obj + su_synth.voices + su_voice.workspace - su_unit.size
|
|
push COM ; Stack: COM
|
|
push VAL ; Stack: VAL COM
|
|
push WRK ; Stack: WRK VAL COM
|
|
%if DELAY_ID > -1
|
|
mov ecx, MANGLE_DATA(su_delay_buffer) ; reset delaywrk to first delayline
|
|
mov dword [MANGLE_DATA(su_delay_buffer_ofs)], ecx
|
|
%endif
|
|
xor ecx, ecx ; voice = 0
|
|
push ecx ; Stack: voice WRK VAL COM
|
|
su_run_vm_loop: ; loop until all voices done
|
|
movzx eax, byte [COM] ; eax = command byte
|
|
inc COM ; move to next instruction
|
|
add WRK, su_unit.size ; move WRK to next unit
|
|
push eax
|
|
shr eax,1
|
|
mov al,byte [eax+su_opcode_numparams]
|
|
push eax
|
|
call su_transform_values
|
|
mov ecx, dword [esp+8]
|
|
pop eax
|
|
shr eax,1
|
|
call dword [eax*4+su_synth_commands] ; call the function corresponding to the instruction
|
|
cmp dword [esp],MAX_VOICES ; if (voice < MAX_VOICES)
|
|
jl su_run_vm_loop ; goto vm_loop
|
|
add esp, 16 ; Stack cleared
|
|
ret
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; FloatRandomNumber function
|
|
;-------------------------------------------------------------------------------
|
|
; Output: st0 : result
|
|
;-------------------------------------------------------------------------------
|
|
SECT_TEXT(surandom)
|
|
|
|
EXPORT MANGLE_FUNC(FloatRandomNumber,0)
|
|
push eax
|
|
imul eax,dword [MANGLE_DATA(RandSeed)],16007
|
|
mov dword [MANGLE_DATA(RandSeed)], eax
|
|
fild dword [MANGLE_DATA(RandSeed)]
|
|
fidiv dword [c_RandDiv]
|
|
pop eax
|
|
ret
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; su_transform_values function: transforms values and adds modulations
|
|
;-------------------------------------------------------------------------------
|
|
; Input: [esp] : number of bytes to transform
|
|
; VAL : pointer to byte stream
|
|
; Output: eax : last transformed byte (zero extended)
|
|
; edx : pointer to su_transformed_values, containing
|
|
; each byte transformed as x/128.0f+modulations
|
|
; VAL : updated to point after the transformed bytes
|
|
;-------------------------------------------------------------------------------
|
|
SECT_TEXT(sutransf)
|
|
|
|
su_transform_values:
|
|
push ecx
|
|
xor ecx, ecx
|
|
xor eax, eax
|
|
mov edx, su_transformed_values
|
|
su_transform_values_loop:
|
|
cmp ecx, dword [esp+8]
|
|
jge su_transform_values_out
|
|
lodsb
|
|
push eax
|
|
fild dword [esp]
|
|
fmul dword [c_i128]
|
|
fadd dword [WRK+su_unit.ports+ecx*4]
|
|
fstp dword [edx+ecx*4]
|
|
mov dword [WRK+su_unit.ports+ecx*4], 0
|
|
pop eax
|
|
inc ecx
|
|
jmp su_transform_values_loop
|
|
su_transform_values_out:
|
|
pop ecx
|
|
ret 4
|
|
|
|
%macro TRANSFORM_VALUES 1
|
|
push %1 %+ .params/4
|
|
call su_transform_values
|
|
%endmacro
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; su_env_map function: computes 2^(-24*x) of the envelope parameter
|
|
;-------------------------------------------------------------------------------
|
|
; Input: eax : envelope parameter (0 = attac, 1 = decay...)
|
|
; edx : pointer to su_transformed_values
|
|
; Output: st0 : 2^(-24*x), where x is the parameter in the range 0-1
|
|
;-------------------------------------------------------------------------------
|
|
SECT_TEXT(supower)
|
|
|
|
%if ENVELOPE_ID > -1
|
|
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
|
|
fchs ; -24*x
|
|
; flow into Power function, which outputs 2^(-24*x)
|
|
%endif
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; su_power function: computes 2^x
|
|
;-------------------------------------------------------------------------------
|
|
; Input: st0 : x
|
|
; Output: st0 : 2^x
|
|
;-------------------------------------------------------------------------------
|
|
EXPORT MANGLE_FUNC(su_power,0)
|
|
fld1 ; 1 x
|
|
fld st1 ; x 1 x
|
|
fprem ; mod(x,1) 1 x
|
|
f2xm1 ; 2^mod(x,1)-1 1 x
|
|
faddp st1,st0 ; 2^mod(x,1) x
|
|
fscale ; 2^mod(x,1)*2^trunc(x) x
|
|
; Equal to:
|
|
; 2^x x
|
|
fstp st1 ; 2^x
|
|
ret
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; Include the rest of the code
|
|
;-------------------------------------------------------------------------------
|
|
%include "opcodes/arithmetic.asm"
|
|
%include "opcodes/flowcontrol.asm"
|
|
%include "opcodes/sources.asm"
|
|
%include "opcodes/sinks.asm"
|
|
; warning: at the moment effects has to be assembled after
|
|
; sources, as sources.asm defines SU_USE_WAVESHAPER
|
|
; if needed.
|
|
%include "opcodes/effects.asm"
|
|
%include "player.asm"
|
|
%include "introspection.asm"
|