1#![forbid(unsafe_code)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc(
4 html_logo_url = "https://bevy.org/assets/icon.png",
5 html_favicon_url = "https://bevy.org/assets/icon.png"
6)]
7
8extern crate alloc;
31
32mod audio;
33mod audio_output;
34mod audio_source;
35mod pitch;
36mod sinks;
37mod volume;
38
39pub mod prelude {
43 #[doc(hidden)]
44 pub use crate::{
45 AudioPlayer, AudioSink, AudioSinkPlayback, AudioSource, Decodable, GlobalVolume, Pitch,
46 PlaybackSettings, SpatialAudioSink, SpatialListener,
47 };
48}
49
50pub use audio::*;
51pub use audio_source::*;
52pub use pitch::*;
53pub use volume::*;
54
55pub use rodio::{cpal::Sample as CpalSample, source::Source, Sample};
56pub use sinks::*;
57
58use bevy_app::prelude::*;
59use bevy_asset::{Asset, AssetApp};
60use bevy_ecs::prelude::*;
61use bevy_transform::TransformSystems;
62
63use audio_output::*;
64
65#[derive(SystemSet, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
67struct AudioPlaybackSystems;
68
69#[derive(Default)]
73pub struct AudioPlugin {
74 pub global_volume: GlobalVolume,
76 pub default_spatial_scale: SpatialScale,
79}
80
81impl Plugin for AudioPlugin {
82 fn build(&self, app: &mut App) {
83 app.insert_resource(self.global_volume)
84 .insert_resource(DefaultSpatialScale(self.default_spatial_scale))
85 .configure_sets(
86 PostUpdate,
87 AudioPlaybackSystems
88 .run_if(audio_output_available)
89 .after(TransformSystems::Propagate), )
91 .add_systems(
92 PostUpdate,
93 (update_emitter_positions, update_listener_positions).in_set(AudioPlaybackSystems),
94 )
95 .init_resource::<AudioOutput>();
96
97 #[cfg(any(feature = "mp3", feature = "flac", feature = "wav", feature = "vorbis"))]
98 {
99 app.add_audio_source::<AudioSource>();
100 app.init_asset_loader::<AudioLoader>();
101 }
102
103 app.add_audio_source::<Pitch>();
104 }
105}
106
107impl AddAudioSource for App {
108 fn add_audio_source<T>(&mut self) -> &mut Self
109 where
110 T: Decodable + Asset,
111 f32: rodio::cpal::FromSample<T::DecoderItem>,
112 {
113 self.init_asset::<T>().add_systems(
114 PostUpdate,
115 (play_queued_audio_system::<T>, cleanup_finished_audio::<T>)
116 .in_set(AudioPlaybackSystems),
117 );
118 self
119 }
120}