sointu/vm/compiler/templates/wasm/patch.wat
5684185+vsariola@users.noreply.github.com 01bf409929 refactor(vm): rename Commands/Values to Opcodes/Operands
The commands and values were not very good names to what the
byte sequences actually are: opcodes and their operands. In
many other places, we were already calling the byte in the Command
stream as Opcode, so a logical name for a sequence of these is
Opcodes. Values is such a generic name that it's not immediately
clear that this sequence is related to the opcodes. Operands is not
perfect but clearly suggests that this sequence is related to
the Opcodes.
2023-10-18 19:53:47 +03:00

145 lines
7.0 KiB
Plaintext

;;-------------------------------------------------------------------------------
;; su_run_vm function: runs the entire virtual machine once, creating 1 sample
;;-------------------------------------------------------------------------------
(func $su_run_vm (local $opcodeWithStereo i32) (local $opcode i32) (local $paramNum i32) (local $paramX4 i32) (local $WRKplusparam i32)
loop $vm_loop
(local.set $opcodeWithStereo (i32.load8_u (global.get $COM)))
(global.set $COM (i32.add (global.get $COM) (i32.const 1))) ;; move to next instruction
(global.set $WRK (i32.add (global.get $WRK) (i32.const 64))) ;; move WRK to next unit
(if (local.tee $opcode (i32.shr_u (local.get $opcodeWithStereo) (i32.const 1)))(then ;; if $opcode = $opcodeStereo >> 1; $opcode != 0 {
(local.set $paramNum (i32.const 0))
(local.set $paramX4 (i32.const 0))
loop $transform_operands_loop
{{- $addr := sub (index .Labels "su_vm_transformcounts") 1}}
(if (i32.lt_u (local.get $paramNum) (i32.load8_u offset={{$addr}} (local.get $opcode)))(then ;;(i32.ge (local.get $paramNum) (i32.load8_u (local.get $opcode))) /*TODO: offset to transformvalues
(local.set $WRKplusparam (i32.add (global.get $WRK) (local.get $paramX4)))
(f32.store offset={{index .Labels "su_transformedoperands"}}
(local.get $paramX4)
(f32.add
(f32.mul
(f32.convert_i32_u (call $scanOperand))
(f32.const 0.0078125) ;; scale from 0-128 to 0.0 - 1.0
)
(f32.load offset=32 (local.get $WRKplusparam)) ;; add modulation
)
)
(f32.store offset=32 (local.get $WRKplusparam) (f32.const 0.0)) ;; clear modulations
(local.set $paramNum (i32.add (local.get $paramNum) (i32.const 1))) ;; $paramNum++
(local.set $paramX4 (i32.add (local.get $paramX4) (i32.const 4)))
br $transform_operands_loop ;; continue looping
))
;; paramNum was >= the number of parameters to transform, exiting loop
end
(call_indirect (type $opcode_func_signature) (i32.and (local.get $opcodeWithStereo) (i32.const 1)) (local.get $opcode))
)(else ;; advance to next voice
(global.set $voice (i32.add (global.get $voice) (i32.const 4096))) ;; advance to next voice
(global.set $WRK (global.get $voice)) ;; set WRK point to beginning of voice
(global.set $voicesRemain (i32.sub (global.get $voicesRemain) (i32.const 1)))
{{- if .SupportsPolyphony}}
(if (i32.and (i32.shr_u (i32.const {{.PolyphonyBitmask | printf "%v"}}) (global.get $voicesRemain)) (i32.const 1))(then
(global.set $VAL (global.get $VAL_instr_start))
(global.set $COM (global.get $COM_instr_start))
))
(global.set $VAL_instr_start (global.get $VAL))
(global.set $COM_instr_start (global.get $COM))
{{- end}}
(br_if 2 (i32.eqz (global.get $voicesRemain))) ;; if no more voices remain, return from function
))
br $vm_loop
end
)
{{- template "arithmetic.wat" .}}
{{- template "effects.wat" .}}
{{- template "sources.wat" .}}
{{- template "sinks.wat" .}}
;;-------------------------------------------------------------------------------
;; $input returns the float value of a transformed to 0.0 - 1.0f range.
;; The transformed values start at 512 (TODO: change magic constants somehow)
;;-------------------------------------------------------------------------------
(func $input (param $inputNumber i32) (result f32)
(f32.load offset={{index .Labels "su_transformedoperands"}} (i32.mul (local.get $inputNumber) (i32.const 4)))
)
;;-------------------------------------------------------------------------------
;; $inputSigned returns the float value of a transformed to -1.0 - 1.0f range.
;;-------------------------------------------------------------------------------
(func $inputSigned (param $inputNumber i32) (result f32)
(f32.sub (f32.mul (call $input (local.get $inputNumber)) (f32.const 2)) (f32.const 1))
)
;;-------------------------------------------------------------------------------
;; $nonLinearMap: x -> 2^(-24*input[x])
;;-------------------------------------------------------------------------------
(func $nonLinearMap (param $value i32) (result f32)
(call $pow2
(f32.mul
(f32.const -24)
(call $input (local.get $value))
)
)
)
;;-------------------------------------------------------------------------------
;; $pow2: x -> 2^x
;;-------------------------------------------------------------------------------
(func $pow2 (param $value f32) (result f32)
(call $pow (f32.const 2) (local.get $value))
)
;;-------------------------------------------------------------------------------
;; Waveshaper(x,a): "distorts" signal x by amount a
;; Returns x*a/(1-a+(2*a-1)*abs(x))
;;-------------------------------------------------------------------------------
(func $waveshaper (param $signal f32) (param $amount f32) (result f32)
(local.set $signal (call $clip (local.get $signal)))
(f32.mul
(local.get $signal)
(f32.div
(local.get $amount)
(f32.add
(f32.const 1)
(f32.sub
(f32.mul
(f32.sub
(f32.add (local.get $amount) (local.get $amount))
(f32.const 1)
)
(f32.abs (local.get $signal))
)
(local.get $amount)
)
)
)
)
)
;;-------------------------------------------------------------------------------
;; Clip(a : f32) returns min(max(a,-1),1)
;;-------------------------------------------------------------------------------
(func $clip (param $value f32) (result f32)
(f32.min (f32.max (local.get $value) (f32.const -1.0)) (f32.const 1.0))
)
(func $stereoHelper (param $stereo i32) (param $tableIndex i32)
(if (local.get $stereo)(then
(call $pop)
(global.set $WRK (i32.add (global.get $WRK) (i32.const 16)))
(call_indirect (type $opcode_func_signature) (i32.const 0) (local.get $tableIndex))
(global.set $WRK (i32.sub (global.get $WRK) (i32.const 16)))
(call $push)
))
)
;;-------------------------------------------------------------------------------
;; 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.
;;-------------------------------------------------------------------------------
(table {{.Instructions | len | add 1}} funcref)
(elem (i32.const 1) ;; start the indices at 1, as 0 is reserved for advance
{{- range .Instructions}}
$su_op_{{.}}
{{- end}}
)