Skip to content

Commit 5d2e78a

Browse files
evie-calicoISSOtmavivace
authored
Part II, Lesson 6 (#47)
Co-authored-by: Eldred Habert <eldredhabert0@gmail.com> Co-authored-by: Antonio Vivace <avivace4@gmail.com>
1 parent 2965fc4 commit 5d2e78a

2 files changed

Lines changed: 895 additions & 0 deletions

File tree

src/part2/audio.md

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
# Audio
2+
3+
In the last few chapters we implemented the bulk of our game's interactivity, but it would be nice to add some feedback to make brick-breaking a bit more satisfying.
4+
5+
The Game Boy has 4 channels for producing sound: 2 pulse channels, a wave channel, and a noise channel.
6+
Each type of channel has a unique type of sound that it can produce.
7+
For example, the pulse channels can play notes, making them ideal for melodies, while the noise channel is less melodic, making it better for percussion.
8+
The wave channel is unique in that it can be used to play simple waveforms.
9+
You can almost think of this as a custom instrument, though it's very limited.
10+
11+
Here's a diagram from [this page](https://gbdev.io/pandocs/Audio.html) of the Pandocs showing each channel.
12+
<svg viewBox="0 0 480 220" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
13+
<defs>
14+
<style type="text/css">
15+
text {
16+
fill: var(--fg);
17+
dominant-baseline: middle;
18+
}
19+
.centered { text-anchor: middle; }
20+
.right { text-anchor: end; }
21+
rect, path, use {
22+
stroke: var(--fg);
23+
fill: var(--fg);
24+
}
25+
.inverted {
26+
stroke: var(--bg);
27+
fill: var(--bg);
28+
}
29+
.unfilled {
30+
fill: none !important;
31+
}
32+
.no-stroke {
33+
stroke: none !important;
34+
}
35+
</style>
36+
<path d="M 0,-5
37+
v 10
38+
l 10,-5
39+
z" id="arrow-head"></path>
40+
</defs>
41+
<text x="85" y="36" class="right">Channel 1</text>
42+
<rect x="95" y="15" width="40" height="40"></rect>
43+
<path d="M 95,45
44+
h 10
45+
v -20
46+
h 10
47+
v 20
48+
h 10
49+
v -20
50+
h 10" class="inverted unfilled"></path>
51+
<text x="85" y="86" class="right">Channel 2</text>
52+
<rect x="95" y="65" width="40" height="40"></rect>
53+
<path d="M 95,95
54+
h 10
55+
v -20
56+
h 10
57+
v 20
58+
h 10
59+
v -20
60+
h 10" class="inverted unfilled"></path>
61+
<text x="85" y="136" class="right">Channel 3</text>
62+
<rect x="95" y="115" width="40" height="40"></rect>
63+
<path d="M 95,141
64+
h 2
65+
v -2
66+
h 2
67+
v -3
68+
h 2
69+
v -3
70+
h 2
71+
v -3
72+
h 2
73+
v -2
74+
h 2
75+
v -1
76+
h 2
77+
v 1
78+
h 2
79+
v 2
80+
h 2
81+
v 5
82+
h 2
83+
v 4
84+
h 2
85+
v 2
86+
h 2
87+
v 1
88+
h 4
89+
v -10
90+
h 2
91+
v -5
92+
h 2
93+
v 15
94+
h 2
95+
v -14
96+
h 2
97+
v 7
98+
h 2
99+
v 4
100+
h 2
101+
v 2
102+
h 4
103+
v 1
104+
h 4
105+
v -1
106+
h 2
107+
v -1
108+
h 2
109+
v -2
110+
h 2
111+
v -2
112+
h 2
113+
v -3
114+
h 2
115+
v -2
116+
h 2
117+
v -2
118+
h 2" class="inverted unfilled"></path>
119+
<text x="85" y="186" class="right">Channel 4</text>
120+
<rect x="95" y="165" width="40" height="40"></rect>
121+
<path d="M 95,195
122+
h 2
123+
v -20
124+
h 2
125+
v 20
126+
h 5
127+
v -20
128+
h 2
129+
v 20
130+
h 1
131+
v -20
132+
h 6
133+
v 20
134+
h 3
135+
v -20
136+
h 2
137+
v 20
138+
h 1
139+
v -20
140+
h 2
141+
v 20
142+
h 5
143+
v -20
144+
h 1
145+
v 20
146+
h 4
147+
v -20
148+
h 2
149+
v 20
150+
h 1
151+
v -20
152+
h 1" class="inverted unfilled"></path>
153+
<path d="M 135,35
154+
h 30
155+
m -30,50
156+
h 30
157+
m -30,50
158+
h 30
159+
m -30,50
160+
h 30
161+
v -150
162+
m 0,75
163+
h 30" class="unfilled"></path>
164+
<use x="185" y="110" href="#arrow-head"></use>
165+
<rect x="195" y="95" width="60" height="30"></rect>
166+
<text x="225" y="110" class="centered inverted no-stroke">Mixer</text>
167+
<path d="M 255,102
168+
h 30" class="unfilled"></path>
169+
<use x="275" y="102" href="#arrow-head"></use>
170+
<path d="M 255,118
171+
h 30" class="unfilled"></path>
172+
<use x="275" y="118" href="#arrow-head"></use>
173+
<rect x="285" y="95" width="80" height="30"></rect>
174+
<text x="325" y="110" class="centered inverted no-stroke">Amplifier</text>
175+
<path d="M 365,102
176+
h 30" class="unfilled"></path>
177+
<use x="385" y="102" href="#arrow-head"></use>
178+
<path d="M 365,118
179+
h 30" class="unfilled"></path>
180+
<use x="385" y="118" href="#arrow-head"></use>
181+
<rect x="395" y="95" width="80" height="30"></rect>
182+
<text x="435" y="110" class="centered inverted no-stroke">Output</text>
183+
</svg>
184+
185+
Audio channels can be controlled through the Game Boy's large number of "NR" registers.
186+
Each of these registers configures the behavior of a channel and can be used to play specific sounds.
187+
In addition, channels 1, 2, and 4 have a hardware envelope, which is used to fade the channel out over time; this is very useful for simple sound effects!
188+
189+
::: tip
190+
191+
If you'd like a more in-depth look at the audio registers, check out the [audio articles](https://gbdev.io/pandocs/Audio.html) on the Pandocs.
192+
193+
:::
194+
195+
For the simple sound effects in our game, all we need to do is write a few values to the NR registers, and the Game Boy will handle the rest.
196+
We can use a tool like [gbsfx studio](https://daid.github.io/gbsfx-studio/) to create a sound we like, and then copy the code into our game to play it.
197+
198+
We'll start with a "bounce" sound effect. Let's use channel 2, which is a pulse channel, and play a short note.
199+
The following code is a sample bounce sound, but feel free to play around and find a sound you like.
200+
201+
```rgbasm
202+
ld a, $85
203+
ld [rNR21], a
204+
ld a, $70
205+
ld [rNR22], a
206+
ld a, $0d
207+
ld [rNR23], a
208+
ld a, $c3
209+
ld [rNR24], a
210+
```
211+
212+
To use this in our game, we'll put it within a short function which we can call any time a bounce sound needs to be played.
213+
214+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/audio/main.asm:bounce-sound}}
215+
{{#include ../../unbricked/audio/main.asm:bounce-sound}}
216+
```
217+
218+
Now just call this function at the end of each of our bouncing checks.
219+
Don't forget the paddle!
220+
221+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/audio/main.asm:updated-bounce}}
222+
{{#include ../../unbricked/audio/main.asm:updated-bounce}}
223+
```
224+
225+
A sound effect would make destroying bricks a lot more satisfying.
226+
This time, let's use the noise channel to play a sound.
227+
Since we're using a different channel, the "bounce" and "break" sounds can overlap without any issue!
228+
229+
This is an example sound, but feel free to create your own.
230+
231+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/audio/main.asm:break-sound}}
232+
{{#include ../../unbricked/audio/main.asm:break-sound}}
233+
```
234+
235+
And just like with the bouncing sound, we'll need to call this function in our brick-breaking code.
236+
237+
```rgbasm,linenos,start={{#line_no_of "" ../../unbricked/audio/main.asm:check-for-brick}}
238+
{{#include ../../unbricked/audio/main.asm:check-for-brick}}
239+
```
240+
241+
Now the game has some audiotory feedback!

0 commit comments

Comments
 (0)