Skip to main content
The audio system manages music and sound effects using the Game Boy’s four hardware audio channels through a sophisticated software-based music engine.

Audio Channels

The Game Boy has 4 hardware audio channels defined in constants/audio_constants.asm:
const_def
const CHAN1 ; 0 - Square wave with sweep
const CHAN2 ; 1 - Square wave
const CHAN3 ; 2 - Wave channel (custom waveforms)
const CHAN4 ; 3 - Noise channel
DEF NUM_MUSIC_CHANS EQU const_value
The game uses 8 logical channels: 4 for music and 4 for sound effects. SFX channels temporarily override music channels when sound effects play.

Hardware Channel Properties

Channel Base Addresses

DEF HW_CH1_BASE EQU LOW(rAUD1SWEEP)
DEF HW_CH2_BASE EQU LOW(rAUD2LEN) - 1
DEF HW_CH3_BASE EQU LOW(rAUD3ENA)
DEF HW_CH4_BASE EQU LOW(rAUD4LEN) - 1
These map to Game Boy hardware registers:
  • Channel 1: Square wave with frequency sweep capability
  • Channel 2: Square wave (no sweep)
  • Channel 3: Wave channel (custom 32-sample waveforms)
  • Channel 4: White noise generator

Channel Enable Masks

DEF HW_CH1_ENABLE_MASK EQU %00010001
DEF HW_CH2_ENABLE_MASK EQU %00100010
DEF HW_CH3_ENABLE_MASK EQU %01000100
DEF HW_CH4_ENABLE_MASK EQU %10001000
These masks control both the left and right audio outputs independently, allowing stereo panning effects.

Music Engine

The game uses three separate but identical audio engines in audio/engine_[1|2|3].asm stored in different ROM banks.

Update Loop

From audio/engine_1.asm:
Audio1_UpdateMusic::
    ld c, CHAN1
.loop
    ld b, 0
    ld hl, wChannelSoundIDs
    add hl, bc
    ld a, [hl]
    and a
    jr z, .nextChannel
    ld a, c
    cp CHAN5
    jr nc, .applyAffects ; if sfx channel
    ld a, [wMuteAudioAndPauseMusic]
    and a
    jr z, .applyAffects
    bit BIT_MUTE_AUDIO, a
    jr nz, .nextChannel
    ; ... mute audio logic ...
.applyAffects
    call Audio1_ApplyMusicAffects
.nextChannel
    ld a, c
    inc c ; inc channel number
    cp CHAN8
    jr nz, .loop
    ret
1

Channel Iteration

Loops through all 8 channels (CHAN1-CHAN8) each frame.
2

Active Check

Checks if channel has an active sound or music playing.
3

Mute Handling

If audio is muted, disables music channels but allows SFX.
4

Apply Effects

Calls ApplyMusicAffects to process note delays, vibrato, pitch slides, etc.

Music Effects

The engine supports sophisticated musical effects:

Note Delay Counter

ld hl, wChannelNoteDelayCounters
add hl, bc
ld a, [hl]
cp 1
jp z, Audio1_PlayNextNote
dec a
ld [hl], a
Each channel has a counter that decrements each frame. When it reaches 1, the next note plays.

Vibrato

.checkForVibrato
    ld hl, wChannelVibratoExtents
    add hl, bc
    ld a, [hl]
    and a
    jr nz, .vibrato
    ret ; no vibrato
.vibrato
    ld d, a
    ld hl, wChannelVibratoRates
    add hl, bc
    ld a, [hl]
    and $f
Vibrato oscillates the pitch above and below the base frequency for a richer sound.

Pitch Slide

.checkForPitchSlide
    ld hl, wChannelFlags1
    add hl, bc
    bit BIT_PITCH_SLIDE_ON, [hl]
    jr z, .checkVibratoDelay
    jp Audio1_ApplyPitchSlide
Smooth pitch bends between notes, used for effects like portamento.

Duty Cycle Rotation

bit BIT_ROTATE_DUTY_CYCLE, [hl]
jr z, .checkForExecuteMusic
call Audio1_ApplyDutyCyclePattern
Changes the waveform shape on square wave channels for timbral variation.

Channel Flags

Two flag bytes control channel behavior:

Channel Flags 1

const_def
const BIT_PERFECT_PITCH          ; 0
const BIT_SOUND_CALL             ; 1 - if in sound call
const BIT_NOISE_OR_SFX           ; 2 - if noise or SFX channel
const BIT_VIBRATO_DIRECTION      ; 3 - pitch above/below normal
const BIT_PITCH_SLIDE_ON         ; 4
const BIT_PITCH_SLIDE_DECREASING ; 5
const BIT_ROTATE_DUTY_CYCLE      ; 6

Channel Flags 2

DEF BIT_EXECUTE_MUSIC EQU 0 ; if in execute music
These flags allow each channel to have independent effects like vibrato or pitch slides, enabling rich polyphonic music.

Musical Notes

Twelve pitches per octave:
const_def
const C_  ; 0
const C#  ; 1
const D_  ; 2
const D#  ; 3
const E_  ; 4
const F_  ; 5
const F#  ; 6
const G_  ; 7
const G#  ; 8
const A_  ; 9
const A#  ; A
const B_  ; B
DEF NUM_NOTES EQU const_value
Pitch tables in audio/notes.asm convert note IDs to hardware frequency values.

Sound Effects

Sound effects are organized in audio.asm:
SECTION "Sound Effect Headers 1", ROMX
INCLUDE "audio/headers/sfxheaders1.asm"

SECTION "Sound Effect Headers 2", ROMX
INCLUDE "audio/headers/sfxheaders2.asm"

SECTION "Sound Effect Headers 3", ROMX
INCLUDE "audio/headers/sfxheaders3.asm"

SFX Categories

From audio.asm:
INCLUDE "audio/sfx/start_menu_1.asm"
INCLUDE "audio/sfx/purchase_1.asm"
INCLUDE "audio/sfx/press_ab_1.asm"
INCLUDE "audio/sfx/save_1.asm"
INCLUDE "audio/sfx/collision_1.asm"
INCLUDE "audio/sfx/ledge_1.asm"
INCLUDE "audio/sfx/push_boulder_1.asm"
INCLUDE "audio/sfx/cut_1.asm"
INCLUDE "audio/sfx/fly_1.asm"
INCLUDE "audio/sfx/teleport_exit1_1.asm"
INCLUDE "audio/sfx/healing_machine_1.asm"
INCLUDE "audio/sfx/heal_hp_1.asm"
INCLUDE "audio/sfx/heal_ailment_1.asm"
INCLUDE "audio/sfx/turn_on_pc_1.asm"
INCLUDE "audio/sfx/turn_off_pc_1.asm"
INCLUDE "audio/sfx/enter_pc_1.asm"

Pokémon Cries

Pokémon cries are special sound effects:
INCLUDE "audio/sfx/cry00_1.asm"
INCLUDE "audio/sfx/cry01_1.asm"
INCLUDE "audio/sfx/cry02_1.asm"
; ... cry03 through cry25 ...
Each cry is synthesized in real-time by modulating Channel 3’s waveform based on parameters stored in data/pokemon/cries.asm.
Pokémon cries are not pre-recorded samples. They’re generated by the audio engine using base waveforms and pitch/length parameters, saving significant ROM space.

Wave Patterns

Channel 3 uses custom 32-sample waveforms:
Audio1_WavePointers:
INCLUDE "audio/wave_samples.asm"
The wave channel can load different waveforms for varied timbres, from smooth sine waves to harsh sawtooths.

Music Headers

Music tracks are organized with headers:
SECTION "Music Headers 1", ROMX
INCLUDE "audio/headers/musicheaders1.asm"

SECTION "Music Headers 2", ROMX
INCLUDE "audio/headers/musicheaders2.asm"

SECTION "Music Headers 3", ROMX
INCLUDE "audio/headers/musicheaders3.asm"
Each header points to channel data for a music track, specifying which channels are used and where their note sequences are stored.

Music Tracks

Some notable tracks:
INCLUDE "audio/music/celadon.asm"
INCLUDE "audio/music/cinnabar.asm"
INCLUDE "audio/music/cities1.asm"
INCLUDE "audio/music/cities2.asm"

Audio Muting

The game can mute audio selectively:
DEF BIT_MUTE_AUDIO EQU 7

; When bit 7 is set in wMuteAudioAndPauseMusic:
ld a, [wMuteAudioAndPauseMusic]
bit BIT_MUTE_AUDIO, a
jr nz, .nextChannel  ; skip music channels
This allows menus and text to mute background music while still playing sound effects.

Low Health Alarm

A special audio feature:
DEF BIT_LOW_HEALTH_ALARM EQU 7
DEF LOW_HEALTH_TIMER_MASK EQU %01111111
DEF DISABLE_LOW_HEALTH_ALARM EQU $ff
When a Pokémon’s HP drops below 20%, a beeping sound plays periodically to alert the player. Implementation in audio/low_health_alarm.asm.

Noise Instruments

Channel 4 (noise) has 19 preset instruments:
INCLUDE "audio/sfx/noise_instrument01_1.asm"
INCLUDE "audio/sfx/noise_instrument02_1.asm"
; ... through noise_instrument19 ...
These provide various percussion and sound effect timbres by configuring the noise channel’s frequency and envelope.

Hardware Registers

The engine directly manipulates Game Boy audio registers:
const_def 1
const REG_DUTY_SOUND_LEN  ; 1
const REG_VOLUME_ENVELOPE ; 2
const REG_FREQUENCY_LO    ; 3
Each channel has multiple registers controlling:
  • Duty cycle (square wave shape)
  • Sound length
  • Volume envelope (fade in/out)
  • Frequency (pitch)
Direct hardware access requires careful timing. Writing to audio registers at the wrong time can cause audio glitches or crashes.

Maps

Map music assignments

Hardware

Game Boy hardware details

Reference

Audio constants reference

Development

Build tools and audio workflow

Key Files

  • audio.asm - Main audio assembly file
  • audio/engine_1.asm - Primary audio engine (duplicated in engines 2 & 3)
  • constants/audio_constants.asm - Audio constants
  • constants/music_constants.asm - Music track IDs
  • audio/headers/ - Music and SFX headers
  • audio/music/ - Music track data
  • audio/sfx/ - Sound effect data
  • audio/wave_samples.asm - Channel 3 waveforms
  • audio/low_health_alarm.asm - Low HP warning sound

Build docs developers (and LLMs) love