diff --git a/CHANGELOG.md b/CHANGELOG.md index bbe4628946f67..988232d13f9e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ - New methods `Color::rgb_linear` and `Color::rgba_linear` will accept colors already in linear sRGB (the old behavior) - Individual color-components must now be accessed through setters and getters: `.r`, `.g`, `.b`, `.a`, `.set_r`, `.set_g`, `.set_b`, `.set_a`, and the corresponding methods with the `*_linear` suffix. - Despawning an entity multiple times causes a debug-level log message to be emitted instead of a panic [649] [651] +- Breaking Change: Migrated to rodio 0.12, this means: + - Playing an mp3 no longer sometimes panics in debug mode + - New method of playing audio can be found in the audio example (an intermediary `Audio` struct is used instead of `AudioOutput` directly) [696]: https://github.com/bevyengine/bevy/pull/696 [689]: https://github.com/bevyengine/bevy/pull/689 diff --git a/crates/bevy_audio/Cargo.toml b/crates/bevy_audio/Cargo.toml index c8a9e480b31a0..bd6481c61511d 100644 --- a/crates/bevy_audio/Cargo.toml +++ b/crates/bevy_audio/Cargo.toml @@ -22,7 +22,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.2.1" } # other anyhow = "1.0" -rodio = { version = "0.11", default-features = false } +rodio = { version = "0.12", default-features = false } parking_lot = "0.11.0" [features] diff --git a/crates/bevy_audio/src/audio.rs b/crates/bevy_audio/src/audio.rs new file mode 100644 index 0000000000000..0c6d0ef80e6be --- /dev/null +++ b/crates/bevy_audio/src/audio.rs @@ -0,0 +1,43 @@ +use crate::{AudioSource, Decodable}; +use bevy_asset::Handle; +use parking_lot::RwLock; +use std::{collections::VecDeque, fmt}; + +/// The external struct used to play audio +pub struct Audio
+where
+ P: Decodable,
+{
+ pub queue: RwLock fmt::Debug for Audio
+where
+ P: Decodable,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Audio").field("queue", &self.queue).finish()
+ }
+}
+
+impl Default for Audio
+where
+ P: Decodable,
+{
+ fn default() -> Self {
+ Self {
+ queue: Default::default(),
+ }
+ }
+}
+
+impl Audio
+where
+ P: Decodable,
+ ::Decoder: rodio::Source + Send + Sync,
+ < ::Decoder as Iterator>::Item: rodio::Sample + Send + Sync,
+{
+ pub fn play(&self, audio_source: Handle ) {
+ self.queue.write().push_front(audio_source);
+ }
+}
diff --git a/crates/bevy_audio/src/audio_output.rs b/crates/bevy_audio/src/audio_output.rs
index 50c29a9670b6a..2571b0c72b9a4 100644
--- a/crates/bevy_audio/src/audio_output.rs
+++ b/crates/bevy_audio/src/audio_output.rs
@@ -1,28 +1,17 @@
-use crate::{AudioSource, Decodable};
-use bevy_asset::{Asset, Assets, Handle};
-use bevy_ecs::Res;
-use parking_lot::RwLock;
-use rodio::{Device, Sink};
-use std::{collections::VecDeque, fmt};
+use crate::{Audio, AudioSource, Decodable};
+use bevy_asset::{Asset, Assets};
+use bevy_ecs::{Resources, World};
+use rodio::{OutputStream, OutputStreamHandle, Sink};
+use std::marker::PhantomData;
-/// Used to play audio on the current "audio device"
+/// Used internally to play audio on the current "audio device"
pub struct AudioOutput
where
P: Decodable,
{
- device: Device,
- queue: RwLock fmt::Debug for AudioOutput
-where
- P: Decodable,
-{
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("AudioOutput")
- .field("queue", &self.queue)
- .finish()
- }
+ _stream: OutputStream,
+ stream_handle: OutputStreamHandle,
+ phantom: PhantomData ,
}
impl Default for AudioOutput
@@ -30,9 +19,12 @@ where
P: Decodable,
{
fn default() -> Self {
+ let (stream, stream_handle) = OutputStream::try_default().unwrap();
+
Self {
- device: rodio::default_output_device().unwrap(),
- queue: Default::default(),
+ _stream: stream,
+ stream_handle,
+ phantom: PhantomData,
}
}
}
@@ -43,18 +35,14 @@ where
::Decoder: rodio::Source + Send + Sync,
< ::Decoder as Iterator>::Item: rodio::Sample + Send + Sync,
{
- pub fn play_source(&self, audio_source: &P) {
- let sink = Sink::new(&self.device);
+ fn play_source(&self, audio_source: &P) {
+ let sink = Sink::try_new(&self.stream_handle).unwrap();
sink.append(audio_source.decoder());
sink.detach();
}
- pub fn play(&self, audio_source: Handle ) {
- self.queue.write().push_front(audio_source);
- }
-
- pub fn try_play_queued(&self, audio_sources: &Assets ) {
- let mut queue = self.queue.write();
+ fn try_play_queued(&self, audio_sources: &Assets , audio: &mut Audio ) {
+ let mut queue = audio.queue.write();
let len = queue.len();
let mut i = 0;
while i < len {
@@ -70,14 +58,17 @@ where
}
}
-/// Plays audio currently queued in the [AudioOutput] resource
-pub fn play_queued_audio_system ::Decoder: rodio::Source + Send + Sync,
< ::Decoder as Iterator>::Item: rodio::Sample + Send + Sync,
{
- audio_output.try_play_queued(&audio_sources);
+ let audio_output = resources.get_thread_local::