//! Audio support for the game engine Bevy //! //! ```no_run //! # use bevy_ecs::prelude::*; //! # use bevy_audio::{AudioBundle, AudioPlugin, PlaybackSettings}; //! # use bevy_asset::{AssetPlugin, AssetServer}; //! # use bevy_app::{App, AppExit, NoopPluginGroup as MinimalPlugins, Startup}; //! fn main() { //! App::new() //! .add_plugins((MinimalPlugins, AssetPlugin::default(), AudioPlugin::default())) //! .add_systems(Startup, play_background_audio) //! .run(); //! } //! //! fn play_background_audio(asset_server: Res, mut commands: Commands) { //! commands.spawn(AudioBundle { //! source: asset_server.load("background_audio.ogg"), //! settings: PlaybackSettings::LOOP, //! }); //! } //! ``` #![forbid(unsafe_code)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] mod audio; mod audio_output; mod audio_source; mod pitch; mod sinks; #[allow(missing_docs)] pub mod prelude { #[doc(hidden)] pub use crate::{ AudioBundle, AudioSink, AudioSinkPlayback, AudioSource, AudioSourceBundle, Decodable, GlobalVolume, Pitch, PitchBundle, PlaybackSettings, SpatialAudioSink, SpatialListener, }; } pub use audio::*; pub use audio_source::*; pub use pitch::*; pub use rodio::cpal::Sample as CpalSample; pub use rodio::source::Source; pub use rodio::Sample; pub use sinks::*; use bevy_app::prelude::*; use bevy_asset::{Asset, AssetApp}; use bevy_ecs::prelude::*; use bevy_transform::TransformSystem; use audio_output::*; /// Set for the audio playback systems, so they can share a run condition #[derive(SystemSet, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] struct AudioPlaySet; /// Adds support for audio playback to a Bevy Application /// /// Insert an [`AudioBundle`] onto your entities to play audio. #[derive(Default)] pub struct AudioPlugin { /// The global volume for all audio entities. pub global_volume: GlobalVolume, /// The scale factor applied to the positions of audio sources and listeners for /// spatial audio. pub default_spatial_scale: SpatialScale, } impl Plugin for AudioPlugin { fn build(&self, app: &mut App) { app.register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .insert_resource(self.global_volume) .insert_resource(DefaultSpatialScale(self.default_spatial_scale)) .configure_sets( PostUpdate, AudioPlaySet .run_if(audio_output_available) .after(TransformSystem::TransformPropagate), // For spatial audio transforms ) .add_systems( PostUpdate, (update_emitter_positions, update_listener_positions).in_set(AudioPlaySet), ) .init_resource::(); #[cfg(any(feature = "mp3", feature = "flac", feature = "wav", feature = "vorbis"))] { app.add_audio_source::(); app.init_asset_loader::(); } app.add_audio_source::(); } } impl AddAudioSource for App { fn add_audio_source(&mut self) -> &mut Self where T: Decodable + Asset, f32: rodio::cpal::FromSample, { self.init_asset::().add_systems( PostUpdate, (play_queued_audio_system::, cleanup_finished_audio::).in_set(AudioPlaySet), ); self } }