feat: add the ability to use Sointu as a sync-tracker

There is a new "sync" opcode that saves the top-most signal every 256 samples to the new "syncBuffer" output. Additionally, you can enable saving the current fractional row as sync[0], avoiding calculating the beat in the shader, but also calculating the beat correctly when the beat is modulated.
This commit is contained in:
vsariola
2021-03-09 23:47:27 +02:00
parent a3bdf565fd
commit 99dbdfe223
30 changed files with 375 additions and 88 deletions

View File

@ -21,3 +21,24 @@
fstp dword [{{.WRK}}] ; save the remainder for future
ret
{{end}}
{{- if or .RowSync (.HasOp "sync")}}
;-------------------------------------------------------------------------------
; SYNC opcode: save the stack top to sync buffer
;-------------------------------------------------------------------------------
{{.Func "su_op_sync" "Opcode"}}
{{- if not .Library}}
; TODO: syncs are NOPs when compiling as library, should figure out a way to
; make them work when compiling to use the native track also
mov {{.AX}}, [{{.Stack "GlobalTick"}}]
test al, al
jne su_op_sync_skip
xchg {{.AX}}, [{{.Stack "SyncBufPtr"}}]
fst dword [{{.AX}}]
add {{.AX}}, 4
xchg {{.AX}}, [{{.Stack "SyncBufPtr"}}]
su_op_sync_skip:
{{- end}}
ret
{{end}}

View File

@ -14,6 +14,14 @@
;-------------------------------------------------------------------------------
{{.Func "su_run_vm"}}
{{- .PushRegs .CX "DelayWorkSpace" .DX "Synth" .COM "CommandStream" .WRK "Voice" .VAL "ValueStream" | indent 4}}
{{- if .RowSync}}
fild dword [{{.Stack "Sample"}}]
{{.Int .Song.SamplesPerRow | .Prepare | indent 8}}
fidiv dword [{{.Int .Song.SamplesPerRow | .Use}}]
fiadd dword [{{.Stack "Row"}}]
{{.Call "su_op_sync"}}
fstp st0
{{- end}}
su_run_vm_loop: ; loop until all voices done
movzx edi, byte [{{.COM}}] ; edi = command byte
inc {{.COM}} ; move to next instruction

View File

@ -14,12 +14,22 @@ su_synth_obj:
; the output buffer. Renders the compile time hard-coded song to the buffer.
; Stack: output_ptr
;-------------------------------------------------------------------------------
{{- if or .RowSync (.HasOp "sync")}}
{{.ExportFunc "su_render_song" "OutputBufPtr" "SyncBufPtr"}}
{{- else}}
{{.ExportFunc "su_render_song" "OutputBufPtr"}}
{{- end}}
{{- if .Amd64}}
{{- if eq .OS "windows"}}
{{- .PushRegs "rcx" "OutputBufPtr" "rdi" "NonVolatileRsi" "rsi" "NonVolatile" "rbx" "NonVolatileRbx" "rbp" "NonVolatileRbp" | indent 4}} ; rcx = ptr to buf. rdi,rsi,rbx,rbp nonvolatile
{{- if or .RowSync (.HasOp "sync")}}
{{- .PushRegs "rdx" "SyncBufPtr" | indent 4}}
{{- end}}
{{- else}} ; SystemV amd64 ABI, linux mac or hopefully something similar
{{- .PushRegs "rdi" "OutputBufPtr" "rbx" "NonVolatileRbx" "rbp" "NonVolatileRbp" | indent 4}}
{{- if or .RowSync (.HasOp "sync")}}
{{- .PushRegs "rsi" "SyncBufPtr" | indent 4}}
{{- end}}
{{- end}}
{{- else}}
{{- .PushRegs | indent 4}}
@ -68,6 +78,9 @@ su_render_sampleloop: ; loop through every sample in the row
{{$.Pop $.AX}}
{{- end}}
{{- if .Amd64}}
{{- if or .RowSync (.HasOp "sync")}}
{{.Pop .AX}} ; pop the sync buf ptr away
{{- end}}
{{- if eq .OS "windows"}}
; Windows64 ABI, rdi rsi rbx rbp non-volatile
{{- .PopRegs "rcx" "rdi" "rsi" "rbx" "rbp" | indent 4}}
@ -78,8 +91,12 @@ su_render_sampleloop: ; loop through every sample in the row
ret
{{- else}}
{{- .PopRegs | indent 4}}
{{- if or .RowSync (.HasOp "sync")}}
ret 8
{{- else}}
ret 4
{{- end}}
{{- end}}
;-------------------------------------------------------------------------------
; su_update_voices function: polyphonic & chord implementation

View File

@ -13,6 +13,15 @@
#define SU_LENGTH_IN_ROWS (SU_LENGTH_IN_PATTERNS*SU_PATTERN_SIZE)
#define SU_SAMPLES_PER_ROW (SU_SAMPLE_RATE*60/(SU_BPM*SU_ROWS_PER_BEAT))
{{- if or .RowSync (.HasOp "sync")}}
{{- if .RowSync}}
#define SU_NUMSYNCS {{add1 .Song.Patch.NumSyncs}}
{{- else}}
#define SU_NUMSYNCS {{.Song.Patch.NumSyncs}}
{{- end}}
#define SU_SYNCBUFFER_LENGTH ((SU_LENGTH_IN_SAMPLES+255)>>8)*SU_NUMSYNCS
{{- end}}
#include <stdint.h>
#if UINTPTR_MAX == 0xffffffff
#if defined(__clang__) || defined(__GNUC__)
@ -39,7 +48,12 @@ typedef float SUsample;
extern "C" {
#endif
{{- if or .RowSync (.HasOp "sync")}}
void SU_CALLCONV su_render_song(SUsample *buffer,float *syncBuffer);
#define SU_SYNC
{{- else}}
void SU_CALLCONV su_render_song(SUsample *buffer);
{{- end}}
{{- if gt (.SampleOffsets | len) 0}}
void SU_CALLCONV su_load_gmdls();
#define SU_LOAD_GMDLS