diff --git a/.github/workflows/update-caches.yml b/.github/workflows/update-caches.yml index 0a1d137271b96..add43e0579379 100644 --- a/.github/workflows/update-caches.yml +++ b/.github/workflows/update-caches.yml @@ -83,7 +83,7 @@ jobs: target: aarch64-linux-android - os: macos-14 toolchain: stable - target: aarch64-apple-ios-sim + target: arm64-apple-ios-simulator steps: # prepare the date - used to rebuild the cache daily to update the cache for rust nightly, even if no change on Bevy dependencies diff --git a/.github/workflows/validation-jobs.yml b/.github/workflows/validation-jobs.yml index 7d3d75d9df11f..7c38c457e3c51 100644 --- a/.github/workflows/validation-jobs.yml +++ b/.github/workflows/validation-jobs.yml @@ -36,11 +36,11 @@ jobs: - uses: actions/cache/restore@v4 with: # key won't match, will rely on restore-keys - key: ${{ runner.os }}-stable-aarch64-apple-ios-sim-${{ hashFiles('**/Cargo.toml') }}- + key: ${{ runner.os }}-stable-arm64-apple-ios-simulator-${{ hashFiles('**/Cargo.toml') }}- # See .github/workflows/validation-jobs.yml for how keys are generated restore-keys: | - ${{ runner.os }}-stable-aarch64-apple-ios-sim-${{ hashFiles('**/Cargo.toml') }}- - ${{ runner.os }}-stable-aarch64-apple-ios-sim- + ${{ runner.os }}-stable-arm64-apple-ios-simulator-${{ hashFiles('**/Cargo.toml') }}- + ${{ runner.os }}-stable-arm64-apple-ios-simulator- path: | ~/.cargo/bin/ ~/.cargo/registry/index/ @@ -49,7 +49,7 @@ jobs: target/ - name: Add iOS targets - run: rustup target add aarch64-apple-ios-sim + run: rustup target add arm64-apple-ios-simulator - name: Build and install iOS app in iOS Simulator. run: cd examples/mobile && make install diff --git a/Cargo.toml b/Cargo.toml index ce3b87468e628..fdf003185ff40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -194,7 +194,6 @@ default_app = [ default_platform = [ "std", "android-game-activity", - "android_shared_stdcxx", "bevy_gilrs", "bevy_winit", "default_font", @@ -488,35 +487,35 @@ zstd_rust = ["bevy_internal/zstd_rust"] # For KTX2 Zstandard decompression using [zstd](https://crates.io/crates/zstd). This is a faster backend, but uses unsafe C bindings. For the safe option, stick to the default backend with "zstd_rust". zstd_c = ["bevy_internal/zstd_c"] -# FLAC audio format support -flac = ["bevy_internal/flac"] +# FLAC audio format support (through `claxon`) +fallback-flac = ["bevy_internal/fallback-flac"] -# MP3 audio format support -mp3 = ["bevy_internal/mp3"] +# OGG/VORBIS audio format support (through `symphonia`) +fallback-vorbis = ["bevy_internal/fallback-vorbis"] -# OGG/VORBIS audio format support -vorbis = ["bevy_internal/vorbis"] +# WAV audio format support (through `hound`) +fallback-wav = ["bevy_internal/fallback-wav"] -# WAV audio format support -wav = ["bevy_internal/wav"] +# AAC audio format support (through `symphonia`) +aac = ["bevy_internal/aac"] -# AAC audio format support (through symphonia) -symphonia-aac = ["bevy_internal/symphonia-aac"] +# AAC, FLAC, MP3, MP4, WAV (through `symphonia`) and OGG/VORBIS (through `lewton`) audio formats support +audio-all = ["bevy_internal/audio-all"] -# AAC, FLAC, MP3, MP4, OGG/VORBIS, and WAV audio formats support (through symphonia) -symphonia-all = ["bevy_internal/symphonia-all"] +# FLAC audio format support (through `symphonia`) +flac = ["bevy_internal/flac"] -# FLAC audio format support (through symphonia) -symphonia-flac = ["bevy_internal/symphonia-flac"] +# MP4 audio format support (through `symphonia`). It also enables AAC support. +mp4 = ["bevy_internal/mp4"] -# MP4 audio format support (through symphonia) -symphonia-isomp4 = ["bevy_internal/symphonia-isomp4"] +# MP3 audio format support (through `symphonia`) +mp3 = ["bevy_internal/mp3"] -# OGG/VORBIS audio format support (through symphonia) -symphonia-vorbis = ["bevy_internal/symphonia-vorbis"] +# OGG/VORBIS audio format support (through `lewton`) +vorbis = ["bevy_internal/vorbis"] -# WAV audio format support (through symphonia) -symphonia-wav = ["bevy_internal/symphonia-wav"] +# WAV audio format support (through `symphonia`) +wav = ["bevy_internal/wav"] # Enable serialization support through serde serialize = ["bevy_internal/serialize"] @@ -551,9 +550,6 @@ morph = ["bevy_internal/morph"] # Enables bevy_mesh and bevy_animation morph weight support morph_animation = ["bevy_internal/morph_animation"] -# Enable using a shared stdlib for cxx on Android -android_shared_stdcxx = ["bevy_internal/android_shared_stdcxx"] - # Enable detailed trace event logging. These trace events are expensive even when off, thus they require compile time opt-in detailed_trace = ["bevy_internal/detailed_trace"] @@ -4923,3 +4919,7 @@ name = "Mirror" description = "Demonstrates how to create a mirror with a second camera" category = "3D Rendering" wasm = true + +[patch.crates-io] +cpal = { git = "https://github.com/RustAudio/cpal.git", rev = "e32ee65a5335301553cc9650b949b868f922d748" } +rodio = { git = "https://github.com/philpax/rodio.git", rev = "1a66725ce9ecfd7a89ba780e249477cdd8c644e0" } diff --git a/crates/bevy_audio/Cargo.toml b/crates/bevy_audio/Cargo.toml index 586d3045b791d..2d5f6f0f1dd18 100644 --- a/crates/bevy_audio/Cargo.toml +++ b/crates/bevy_audio/Cargo.toml @@ -18,22 +18,17 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.18.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.18.0-dev" } # other -# TODO: Remove `coreaudio-sys` dep below when updating `cpal`. -rodio = { version = "0.20", default-features = false } +rodio = { version = "0.21", default-features = false, features = ["playback"] } tracing = { version = "0.1", default-features = false, features = ["std"] } [target.'cfg(target_os = "android")'.dependencies] -cpal = { version = "0.15", optional = true } - -[target.'cfg(target_vendor = "apple")'.dependencies] -# NOTE: Explicitly depend on this patch version to fix: -# https://github.com/bevyengine/bevy/issues/18893 -coreaudio-sys = { version = "0.2.17", default-features = false } +cpal = { version = "0.16", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] # TODO: Assuming all wasm builds are for the browser. Require `no_std` support to break assumption. -rodio = { version = "0.20", default-features = false, features = [ +rodio = { version = "0.21", default-features = false, features = [ "wasm-bindgen", + "playback", ] } bevy_app = { path = "../bevy_app", version = "0.18.0-dev", default-features = false, features = [ "web", @@ -43,18 +38,24 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.18.0-dev", default-featu ] } [features] +fallback-flac = ["rodio/claxon"] +fallback-wav = ["rodio/hound"] +# TODO: Swap fallback-vorbis and vorbis features +# once https://github.com/RustAudio/rodio/issues/775 is resolved +fallback-vorbis = ["rodio/vorbis"] mp3 = ["rodio/mp3"] +mp4 = ["rodio/mp4"] flac = ["rodio/flac"] wav = ["rodio/wav"] -vorbis = ["rodio/vorbis"] -symphonia-aac = ["rodio/symphonia-aac"] -symphonia-all = ["rodio/symphonia-all"] -symphonia-flac = ["rodio/symphonia-flac"] -symphonia-isomp4 = ["rodio/symphonia-isomp4"] -symphonia-vorbis = ["rodio/symphonia-vorbis"] -symphonia-wav = ["rodio/symphonia-wav"] -# Enable using a shared stdlib for cxx on Android. -android_shared_stdcxx = ["cpal/oboe-shared-stdcxx"] +vorbis = ["rodio/lewton"] +aac = ["rodio/symphonia-aac"] +audio-all = [ + "rodio/flac", + "rodio/mp3", + "rodio/mp4", + "rodio/lewton", + "rodio/wav", +] [lints] workspace = true diff --git a/crates/bevy_audio/src/audio_output.rs b/crates/bevy_audio/src/audio_output.rs index d02d326501298..15236b6678ff7 100644 --- a/crates/bevy_audio/src/audio_output.rs +++ b/crates/bevy_audio/src/audio_output.rs @@ -6,42 +6,25 @@ use bevy_asset::{Asset, Assets}; use bevy_ecs::{prelude::*, system::SystemParam}; use bevy_math::Vec3; use bevy_transform::prelude::GlobalTransform; -use rodio::{OutputStream, OutputStreamHandle, Sink, Source, SpatialSink}; +use rodio::{OutputStream, OutputStreamBuilder, Sink, Source, SpatialSink}; use tracing::warn; use crate::{AudioSink, AudioSinkPlayback}; /// Used internally to play audio on the current "audio device" -/// -/// ## Note -/// -/// Initializing this resource will leak [`OutputStream`] -/// using [`std::mem::forget`]. -/// This is done to avoid storing this in the struct (and making this `!Send`) -/// while preventing it from dropping (to avoid halting of audio). -/// -/// This is fine when initializing this once (as is default when adding this plugin), -/// since the memory cost will be the same. -/// However, repeatedly inserting this resource into the app will **leak more memory**. #[derive(Resource)] pub(crate) struct AudioOutput { - stream_handle: Option, + stream: Option, } impl Default for AudioOutput { fn default() -> Self { - if let Ok((stream, stream_handle)) = OutputStream::try_default() { - // We leak `OutputStream` to prevent the audio from stopping. - core::mem::forget(stream); - Self { - stream_handle: Some(stream_handle), - } - } else { - warn!("No audio device found."); - Self { - stream_handle: None, - } - } + let stream = OutputStreamBuilder::open_default_stream() + .inspect_err(|_err| { + warn!("No audio device found."); + }) + .ok(); + Self { stream } } } @@ -111,12 +94,13 @@ pub(crate) fn play_queued_audio_system( default_spatial_scale: Res, mut commands: Commands, ) where - f32: rodio::cpal::FromSample, + f32: rodio::cpal::FromSample, { - let Some(stream_handle) = audio_output.stream_handle.as_ref() else { + let Some(stream) = audio_output.stream.as_ref() else { // audio output unavailable; cannot play sound return; }; + let mixer = stream.mixer(); for (entity, source_handle, settings, maybe_emitter_transform) in &query_nonplaying { let Some(audio_source) = audio_sources.get(&source_handle.0) else { @@ -144,18 +128,12 @@ pub(crate) fn play_queued_audio_system( Vec3::ZERO.into() }; - let sink = match SpatialSink::try_new( - stream_handle, + let sink = SpatialSink::connect_new( + mixer, emitter_translation, (left_ear * scale).into(), (right_ear * scale).into(), - ) { - Ok(sink) => sink, - Err(err) => { - warn!("Error creating spatial sink: {err:?}"); - continue; - } - }; + ); let decoder = audio_source.decoder(); @@ -226,14 +204,7 @@ pub(crate) fn play_queued_audio_system( .insert((sink, PlaybackRemoveMarker)), }; } else { - let sink = match Sink::try_new(stream_handle) { - Ok(sink) => sink, - Err(err) => { - warn!("Error creating sink: {err:?}"); - continue; - } - }; - + let sink = Sink::connect_new(mixer); let decoder = audio_source.decoder(); match settings.mode { @@ -359,7 +330,7 @@ pub(crate) fn cleanup_finished_audio( /// Run Condition to only play audio if the audio output is available pub(crate) fn audio_output_available(audio_output: Res) -> bool { - audio_output.stream_handle.is_some() + audio_output.stream.is_some() } /// Updates spatial audio sinks when emitter positions change. diff --git a/crates/bevy_audio/src/audio_source.rs b/crates/bevy_audio/src/audio_source.rs index 9cf3ca988b0b1..57275d1c637a6 100644 --- a/crates/bevy_audio/src/audio_source.rs +++ b/crates/bevy_audio/src/audio_source.rs @@ -30,10 +30,11 @@ impl AsRef<[u8]> for AudioSource { /// /// This asset loader supports different audio formats based on the enable Bevy features. /// The feature `bevy/vorbis` enables loading from `.ogg` files and is enabled by default. -/// Other file endings can be loaded from with additional features: +/// Other file extensions can be loaded from with additional features: /// `.mp3` with `bevy/mp3` -/// `.flac` with `bevy/flac` -/// `.wav` with `bevy/wav` +/// `.flac` with `bevy/flac` or `bevy/fallback-flac` +/// `.wav` with `bevy/wav` or `bevy/fallback-wav` +/// The `bevy/audio-all` feature will enable all file extensions. #[derive(Default)] pub struct AudioLoader; @@ -57,17 +58,17 @@ impl AssetLoader for AudioLoader { fn extensions(&self) -> &[&str] { &[ - #[cfg(feature = "mp3")] + #[cfg(any(feature = "mp3", feature = "audio-all"))] "mp3", - #[cfg(feature = "flac")] + #[cfg(any(feature = "flac", feature = "fallback-flac", feature = "audio-all"))] "flac", - #[cfg(feature = "wav")] + #[cfg(any(feature = "wav", feature = "fallback-wav", feature = "audio-all"))] "wav", - #[cfg(feature = "vorbis")] + #[cfg(any(feature = "vorbis", feature = "fallback-vorbis", feature = "audio-all"))] "oga", - #[cfg(feature = "vorbis")] + #[cfg(any(feature = "vorbis", feature = "fallback-vorbis", feature = "audio-all"))] "ogg", - #[cfg(feature = "vorbis")] + #[cfg(any(feature = "vorbis", feature = "fallback-vorbis", feature = "audio-all"))] "spx", ] } @@ -80,22 +81,16 @@ impl AssetLoader for AudioLoader { /// This trait is implemented for [`AudioSource`]. /// Check the example [`decodable`](https://github.com/bevyengine/bevy/blob/latest/examples/audio/decodable.rs) for how to implement this trait on a custom type. pub trait Decodable: Send + Sync + 'static { - /// The type of the audio samples. - /// Usually a [`u16`], [`i16`] or [`f32`], as those implement [`rodio::Sample`]. - /// Other types can implement the [`rodio::Sample`] trait as well. - type DecoderItem: rodio::Sample + Send + Sync; - /// The type of the iterator of the audio samples, - /// which iterates over samples of type [`Self::DecoderItem`]. + /// which iterates over samples of type [`rodio::Sample`]. /// Must be a [`rodio::Source`] so that it can provide information on the audio it is iterating over. - type Decoder: rodio::Source + Send + Iterator; + type Decoder: rodio::Source + Send + Iterator; /// Build and return a [`Self::Decoder`] of the implementing type fn decoder(&self) -> Self::Decoder; } impl Decodable for AudioSource { - type DecoderItem = > as Iterator>::Item; type Decoder = rodio::Decoder>; fn decoder(&self) -> Self::Decoder { @@ -115,5 +110,5 @@ pub trait AddAudioSource { fn add_audio_source(&mut self) -> &mut Self where T: Decodable + Asset, - f32: rodio::cpal::FromSample; + f32: rodio::cpal::FromSample; } diff --git a/crates/bevy_audio/src/lib.rs b/crates/bevy_audio/src/lib.rs index 3fd7aed5ee524..46c69eb22410c 100644 --- a/crates/bevy_audio/src/lib.rs +++ b/crates/bevy_audio/src/lib.rs @@ -52,7 +52,7 @@ pub use audio_source::*; pub use pitch::*; pub use volume::*; -pub use rodio::{cpal::Sample as CpalSample, source::Source, Sample}; +pub use rodio::{cpal::Sample as CpalSample, source::Source, ChannelCount, Sample, SampleRate}; pub use sinks::*; use bevy_app::prelude::*; @@ -108,7 +108,7 @@ impl AddAudioSource for App { fn add_audio_source(&mut self) -> &mut Self where T: Decodable + Asset, - f32: rodio::cpal::FromSample, + f32: rodio::cpal::FromSample, { self.init_asset::().add_systems( PostUpdate, diff --git a/crates/bevy_audio/src/pitch.rs b/crates/bevy_audio/src/pitch.rs index d85b9b31cf071..2869ed9c5d333 100644 --- a/crates/bevy_audio/src/pitch.rs +++ b/crates/bevy_audio/src/pitch.rs @@ -26,7 +26,6 @@ impl Pitch { } impl Decodable for Pitch { - type DecoderItem = ::Item; type Decoder = TakeDuration; fn decoder(&self) -> Self::Decoder { diff --git a/crates/bevy_audio/src/sinks.rs b/crates/bevy_audio/src/sinks.rs index 1e020d1fd8d71..4e94731bb3c9a 100644 --- a/crates/bevy_audio/src/sinks.rs +++ b/crates/bevy_audio/src/sinks.rs @@ -412,7 +412,7 @@ mod tests { #[test] fn test_audio_sink() { - let (sink, _queue_rx) = Sink::new_idle(); + let (sink, _queue_rx) = Sink::new(); let audio_sink = AudioSink::new(sink); test_audio_sink_playback(audio_sink); } diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index c894e3664405f..5ca3160645eec 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -90,14 +90,14 @@ force_disable_dlss = [ # Audio format support (vorbis is enabled by default) flac = ["bevy_audio/flac"] mp3 = ["bevy_audio/mp3"] +mp4 = ["bevy_audio/mp4"] vorbis = ["bevy_audio/vorbis"] wav = ["bevy_audio/wav"] -symphonia-aac = ["bevy_audio/symphonia-aac"] -symphonia-all = ["bevy_audio/symphonia-all"] -symphonia-flac = ["bevy_audio/symphonia-flac"] -symphonia-isomp4 = ["bevy_audio/symphonia-isomp4"] -symphonia-vorbis = ["bevy_audio/symphonia-vorbis"] -symphonia-wav = ["bevy_audio/symphonia-wav"] +aac = ["bevy_audio/aac"] +audio-all = ["bevy_audio/audio-all"] +fallback-flac = ["bevy_audio/fallback-flac"] +fallback-vorbis = ["bevy_audio/fallback-vorbis"] +fallback-wav = ["bevy_audio/fallback-wav"] # Shader formats shader_format_glsl = [ @@ -261,9 +261,6 @@ bevy_gltf = ["dep:bevy_gltf", "bevy_scene", "bevy_pbr"] # Used to disable code that is unsupported when Bevy is dynamically linked dynamic_linking = ["bevy_diagnostic/dynamic_linking"] -# Enable using a shared stdlib for cxx on Android. -android_shared_stdcxx = ["bevy_audio/android_shared_stdcxx"] - # Enable AccessKit on Unix backends (currently only works with experimental # screen readers and forks.) accesskit_unix = ["bevy_winit/accesskit_unix"] diff --git a/deny.toml b/deny.toml index a203dfaaa8808..4f2fb38ab1151 100644 --- a/deny.toml +++ b/deny.toml @@ -48,9 +48,6 @@ exceptions = [ { name = "symphonia-codec-aac", allow = [ "MPL-2.0", ] }, - { name = "symphonia-codec-adpcm", allow = [ - "MPL-2.0", - ] }, { name = "symphonia-codec-pcm", allow = [ "MPL-2.0", ] }, @@ -63,6 +60,9 @@ exceptions = [ { name = "symphonia-format-isomp4", allow = [ "MPL-2.0", ] }, + { name = "symphonia-format-ogg", allow = [ + "MPL-2.0", + ] }, { name = "symphonia-format-riff", allow = [ "MPL-2.0", ] }, diff --git a/docs-template/EXAMPLE_README.md.tpl b/docs-template/EXAMPLE_README.md.tpl index e1300061978b9..e818a4d6701a5 100644 --- a/docs-template/EXAMPLE_README.md.tpl +++ b/docs-template/EXAMPLE_README.md.tpl @@ -160,10 +160,12 @@ In its examples, Bevy targets the minimum Android API that Play Store Users of older phones may want to use an older API when testing. By default, Bevy uses [`GameActivity`](https://developer.android.com/games/agdk/game-activity), which only works for Android API level 31 and higher, so if you want to use older API, you need to switch to `NativeActivity`. +Keep in mind that if you are using `bevy_audio` the minimum supported Android API version is 26 (Android 8/Oreo). + To use `NativeActivity`, you need to edit it in `cargo.toml` manually like this: ```toml -bevy = { version = "0.14", default-features = false, features = ["android-native-activity", ...] } +bevy = { version = "0.16", default-features = false, features = ["android-native-activity", ...] } ``` Then build it as the [Build & Run](#build--run) section stated above. @@ -184,10 +186,10 @@ You need to install the correct rust targets: - `aarch64-apple-ios`: iOS devices - `x86_64-apple-ios`: iOS simulator on x86 processors -- `aarch64-apple-ios-sim`: iOS simulator on Apple processors +- `arm64-apple-ios-simulator`: iOS simulator on Apple processors ```sh -rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim +rustup target add aarch64-apple-ios x86_64-apple-ios arm64-apple-ios-simulator ``` #### Build & Run diff --git a/docs/cargo_features.md b/docs/cargo_features.md index 5f7e33960539d..f3461847c9565 100644 --- a/docs/cargo_features.md +++ b/docs/cargo_features.md @@ -57,13 +57,14 @@ This is the complete `bevy` cargo feature list, without "profiles" or "collectio |Feature|Description| |-|-| +|aac|AAC audio format support (through `symphonia`)| |accesskit_unix|Enable AccessKit on Unix backends (currently only works with experimental screen readers and forks.)| |android-game-activity|Android GameActivity support. Default, choose between this and `android-native-activity`.| |android-native-activity|Android NativeActivity support. Legacy, should be avoided for most new Android games.| -|android_shared_stdcxx|Enable using a shared stdlib for cxx on Android| |asset_processor|Enables the built-in asset processor for processed assets.| |async-io|Use async-io's implementation of block_on instead of futures-lite's implementation. This is preferred if your application uses async-io.| |async_executor|Uses `async-executor` as a task execution backend.| +|audio-all|AAC, FLAC, MP3, MP4, WAV (through `symphonia`) and OGG/VORBIS (through `lewton`) audio formats support| |basis-universal|Basis Universal compressed texture support| |bevy_animation|Provides animation functionality| |bevy_anti_alias|Provides various anti aliasing solutions| @@ -120,9 +121,12 @@ This is the complete `bevy` cargo feature list, without "profiles" or "collectio |experimental_bevy_ui_widgets|Experimental headless widget collection for Bevy UI.| |experimental_pbr_pcss|Enable support for PCSS, at the risk of blowing past the global, per-shader sampler limit on older/lower-end GPUs| |exr|EXR image format support| +|fallback-flac|FLAC audio format support (through `claxon`)| +|fallback-vorbis|OGG/VORBIS audio format support (through `symphonia`)| +|fallback-wav|WAV audio format support (through `hound`)| |ff|Farbfeld image format support| |file_watcher|Enables watching the filesystem for Bevy Asset hot-reloading| -|flac|FLAC audio format support| +|flac|FLAC audio format support (through `symphonia`)| |force_disable_dlss|Forcibly disable DLSS so that cargo build --all-features works without the DLSS SDK being installed. Not meant for users.| |free_camera|Enables the free cam from bevy_camera_controller| |ghost_nodes|Experimental support for nodes that are ignored for UI layouting| @@ -142,7 +146,8 @@ This is the complete `bevy` cargo feature list, without "profiles" or "collectio |meshlet_processor|Enables processing meshes into meshlet meshes for bevy_pbr| |morph|Enables support for morph target weights in bevy_mesh| |morph_animation|Enables bevy_mesh and bevy_animation morph weight support| -|mp3|MP3 audio format support| +|mp3|MP3 audio format support (through `symphonia`)| +|mp4|MP4 audio format support (through `symphonia`). It also enables AAC support.| |multi_threaded|Enables multithreaded parallelism in the engine. Disabling it forces all engine tasks to run on a single thread.| |pan_camera|Enables the pan camera from bevy_camera_controller| |pbr_anisotropy_texture|Enable support for anisotropy texture in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| @@ -168,12 +173,6 @@ This is the complete `bevy` cargo feature list, without "profiles" or "collectio |sprite_picking|Provides an implementation for picking sprites| |statically-linked-dxc|Statically linked DXC shader compiler for DirectX 12| |std|Allows access to the `std` crate.| -|symphonia-aac|AAC audio format support (through symphonia)| -|symphonia-all|AAC, FLAC, MP3, MP4, OGG/VORBIS, and WAV audio formats support (through symphonia)| -|symphonia-flac|FLAC audio format support (through symphonia)| -|symphonia-isomp4|MP4 audio format support (through symphonia)| -|symphonia-vorbis|OGG/VORBIS audio format support (through symphonia)| -|symphonia-wav|WAV audio format support (through symphonia)| |sysinfo_plugin|Enables system information diagnostic plugin| |tga|TGA image format support| |tiff|TIFF image format support| @@ -184,8 +183,8 @@ This is the complete `bevy` cargo feature list, without "profiles" or "collectio |trace_tracy_memory|Tracing support, with memory profiling, exposing a port for Tracy| |track_location|Enables source location tracking for change detection and spawning/despawning, which can assist with debugging| |ui_picking|Provides an implementation for picking UI| -|vorbis|OGG/VORBIS audio format support| -|wav|WAV audio format support| +|vorbis|OGG/VORBIS audio format support (through `lewton`)| +|wav|WAV audio format support (through `symphonia`)| |wayland|Wayland display server support| |web|Enables use of browser APIs. Note this is currently only applicable on `wasm32` architectures.| |web_asset_cache|Enable caching downloaded assets on the filesystem. NOTE: this cache currently never invalidates entries!| diff --git a/examples/README.md b/examples/README.md index 324fac7163be3..f70a2ffb6a3ec 100644 --- a/examples/README.md +++ b/examples/README.md @@ -721,10 +721,12 @@ In its examples, Bevy targets the minimum Android API that Play Store Users of older phones may want to use an older API when testing. By default, Bevy uses [`GameActivity`](https://developer.android.com/games/agdk/game-activity), which only works for Android API level 31 and higher, so if you want to use older API, you need to switch to `NativeActivity`. +Keep in mind that if you are using `bevy_audio` the minimum supported Android API version is 26 (Android 8/Oreo). + To use `NativeActivity`, you need to edit it in `cargo.toml` manually like this: ```toml -bevy = { version = "0.14", default-features = false, features = ["android-native-activity", ...] } +bevy = { version = "0.16", default-features = false, features = ["android-native-activity", ...] } ``` Then build it as the [Build & Run](#build--run) section stated above. @@ -745,10 +747,10 @@ You need to install the correct rust targets: - `aarch64-apple-ios`: iOS devices - `x86_64-apple-ios`: iOS simulator on x86 processors -- `aarch64-apple-ios-sim`: iOS simulator on Apple processors +- `arm64-apple-ios-simulator`: iOS simulator on Apple processors ```sh -rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim +rustup target add aarch64-apple-ios x86_64-apple-ios arm64-apple-ios-simulator ``` #### Build & Run diff --git a/examples/audio/decodable.rs b/examples/audio/decodable.rs index c738668219479..8f7e67ad14dfa 100644 --- a/examples/audio/decodable.rs +++ b/examples/audio/decodable.rs @@ -1,7 +1,7 @@ //! Shows how to create a custom [`Decodable`] type by implementing a Sine wave. use bevy::{ - audio::{AddAudioSource, AudioPlugin, Source, Volume}, + audio::{AddAudioSource, AudioPlugin, ChannelCount, SampleRate, Source, Volume}, math::ops, prelude::*, reflect::TypePath, @@ -24,7 +24,7 @@ struct SineDecoder { progress_per_frame: f32, // how long a period is period: f32, - sample_rate: u32, + sample_rate: SampleRate, } impl SineDecoder { @@ -35,7 +35,7 @@ impl SineDecoder { current_progress: 0., progress_per_frame: frequency / sample_rate as f32, period: std::f32::consts::PI * 2., - sample_rate, + sample_rate: SampleRate::new(sample_rate).unwrap(), } } } @@ -54,15 +54,15 @@ impl Iterator for SineDecoder { // `Source` is what allows the audio source to be played by bevy. // This trait provides information on the audio. impl Source for SineDecoder { - fn current_frame_len(&self) -> Option { + fn current_span_len(&self) -> Option { None } - fn channels(&self) -> u16 { - 1 + fn channels(&self) -> ChannelCount { + ChannelCount::new(1).unwrap() } - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.sample_rate } @@ -73,8 +73,6 @@ impl Source for SineDecoder { // Finally `Decodable` can be implemented for our `SineAudio`. impl Decodable for SineAudio { - type DecoderItem = ::Item; - type Decoder = SineDecoder; fn decoder(&self) -> Self::Decoder { diff --git a/examples/mobile/android_basic/Cargo.toml b/examples/mobile/android_basic/Cargo.toml index e1a1d3a5bff84..d5a66368b600c 100644 --- a/examples/mobile/android_basic/Cargo.toml +++ b/examples/mobile/android_basic/Cargo.toml @@ -14,7 +14,6 @@ crate-type = ["staticlib", "cdylib"] [dependencies] bevy = { path = "../../", default-features = false, features = [ "android-native-activity", - "android_shared_stdcxx", "gltf_animation", "bevy_animation", "bevy_asset", diff --git a/examples/mobile/android_basic/readme.md b/examples/mobile/android_basic/readme.md index 6db652fff6a95..ab812b17b40c9 100644 --- a/examples/mobile/android_basic/readme.md +++ b/examples/mobile/android_basic/readme.md @@ -47,6 +47,8 @@ Bevy by default targets Android API level 33 in its examples which is the Users of older phones may want to use an older API when testing. +Keep in mind that if you are using `bevy_audio` the minimum supported Android API version is 26 (Android 8/Oreo). + To use a different API, the following fields must be updated in `Cargo.toml`: ```toml diff --git a/examples/mobile/build_rust_deps.sh b/examples/mobile/build_rust_deps.sh index 79eeddb28de85..53d5761ac3c04 100755 --- a/examples/mobile/build_rust_deps.sh +++ b/examples/mobile/build_rust_deps.sh @@ -54,7 +54,7 @@ for arch in $ARCHS; do TARGET=aarch64-apple-ios else # M1 iOS simulator - TARGET=aarch64-apple-ios-sim + TARGET=arm64-apple-ios-simulator fi esac diff --git a/examples/movement/physics_in_fixed_timestep.rs b/examples/movement/physics_in_fixed_timestep.rs index eee2914356484..5c33a067e4240 100644 --- a/examples/movement/physics_in_fixed_timestep.rs +++ b/examples/movement/physics_in_fixed_timestep.rs @@ -160,7 +160,7 @@ struct Velocity(Vec3); /// /// If you want to make sure that this component is always initialized /// with the same value as the `Transform`'s translation, you can -/// use a [component lifecycle hook](https://docs.rs/bevy/0.14.0/bevy/ecs/component/struct.ComponentHooks.html) +/// use a [component lifecycle hook](https://docs.rs/bevy/latest/bevy/ecs/component/struct.ComponentHooks.html) #[derive(Debug, Component, Clone, Copy, PartialEq, Default, Deref, DerefMut)] struct PhysicalTranslation(Vec3); diff --git a/release-content/migration-guides/rodio_0_21.md b/release-content/migration-guides/rodio_0_21.md new file mode 100644 index 0000000000000..f003527061460 --- /dev/null +++ b/release-content/migration-guides/rodio_0_21.md @@ -0,0 +1,47 @@ +--- +title: "Rodio 0.21 Update" +pull_requests: [20323] +--- + +`rodio` was updated to `0.21` and `cpal` to `0.16`. The following sections will guide you through the necessary changes to ensure compatibility. + +## Audio Feature Flags + +Audio format related features were reworked and now `symphonia` will be the default backend for most of them. + +By default, Bevy will enable the `vorbis` feature, which supports OGG/VORBIS files through `lewton`. + +If you are not using Bevy's default features, here's a list you can use for reference: + +- `vorbis`: OGG/VORBIS audio format support (through `lewton`). +- `wav`: WAV audio format support (through `symphonia`). +- `mp3`: MP3 audio format support (through `symphonia`). +- `mp4`: MP4 audio format support (through `symphonia`). It also enables AAC support. +- `flac`: FLAC audio format support (through `symphonia`). +- `aac`: AAC audio format support (through `symphonia`). + +There are also "fallback" backend flags you can use for certain formats: + +- `fallback-flac`: FLAC audio format support (through `claxon`). +- `fallback-vorbis`: OGG/VORBIS audio format support (through `symphonia`). +- `fallback-wav`: WAV audio format support (through `hound`). + +Notice that OGG/VORBIS support through `symphonia` is not the default due to issues with buffering, reverb, looping and spatial audio. Check the following issues/PRs for additional context: + +- +- + +The `audio-all` feature was added for convenience. It will enable all the available audio formats. Here's the full list and the corresponding backend for each format: + +- AAC, FLAC, MP3, MP4, and WAV: `symphonia`. +- OGG/VORBIS: `lewton`. + +## Audio Traits + +`type DecoderItem` was removed from the `Decodable` trait. Now `rodio::Sample` is an alias for `f32`. + +## Android Related Features + +The `android_shared_stdcxx` feature was removed, as `cpal`'s `oboe-shared-stdcxx` feature was also removed in favor of Android NDK audio APIs. + +Keep in mind that if you are using `bevy_audio` the minimum supported Android API version is now 26 (Android 8/Oreo). diff --git a/tools/example-showcase/disable-audio.patch b/tools/example-showcase/disable-audio.patch index fa495d9f9c226..8d2fb465bb366 100644 --- a/tools/example-showcase/disable-audio.patch +++ b/tools/example-showcase/disable-audio.patch @@ -1,32 +1,35 @@ diff --git a/crates/bevy_audio/src/audio_output.rs b/crates/bevy_audio/src/audio_output.rs -index 3e8082e23..624769443 100644 +index 15236b667..57f116bde 100644 --- a/crates/bevy_audio/src/audio_output.rs +++ b/crates/bevy_audio/src/audio_output.rs -@@ -7,7 +7,7 @@ use bevy_ecs::{prelude::*, system::SystemParam}; +@@ -6,28 +6,17 @@ use bevy_asset::{Asset, Assets}; + use bevy_ecs::{prelude::*, system::SystemParam}; use bevy_math::Vec3; use bevy_transform::prelude::GlobalTransform; --use rodio::{OutputStream, OutputStreamHandle, Sink, Source, SpatialSink}; -+use rodio::{OutputStreamHandle, Sink, Source, SpatialSink}; +-use rodio::{OutputStream, OutputStreamBuilder, Sink, Source, SpatialSink}; ++use rodio::{OutputStream, Sink, Source, SpatialSink}; use tracing::warn; use crate::{AudioSink, AudioSinkPlayback}; -@@ -30,18 +30,10 @@ pub(crate) struct AudioOutput { - - impl Default for AudioOutput { - fn default() -> Self { -- if let Ok((stream, stream_handle)) = OutputStream::try_default() { -- // We leak `OutputStream` to prevent the audio from stopping. -- core::mem::forget(stream); -- Self { -- stream_handle: Some(stream_handle), -- } -- } else { - warn!("No audio device found."); - Self { - stream_handle: None, - } -- } - } + /// Used internally to play audio on the current "audio device" +-#[derive(Resource)] ++#[derive(Resource, Default)] + pub(crate) struct AudioOutput { + stream: Option, } +-impl Default for AudioOutput { +- fn default() -> Self { +- let stream = OutputStreamBuilder::open_default_stream() +- .inspect_err(|_err| { +- warn!("No audio device found."); +- }) +- .ok(); +- Self { stream } +- } +-} +- + /// Marker for internal use, to despawn entities when playback finishes. + #[derive(Component, Default)] + pub struct PlaybackDespawnMarker;