Skip to content

Commit 5a505bb

Browse files
authored
Merge pull request #45 from CleanCut/audio-switch
Switch from bevy_kira_audio to built-in bevy audio
2 parents 005022f + a5aeb80 commit 5a505bb

File tree

10 files changed

+69
-52
lines changed

10 files changed

+69
-52
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@
33

44
### Improved
55

6-
- Updated to bevy 0.7, bevy_kira_audio 0.9, and bevy_prototype_lyon 0.5
6+
- Updated to bevy 0.7 and bevy_prototype_lyon 0.5
7+
- Stopped using bevy_kira_audio in favor of the built-in bevy audio which nows has all the features we need.
8+
9+
### BREAKING CHANGES
10+
11+
Yes, I know I shouldn't be releasing breaking changes in a patch release...but no one should be using any 5.x versions until I start teaching classes with it publicly...so I'm going to break it until I start teaching with 5.x.
12+
13+
- Renamed the music file extensions to `.ogg` since [bevy doesn't support that file extension yet](https://github.com/bevyengine/bevy/pull/4703) -- this means the asset pack is now different.
714

815
## [5.0.3] - 2022-04-29
916

Cargo.toml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ exclude = [
2222

2323
[dependencies]
2424
bevy = { version = "0.7.0", default-features = false, features = [
25-
#"bevy_audio"
26-
"bevy_dynamic_plugin",
25+
"bevy_audio",
2726
"bevy_gilrs",
2827
"bevy_gltf",
2928
"bevy_winit",
@@ -32,12 +31,7 @@ bevy = { version = "0.7.0", default-features = false, features = [
3231
"hdr",
3332
"mp3",
3433
"x11",
35-
] }
36-
bevy_kira_audio = { version = "0.9", features = [
37-
"flac",
38-
"mp3",
39-
"ogg",
40-
"wav",
34+
"vorbis",
4135
] }
4236
bevy_prototype_lyon = "0.5"
4337
lazy_static = "1.4"
File renamed without changes.
File renamed without changes.

assets/audio/music/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
The music files "Arcade Fantasy.oga", "Classy 8-Bit.oga", "Mysterious Magic.oga", and "Whimsical Popsicle.oga" have been licensed for non-attribution use in Rusty Engine itself by a commercial license agreement between the author of Rusty Engine and the creator of the music, Eric Matyas. However, any distribution of these music files in any project created using Rusty Engine must include attribution information as per the directions at https://soundimage.org/attribution-info/ or be independently licensed.
1+
The music files "Arcade Fantasy.ogg", "Classy 8-Bit.ogg", "Mysterious Magic.ogg", and "Whimsical Popsicle.ogg" have been licensed for non-attribution use in Rusty Engine itself by a commercial license agreement between the author of Rusty Engine and the creator of the music, Eric Matyas. However, any distribution of these music files in any project created using Rusty Engine must include attribution information as per the directions at https://soundimage.org/attribution-info/ or be independently licensed.

src/audio.rs

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
//! # use rusty_engine::prelude::*;
1010
//! #
1111
//! # fn main() {
12-
//! # let mut engine = Game::new();
12+
//! # let mut game = Game::new();
1313
//! // Inside your logic function...
14-
//! engine.audio_manager.play_sfx("my_sound_effect.mp3", 1.0);
15-
//! # engine.run(());
14+
//! game.audio_manager.play_sfx("my_sound_effect.mp3", 1.0);
15+
//! # game.run(());
1616
//! # }
1717
//! ```
1818
//!
@@ -22,10 +22,10 @@
2222
//! # use rusty_engine::prelude::*;
2323
//! #
2424
//! # fn main() {
25-
//! # let mut engine = Game::new();
25+
//! # let mut game = Game::new();
2626
//! // Inside your logic function...
27-
//! engine.audio_manager.play_music("my_game/spooky_loop.ogg", 1.0);
28-
//! # engine.run(());
27+
//! game.audio_manager.play_music("my_game/spooky_loop.ogg", 1.0);
28+
//! # game.run(());
2929
//! # }
3030
//! ```
3131
//!
@@ -36,19 +36,18 @@
3636
//! use rusty_engine::prelude::*;
3737
//!
3838
//! # fn main() {
39-
//! # let mut engine = Game::new();
39+
//! # let mut game = Game::new();
4040
//! // Inside your logic function...
41-
//! engine.audio_manager.play_sfx(SfxPreset::Confirmation1, 1.0);
42-
//! engine.audio_manager.play_music(MusicPreset::Classy8Bit, 1.0);
43-
//! # engine.run(());
41+
//! game.audio_manager.play_sfx(SfxPreset::Confirmation1, 1.0);
42+
//! game.audio_manager.play_music(MusicPreset::Classy8Bit, 1.0);
43+
//! # game.run(());
4444
//! # }
4545
//! ```
4646
//!
4747
4848
use crate::prelude::Engine;
49-
use bevy::prelude::*;
50-
use bevy_kira_audio::{Audio, AudioChannel};
51-
use std::array::IntoIter;
49+
use bevy::{audio::AudioSink, prelude::*};
50+
use std::{array::IntoIter, fmt::Debug};
5251

5352
#[derive(Default)]
5453
#[doc(hidden)]
@@ -64,14 +63,24 @@ impl Plugin for AudioManagerPlugin {
6463
/// You will interact with a [`AudioManager`] for all audio needs in Rusty Engine. It is exposed
6564
/// through the [`Engine`](crate::prelude::Engine) struct provided to your logic function
6665
/// each frame as the [`audio_manager`](crate::prelude::Engine::audio_manager) field.
67-
#[derive(Debug, Default)]
66+
#[derive(Default)]
6867
pub struct AudioManager {
6968
sfx_queue: Vec<(String, f32)>,
7069
music_queue: Vec<Option<(String, f32)>>,
71-
playing: AudioChannel,
70+
playing: Option<Handle<AudioSink>>,
7271
music_playing: bool,
7372
}
7473

74+
impl Debug for AudioManager {
75+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76+
f.debug_struct("AudioManager")
77+
.field("sfx_queue", &self.sfx_queue)
78+
.field("music_queue", &self.music_queue)
79+
.field("music_playing", &self.music_playing)
80+
.finish()
81+
}
82+
}
83+
7584
impl AudioManager {
7685
/// Play a sound effect. `volume` ranges from `0.0` to `1.0`. `sfx` can be an [`SfxPreset`] or a
7786
/// string containing the relative path/filename of a sound file within the `assets/audio`
@@ -107,7 +116,7 @@ impl AudioManager {
107116
/// `sfx` example by cloning the `rusty_engine` repository and running the following command:
108117
///
109118
/// ```text
110-
/// cargo run --release --example sfx
119+
/// cargo run --release --example sfx_sampler
111120
/// ```
112121
pub enum SfxPreset {
113122
Click,
@@ -185,7 +194,7 @@ impl From<SfxPreset> for String {
185194
/// by cloning the `rusty_engine` repository and running the following command:
186195
///
187196
/// ```text
188-
/// cargo run --release --example music
197+
/// cargo run --release --example music_sampler
189198
/// ```
190199
#[derive(Copy, Clone, Debug)]
191200
pub enum MusicPreset {
@@ -208,9 +217,9 @@ impl MusicPreset {
208217
impl From<MusicPreset> for String {
209218
fn from(music_preset: MusicPreset) -> String {
210219
match music_preset {
211-
MusicPreset::Classy8Bit => "music/Classy 8-Bit.oga".into(),
212-
MusicPreset::MysteriousMagic => "music/Mysterious Magic.oga".into(),
213-
MusicPreset::WhimsicalPopsicle => "music/Whimsical Popsicle.oga".into(),
220+
MusicPreset::Classy8Bit => "music/Classy 8-Bit.ogg".into(),
221+
MusicPreset::MysteriousMagic => "music/Mysterious Magic.ogg".into(),
222+
MusicPreset::WhimsicalPopsicle => "music/Whimsical Popsicle.ogg".into(),
214223
}
215224
}
216225
}
@@ -220,30 +229,41 @@ impl From<MusicPreset> for String {
220229
pub fn queue_managed_audio_system(
221230
asset_server: Res<AssetServer>,
222231
audio: Res<Audio>,
232+
audio_sinks: Res<Assets<AudioSink>>,
223233
mut game_state: ResMut<Engine>,
224234
) {
225235
for (sfx, volume) in game_state.audio_manager.sfx_queue.drain(..) {
226236
let sfx_path = format!("audio/{}", sfx);
227237
let sfx_handle = asset_server.load(sfx_path.as_str());
228-
// To be able to set the volume of a sound effect, we need the channel it is being played
229-
// in. We'll start by naively creating a new channel for every single sound effect. If this
230-
// ends up being a performance or correctness problem, we'll need to circle back and do
231-
// something more sophisticated (like keep a set number of channels around at different
232-
// volumes).
233-
let new_sfx_channel = AudioChannel::new(sfx_path);
234-
audio.set_volume_in_channel(volume, &new_sfx_channel);
235-
audio.play_in_channel(sfx_handle, &new_sfx_channel);
238+
audio.play_with_settings(
239+
sfx_handle,
240+
PlaybackSettings {
241+
volume,
242+
..Default::default()
243+
},
244+
);
236245
}
237-
let mut playing_music = game_state.audio_manager.playing.clone();
238-
for item in game_state.audio_manager.music_queue.drain(..) {
239-
audio.stop_channel(&playing_music);
246+
#[allow(clippy::for_loops_over_fallibles)]
247+
for item in game_state.audio_manager.music_queue.drain(..).last() {
248+
// stop any music currently playing
249+
if let Some(sink_handle) = &game_state.audio_manager.playing {
250+
if let Some(sink) = audio_sinks.get(sink_handle) {
251+
sink.stop();
252+
}
253+
}
254+
// start the new music...if we have some
240255
if let Some((music, volume)) = item {
241256
let music_path = format!("audio/{}", music);
242257
let music_handle = asset_server.load(music_path.as_str());
243-
playing_music = AudioChannel::new(music_path);
244-
audio.set_volume_in_channel(volume, &playing_music);
245-
audio.play_looped_in_channel(music_handle, &playing_music);
258+
let sink_handle = audio_sinks.get_handle(audio.play_with_settings(
259+
music_handle,
260+
PlaybackSettings {
261+
repeat: true,
262+
volume,
263+
..Default::default()
264+
},
265+
));
266+
game_state.audio_manager.playing = Some(sink_handle);
246267
}
247268
}
248-
game_state.audio_manager.playing = playing_music;
249269
}

src/game.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use bevy::{
1010
},
1111
utils::HashMap,
1212
};
13-
use bevy_kira_audio::*;
1413
use bevy_prototype_lyon::prelude::*;
1514
use std::{
1615
ops::{Deref, DerefMut},
@@ -297,12 +296,9 @@ impl<S: Send + Sync + 'static> Game<S> {
297296
.insert_resource::<S>(initial_game_state);
298297
self.app
299298
// Built-ins
300-
.add_plugins_with(DefaultPlugins, |group| {
301-
group.disable::<bevy::audio::AudioPlugin>()
302-
})
299+
.add_plugins(DefaultPlugins)
303300
.add_system(exit_on_esc_system)
304301
// External Plugins
305-
.add_plugin(AudioPlugin) // kira_bevy_audio
306302
.add_plugin(ShapePlugin) // bevy_prototype_lyon, for displaying sprite colliders
307303
// Rusty Engine Plugins
308304
.add_plugin(AudioManagerPlugin)

tutorial/src/200-audio.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
Rusty Engine has a basic audio system. You can play one looping music track, and quite a few concurrent sound effects. There are some music and sound effect files included in the asset pack.
44

5-
Supported audio file formats are `ogg` (including `oga`), `mp3`, `flac`, and `wav`.
5+
Supported audio file formats are `ogg`, `mp3`, `flac`, and `wav`.
66

77
All audio is accessed through methods on the audio manager accessed through `Engine.audio_manager`.

tutorial/src/205-music.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The second parameter is the volume, which should be a value between `0.0` (silen
1313
game.audio_manager.play_music(MusicPreset::Classy8Bit, 1.0);
1414
1515
// using a filepath relative to `assets/audio`
16-
game.audio_manager.play_music("music/Classy 8-Bit.oga", 1.0);
16+
game.audio_manager.play_music("music/Classy 8-Bit.ogg", 1.0);
1717
```
1818

1919
Any music already playing will be stopped to play a new music selection.

0 commit comments

Comments
 (0)