diff --git a/agb/src/sound/mixer/mod.rs b/agb/src/sound/mixer/mod.rs index 134fb60..42daed0 100644 --- a/agb/src/sound/mixer/mod.rs +++ b/agb/src/sound/mixer/mod.rs @@ -1,3 +1,99 @@ +//! # 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 compile time by enabling +//! certain features within the crate. The following features are currently available: +//! +//! | Feature | Frequency | +//! |---------|-----------| +//! | none | 10512Hz | +//! | freq18157 | 18157Hz | +//! | freq32768[^32768Hz] | 32768Hz | +//! +//! All wav files you use within your application / game must use this _exact_ frequency. +//! You will get a compile error if you use the incorrect frequency for your file. +//! +//! 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`](crate::Gba) struct +//! as follows: +//! +//! ``` +//! let mut mixer = gba.mixer.mixer(); +//! mixer.enable(); +//! ``` +//! +//! ## Doing the per-frame work +//! +//! Then, you have a choice of whether you want to use interrupts or do the buffer swapping +//! yourself after a vblank interrupt. If you are using 32768Hz as the frequency of your +//! files, you _must_ use the interrupt version. +//! +//! Without interrupts: +//! +//! ``` +//! // Somewhere in your main loop: +//! mixer.frame(); +//! vblank.wait_for_vblank(); +//! mixer.after_vblank(); +//! ``` +//! +//! Or with interrupts: +//! +//! ``` +//! // outside your main loop, close to initialisation +//! let _mixer_interrupt = mixer.setup_interrupt_handler(); +//! +//! // inside your main loop +//! mixer.frame(); +//! vblank.wait_for_vblank(); +//! ``` +//! +//! 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. +//! +//! ## 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!`](crate::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!("sfx/my_crazy_sound.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`](Mixer::play_sound), the mixer will play that sound until +//! it has finished. +//! +//! [^32768Hz]: You must use interrupts when using 32768Hz + mod hw; mod sw_mixer; diff --git a/agb/src/sound/mod.rs b/agb/src/sound/mod.rs index 1236802..f72600e 100644 --- a/agb/src/sound/mod.rs +++ b/agb/src/sound/mod.rs @@ -1,2 +1,17 @@ +//! # Game Boy Advance audio +//! +//! The GBA has 2 different ways of producing sound, which agb has support for. +//! You currently cannot use both at the same time, and currently there is no +//! compile time prevention of using both, but you should either use the DMG +//! which allows for Game Boy and Game Boy Color style sound effects, or the mixer +//! which allows for more advanced sounds. +//! +//! The [`dmg`](crate::sound::dmg) module is very rudimentry and doesn't support most of the possible +//! sounds possible. However, it may be expanded in the future. +//! +//! The [`mixer`](crate::sound::mixer) module is high performance, and allows for playing wav files at +//! various levels of quality. Check out the module documentation for more. + pub mod dmg; + pub mod mixer;