diff --git a/README.md b/README.md index 644186c..1952d58 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,11 @@ New features since fork signals in an arbitrary way. Actually, 4klang could already do this but in a very awkward way: it had FLD (load value) opcode that could be modulated; FLD 0 with modulation basically achieved what RECEIVE does, except that - RECEIVE can also handle stereo signals. + RECEIVE can also handle stereo signals. Additionally, we have OUTAUX, AUX + and IN opcodes, which route the signals through global main or aux ports, + more closer to how 4klang does. But this time we have 8 mono ports / 4 + stereo ports, so even this method of routing is unlikely to run out of ports + in small intros. - **Pattern length does not have to be a power of 2**. - **Sample-based oscillators, with samples imported from gm.dls**. Reading gm.dls is obviously Windows only, but the sample mechanism can be used also diff --git a/src/opcodes/sinks.asm b/src/opcodes/sinks.asm index 7b4d780..37c578a 100644 --- a/src/opcodes/sinks.asm +++ b/src/opcodes/sinks.asm @@ -1,8 +1,8 @@ ;------------------------------------------------------------------------------- ; OUT opcode: outputs and pops the signal ;------------------------------------------------------------------------------- -; Mono: add ST0 to global left port -; Stereo: also add ST1 to global right port +; Mono: add ST0 to main left port +; Stereo: also add ST1 to main right port ;------------------------------------------------------------------------------- %if OUT_ID > -1 @@ -23,6 +23,61 @@ EXPORT MANGLE_FUNC(su_op_out,0) ; l r %endif ; SU_OUT_ID > -1 +;------------------------------------------------------------------------------- +; OUTAUX opcode: outputs to main and aux1 outputs and pops the signal +;------------------------------------------------------------------------------- +; Mono: add outgain*ST0 to main left port and auxgain*ST0 to aux1 left +; Stereo: also add outgain*ST1 to main right port and auxgain*ST1 to aux1 right +;------------------------------------------------------------------------------- +%if OUTAUX_ID > -1 + +SECT_TEXT(suoutaux) + +EXPORT MANGLE_FUNC(su_op_outaux,0) ; l r + mov _AX, [_SP + su_stack.synth] + %ifdef INCLUDE_STEREO_OUTAUX + jnc su_op_outaux_mono + call su_op_outaux_mono + add _AX, 4 + su_op_outaux_mono: + %endif + fld st0 ; l l + fmul dword [INP + su_outaux_ports.outgain] ; g*l + fadd dword [_AX + su_synth.left] ; g*l+o + fstp dword [_AX + su_synth.left] ; o'=g*l+o + fmul dword [INP + su_outaux_ports.auxgain] ; h*l + fadd dword [_AX + su_synth.aux] ; h*l+a + fstp dword [_AX + su_synth.aux] ; a'=h*l+a + ret + +%endif ; SU_OUTAUX_ID > -1 + +;------------------------------------------------------------------------------- +; AUX opcode: outputs the signal to aux (or main) port and pops the signal +;------------------------------------------------------------------------------- +; Mono: add gain*ST0 to left port +; Stereo: also add gain*ST1 to right port +;------------------------------------------------------------------------------- +%if AUX_ID > -1 + +SECT_TEXT(suopaux) + +EXPORT MANGLE_FUNC(su_op_aux,0) ; l r + lodsb + mov _DI, [_SP + su_stack.synth] + %ifdef INCLUDE_STEREO_AUX + jnc su_op_aux_mono + call su_op_aux_mono + add _DI, 4 + su_op_aux_mono: + %endif + fmul dword [INP + su_aux_ports.gain] ; g*l + fadd dword [_DI + su_synth.left + _AX*4] ; g*l+o + fstp dword [_DI + su_synth.left + _AX*4] ; o'=g*l+o + ret + +%endif ; SU_AUX_ID > -1 + ;------------------------------------------------------------------------------- ; SEND opcode: adds the signal to a port ;------------------------------------------------------------------------------- diff --git a/src/opcodes/sinks.inc b/src/opcodes/sinks.inc index 4d2bbea..4719c56 100644 --- a/src/opcodes/sinks.inc +++ b/src/opcodes/sinks.inc @@ -27,6 +27,66 @@ struc su_out_ports .params endstruc +;------------------------------------------------------------------------------- +; OUTAUX structs +;------------------------------------------------------------------------------- +%assign OUTAUX_ID -1 +%macro USE_OUTAUX 0 + %if OUTAUX_ID == -1 + %assign OUTAUX_ID CUR_ID + %assign CUR_ID CUR_ID + 2 + %xdefine OPCODES OPCODES MANGLE_FUNC(su_op_outaux,0), + %xdefine NUMPARAMS NUMPARAMS 2, + %endif +%endmacro + +%macro SU_OUTAUX 3 + db %2 + db %3 + USE_OUTAUX + %xdefine CMDS CMDS OUTAUX_ID+%1, + %if %1 == STEREO + %define INCLUDE_STEREO_OUTAUX + %endif +%endmacro + +%define OUTGAIN(val) val +%define AUXGAIN(val) val + +struc su_outaux_ports + .outgain resd 1 + .auxgain resd 1 +endstruc + +;------------------------------------------------------------------------------- +; AUX defines +;------------------------------------------------------------------------------- +%assign AUX_ID -1 +%macro USE_AUX 0 + %if AUX_ID == -1 + %assign AUX_ID CUR_ID + %assign CUR_ID CUR_ID + 2 + %xdefine OPCODES OPCODES MANGLE_FUNC(su_op_aux,0), + %xdefine NUMPARAMS NUMPARAMS 1, + %endif +%endmacro + +%macro SU_AUX 3 + db %2 + db %3 + USE_AUX + %xdefine CMDS CMDS AUX_ID+%1, + %if %1 == STEREO + %define INCLUDE_STEREO_AUX + %endif +%endmacro + +%define CHANNEL(val) val + +struc su_aux_ports + .gain resd 1 +endstruc + ;------------------------------------------------------------------------------- ; SEND structs ;------------------------------------------------------------------------------- diff --git a/src/opcodes/sources.asm b/src/opcodes/sources.asm index 51cb6d4..859434b 100644 --- a/src/opcodes/sources.asm +++ b/src/opcodes/sources.asm @@ -406,3 +406,35 @@ su_op_receive_mono: ret %endif ; RECEIVE_ID > -1 + +;------------------------------------------------------------------------------- +; IN opcode: inputs and clears a global port +;------------------------------------------------------------------------------- +; Mono: push the left channel of a global port (out or aux) +; Stereo: also push the right channel (stack in l r order) +;------------------------------------------------------------------------------- +%if IN_ID > -1 + +SECT_TEXT(suopin) + +EXPORT MANGLE_FUNC(su_op_in,0) + lodsb + %ifdef INCLUDE_STEREO_IN + mov _DI, [_SP + su_stack.synth] + jnc su_op_in_mono + call su_op_in_right + su_op_in_mono: + sub _DI, 4 + su_op_in_right: + xor ecx, ecx + fld dword [_DI + su_synth.right + _AX*4] + mov dword [_DI + su_synth.right + _AX*4], ecx + %else + xor ecx, ecx + mov _DI, [_SP + su_stack.synth] + fld dword [_DI + su_synth.left + _AX*4] + mov dword [_DI + su_synth.left + _AX*4], ecx + %endif + ret + +%endif ; SU_IN_ID > -1 diff --git a/src/opcodes/sources.inc b/src/opcodes/sources.inc index dc6d807..2a48dd2 100644 --- a/src/opcodes/sources.inc +++ b/src/opcodes/sources.inc @@ -250,3 +250,25 @@ struc su_receive_ports .left resd 1 .right resd 1 endstruc + +;------------------------------------------------------------------------------- +; IN defines +;------------------------------------------------------------------------------- +%assign IN_ID -1 +%macro USE_IN 0 + %if IN_ID == -1 + %assign IN_ID CUR_ID + %assign CUR_ID CUR_ID + 2 + %xdefine OPCODES OPCODES MANGLE_FUNC(su_op_in,0), + %xdefine NUMPARAMS NUMPARAMS 0, + %endif +%endmacro + +%macro SU_IN 2 + db %2 + USE_IN + %xdefine CMDS CMDS IN_ID+%1, + %if %1 == STEREO + %define INCLUDE_STEREO_IN + %endif +%endmacro diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a09e735..91f6f8f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -59,6 +59,12 @@ regression_test(test_send_stereo SEND) regression_test(test_send_global SEND) regression_test(test_receive SEND RECEIVE) regression_test(test_receive_stereo RECEIVE) +regression_test(test_in LOADVAL IN) +regression_test(test_in_stereo IN) +regression_test(test_outaux IN OUTAUX) +regression_test(test_outaux_stereo OUTAUX) +regression_test(test_aux LOADVAL AUX) +regression_test(test_aux_stereo AUX) regression_test(test_panning ENVELOPE PANNING) regression_test(test_panning_stereo PANNING) regression_test(test_multiple_instruments ENVELOPE) diff --git a/tests/expected_output/test_aux.raw b/tests/expected_output/test_aux.raw new file mode 100644 index 0000000..a4992f6 Binary files /dev/null and b/tests/expected_output/test_aux.raw differ diff --git a/tests/expected_output/test_aux_stereo.raw b/tests/expected_output/test_aux_stereo.raw new file mode 100644 index 0000000..a4992f6 Binary files /dev/null and b/tests/expected_output/test_aux_stereo.raw differ diff --git a/tests/expected_output/test_in.raw b/tests/expected_output/test_in.raw new file mode 100644 index 0000000..a4992f6 Binary files /dev/null and b/tests/expected_output/test_in.raw differ diff --git a/tests/expected_output/test_in_stereo.raw b/tests/expected_output/test_in_stereo.raw new file mode 100644 index 0000000..a4992f6 Binary files /dev/null and b/tests/expected_output/test_in_stereo.raw differ diff --git a/tests/expected_output/test_outaux.raw b/tests/expected_output/test_outaux.raw new file mode 100644 index 0000000..a4992f6 Binary files /dev/null and b/tests/expected_output/test_outaux.raw differ diff --git a/tests/expected_output/test_outaux_stereo.raw b/tests/expected_output/test_outaux_stereo.raw new file mode 100644 index 0000000..a4992f6 Binary files /dev/null and b/tests/expected_output/test_outaux_stereo.raw differ diff --git a/tests/test_aux.asm b/tests/test_aux.asm new file mode 100644 index 0000000..f3d5475 --- /dev/null +++ b/tests/test_aux.asm @@ -0,0 +1,24 @@ +%define BPM 100 +%define SINGLE_FILE +%define USE_SECTIONS + +%include "../src/sointu.inc" + +SU_BEGIN_PATTERNS + PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 +SU_END_PATTERNS + +SU_BEGIN_TRACKS + TRACK VOICES(1),0 +SU_END_TRACKS + +SU_BEGIN_PATCH + SU_BEGIN_INSTRUMENT VOICES(1) ; Instrument0 + SU_LOADVAL MONO,VALUE(0) + SU_AUX MONO,GAIN(64),CHANNEL(1) + SU_LOADVAL MONO,VALUE(96) + SU_AUX MONO,GAIN(128),CHANNEL(0) + SU_END_INSTRUMENT +SU_END_PATCH + +%include "../src/sointu.asm" diff --git a/tests/test_aux_stereo.asm b/tests/test_aux_stereo.asm new file mode 100644 index 0000000..220b1d9 --- /dev/null +++ b/tests/test_aux_stereo.asm @@ -0,0 +1,30 @@ +%define BPM 100 +%define SINGLE_FILE +%define USE_SECTIONS + +%include "../src/sointu.inc" + +SU_BEGIN_PATTERNS + PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 +SU_END_PATTERNS + +SU_BEGIN_TRACKS + TRACK VOICES(1),0 +SU_END_TRACKS + +SU_BEGIN_PATCH + SU_BEGIN_INSTRUMENT VOICES(1) ; Instrument0 + SU_LOADVAL MONO,VALUE(0) + SU_LOADVAL MONO,VALUE(64) + SU_AUX STEREO,GAIN(128),CHANNEL(0) + SU_LOADVAL MONO,VALUE(128) + SU_LOADVAL MONO,VALUE(128) + SU_AUX STEREO,GAIN(64),CHANNEL(2) + SU_IN STEREO,CHANNEL(0) + SU_IN STEREO,CHANNEL(2) + SU_ADDP STEREO + SU_OUT STEREO,GAIN(128) + SU_END_INSTRUMENT +SU_END_PATCH + +%include "../src/sointu.asm" diff --git a/tests/test_in.asm b/tests/test_in.asm new file mode 100644 index 0000000..deb4b9b --- /dev/null +++ b/tests/test_in.asm @@ -0,0 +1,29 @@ +%define BPM 100 +%define SINGLE_FILE +%define USE_SECTIONS + +%include "../src/sointu.inc" + +SU_BEGIN_PATTERNS + PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 +SU_END_PATTERNS + +SU_BEGIN_TRACKS + TRACK VOICES(1),0 +SU_END_TRACKS + +SU_BEGIN_PATCH + SU_BEGIN_INSTRUMENT VOICES(1) ; Instrument0 + SU_LOADVAL MONO,VALUE(0) + SU_LOADVAL MONO,VALUE(64) + SU_OUT STEREO,GAIN(128) + SU_IN MONO,CHANNEL(1) + SU_IN MONO,CHANNEL(0) + SU_LOADVAL MONO,VALUE(96) + SU_LOADVAL MONO,VALUE(96) + SU_ADDP STEREO + SU_OUT STEREO,GAIN(128) + SU_END_INSTRUMENT +SU_END_PATCH + +%include "../src/sointu.asm" diff --git a/tests/test_in_stereo.asm b/tests/test_in_stereo.asm new file mode 100644 index 0000000..f8f5a27 --- /dev/null +++ b/tests/test_in_stereo.asm @@ -0,0 +1,28 @@ +%define BPM 100 +%define SINGLE_FILE +%define USE_SECTIONS + +%include "../src/sointu.inc" + +SU_BEGIN_PATTERNS + PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 +SU_END_PATTERNS + +SU_BEGIN_TRACKS + TRACK VOICES(1),0 +SU_END_TRACKS + +SU_BEGIN_PATCH + SU_BEGIN_INSTRUMENT VOICES(1) ; Instrument0 + SU_LOADVAL MONO,VALUE(0) + SU_LOADVAL MONO,VALUE(64) + SU_OUT STEREO,GAIN(128) + SU_IN STEREO,CHANNEL(0) + SU_LOADVAL MONO,VALUE(96) + SU_LOADVAL MONO,VALUE(96) + SU_ADDP STEREO + SU_OUT STEREO,GAIN(128) + SU_END_INSTRUMENT +SU_END_PATCH + +%include "../src/sointu.asm" diff --git a/tests/test_outaux.asm b/tests/test_outaux.asm new file mode 100644 index 0000000..a2e89df --- /dev/null +++ b/tests/test_outaux.asm @@ -0,0 +1,28 @@ +%define BPM 100 +%define SINGLE_FILE +%define USE_SECTIONS + +%include "../src/sointu.inc" + +SU_BEGIN_PATTERNS + PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 +SU_END_PATTERNS + +SU_BEGIN_TRACKS + TRACK VOICES(1),0 +SU_END_TRACKS + +SU_BEGIN_PATCH + SU_BEGIN_INSTRUMENT VOICES(1) ; Instrument0 + SU_LOADVAL MONO,VALUE(0) + SU_OUTAUX MONO,OUTGAIN(32),AUXGAIN(64) + SU_IN MONO,CHANNEL(0) + SU_IN MONO,CHANNEL(2) + SU_LOADVAL MONO,VALUE(48) + SU_LOADVAL MONO,VALUE(128) + SU_ADDP STEREO + SU_OUT STEREO,GAIN(128) + SU_END_INSTRUMENT +SU_END_PATCH + +%include "../src/sointu.asm" diff --git a/tests/test_outaux_stereo.asm b/tests/test_outaux_stereo.asm new file mode 100644 index 0000000..e26cbf0 --- /dev/null +++ b/tests/test_outaux_stereo.asm @@ -0,0 +1,29 @@ +%define BPM 100 +%define SINGLE_FILE +%define USE_SECTIONS + +%include "../src/sointu.inc" + +SU_BEGIN_PATTERNS + PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 +SU_END_PATTERNS + +SU_BEGIN_TRACKS + TRACK VOICES(1),0 +SU_END_TRACKS + +SU_BEGIN_PATCH + SU_BEGIN_INSTRUMENT VOICES(1) ; Instrument0 + SU_LOADVAL MONO,VALUE(0) + SU_LOADVAL MONO,VALUE(128) + SU_OUTAUX STEREO,OUTGAIN(16),AUXGAIN(48) + SU_IN MONO,CHANNEL(1) + SU_IN MONO,CHANNEL(0) + SU_IN MONO,CHANNEL(3) + SU_IN MONO,CHANNEL(2) + SU_ADDP STEREO + SU_OUT STEREO,GAIN(128) + SU_END_INSTRUMENT +SU_END_PATCH + +%include "../src/sointu.asm"