feat(vm): add frequency modulation for oscillators

Closes #105
This commit is contained in:
5684185+vsariola@users.noreply.github.com
2023-10-07 14:42:48 +03:00
parent 12dd3dada0
commit e5691d670a
10 changed files with 80 additions and 0 deletions

View File

@ -99,6 +99,11 @@ su_op_noise_mono:
; Stereo: push l r on stack, where l has opposite detune compared to r
;-------------------------------------------------------------------------------
{{.Func "su_op_oscillator" "Opcode"}}
{{- if .SupportsModulation "oscillator" "frequency"}}
push 0
pop {{.CX}} ; clear cx without affecting flags
xchg ecx, dword [{{.Modulation "oscillator" "frequency"}}]
{{- end}}
lodsb ; load the flags
{{- if .Library}}
mov {{.DI}}, [{{.Stack "SampleTable"}}]; we need to put this in a register, as the stereo & unisons screw the stack positions
@ -175,6 +180,11 @@ su_op_oscillat_normalize_note:
fmul dword [{{.Float 0.000092696138 | .Use}}] ; // st0 is now frequency
su_op_oscillat_normalized:
fadd dword [{{.WRK}}]
{{- if .SupportsModulation "oscillator" "frequency"}}
push {{.CX}}
fadd dword [{{.SP}}]
pop {{.CX}}
{{- end}}
{{- if .SupportsParamValue "oscillator" "type" .Sample}}
test al, byte 0x80
jz short su_op_oscillat_not_sample

View File

@ -107,9 +107,16 @@
{{- if .SupportsParamValueOtherThan "oscillator" "unison" 0}}
(local $unison i32) (local $WRK_stash i32) (local $detune_stash f32)
{{- end}}
{{- if .SupportsModulation "oscillator" "frequency"}}
(local $freqMod f32)
{{- end}}
{{- if .Stereo "oscillator"}}
(local $WRK_stereostash i32)
(local.set $WRK_stereostash (global.get $WRK))
{{- end}}
{{- if .SupportsModulation "oscillator" "frequency"}}
(local.set $freqMod (f32.load offset={{.InputNumber "oscillator" "frequency" | mul 4 | add 32}} (global.get $WRK)))
(f32.store offset={{.InputNumber "oscillator" "frequency" | mul 4 | add 32}} (global.get $WRK) (f32.const 0))
{{- end}}
(local.set $flags (call $scanValueByte))
(local.set $detune (call $inputSigned (i32.const {{.InputNumber "oscillator" "detune"}})))
@ -146,6 +153,9 @@
(f32.const 0.000092696138) ;; scaling constant to get middle-C to where it should be
(i32.and (local.get $flags) (i32.const 0x8))
))
{{- if .SupportsModulation "oscillator" "frequency"}}
(f32.add (local.get $freqMod))
{{- end}}
(f32.add (f32.load (global.get $WRK))) ;; add the current phase of the oscillator
)
(f32.floor (local.get $phase))

View File

@ -454,6 +454,7 @@ func (s *Interpreter) Render(buffer []float32, maxtime int) (samples int, time i
} else {
omega *= 0.000038 // pretty random scaling constant to get LFOs into reasonable range. Historical reasons, goes all the way back to 4klang
}
omega += float64(unit.ports[6]) // add frequency modulation
var amplitude float32
*statevar += float32(omega)
if flags&0x80 == 0x80 { // if this is a sample oscillator
@ -515,6 +516,7 @@ func (s *Interpreter) Render(buffer []float32, maxtime int) (samples int, time i
stack = append(stack, output)
detuneStereo = -detuneStereo
}
unit.ports[6] = 0
case opDelay:
pregain2 := params[0] * params[0]
damp := params[3]