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.