bevy_kira_audio
repository·main·Indexed 19 days ago
https://github.com/niklasei/bevy_kira_audioA Bevy plugin that integrates the Kira audio engine to provide a robust alternative to Bevy's default audio system. It supports multiple formats (ogg, mp3, wav, flac), channel-based control, smooth audio transitions via AudioTween, and limited spatial audio support. Version 0.26.0.
What's inside bevy_kira_audio
- The plugin currently offers limited spatial audio support. It automatically adjusts the volume and panning of an audio source based on the relative positions of the emitter and the receiver.
How audio channels and instances work
mainThe plugin provides two primary ways to manage audio:
- Audio Channels: You can control an entire channel. Changes to a channel (like volume, panning, or playback speed) affect all sounds playing within that channel. Channels can be customized and accessed via Bevy's ECS.
- Audio Instances: You can control a single, specific instance of a playing sound independently of its channel.
Both methods support audio transitions using Tweens and various easing functions.
Run bevy_kira_audio examples
mainYou can explore the capabilities of
bevy_kira_audioby running the provided examples. Use the following command to run a specific example:cargo run --example <example_name>Available examples include:
basic: Basic functionality display.channel_control: Controlling an audio channel.custom_channel: Adding and using a custom audio channel.dynamic_channels: Using dynamic audio channels.instance_control: Controlling a single audio instance.multiple_channels: GUI application with control over three different audio channels.settings: Supported settings when playing a sound.settings_loader: Loading a sound with applied settings.spatial: Limited support for spatial audio.status: Continuously getting the playback state of a sound.stress_test: Playing a high number of sounds every frame.
cargo run --example basicSetup bevy_kira_audio in a Bevy project
mainTo use
bevy_kira_audio, you must disable Bevy's defaultaudiofeature, as it is incompatible. When configuring your Bevy dependencies, ensure you use the default features minusaudio(e.g.,"2d", "3d", "ui").To play audio files, you must enable the corresponding format features in
bevy_kira_audio:ogg(enabled by default),mp3,wav, orflac.use bevy_kira_audio::prelude::*; use bevy::prelude::*; fn main() { App::new() .add_plugins((DefaultPlugins, AudioPlugin)) .add_systems(Startup, start_background_audio) .run(); } fn start_background_audio(asset_server: Res<AssetServer>, audio: Res<Audio>) { audio.play(asset_server.load("background_audio.ogg")).looped(); }How Audio channels and the MainTrack work
mainThe audio engine is organized into channels. By default, the plugin provides a
MainTrackwhich is exposed via theAudiotype alias (type Audio = AudioChannel<MainTrack>;).- MainTrack: The default channel used for general audio playback.
- AudioChannel<T>: A resource used to play and control sounds on a specific track. You can define your own custom channels using
AudioApp::add_audio_channel.
Identify audio channels using Channel enum
mainAudio can be organized into channels to allow for grouped control. The
Channelenum supports two types of identification:Typed(TypeId): Uses a RustTypeIdfor type-safe channel identification.Dynamic(String): Uses a string identifier for flexible, name-based channel management.
#[derive(Clone, PartialEq, Eq, Hash)] pub enum Channel { Typed(TypeId), Dynamic(String), }Load audio with pre-configured settings via RON
mainIf the
settings_loaderfeature is enabled, you can define audio settings in.ronfiles. This allows you to load anAudioSourcethat already has specific behaviors (like looping or intros) applied by default.Example
.ronconfiguration for a looping sound with a 3-second intro:( // The actual sound asset in your assets directory asset: "sounds/loop.ogg", loop_behavior: Some(3.0), )How spatial audio emitters and receivers work together
mainSpatial audio is implemented using a producer-consumer model with two primary components:
SpatialAudioReceiver: Represents the listener (e.g., the Camera or the Player). Important: There can only be exactly one entity with this component in the world at any given time.SpatialAudioEmitter: Represents the source of the sound. You add this to entities that should emit sound. It holds a list ofHandle<AudioInstance>s that will be automatically panned and attenuated based on the distance and angle to the receiver.
The plugin calculates volume based on distance (attenuation) and panning based on the angle relative to the receiver's orientation.
// Example setup // 1. The Receiver (usually on the camera) commands.spawn((Camera3dBundle::default(), SpatialAudioReceiver)); // 2. The Emitter (on a sound-producing entity) commands.spawn((SpatialAudioEmitter { instances: vec![my_audio_handle] }, Transform::from_xyz(10.0, 0.0, 0.0)));Install and setup the AudioPlugin
mainTo use
bevy_kira_audio, add theAudioPluginto your BevyApp. This initializes theAudioresource (the defaultMainTrack), asset loaders for supported formats (MP3, OGG, WAV, FLAC, etc.), and the internal audio management systems.Note that you must also include Bevy's
AssetPluginfor the audio assets to load correctly.use bevy_kira_audio::prelude easily; use bevy::prelude easily; use bevy::asset::AssetPlugin; fn main() { App::new() .add_plugins(MinimalPlugins) .add_plugins(AssetPlugin::default()) .add_plugins(AudioPlugin) .add_systems(Startup, start_background_audio) .run(); } fn start_background_audio(asset_server: Res<AssetServer>, audio: Res<Audio>) { // Play a looped background track audio.play(asset_server.load("background_audio.mp3")).looped(); }Set up the SpatialAudioPlugin
mainTo enable spatial audio in your Bevy application, add the
SpatialAudioPluginto yourApp. This plugin manages the relationship between audio emitters and a receiver, calculating volume attenuation and panning based on their relative positions in 3D space.use bevy::prelude::*; use bevy_kira_audio::SpatialAudioPlugin; fn main() { App::new() .add_plugins(DefaultPlugins) .add_plugins(SpatialAudioPlugin) .run(); }Add audio channels to your Bevy App
mainTo use typed audio channels, use the
add_audio_channel::<T>()extension method on your BevyApp. This registers the necessary systems and inserts theAudioChannel<T>resource.- Define a marker struct for your channel.
- Call
.add_audio_channel::<YourMarker>()during app setup. - Access the channel via
Res<AudioChannel<YourMarker>>in your systems.
use bevy::prelude::*; use bevy_kira_audio::prelude::*; #[derive(Resource)] struct Background; fn main() { App::new() .add_plugins(DefaultPlugins) .add_plugins(AudioPlugin) .add_audio_channel::<Background>() // Register the channel .add_systems(Startup, setup_audio) .run(); } fn setup_audio(mut background: ResMut<AudioChannel<Background>>, asset_server: Res<AssetServer>) { // Use the channel to play a sound background.play(asset_server.load("sounds/loop.ogg")); }Configure sound settings and playback behavior
mainYou can configure audio properties like volume, panning, playback rate, and looping at the moment of playback. Most changes can be applied as smooth transitions using
AudioTweenandAudioEasing.Key methods for configuring playback:
.loop_from(duration): Sets a specific point in the track to loop from (useful for 'intro' sections)..fade_in(AudioTween): Smoothly increases volume..with_panning(value): Sets stereo panning (e.g.,1.0for right ear)..with_playback_rate(value): Changes speed and pitch..with_volume(decibels): Sets volume in decibels..reverse(): Plays the track in reverse.
use bevy_kira_audio::prelude::*; use bevy::prelude::*; use std::time::Duration; fn play_audio(asset_server: Res<AssetServer>, audio: Res<Audio>) { audio.play(asset_server.load("background_audio.ogg")) // The first 0.5 seconds will not be looped and are the "intro" .loop_from(0.5) // Fade-in with a dynamic easing .fade_in(AudioTween::new(Duration::from_secs(2), AudioEasing::OutPowi(2))) // Only play on our right ear .with_panning(1.0) // Increase playback rate by 50% (this also increases the pitch) .with_playback_rate(1.5) // Play at lower volume (-10dB) .with_volume(-10.) // play the track reversed .reverse(); }