audio_control/
audio_control.rs

1//! This example illustrates how to load and play an audio file, and control how it's played.
2
3use bevy::{math::ops, prelude::*};
4
5fn 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
16fn 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)]
49struct MyMusic;
50
51#[derive(Component)]
52struct ProgressText;
53
54fn 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
61fn 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
72fn 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
85fn 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
98fn 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}