Hello Audio
Now that you can draw and move a sprite, the next step is sound.
This demo plays a short PSG jingle when you press A.
The code
#include <gba/bios>
#include <gba/interrupt>
#include <gba/keyinput>
#include <gba/music>
#include <gba/peripherals>
using namespace gba::music;
using namespace gba::music::literals;
namespace {
// One-shot PSG jingle (SQ1). Press A to restart playback.
// .press() applies staccato: each note plays for half duration, rest for half.
// Compiled at 2_cps (2 cycles per second) for a snappy tempo.
static constexpr auto jingle = compile<2_cps>(note("c5 e5 g5 c6").channel(channel::sq1).press());
} // namespace
int main() {
gba::irq_handler = {};
gba::reg_dispstat = {.enable_irq_vblank = true};
gba::reg_ie = {.vblank = true};
gba::reg_ime = true;
// Basic PSG routing for SQ1 on both speakers.
gba::reg_soundcnt_x = {.master_enable = true};
gba::reg_soundcnt_l = {
.volume_right = 7,
.volume_left = 7,
.enable_1_right = true,
.enable_1_left = true,
};
gba::reg_soundcnt_h = {.psg_volume = 2};
gba::keypad keys;
auto player = music_player<jingle>{};
while (true) {
gba::VBlankIntrWait();
keys = gba::reg_keyinput;
if (keys.pressed(gba::key_a)) {
player = {};
}
player();
}
}
What is happening?
- We set up VBlank + interrupts as in earlier chapters.
- We enable PSG output with
reg_soundcnt_x,reg_soundcnt_l, andreg_soundcnt_h. note("c5 e5 g5 c6").channel(channel::sq1).press()builds a staccato pattern (each note plays half duration, rests half), ensuring the jingle ends in silence naturally.compile<2_cps>(...)compiles at 2 cycles per second (4x faster than the default 0.5 cps), making the jingle snappy and brief.music_player<jingle>advances once per frame, dispatching note events.- Pressing
Aresets the player withplayer = {}, restarting the jingle from the beginning.
Next step
Move on to Registers & Peripherals, then dive deeper into Music Composition.