Module agb::sound::mixer

source ·
Expand description

agb mixer

The agb software mixer allows for high performance playing of background music and sound effects.

Most games will need some form of sound effects or background music. The GBA has no hardware sound mixer, so in order to play more than one sound at once, you have to use a software mixer.

agb’s software mixer allows for up to 8 simultaneous sounds played at once at various speeds and volumes.

Concepts

The mixer runs at a fixed frequency which is determined at initialisation time by passing certain Frequency options.

All wav files you use within your application / game must use this exact frequency. If you don’t use this frequency, the sound will play either too slowly or too quickly.

The mixer can play both mono and stereo sounds, but only mono sound effects can have effects applied to them (such as changing the speed at which they play or the panning). Since the sound mixer runs in software, you must do some sound mixing every frame.

Creating the mixer

To create a sound mixer, you will need to get it out of the Gba struct as follows:

use agb::sound::mixer::Frequency;
let mut mixer = gba.mixer.mixer(Frequency::Hz10512);
mixer.enable();

Pass a frequency option. This option must be used for the entire lifetime of the mixer variable. If you want to change frequency, you will need to drop this one and create a new one.

Doing the per-frame work

Despite being high performance, the mixer still takes a sizable portion of CPU time (6-10% depending on number of channels and frequency) to do the per-frame tasks, so should be done towards the end of the frame time (just before waiting for vblank) in order to give as much time during vblank as possible for rendering related tasks.

In order to avoid skipping audio, call the Mixer::frame() function at least once per frame as shown below:

use agb::sound::mixer::Frequency;
let mut mixer = gba.mixer.mixer(Frequency::Hz10512);
let vblank = agb::interrupt::VBlank::get();
// Somewhere in your main loop:
mixer.frame();
vblank.wait_for_vblank();

Loading a sample

To load a sample, you must have it in wav format (both stereo and mono work) at exactly the selected frequency based on the features enabled in the agb crate.

Use the include_wav! macro in order to load the sound. This will produce an error if your wav file is of the wrong frequency.

// Outside your main function in global scope:
const MY_CRAZY_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav");

// Then to play the sound:
let mut channel = SoundChannel::new(MY_CRAZY_SOUND);
channel.stereo();
let _ = mixer.play_sound(channel); // we don't mind if this sound doesn't actually play

See the SoundChannel struct for more details on how you can configure the sounds to play.

Once you have run play_sound, the mixer will play that sound until it has finished.

Structs

  • A pointer to a currently playing channel.
  • The main software mixer struct.
  • Controls access to the mixer and the underlying hardware it uses. A zero sized type that ensures that mixer access is exclusive.
  • Describes one sound which should be playing. This could be a sound effect or the background music. Use the factory methods on this to modify how it is played.

Enums

  • The supported frequencies within AGB. These are chosen to work well with the hardware. Note that the higher the frequency, the better the quality of the sound but the more CPU time sound mixing will take.