fix(vm/compiler): invert the logic of the release flag in the voices (closes #102)

This makes all envelopes released by default, instead of attacking. Add also test to demonstrate the buggy behaviour.
This commit is contained in:
5684185+vsariola@users.noreply.github.com
2023-09-02 20:54:37 +03:00
parent 20b0598a57
commit 1ac2ad3c75
13 changed files with 46 additions and 19 deletions

View File

@ -102,6 +102,7 @@ func (bridgesynth *BridgeSynth) Trigger(voice int, note byte) {
}
s.SynthWrk.Voices[voice] = C.Voice{}
s.SynthWrk.Voices[voice].Note = C.int(note)
s.SynthWrk.Voices[voice].Sustain = 1
}
// Release is part of C.Synths' implementation of sointu.Synth interface
@ -110,7 +111,7 @@ func (bridgesynth *BridgeSynth) Release(voice int) {
if voice < 0 || voice >= len(s.SynthWrk.Voices) {
return
}
s.SynthWrk.Voices[voice].Release = 1
s.SynthWrk.Voices[voice].Sustain = 0
}
// Update

View File

@ -9,7 +9,7 @@ typedef struct Unit {
typedef struct Voice {
int Note;
int Release;
int Sustain;
float Inputs[8];
float Reserved[6];
struct Unit Units[63];

View File

@ -137,7 +137,7 @@ su_calculate_voices_loop: ; do {
add edi, ebx
shl edi, 12 ; each unit = 64 bytes and there are 1<<MAX_UNITS_SHIFT units + small header
{{- .Prepare "su_synth_obj" | indent 4}}
inc dword [{{.Use "su_synth_obj"}} + su_synthworkspace.voices + su_voice.release + {{.DI}}] ; set the voice currently active to release; notice that it could increment any number of times
and dword [{{.Use "su_synth_obj"}} + su_synthworkspace.voices + su_voice.sustain + {{.DI}}], 0 ; set the voice currently active to release; notice that it could increment any number of times
cmp al, {{.Hold}} ; if cl < HLD (no new note triggered)
jl su_update_voices_nexttrack ; goto nexttrack
inc ecx ; curvoice++
@ -150,7 +150,8 @@ su_update_voices_skipreset:
shl ecx, 12 ; each unit = 64 bytes and there are 1<<6 units + small header
lea {{.DI}},[{{.Use "su_synth_obj"}} + su_synthworkspace.voices + {{.CX}}]
stosd ; save note
mov ecx, (su_voice.size - su_voice.release)/4
stosd ; save release
mov ecx, (su_voice.size - su_voice.inputs)/4
xor eax, eax
rep stosd ; clear the workspace of the new voice, retriggering oscillators
su_update_voices_nexttrack:
@ -180,11 +181,12 @@ su_update_voices_trackloop:
movzx eax, byte [{{.Use "su_patterns" .AX}} + {{.DX}}] ; ecx = note
cmp al, {{.Hold}} ; anything but hold causes action
je short su_update_voices_nexttrack
inc dword [{{.DI}}+su_voice.release] ; set the voice currently active to release; notice that it could increment any number of times
mov dword [{{.DI}}+su_voice.sustain], eax ; set the voice currently active to release
jb su_update_voices_nexttrack ; if cl < HLD (no new note triggered) goto nexttrack
su_update_voices_retrigger:
stosd ; save note
mov ecx, (su_voice.size - su_voice.release)/4 ; could be xor ecx, ecx; mov ch,...>>8, but will it actually be smaller after compression?
stosd ; save sustain
mov ecx, (su_voice.size - su_voice.inputs)/4 ; could be xor ecx, ecx; mov ch,...>>8, but will it actually be smaller after compression?
xor eax, eax
rep stosd ; clear the workspace of the new voice, retriggering oscillators
jmp short su_update_voices_skipadd

View File

@ -15,9 +15,9 @@
ret
su_op_envelope_mono:
{{- end}}
mov eax, dword [{{.INP}}-su_voice.inputs+su_voice.release] ; eax = su_instrument.release
test eax, eax ; if (eax == 0)
je su_op_envelope_process ; goto process
mov eax, dword [{{.INP}}-su_voice.inputs+su_voice.sustain] ; eax = su_instrument.sustain
test eax, eax ; if (eax != 0)
jne su_op_envelope_process ; goto process
mov al, {{.InputNumber "envelope" "release"}} ; [state]=RELEASE
mov dword [{{.WRK}}], eax ; note that mov al, XXX; mov ..., eax is less bytes than doing it directly
su_op_envelope_process:

View File

@ -12,7 +12,7 @@ endstruc
;-------------------------------------------------------------------------------
struc su_voice
.note resd 1
.release resd 1
.sustain resd 1
.inputs resd 8
.reserved resd 6 ; this is done to so the whole voice is 2^n long, see polyphonic player
.workspace resb 63 * su_unit.size

View File

@ -272,7 +272,7 @@
)
(i32.const 4096)
)
(i32.const 1)
(i32.const 0)
) ;; release the note
(if (i32.gt_u (local.get $note) (i32.const {{.Hold}}))(then
(local.set $di (i32.add
@ -290,6 +290,7 @@
))
(memory.fill (local.get $di) (i32.const 0) (i32.const 4096))
(i32.store (local.get $di) (local.get $note))
(i32.store offset=4 (local.get $di) (local.get $note))
(i32.store8 offset={{index .Labels "su_trackcurrentvoice"}} (local.get $tracksRemaining) (local.get $voiceNo))
))
))
@ -311,10 +312,11 @@
(i32.load8_u offset={{index .Labels "su_patterns"}})
(local.tee $note)
(if (i32.ne (i32.const {{.Hold}}))(then
(i32.store offset=4 (local.get $di) (i32.const 1)) ;; release the note
(i32.store offset=4 (local.get $di) (i32.const 0)) ;; release the note
(if (i32.gt_u (local.get $note) (i32.const {{.Hold}}))(then
(memory.fill (local.get $di) (i32.const 0) (i32.const 4096))
(i32.store (local.get $di) (local.get $note))
(i32.store offset=4 (local.get $di) (local.get $note))
))
))
(local.set $di (i32.add (local.get $di) (i32.const 4096)))

View File

@ -30,7 +30,7 @@
;; Stereo: push the envelope valeu on stack twice
;;-------------------------------------------------------------------------------
(func $su_op_envelope (param $stereo i32) (local $state i32) (local $level f32) (local $delta f32)
(if (i32.load offset=4 (global.get $voice)) (then ;; if voice.release > 0
(if (i32.eqz (i32.load offset=4 (global.get $voice))) (then ;; if voice.sustain == 0
(i32.store (global.get $WRK) (i32.const {{.InputNumber "envelope" "release"}})) ;; set envelope state to release
))
(local.set $state (i32.load (global.get $WRK)))