Skip to content

Commit

Permalink
nullsound: pan FX for ADPCM channels
Browse files Browse the repository at this point in the history
  • Loading branch information
dciabrin committed Dec 14, 2024
1 parent fda751e commit 0fcea6b
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 14 deletions.
30 changes: 26 additions & 4 deletions nullsound/nss-adpcm-a.s
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
;; getters for ADPCM-A state
.lclequ VOL, (state_a_vol-state_a)
.lclequ OUT_VOL, (state_a_out_vol-state_a)
.lclequ PAN, (state_a_pan-state_a)

.equ NSS_ADPCM_A_INSTRUMENT_PROPS, 4
.equ NSS_ADPCM_A_NEXT_REGISTER, 8
Expand Down Expand Up @@ -71,6 +72,8 @@ state_a_trigger: .blkb TRIGGER_SIZE
;;; volume
state_a_vol: .blkb 1 ; configured note volume (attenuation)
state_a_out_vol: .blkb 1 ; ym2610 volume after the FX pipeline
;;; pan
state_a_pan: .blkb 1 ; configured pan (b7: left, b6: right)
;;;
state_a_end:
;;; ADPCM-A2
Expand Down Expand Up @@ -128,10 +131,15 @@ init_nss_adpcm_state_tracker::
ld (state_adpcm_a_channel), a
;; set default
ld ix, #state_a1
ld bc, #ADPCM_A_STATE_SIZE
ld d, #6
_a_init:
ld a, #0x1f
ld VOL(ix), a
ld a, #0xc0
ld PAN(ix), a

add ix, bc
dec d
jr nz, _a_init
;; global ADPCM volumes are initialized in the volume state tracker
Expand Down Expand Up @@ -228,17 +236,17 @@ _post_load_a_vol:

;; Pipeline action: load pan+volume register when it is modified
ld a, PIPELINE(ix)
or a, #(STATE_LOAD_VOL|STATE_LOAD_PAN)
and a, #(STATE_LOAD_VOL|STATE_LOAD_PAN)
jr z, _post_load_a_pan_vol
res BIT_LOAD_VOL, PIPELINE(ix)
res BIT_LOAD_PAN, PIPELINE(ix)

;; c: volume + default pan (L/R)
;; c: volume + pan
ld a, OUT_VOL(ix)
or #0xc0
add PAN(ix)
ld c, a

;; set pan+volume for channel in the YM2610
;; set volume + pan for channel in the YM2610
;; b: ADPCM-A channel
ld a, (state_adpcm_a_channel)
add a, #REG_ADPCM_A1_PAN_VOLUME
Expand Down Expand Up @@ -620,3 +628,17 @@ adpcm_a_retrigger::

ld a, #1
ret


;;; ADPCM_A_PAN
;;; Set the pan (l/r) for the current ADPCM-A channel
;;; ------
;;; [ hl ]: pan (b7: left, b6: right)
adpcm_a_pan::
ld a, (hl)
inc hl
ld PAN(ix), a
set BIT_LOAD_PAN, PIPELINE(ix)

ld a, #1
ret
28 changes: 27 additions & 1 deletion nullsound/nss-adpcm-b.s
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
.lclequ DELTA_N, (state_b_note_delta_n-state_b)
.lclequ VOL, (state_b_vol-state_b)
.lclequ OUT_VOL, (state_b_out_vol-state_b)
.lclequ PAN, (state_b_pan-state_b)
.lclequ INSTR, (state_b_instr-state_b)
.lclequ START_CMD, (state_b_instr_start_cmd-state_b)

Expand Down Expand Up @@ -85,6 +86,8 @@ state_b_instr_start_cmd: .blkb 1 ; instrument play command (with
;;; volume
state_b_vol: .blkb 1 ; configured note volume (attenuation)
state_b_out_vol: .blkb 1 ; ym2610 volume after the FX pipeline
;;; pan
state_b_pan: .blkb 1 ; configured pan (b7: left, b6: right)
;;;
state_b_end:

Expand Down Expand Up @@ -176,9 +179,18 @@ _b_post_check_playing:
ld b, #REG_ADPCM_B_VOLUME
ld c, OUT_VOL(ix)
call ym2610_write_port_a

res BIT_LOAD_VOL, PIPELINE(ix)
_post_load_b_vol:

;; Pipeline action: load pan if requested
bit BIT_LOAD_PAN, PIPELINE(ix)
jr z, _post_load_b_pan
ld b, #REG_ADPCM_B_PAN
ld c, PAN(ix)
call ym2610_write_port_a
res BIT_LOAD_PAN, PIPELINE(ix)
_post_load_b_pan:

;; Pipeline action: load note register when the note state is modified
bit BIT_LOAD_NOTE, PIPELINE(ix)
jr z, _post_load_b_note
Expand Down Expand Up @@ -779,3 +791,17 @@ adpcm_b_cut::

ld a, #1
ret


;;; ADPCM_B_PAN
;;; Set the pan (l/r) for the channel
;;; ------
;;; [ hl ]: pan (b7: left, b6: right)
adpcm_b_pan::
ld a, (hl)
inc hl
ld PAN(ix), a
set BIT_LOAD_PAN, PIPELINE(ix)

ld a, #1
ret
2 changes: 2 additions & 0 deletions nullsound/stream.s
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,8 @@ nss_opcodes:
.nss_op adpcm_b_cut
.nss_op adpcm_b_delay
.nss_op adpcm_a_retrigger
.nss_op adpcm_a_pan
.nss_op adpcm_b_pan



Expand Down
30 changes: 21 additions & 9 deletions tools/nsstool.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ def register_nss_ops():
("b_cut", ["delay"]),
("b_delay", ["delay"]),
("a_retrigger", ["delay"]),
("a_pan", ["pan_mask"]),
("b_pan", ["pan_mask"]),
# reserved opcodes
("nss_label", ["pat"])
)
Expand All @@ -301,6 +303,15 @@ def register_nss_ops():
globals()[cname]=make_dataclass(cname, fields)


def convert_pan(fx, fxval):
if fx == 0x08: # pan
pan_l = 0x80 if (fxval & 0xf0) else 0
pan_r = 0x40 if (fxval & 0x0f) else 0
elif fx == 0x80: # old pan
pan_l = 0x80 if fxval in [0x00, 0x80] else 0
pan_r = 0x40 if fxval in [0x80, 0xff] else 0
return pan_l|pan_r;


#
# Furnace module conversion functions
Expand All @@ -317,15 +328,7 @@ def convert_fm_row(row, channel):
opcodes.append(fm_vol(row.vol))
# pre-instrument effects
for fx, fxval in row.fx:
if fx == 0x08: # pan
pan_l = 0x80 if (fxval & 0xf0) else 0
pan_r = 0x40 if (fxval & 0x0f) else 0
opcodes.append(fm_pan(pan_l|pan_r))
elif fx == 0x80: # old pan
pan_l = 0x80 if fxval in [0x00, 0x80] else 0
pan_r = 0x40 if fxval in [0x80, 0xff] else 0
opcodes.append(fm_pan(pan_l|pan_r))
elif fx == 0xed: # note delay
if fx == 0xed: # note delay
opcodes.append(fm_delay(fxval))
# instrument
if row.ins != -1:
Expand Down Expand Up @@ -382,6 +385,9 @@ def convert_fm_row(row, channel):
opcodes.append(fm_porta(fxval))
elif fx == 0xec: # cut
opcodes.append(fm_cut(fxval))
elif fx in [0x08, 0x80]: # panning
pan_mask = convert_pan(fx, fxval)
opcodes.append(fm_pan(pan_mask))
else:
add_unknown_fx('FM', fx)

Expand Down Expand Up @@ -521,6 +527,9 @@ def convert_a_row(row, channel):
opcodes.append(groove(fxval))
elif fx == 0xec: # cut
opcodes.append(a_cut(fxval))
elif fx in [0x08, 0x80]: # panning
pan_mask = convert_pan(fx, fxval)
opcodes.append(a_pan(pan_mask))
else:
add_unknown_fx('ADPCM-A', fx)

Expand Down Expand Up @@ -571,6 +580,9 @@ def convert_b_row(row, channel):
opcodes.append(b_porta(fxval))
elif fx == 0xec: # cut
opcodes.append(b_cut(fxval))
elif fx in [0x08, 0x80]: # panning
pan_mask = convert_pan(fx, fxval)
opcodes.append(b_pan(pan_mask))
else:
add_unknown_fx('ADPCM-B', fx)

Expand Down

0 comments on commit 0fcea6b

Please sign in to comment.