Skip to content

Audio: sound channels & timing

Trace sound from PSG channels and timer-driven FIFOs through mixing and host audio buffers.

5 min read Updated 28 Oct 2026

On this page

GBA sound is generated by emulated hardware activity, not by playing a single music file associated with the game. The game writes sound registers, supplies sample data and uses timers to control playback. GBAx advances that sound state along the same emulated timeline as the CPU and video, then gives the resulting samples to the host audio system.

There are two timing problems to solve. The core must produce the sounds the game requested at the correct emulated moments. The frontend must deliver those samples to the real audio device steadily enough to avoid gaps.

Two families of sound channels

The GBA combines four legacy-style programmable sound channels with two Direct Sound channels. The legacy group contains two pulse channels, a programmable wave channel and a noise channel. Registers control properties such as frequency, envelope, length and routing. The core maintains the evolving state of those generators.

Direct Sound channels A and B instead consume signed 8-bit sample data. The game can use them for voices, percussion or software-mixed music. Their input arrives through FIFO registers: a queue holds samples until a selected timer advances playback. Software commonly configures DMA to refill those queues.

Sound path What the game supplies What the core maintains
Pulse, wave and noise Channel settings and wave data. Generator phase, counters, envelopes and channel state.
Direct Sound A/B Sample bytes, timer selection and FIFO/DMA setup. Queued samples, the currently consumed value and refill activity.
Output mix Routing, volume and bias/resolution settings. Left/right samples and timing before host playback.

Follow one Direct Sound sample

Suppose a game has placed a sequence of sample bytes in work RAM and configured a sound FIFO to use a hardware timer. A timer overflow advances that channel. The core consumes the next sample byte and uses it as the channel’s contribution until playback advances again.

As the FIFO runs low, the audio code can schedule the configured DMA channel to transfer more data. That transfer reads memory and writes the FIFO registers. It is part of the emulated bus activity, so the refill is not a free background copy detached from the CPU’s timeline.

  1. Sample memoryThe game prepares signed sample bytes in RAM.
  2. DMA refillA configured transfer supplies the sound FIFO.
  3. Timer overflowThe selected timer advances Direct Sound playback.
  4. Mix and queueThe core combines channels and buffers output samples.
Direct Sound joins three subsystems: memory transfers, timers and audio. The host speaker is reached only after the resulting mix is delivered by the frontend.

In the reviewed source, timer handling calls GBAAudioSampleFIFO for the channels attached to that timer. The FIFO path can request DMA work through the DMA scheduler. Following those function calls shows why a timing error in a transfer or timer may be heard as an audio error.

Mixing the channels into left and right output

GBAAudioSample advances the legacy sound generators, obtains their contribution and combines it with Direct Sound according to the enabled left/right routing and volume controls. The result passes through bias and range handling before being written as output samples.

Register writes also interact with time. Several sound-register handlers first bring the audio state up to the current timestamp before applying the new setting. That prevents a volume or frequency change from being applied retroactively to a span of sound that should have used the previous value.

The reviewed core initialises its internal sample interval from a 32,768 Hz baseline, and sound-bias resolution settings can change the interval. This is an internal emulation detail, not a guarantee that your operating system’s audio device is configured to that rate. The host output path must bridge the core’s stream and the device’s requirements.

The buffer between emulated time and real time

The core can calculate many samples in a short burst of host execution. Your audio device, however, consumes a continuous stream at its configured rate. A buffer absorbs the difference between those schedules. The frontend and core coordinate access to that buffer so one can produce while the other consumes.

If the device runs out of samples, you may hear a gap, pop or crackle. Increasing a buffer can make playback more tolerant of host scheduling delays, but it can also increase the time between an action and the sound you hear. A very small buffer reduces that cushion. There is no single setting that proves emulation accuracy on every machine.

In the Preview 1 desktop build, SDL audio support is included. The browser player has a separate browser-audio environment and may need a deliberate click or key press before audio can start. A muted browser tab and an incorrect emulated sound register are completely different failure modes, even though both produce silence.

A useful troubleshooting sequence

  1. Check the output path. Confirm that GBAx or the browser tab is not muted and that the intended operating-system audio device is selected.
  2. Use a repeatable scene. Test the same game, location and actions. Record whether the sound is consistently wrong or intermittently interrupted.
  3. Check speed and load. Fast-forward changes the relationship between emulated time and playback. Heavy host load or a backgrounded browser can also change scheduling.
  4. Change one setting at a time. Compare buffer or synchronisation choices where your frontend exposes them, then return to the original setting before testing another variable.
  5. Separate channels from delivery. A missing instrument in the same scene suggests a different investigation from random crackles that disappear when the output setup changes.

A report should include the GBAx build, operating system, audio device, relevant settings and the shortest reliable reproduction. A short recording can demonstrate the symptom, but the scene and setup are what allow someone else to investigate it.

What improved sound can—and cannot—mean

Accurate channel behaviour and good sample handling can remove errors introduced by an emulator. They do not automatically replace the game’s original instruments or turn low-resolution source samples into studio recordings. mGBA’s own development history discusses improvements to audio sampling and edge-case behaviour; those are specific engineering changes, not a blanket promise of remastered audio.

Preview 1 also disables the optional FFmpeg recording integration in its release profile. Playback and recording are separate capabilities. Continue with timers and DMA to see the scheduling machinery that drives Direct Sound, or the troubleshooting guide for a broader diagnosis process.

Sources & implementation

Implementation references follow GBAx 2.0.0 Preview 1, commit c1a826ae. The hardware implementation derives from mGBA; these links point to the matching GBAx source, rather than assuming a newer upstream revision behaves identically.

Further reading: mGBA 0.10: audio development context.

Need help with a specific problem? Start with troubleshooting →