docs/bevy/examples/audio/audio_control.rs 2.8 K · 113 lines · raw · history

1 //! This example illustrates how to load and play an audio file, and control how it's played.
2
3 use bevy::{math::ops, prelude::*};
4
5 fn main() {
6 App::new()
7 .add_plugins(DefaultPlugins)
8 .add_systems(Startup, setup)
9 .add_systems(
10 Update,
11 (update_progress_text, update_speed, pause, mute, volume),
12 )
13 .run();
14 }
15
16 fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
17 commands.spawn((
18 AudioPlayer::new(asset_server.load("sounds/Windless Slopes.ogg")),
19 MyMusic,
20 ));
21
22 commands.spawn((
23 Text::new(""),
24 Node {
25 position_type: PositionType::Absolute,
26 top: px(12),
27 left: px(12),
28 ..default()
29 },
30 ProgressText,
31 ));
32
33 // example instructions
34 commands.spawn((
35 Text::new("-/=: Volume Down/Up\nSpace: Toggle Playback\nM: Toggle Mute"),
36 Node {
37 position_type: PositionType::Absolute,
38 bottom: px(12),
39 left: px(12),
40 ..default()
41 },
42 ));
43
44 // camera
45 commands.spawn(Camera3d::default());
46 }
47
48 #[derive(Component)]
49 struct MyMusic;
50
51 #[derive(Component)]
52 struct ProgressText;
53
54 fn update_progress_text(
55 music_controller: Single<&AudioSink, With<MyMusic>>,
56 mut progress_text: Single<&mut Text, With<ProgressText>>,
57 ) {
58 progress_text.0 = format!("Progress: {}s", music_controller.position().as_secs_f32());
59 }
60
61 fn update_speed(music_controller: Query<&AudioSink, With<MyMusic>>, time: Res<Time>) {
62 let Ok(sink) = music_controller.single() else {
63 return;
64 };
65 if sink.is_paused() {
66 return;
67 }
68
69 sink.set_speed((ops::sin(time.elapsed_secs() / 5.0) + 1.0).max(0.1));
70 }
71
72 fn pause(
73 keyboard_input: Res<ButtonInput<KeyCode>>,
74 music_controller: Query<&AudioSink, With<MyMusic>>,
75 ) {
76 let Ok(sink) = music_controller.single() else {
77 return;
78 };
79
80 if keyboard_input.just_pressed(KeyCode::Space) {
81 sink.toggle_playback();
82 }
83 }
84
85 fn mute(
86 keyboard_input: Res<ButtonInput<KeyCode>>,
87 mut music_controller: Query<&mut AudioSink, With<MyMusic>>,
88 ) {
89 let Ok(mut sink) = music_controller.single_mut() else {
90 return;
91 };
92
93 if keyboard_input.just_pressed(KeyCode::KeyM) {
94 sink.toggle_mute();
95 }
96 }
97
98 fn volume(
99 keyboard_input: Res<ButtonInput<KeyCode>>,
100 mut music_controller: Query<&mut AudioSink, With<MyMusic>>,
101 ) {
102 let Ok(mut sink) = music_controller.single_mut() else {
103 return;
104 };
105
106 if keyboard_input.just_pressed(KeyCode::Equal) {
107 let current_volume = sink.volume();
108 sink.set_volume(current_volume.increase_by_percentage(10.0));
109 } else if keyboard_input.just_pressed(KeyCode::Minus) {
110 let current_volume = sink.volume();
111 sink.set_volume(current_volume.increase_by_percentage(-10.0));
112 }
113 }