Skip to content

Commit c2213e9

Browse files
committed
nullsound: FM vibrato effect
This commit includes a fairly big refactoring to share common parts of the vibrato algo between FM and SSG. It also includes updates to simplify the FM codebase.
1 parent a969cd9 commit c2213e9

File tree

8 files changed

+607
-202
lines changed

8 files changed

+607
-202
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*.lst
77
*.rst
88
*.lib
9+
*.map
10+
*.sym
911

1012
# Libraries
1113
*.a

nullsound/Makefile.in

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ all: nullsound.lib linkcheck.map
1919
-include ../Makefile.config
2020

2121
INCLUDE_FILES=helpers ports ym2610
22-
OBJS=entrypoint bios-commands adpcm ym2610 stream timer nss-fm nss-adpcm nss-ssg
22+
OBJS=entrypoint bios-commands adpcm ym2610 stream timer nss-fm nss-adpcm nss-ssg fx-vibrato
2323
LIB=nullsound.lib
2424

2525
VERSION=@version@
@@ -39,7 +39,7 @@ $(LIB): $(OBJS:%=%.rel)
3939
cat $^ > $@
4040

4141
%.rel: %.s
42-
$(NGSDAS) -g -l -p -u -o $@ $<
42+
$(NGSDAS) -a -g -l -p -s -u -o $@ $<
4343

4444
install: install-nullsound install-include
4545

nullsound/ssg-vibrato.s renamed to nullsound/fx-vibrato.s

+96-131
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,110 @@
1616
;;; You should have received a copy of the GNU Lesser General Public License
1717
;;; along with ngdevkit. If not, see <http://www.gnu.org/licenses/>.
1818

19-
;;; SSG vibrato effect. This file is included by nss-ssg.s
19+
;;; Vibrato effect, common functions for FM and SSG
2020
;;;
2121

22-
.equ VIBRATO_SPEED,(state_vibrato_speed-state_mirrored_ssg)
23-
.equ VIBRATO_DEPTH,(state_vibrato_depth-state_mirrored_ssg)
24-
.equ VIBRATO_POS,(state_vibrato_pos-state_mirrored_ssg)
25-
.equ VIBRATO_PREV,(state_vibrato_prev-state_mirrored_ssg)
26-
.equ VIBRATO_NEXT,(state_vibrato_next-state_mirrored_ssg)
22+
.module nullsound
2723

24+
.include "ym2610.inc"
25+
.include "struct-fx.inc"
2826

29-
;;; Update the vibrato for the current SSG channel
30-
;;; Vibrato oscillates the current note's frequency between the previou
27+
.area CODE
28+
29+
30+
;;; Setup prev and next increments for vibrato
31+
;;; ------
32+
;;; IN:
33+
;;; ix : fm state for channel
34+
;;; the note semitone must be already configured
35+
;;; [ hl ]: prev semitone distance
36+
;;; [hl+1]: next semitone distance
37+
;;; OUT:
38+
;;; de : prev increment (fixed-point)
39+
;;; hl : prev increment (fixed-point)
40+
;;; bc, de, hl modified
41+
vibrato_setup_increments::
42+
;; bc: prev distance from current note
43+
push hl ; +(prev distance)
44+
ld b, (hl)
45+
;; de: output prev increment, scaled by depth (a)
46+
ld a, VIBRATO_DEPTH(ix)
47+
call vibrato_scale_increment
48+
ld e, l
49+
ld d, h
50+
51+
;; bc: next distance from current note
52+
pop hl ; (prev distance)
53+
inc hl
54+
ld b, (hl)
55+
;; hl: output next increment, scaled by depth (a)
56+
ld a, VIBRATO_DEPTH(ix)
57+
call vibrato_scale_increment
58+
59+
ret
60+
61+
62+
;;; Scale a fixed point 16bit value into x/16 fraction
63+
;;; ------
64+
;;; IN:
65+
;;; bc : distance
66+
;;; a : scale factor [1..16]
67+
;;; OUT:
68+
;;; hl : scaled base increment
69+
;;; bc, hl modified
70+
vibrato_scale_increment:
71+
;; bc: base increment (fixed point)
72+
;; there are 8 possible levels, so bc = fixed point distance / 8
73+
ld c, #0
74+
srl b
75+
rr c
76+
srl b
77+
rr c
78+
srl b
79+
rr c
80+
81+
;; scale the base increment based on the vibrato depth
82+
;; depth has 16 possible levels [1..16], so parse 4 bits
83+
ld h, #0
84+
ld l, h
85+
bit 4, a
86+
jr z, _post_bit4
87+
add hl, bc
88+
_post_bit4:
89+
;; shift bc 1 bit to the right
90+
srl b
91+
rr c
92+
bit 3, a
93+
jr z, _post_bit3
94+
add hl, bc
95+
_post_bit3:
96+
srl b
97+
rr c
98+
bit 2, a
99+
jr z, _post_bit2
100+
add hl, bc
101+
_post_bit2:
102+
srl b
103+
rr c
104+
bit 1, a
105+
jr z, _post_bit1
106+
add hl, bc
107+
_post_bit1:
108+
ret
109+
110+
111+
;;; Update the vibrato for the current channel
112+
;;; Vibrato oscillates the current note's frequency between the previous
31113
;;; and the next semitones of the current note, and follows a sine wave.
32114
;;; This function update the frequency by one step among the 64 steps
33115
;;; defined in the sine wave.
34116
;;; ------
35-
;;; hl: mirrored state of the current ssg channel
36-
eval_ssg_vibrato_step::
37-
push hl
38-
push de
39-
push bc
40-
41-
;; ix: mirrored_ssg for current channel
42-
push hl
43-
pop ix
44-
117+
;;; IN:
118+
;;; ix: mirrored state of the current fm channel
119+
;;; OUT:
120+
;;; hl: new note for step (FM: f-num, SSG: period)
121+
;;; bc, de, hl modified
122+
vibrato_eval_step::
45123
;; e: next vibrato pos
46124
ld a, VIBRATO_POS(ix)
47125
add a, VIBRATO_SPEED(ix)
@@ -106,117 +184,4 @@ _post_mul_a0:
106184
;; hl: new note
107185
add hl, de
108186

109-
;; configure SSG channel with new note
110-
;; TODO, update the mirror state only
111-
ld a, (state_ssg_channel)
112-
sla a
113-
ld b, a
114-
ld c, l
115-
call ym2610_write_port_a
116-
inc b
117-
ld c, h
118-
call ym2610_write_port_a
119-
120-
pop bc
121-
pop de
122-
pop hl
123-
124-
ret
125-
126-
127-
;;; Setup prev and next increments for vibrato
128-
;;; ------
129-
;;; ix : ssg state for channel
130-
;;; the note semitone must be already configured
131-
ssg_vibrato_setup_increments::
132-
push bc
133-
push hl
134-
135-
;; reset vibrato sine pos
136-
ld VIBRATO_POS(ix), #0
137-
138-
;; bc: prev distance from current note, fix point
139-
ld hl, #ssg_semitone_distance
140-
ld l, NOTE_SEMITONE_OFFSET(ix)
141-
push hl ; +prev distance
142-
ld b, (hl)
143-
ld c, #0
144-
;; a: vibrato depth
145-
ld a, VIBRATO_DEPTH(ix)
146-
;; hl: output prev increment, scaled by depth (a)
147-
ld h, #0
148-
ld l, h
149-
call ssg_vibrato_scale_increment
150-
ld VIBRATO_PREV(ix), l
151-
ld VIBRATO_PREV+1(ix), h
152-
153-
;; bc: next distance
154-
pop hl ; prev distance
155-
inc hl
156-
ld b, (hl)
157-
ld c, #0
158-
;; a: vibrato depth
159-
ld a, VIBRATO_DEPTH(ix)
160-
;; hl: output next increment, scaled by depth (a)
161-
ld h, #0
162-
ld l, h
163-
call ssg_vibrato_scale_increment
164-
;; hl: -hl (next increment is always negative)
165-
xor a
166-
sub l
167-
ld l, a
168-
sbc a, a
169-
sub h
170-
ld h, a
171-
ld VIBRATO_NEXT(ix), l
172-
ld VIBRATO_NEXT+1(ix), h
173-
174-
pop hl
175-
pop bc
176-
ret
177-
178-
179-
;;; Scale a fixed point 16bit value into x/16 fraction
180-
;;; ------
181-
;;; IN:
182-
;;; bc : distance
183-
;;; a : scale factor [1..16]
184-
;;; OUT:
185-
;;; hl : scaled base increment
186-
;;; bc, hl modified
187-
ssg_vibrato_scale_increment:
188-
;; bc: get base increment
189-
;; there are 8 possible levels, so bc = distance / 8
190-
srl b
191-
rr c
192-
srl b
193-
rr c
194-
srl b
195-
rr c
196-
197-
;; scale the base increment based on the vibrato depth
198-
;; depth has 16 possible levels [1..16], so parse 4 bits
199-
bit 4, a
200-
jr z, _post_bit4
201-
add hl, bc
202-
_post_bit4:
203-
;; shift bc 1 bit to the right
204-
srl b
205-
rr c
206-
bit 3, a
207-
jr z, _post_bit3
208-
add hl, bc
209-
_post_bit3:
210-
srl b
211-
rr c
212-
bit 2, a
213-
jr z, _post_bit2
214-
add hl, bc
215-
_post_bit2:
216-
srl b
217-
rr c
218-
bit 1, a
219-
jr z, _post_bit1
220-
add hl, bc
221-
_post_bit1:
222187
ret

0 commit comments

Comments
 (0)