diff --git a/Cargo.toml b/Cargo.toml index b810a3fa4aa2c..77052e413dbe6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -814,6 +814,26 @@ description = "Shows how to create and register a custom audio source by impleme category = "Audio" wasm = true +[[example]] +name = "spatial_audio_2d" +path = "examples/audio/spatial_audio_2d.rs" + +[package.metadata.example.spatial_audio_2d] +name = "Spatial Audio 2D" +description = "Shows how to play spatial audio, and moving the emitter in 2D" +category = "Audio" +wasm = true + +[[example]] +name = "spatial_audio_3d" +path = "examples/audio/spatial_audio_3d.rs" + +[package.metadata.example.spatial_audio_3d] +name = "Spatial Audio 3D" +description = "Shows how to play spatial audio, and moving the emitter in 3D" +category = "Audio" +wasm = true + # Diagnostics [[example]] name = "log_diagnostics" diff --git a/crates/bevy_audio/Cargo.toml b/crates/bevy_audio/Cargo.toml index 8ea7dee8d63b9..43902b12aaabf 100644 --- a/crates/bevy_audio/Cargo.toml +++ b/crates/bevy_audio/Cargo.toml @@ -13,19 +13,21 @@ keywords = ["bevy"] bevy_app = { path = "../bevy_app", version = "0.9.0" } bevy_asset = { path = "../bevy_asset", version = "0.9.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.9.0" } +bevy_math = { path = "../bevy_math", version = "0.9.0" } bevy_reflect = { path = "../bevy_reflect", version = "0.9.0", features = ["bevy"] } +bevy_transform = { path = "../bevy_transform", version = "0.9.0" } bevy_utils = { path = "../bevy_utils", version = "0.9.0" } # other anyhow = "1.0.4" -rodio = { version = "0.16", default-features = false } +rodio = { version = "0.17", default-features = false } parking_lot = "0.12.1" [target.'cfg(target_os = "android")'.dependencies] -oboe = { version = "0.4", optional = true } +oboe = { version = "0.5", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] -rodio = { version = "0.16", default-features = false, features = ["wasm-bindgen"] } +rodio = { version = "0.17", default-features = false, features = ["wasm-bindgen"] } [features] diff --git a/crates/bevy_audio/src/audio.rs b/crates/bevy_audio/src/audio.rs index d7ac8d615795b..fa08641c73fe0 100644 --- a/crates/bevy_audio/src/audio.rs +++ b/crates/bevy_audio/src/audio.rs @@ -1,6 +1,8 @@ -use crate::{AudioSink, AudioSource, Decodable}; +use crate::{AudioSink, AudioSource, Decodable, SpatialAudioSink}; use bevy_asset::{Asset, Handle, HandleId}; use bevy_ecs::system::Resource; +use bevy_math::Vec3; +use bevy_transform::prelude::Transform; use parking_lot::RwLock; use std::{collections::VecDeque, fmt}; @@ -60,7 +62,7 @@ where /// /// Returns a weak [`Handle`] to the [`AudioSink`]. If this handle isn't changed to a /// strong one, the sink will be detached and the sound will continue playing. Changing it - /// to a strong handle allows for control on the playback through the [`AudioSink`] asset. + /// to a strong handle allows you to control the playback through the [`AudioSink`] asset. /// /// ``` /// # use bevy_ecs::system::Res; @@ -83,6 +85,7 @@ where settings: PlaybackSettings::ONCE, sink_handle: id, source_handle: audio_source, + spatial: None, }; self.queue.write().push_back(config); Handle::::weak(id) @@ -115,14 +118,141 @@ where settings, sink_handle: id, source_handle: audio_source, + spatial: None, }; self.queue.write().push_back(config); Handle::::weak(id) } + + /// Play audio from a [`Handle`] to the audio source, placing the listener at the given + /// transform, an ear on each side separated by `gap`. The audio emitter will placed at + /// `emitter`. + /// + /// `bevy_audio` is not using HRTF for spatial audio, but is transforming the sound to a mono + /// track, and then changing the level of each stereo channel according to the distance between + /// the emitter and each ear by amplifying the difference between what the two ears hear. + /// + /// ``` + /// # use bevy_ecs::system::Res; + /// # use bevy_asset::AssetServer; + /// # use bevy_audio::Audio; + /// # use bevy_math::Vec3; + /// # use bevy_transform::prelude::Transform; + /// fn play_spatial_audio_system(asset_server: Res, audio: Res