Expand description
§banished-audio
Sound for the game and the viewer. It decodes the game’s sounds (xWMA, with banished-wma)
in the program itself, and plays them on a device with 64 channels, as the original
Audio::Device does. On the desktop it plays through rodio;
in the browser it plays through Web Audio. No converted sound files are needed.
| Part | What it does |
|---|---|
decode, load_sound | Decode a SoundBuffer (and the .str stream of music) to float samples |
Sound | A decoded sound and its loop flag. The samples are shared between channels, not copied. |
Device | 64 channels. play takes the first free channel and returns none when all are busy. |
Scene | The layer above the device that plays SoundEffects: timelines, 3D positions, emitters, kinds of sound |
EffectCache | Loads and decodes the sound effects that a scene uses, on all CPU cores natively |
§Use it
[dependencies]
banished-audio = { path = "crates/audio" }
banished-formats = { path = "crates/formats" }On Linux, the build needs the ALSA headers (libasound2-dev and pkg-config).
§Play a sound
use banished_audio::{Device, PlayParams, Sound};
use banished_formats::pkg::Archive;
fn moo(archive: &Archive, device: &mut Device) -> Result<(), String> {
let sound = Sound::load(archive, "Audio/Animal/Cow.rsc:version0")?;
let params = PlayParams { volume: 0.8, pitch: 2.0, ..PlayParams::default() };
match device.play(&sound, params)? {
Some(channel) => println!("playing on channel {}", channel.index()),
None => println!("all 64 channels are busy"),
}
Ok(())
}PlayParams has a start offset, a volume, a pitch in semitones, and an optional loop flag (the
default is the sound’s own flag). Device also has stop, pause, resume, seek,
set_volume, set_pitch, set_looping, set_master_volume and update, which frees the
channels of sounds that ended.
Device::play returns an error when there is no audio output. In the browser, sound starts only
after the player clicks or types on the page; unlock resumes the Web Audio context then.
§Decode without playing
use banished_formats::pkg::Archive;
fn length(archive: &Archive) -> Result<f32, String> {
let (pcm, looping) = banished_audio::load_sound(archive, "Audio/Music/Menu.rsc:music")?;
let frames = pcm.samples.len() / pcm.channels as usize;
println!("looping: {looping}");
Ok(frames as f32 / pcm.sample_rate as f32)
}Pcm has the number of channels, the sample rate, and interleaved samples from -1 to 1.
§Sound effects in a scene
The game does not play sounds directly. It plays SoundEffect resources through a Scene:
an effect is a timeline of sounds with random choices, volumes and pitches. play_effect plays
one for the interface, and play_effect_3d plays one at a position in the world. Emitters
(add_emitter, move_emitter) are ambient sounds tied to a place, such as a river or a forest.
Scene::update mixes them every frame, through any Mixer (the Device is one).
See AUDIO.md for the details.
§Tests
cargo test --release -p banished-audiotests/menu_music.rs decodes the menu music from your game data, and skips without it.
§The API
The full API documentation is at https://tanepiper.github.io/unbanished/api/banished_audio/index.html.
§Related documents
Re-exports§
pub use scene::sound_type;pub use scene::Effect;pub use scene::EffectCache;pub use scene::Mixer;pub use scene::Prepared;pub use scene::Scene;pub use scene::Volumes;
Modules§
Structs§
- Channel
- A playing channel. Handles carry a generation, so one kept after its channel was freed and reused refers to nothing (calls on it do nothing).
- Device
- The multi-channel output (rodio).
- Pcm
- Decoded samples.
- Play
Params - How a channel starts (
Device::Play’s time and floats). - Slots
- Channel bookkeeping without any output: first-free allocation and generations.
- Sound
- A decoded sound buffer (
Audio::SoundBuffer) that any number of channels can play at once; the samples are shared, not copied, per channel.
Constants§
- CHANNELS
Audio::Devicechannel count (loops inFindFreeChannel,Play,Update).
Functions§
- decode
- Decode a
SoundBuffer;streamsupplies the packets of streamed music (its.strentry). - load_
sound - Load and decode a sound by resource reference (e.g.
Audio\\Music\\Menu.rsc:music), reading the.strstream of streamed music. Returns the samples and the resource’s loop flag. - pitch_
ratio - The playback speed for a pitch in semitones: one semitone is the twelfth root of two, as XAudio2’s frequency ratio.