Coder Social home page Coder Social logo

bevy_kira_audio's Introduction

Bevy Kira audio

Crates.io docs license Crates.io

This bevy plugin is intended to test an integration of Kira into Bevy. The goal is to replace or update bevy_audio, if Kira turns out to be a good approach. Currently, this plugin can play ogg, mp3, flac, and wav formats and supports web builds.

Sound can be played in channels. Each channel has controls to pause or stop playback and can change the volume, playback speed, and panning of all sounds playing in it. You can easily add new channels and access them through Bevy's ECS (see the custom_channel example).

Usage

Note: the Bevy feature bevy_audio is enabled by default and not compatible with this plugin. Make sure to not have the bevy_audio feature enabled if you want to use bevy_kira_audio. The same goes for Bevy's vorbis feature. See Bevys' Cargo file for a list of all default features of version 0.14 and list them manually in your Cargo file excluding the ones you do not want. Make sure to set default-features to false for the Bevy dependency. You can take a look at bevy_game_template's cargo file as an example.

To play audio, you usually want to load audio files as assets. This requires AssetLoaders. bevy_kira_audio comes with loaders for most common audio formats. You can enable them with the features ogg (enabled by default), mp3, wav, or flac. The following example assumes that the feature ogg is enabled.

use bevy_kira_audio::prelude::*;
use bevy::prelude::*;

fn main() {
   App::new()
        .add_plugins((DefaultPlugins, AudioPlugin))
        .add_systems(Startup, start_background_audio)
        .run();
}

fn start_background_audio(asset_server: Res<AssetServer>, audio: Res<Audio>) {
    audio.play(asset_server.load("background_audio.ogg")).looped();
}

You can change settings like volume, panning, or playback rate for running sounds, or when starting to play a sound. All changes can be done as smooth transitions. By default, they will be almost instantaneous.

Sound settings

You can configure a sound when playing it:

use bevy_kira_audio::prelude::*;
use bevy::prelude::*;
use std::time::Duration;

fn play_audio(asset_server: Res<AssetServer>, audio: Res<Audio>) {
    audio.play(asset_server.load("background_audio.ogg"))
        // The first 0.5 seconds will not be looped and are the "intro"
        .loop_from(0.5)
        // Fade-in with a dynamic easing
        .fade_in(AudioTween::new(Duration::from_secs(2), AudioEasing::OutPowi(2)))
        // Only play on our right ear
        .with_panning(1.0)
        // Increase playback rate by 50% (this also increases the pitch)
        .with_playback_rate(1.5)
        // Play at half volume
        .with_volume(0.5)
        // play the track reversed
        .reverse();
}

Optionally, you can also load a sound with already applied settings. This requires the feature settings_loader.

Sounds are configured in ron files. The following file loads as a AudioSource which is looped and has a 3 seconds intro before the loop:

(
    // The actual sound file in your assets directory
    file: "sounds/loop.ogg",

    loop_behavior: Some(3.0),
)

would make the loaded sound loop by default and start each repeated playback three seconds into the sound (the three seconds are the intro).

More settings are available. See the settings_loader example for all options.

Controlling sounds

You can either control a whole audio channel and all instances playing in it (channel_control example), or a single audio instance (instance_control example). Both ways offer audio transitions with Tweens supporting multiple easings.

Spatial audio

There is limited spatial audio support. Currently, only the volume of audio and it's panning can be automatically changed based on emitter and receiver positions. Take a look at the spatial example for some code.

Compatible Bevy versions

The main branch is compatible with the latest Bevy release.

Compatibility of bevy_kira_audio versions:

Bevy version bevy_kira_audio version
0.14 0.20
0.13 0.19
0.12 0.18
0.11 0.16 - 0.17
0.10 0.15
0.9 0.13 - 0.14
0.8 0.11 - 0.12
0.7 0.9 - 0.10
0.6 0.8
0.5 0.4 - 0.7
0.4 0.3
0.13 main
main bevy_main

License

Dual-licensed under either of

at your option.

Assets in the examples might be distributed under different terms. See the readme in the examples directory.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

bevy_kira_audio's People

Contributors

64kramsystem avatar 66oj66 avatar benknowles avatar billyb2 avatar cleancut avatar cryscan avatar fluffysquirrels avatar harudagondi avatar niklasei avatar richardvclam avatar romenjelly avatar rparrett avatar striezel avatar tnajdek avatar tracreed avatar zmbush avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

bevy_kira_audio's Issues

Dynamic number of AudioChannels at runtime

Hello, thanks so much for this crate.

I'm currently using 0.9.0 and looking to upgrade to 0.10.0, however in 0.9.0 I'm currently setting a dynamic number of AudioChannels at runtime (use case is using an AudioChannel per enemy so I can set volume per enemy based on distance to the player).

In 0.9.0 this was possible since AudioChannels were keyed by String:

for enemy in enemies {
    channels.insert(
        AudioChannel::new(enemy.id())
    );
}

Is it possible to achieve the same dynamic number of AudioChannels in 0.10.0? Since #44 AudioChannels are resources keyed on a static type; so it seems the number of AudioChannels needs to be fixed at compile-time. I guess I could do something like this with three (or more) volume settings:

    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugin(AudioPlugin)
        .add_audio_channel::<NearestEnemies>()
        .add_audio_channel::<NearEnemies>()
        .add_audio_channel::<DistantEnemies>()

But it wouldn't give the same granular per-enemy volume control possible in 0.9.0

Support additional types audio tweens?

Maybe I'm mistaken, but as far as I understand, it looks like kira supports lots of different tweens (allowing frequency slides etc.), but that the only exposed tween is through the fade_in command.

Or maybe exposing such features is out of scope?

Update to Bevy 0.6.1

With the latest release of Rust 1.59, Bevy 0.6 and older no longer compile. This prevents the usage of bevy_kira_audio with latest Bevy & Rust.

Firefox Sound Observations ๐Ÿ”ฅ ๐ŸฆŠ ๐Ÿ”‰ ๐Ÿ”

I saw the note in the readme about sound playback issues in Firefox and I just wanted to share my experiencewith my own Bevy Kira plugin on web ( I'm not using this plugin, but I am using Kira ).

I also had audio issues on Firefox, but I noticed that Firefox is also using almost 100% of one of my CPU cores. If I resize the browser window so that it is much smaller, though, the CPU usage goes down and the sound playback works nicely. That seems to indicate that the issue isn't actually with the sound playback itself, but how much CPU usage the Bevy game is using on Firefox. It seems that Bevy takes much more CPU on firefox than it does on Chrome.

I'm not sure exactly what causes the CPU usage difference, but at least I think that gives us somewhere to look. If resizing the screen changes the CPU usage, then it is probably rendering. Maybe firefox's rendering is just slower than chrome's.

I'm using a custom renderer, too, so my experience may not be the best benchmark, but that's what I know for what it's worth.

Sounds from the same source do not play together

I tried playing the same sound on two different channels and later stopping just one of them. The result is that all sound stopped.

use std::time::Duration;

use bevy::prelude::*;
use bevy_kira_audio::{Audio, AudioPlugin, AudioSource, AudioChannel};

const SOUND: &str = "sounds/semantic_duration.ogg";

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugin(AudioPlugin)
        .insert_resource(None as Option<HandleUntyped>)
        .add_startup_system(load_audio.label("load"))
        .add_startup_system(play_audio.after("load"))
        .add_system(stop_audio_in_time)
        .run();
}

fn load_audio(asset_server: Res<AssetServer>, mut handle: ResMut<Option<HandleUntyped>>) {
    *handle = Some(asset_server.load_untyped(SOUND));
}

fn play_audio(
    audio: Res<Audio>,
    sounds: Res<Assets<AudioSource>>,
    mut commands: Commands,
) {
    audio.play_looped_in_channel(sounds.get_handle(SOUND), &AudioChannel::new("0".into()));
    audio.play_looped_in_channel(sounds.get_handle(SOUND), &AudioChannel::new("1".into()));
    commands.spawn()
        .insert(Timer::new(Duration::from_secs_f32(3.0), false));
}

fn stop_audio_in_time(
    audio: Res<Audio>,
    time: Res<Time>,
    mut timer: Query<&mut Timer>,
) {
    if timer.single_mut().finished() {
        return;
    }

    if timer.single_mut().tick(time.delta()).finished() {
        audio.stop_channel(&AudioChannel::new("0".into()));
    }
}

Note that if the channel to stop is changed to "1", nothing happens (no sound gets stopped).

Untyped Custom Channels

In 0.10.0 custom channels are distinguished by marker types. It may be hard to utilize a dynamic number of channels at run time. For example, in a game one may want to assign one channel to each collision event to set the volume and pitch accordingly, but they have no idea how many and which channels to be assigned to. In previous versions they only need to use dynamic strings to index these channels, but it's made harder now. Is it possible to have an untyped collection of channels in addition?

Reexport `kira`

Currently, to create a StaticSoundData for AudioSource, you have to import kira with the correct version. I'd like... to not do that lol.

Also, in the case that #63 would be implemented, it is likely that users would have to reimport kira just to implement their own SoundData.

A solution to this is to reexport kira itself.

Strange issue with latest bevy main

error[E0277]: the trait bound `AudioSource: TypeUuid` is not satisfied
  --> src/states/mod.rs:8:22
   |
8  |     pub loop_handle: Handle<AudioSource>,
   |                      ^^^^^^^^^^^^^^^^^^^ the trait `TypeUuid` is not implemented for `AudioSource`
   |
   = note: required because of the requirements on the impl of `Asset` for `AudioSource`
note: required by a bound in `bevy::prelude::Handle`
  --> /Users/visual/.cargo/git/checkouts/bevy-f7ffde730c324c74/91c3b21/crates/bevy_asset/src/handle.rs:65:8
   |
65 |     T: Asset,
   |        ^^^^^ required by this bound in `bevy::prelude::Handle`

For more information about this error, try `rustc --explain E0277`.

Chrome: The AudioContext was not allowed to start.

When using this in a game and running it with WASM on a website, I'm seeing this error from Google Chrome:

The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.
https://goo.gl/7K7WLu

Is there a way for me to resume the audio context after a user gesture? Say I add a button to the website that says "enable audio", that button then calls into my WASM Rust code, and then what? Can the Rust code reinitialize Kira's AudioContext? Or, even better, can I somehow do it fully from JavaScript without having to cross the boundary to Rust?

Inconsistent behavior when plaing sounds in a paused channel

Following scenario:

  1. play sound 1
  2. pause the channel
  3. play sound 2

Currently, only sound 2 will be playing, but sound 1 still exists paused in the channel and will continue once the channel is resumed the next time.

Two options:

  1. playing sounds in a paused channel will pause them automatically
  2. playing sounds in a paused channel will resume the channel and play the new sound

I prefer 2. since 1. feels quite weird. It could come to the situation that some sounds keep stacking up in the same channel and then all start playing at the same time once the channel is resumed.

Using latest commit for bevy_main branch

Would it be alright if the bevy_main branch of this library just always tracked the latest git commit (bevy = { git = "https://github.com/bevyengine/bevy", default-features = false }). It would make it easier for those of use who also keep track of the latest Bevy git commit, instead of having to use a specific revision (as typically, you want to follow the development branch of Bevy since you wan't the latest features all the time).

Bevy 0.9: `cargo update` introduces a 1-second delay to all audios

System: Ubuntu 20.04.5 LTS
Version: 0.13

Everything is fine if only upgrade bevy and bevy_kira_audio. But after running cargo update and recompiling, there is a ~1-second delay for all audios. I'm sure this is due to updating because it is fine again after me restoring Cargo.lock.

Here is a list of updated crates:

    Updating ab_glyph v0.2.16 -> v0.2.18
    Updating ab_glyph_rasterizer v0.1.5 -> v0.1.7
    Removing adler32 v1.2.0
    Updating aho-corasick v0.7.18 -> v0.7.19
    Updating android_system_properties v0.1.4 -> v0.1.5
    Removing ansi_term v0.12.1
    Updating anyhow v1.0.62 -> v1.0.66
    Updating async-executor v1.4.1 -> v1.5.0
      Adding async-lock v2.6.0
    Updating base64 v0.13.0 -> v0.13.1
    Updating bindgen v0.59.2 -> v0.61.0
    Updating bumpalo v3.11.0 -> v3.11.1
    Updating bytemuck v1.12.1 -> v1.12.3
    Updating bytemuck_derive v1.2.1 -> v1.3.0
    Updating cc v1.0.73 -> v1.0.76
    Updating clang-sys v1.3.3 -> v1.4.0
    Updating cocoa v0.24.0 -> v0.24.1
      Adding concurrent-queue v2.0.0
    Updating const_panic v0.2.4 -> v0.2.6
    Updating coreaudio-sys v0.2.10 -> v0.2.11
    Updating crossbeam-utils v0.8.11 -> v0.8.12
    Removing deflate v1.0.0
    Updating erased-serde v0.3.22 -> v0.3.23
      Adding flate2 v1.0.24
    Updating futures-core v0.3.23 -> v0.3.25
    Updating futures-io v0.3.23 -> v0.3.25
    Updating getrandom v0.2.7 -> v0.2.8
    Updating image v0.24.3 -> v0.24.5
    Updating itertools v0.10.3 -> v0.10.5
    Updating itoa v1.0.3 -> v1.0.4
    Updating jobserver v0.1.24 -> v0.1.25
    Updating libc v0.2.132 -> v0.2.137
    Updating libloading v0.7.3 -> v0.7.4
    Updating lock_api v0.4.7 -> v0.4.9
    Removing miniz_oxide v0.5.3
      Adding miniz_oxide v0.5.4
      Adding miniz_oxide v0.6.2
    Updating mio v0.8.4 -> v0.8.5
      Adding nu-ansi-term v0.46.0
    Updating once_cell v1.13.1 -> v1.16.0
      Adding overload v0.1.1
    Updating owned_ttf_parser v0.15.1 -> v0.17.1
    Updating parking_lot_core v0.9.3 -> v0.9.4
    Updating percent-encoding v2.1.0 -> v2.2.0
    Updating pkg-config v0.3.25 -> v0.3.26
    Updating png v0.17.5 -> v0.17.7
    Updating proc-macro2 v1.0.43 -> v1.0.47
    Updating profiling v1.0.6 -> v1.0.7
    Updating regex v1.6.0 -> v1.7.0
    Updating regex-syntax v0.6.27 -> v0.6.28
    Updating serde v1.0.143 -> v1.0.147
    Updating serde_derive v1.0.143 -> v1.0.147
    Updating serde_json v1.0.83 -> v1.0.87
    Updating smallvec v1.9.0 -> v1.10.0
    Updating syn v1.0.99 -> v1.0.103
    Updating thiserror v1.0.32 -> v1.0.37
    Updating thiserror-impl v1.0.32 -> v1.0.37
    Updating tracing v0.1.36 -> v0.1.37
    Updating tracing-attributes v0.1.22 -> v0.1.23
    Updating tracing-core v0.1.29 -> v0.1.30
    Updating tracing-subscriber v0.3.15 -> v0.3.16
    Updating ttf-parser v0.15.2 -> v0.17.1
    Updating unicode-ident v1.0.3 -> v1.0.5
    Updating unicode-width v0.1.9 -> v0.1.10
    Updating unicode-xid v0.2.3 -> v0.2.4
    Updating uuid v1.1.2 -> v1.2.2
      Adding windows-sys v0.42.0
      Adding windows_aarch64_gnullvm v0.42.0
      Adding windows_aarch64_msvc v0.42.0
      Adding windows_i686_gnu v0.42.0
      Adding windows_i686_msvc v0.42.0
      Adding windows_x86_64_gnu v0.42.0
      Adding windows_x86_64_gnullvm v0.42.0
      Adding windows_x86_64_msvc v0.42.0

bevy_master vs bevy_main

The readme states:

The branch bevy_main is tracking bevy/main.

...but there is no bevy_main branch. Perhaps the bevy_master branch was meant to be renamed?

image

audio_output.instances not cleaned up properly

I stress tested an application Im making (for fun really) and it plays audio. Due to the high volume of play commands added I started to get log messages that I think originates from the CommandQueueFull error (perhaps kira printed it?).

I did a profiling and ran the stress test and basically even long after all audio stops playing this method:

pub fn update_instance_states_system(world: &mut World) {

continues to take up in the profiling I did 34-35ms of frame-time (steadily growing from almost no time at start of app then really going haywire after a while). My guess is that the cleanup_stopped_instances don't detect them as faulty or even started but they still exist in the vector or something.

SoundLimitReached causes Panic

Hello again! Upgraded to latest version. Ended up being in a scenario where the amount of sounds played (not super-crazy) caused a panic here: https://github.com/NiklasEi/bevy_kira_audio/blob/main/src/audio_output.rs#L167

This is the full error message: thread 'main' panicked at 'Failed to play sound: SoundLimitReached'

I'm wondering if there is a way to get the limit by code? If so I guess I can implement a rate-limiter on sounds on my side. However I think it would be nice to propagate this error up to the user of bevy_kira_audio :)

Add Tween Options

Hey there!

Would you be open to a pull request that adds versions of the play, stop, etc. functions that additionally take the Tween parameter present in kira?

I was using my own wrapper around kira for Bevy, but would like to switch to this one and that looks like it's the only feature I'm missing.

I think we could re-export Tween from kira, but maybe rename it to AudioTween, just to avoid confusion with any other Bevy tweening plugins or something like that.

Slow loading speed in debug

I've observed on Desktop PC with a powerful dev machine that loading a ~3 minute ~6 MiB .ogg file takes something like 20+ seconds to be ready to play. Even a 6 MiB .wav (so no decompression work) takes several seconds. This means I have to go to great length with preloading and UX delays to hide this loading time to make sure the music is ready to play when the game starts. Given the file sizes, I'd expect both cases to be sub-second loading and decoding.

I appreciate there are good chances this is due to Kira itself and not this binding, but I just wanted to confirm it and see if someone else observed this maybe? I can log an issue with Kira directly if needed. Thanks!

Alternatively, do you know if there is a way to stream while loading maybe?

Sped up audio on the web in the first seconds

On the web build of my game, the audio is sped up in the first few seconds on Vivaldi.

Steps to reproduce:

  • Run game (itch.io)
  • Click on the game during the grey loading screen to enable audio
  • On the title screen the music will be sped up for a few seconds

I have used bevy_asset_loader to load my BGMs and SFXs in another state.
In the title state, Handle<AudioSource>-s should be ready and I just call audio.play_looped(songs.title.clone()); on state enter. (loading, audio played)

Can not use `AudioSource` with bevy_asset_loader on the latest main branch

The following code fails to compile on the latest commit of bevy_kira_audio (b721820).
This issue is very similar to #31, however I can't find a commit that works for me. I absolutely need the feature introduced on this commit, but no commit after this one compiles successfully.

I also do not understand why this error is thrown in the first place. this code clearly shows that TypeUuid is defined for AudioSource so I'm not sure where the error is coming from.

Failing code:

#[derive(AssetCollection)]
pub struct AudioAssets {
    #[asset(path = "audio/flying.ogg")]
    pub flying: Handle<AudioSource>,
}

Error:

error[E0277]: the trait bound `AudioSource: TypeUuid` is not satisfied
   --> src/loading.rs:34:17
    |
34  |     pub flying: Handle<AudioSource>,
    |                 ^^^^^^^^^^^^^^^^^^^ the trait `TypeUuid` is not implemented for `AudioSource`
    |

Cargo.toml

...

[features]
default = [
    "bevy_kira_audio/ogg",
    "bevy/bevy_winit",
    "bevy/render",
    "bevy/png",
    "bevy/x11",
]

dev = ["bevy/dynamic"]

[dependencies]
bevy = { git = "https://github.com/bevyengine/bevy", rev = "7d554146524987b050923841de06c7d18adf66e9", default-features = false }
bevy_kira_audio = { git = "https://github.com/NiklasEi/bevy_kira_audio", rev = "b721820d0f7b479a136cc2a9d51c23bbedd2934e" }
bevy_asset_loader = "0.11.0"
rand = "0.8.5"

[target.'cfg(target_os = "linux")'.dependencies]
winit = { version = "0.26.1", features = ["x11"] }

[build-dependencies]
embed-resource = "1.7.2"

...

Audio doesn't work in Chrome

Seemingly due to Chrome's restrictions on audio autoplay.

Just in case I never get back around to working on this, I figured I'd dump everything I know about the situation somewhere more durable/googleable than discord.

When starting up a bevy project with bevy_kira_audio, this shows up in the console:

The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.

I've attempted the workaround described here:

https://developers.google.com/web/updates/2018/11/web-audio-autoplay#moving-forward

Where AudioContext is proxied and resumed upon interaction with the page, but that doesn't seem to work. The workaround not working seems like it could be an issue with cpal or kira. I'm not sure though.

I suppose I could work around this with some sort of "click to start loading the game" button in js/html, but the wasm package and the assets are large enough that I'd really prefer to have everything loading when the user hits the page.

Another workaround that I'm fine with for my particular application is delaying bevy_kira_audio's creation of the AudioOutput until after the user has clicked on something in-game.

I've implemented this here: rparrett@76b2678

This allows you to

app.insert_resource(AudioInitialization::new(false));
app.add_plugin(AudioPlugin)

And then later on

commands.insert_resource(AudioInitialization::new(true));

And well, it's not much to look at, but it works.

I'd be happy to open a PR against the bevy 0.4 tracking branch if desired, but this doesn't seem like particularly useful code outside of working around what seems to be an issue with cpal. Just thought I'd add a link here for anyone else experiencing the issue.

edit:
A slightly less wacky API for doing (what I did above) is might be something like

app.add_plugin(AudioPlugin { initialize: false })
// ...
fn some_system(audio_init: ResMut<AudioInitialization>) {
    audio_init.needed = true;
}

Allow iterating through `DynamicChannels`

Not sure to what extent this is a good idea, but I'm trying to manage various characteristics of dynamic channels. One missing feature I've noticed is the ability to iterate through all channels.

Might be useful to impl Iterator/IntoIter on DynamicChannels. Also, generally making it more hashmap-like would help as well (I.e. being able to retrieve keys/values.)

Thanks.

Instance handles for Streams

I see that there are Instance handles for sound tracks but not for Streams. Is there a reason for this? it would be nice for example to play multiple streams on a single change and be able to control each one separately.

I would be willing to work on this if it is as simple as replicating the functionality from the normal audio interface.

Retry mechanism for stop commands is broken

If a stop command cannot be processed by Kira, the command is queued again in bevy_kira_audio. But currently, all instance handles are removed from a channel even if stopping them failed.

Stopping a Queued instance

Currently a Quened instance handle cannot be stopped.

This is an example of the scenario using the main branch with commit [63d4f82] instead of v0.10.

trait Channel = Sync + Send + Resource;

pub(crate) struct ChannelState<T> {
    pub(crate) handle: Option<Handle<AudioSource>>,
    pub(crate) instance_handle: Option<InstanceHandle>,
    _marker: PhantomData<T>,
}

impl<T> Default for ChannelState<T> {
    fn default() -> Self {
        Self {
            handle: None,
            instance_handle: None,
            _marker: PhantomData,
        }
    }
}

#[derive(Component, Debug, Default, Clone)]
pub(crate) struct MusicChannel;

pub struct AudioPlugin;

impl Plugin for AudioPlugin {
    fn build(&self, app: &mut App) {
        app.add_plugin(KiraAudioPlugin)
            .insert_resource(ChannelState::<MusicChannel>::default())
            .add_audio_channel::<MusicChannel>()
            .add_enter_system(GameState::MainMenu, play_menu_music)
            .add_enter_system(GameState::InGame, play_game_music)
            .add_system(play_channel::<MusicChannel>)
            .add_system(print_status::<MusicChannel>)
            ;
    }
}

fn print_status<T: Channel>(
    audio: Res<AudioChannel<T>>,
    channel_state: Res<ChannelState<T>>,
    ) {
    if let Some(instance_handle) = &channel_state.instance_handle {
        let state = audio.state(instance_handle.clone());
        println!("Loop audio {:?} {:?}", state, instance_handle);
    }
}

#[allow(clippy::only_used_in_recursion)]
fn play_menu_music(
    mut channel_state: ResMut<ChannelState<MusicChannel>>,
    asset_server: Res<AssetServer>,
    audio: Res<AudioChannel<MusicChannel>>,
) {
    dbg!("play main menu music");
    channel_state.handle = Some(asset_server.load("music/TownTheme.mp3"));
}

#[allow(clippy::only_used_in_recursion)]
fn play_game_music(
    mut channel_state: ResMut<ChannelState<MusicChannel>>,
    asset_server: Res<AssetServer>,
    audio: Res<AudioChannel<MusicChannel>>,
) {
    audio.stop();
    dbg!("play another music");
}

fn play_channel<T: Channel>(
    mut channel_state: ResMut<ChannelState<T>>,
    audio: Res<AudioChannel<T>>,
) {
    if let ChannelState {
        handle: Some(handle),
        ..
    } = &*channel_state
    {
        channel_state.instance_handle = Some(audio.play(handle.clone()));
        channel_state.handle = None;
    }
}
  1. At first, MusicChannel is added.
  2. At game state MainMenu, play_menu_music is to load the mp3 file, it took seconds to load it and it is in the state of Queued
  3. While the instance is still Queued, the game state changed to InGame and there is a new music to be played by play_game_music.
  4. Even though audio.stop() is issued, the instance won't be stopped.
  5. Once the instance is ready, it will play in InGame.

So although there is audio.stop() when the channel is switched over to the new one, now both MainMenu music and the InGame music play together.

Relicense under dual MIT/Apache-2.0

Following bevyengine/bevy#2373 I would like to adapt licensing of this plugin to keep maximal compatibility with Bevy. For other reasons to switch to MIT/Apache 2.0 please take a look at the Bevy issue.

With only two other contributors this should be much easier than for Bevy itself ๐Ÿ˜‰

@rparrett and @CleanCut, I think you know the drill: please comment on this issue with

I license past and future contributions under the dual MIT/Apache-2.0 license, allowing licensees to choose either at their option.

Thanks again for your help!

What is Kira's scope?

Bevy could use the ability to structure multiple sound operations into a chain similar to a UE cue file. This might be a set of samples, then selecting one randomly, then applying an effects filter. A format would describe a series of functions to be applied to yield the final sound. Gameplay would interact with this high level cue-like format.

Do you envision Kira providing that kind of functionality or do you envision it only provides low level services and the operations level features exist at some higher level?

Random sound selection?

Let me know if this belongs in Kira instead of here.

I'd like to be able to specify a list of sounds, not just one, and then some strategy (distribution) to select among them. This would be like a cue in UE4 with several sounds (ex: footsteps) and then you select which one you'd like.

I don't want to write code like this:

fn load_sounds(asset_server: Res<AssetServer>, mut tile_painter_sfx: ResMut<TilePainterSFX>) {
    // We should add support for selecting among samples.
    // This would be similar to cue files in UE.
    // This should probably change from referencing oggs to rons.
    let place_tile_sfx = vec![
        "audio/effects/dirt_impact/dirt_impact_1.ogg",
        //"audio/effects/dirt_impact/dirt_impact_2.ogg",
        "audio/effects/dirt_impact/dirt_impact_3.ogg",
        //"audio/effects/dirt_impact/dirt_impact_4.ogg",
        "audio/effects/dirt_impact/dirt_impact_5.ogg",
        "audio/effects/dirt_impact/dirt_impact_6.ogg",
        "audio/effects/dirt_impact/dirt_impact_7.ogg",
    ];

    for &sfx in place_tile_sfx.iter() {
        tile_painter_sfx.on_place.push(asset_server.load(sfx));
    }
}

// ...
        let mut rng = rand::thread_rng();
        sfx_event_writer.send(UiPlaySoundEvent {
            source: tile_painter_sfx.on_place[rng.gen_range(0..tile_painter_sfx.on_place.len())]
                .clone(),
        });
// ...

I can write the PR, but want to put it in the correct crate and at the correct scope. Suggestions?

Support reading 'chunks' from a single audio file

Hi,

Does kira_audio support having a single audio asset, but then having Audio handles that will read only parts of the audio file? (e.g. from 0.8sec to 1.5sec)

This would be helpful for the web as I would like to limit the number of files that clients have to download, so I'd like to 'merge' all audio files into one.

Build error with latest bevy

Hi-

I'm trying to consume bevy directly from git, due to the fact the latest release 0.5.0 is 6 months old and is missing a few fixes I need (see bevyengine/bevy#2940). However I'm facing many build errors:

error[E0432]: unresolved import `bevy::prelude::AppBuilder`
error[E0432]: unresolved imports `bevy::core::AsBytes`, `bevy::render::pass::RenderPassDepthStencilAttachmentDescriptor`
error[E0261]: use of undeclared lifetime name `'w`
error[E0261]: use of undeclared lifetime name `'s`
error[E0107]: this struct takes 2 lifetime arguments but 1 lifetime argument was supplied

So I have a few questions:

  • Is bevy_kira_audio only supposed to work with bevy on released version?
  • Would it be possible to add some CI to catch those build issues along the way?

Thanks!

Expose `PlayAudioCommand` type

PlayAudioCommand can be accessed by using AudioChannel::play, but the type is hidden behind the private audio module.

Also, this type is not showing up in docs.rs, so to know its methods you have to go to the source code in the repo. You can't even go to the source code through docs.rs.

wasm performance compared to bevy_audio

Hello! ๐Ÿ‘‹
Thanks for all your work! I really love this crate โค๏ธ โค๏ธ

I'm creating this issue because I'd like to document some surprising (to me) behavior of bevy_kira_audio / kira in comparison to bevy_audio ๐Ÿ˜„

Because of some crackling audio in the browser (see #27) I recently ported a project of mine to bevy_audio in a branch to experiment.

After porting I noticed a significant speedup to load times as well as the crackling audio going away.

Anecdotally, when using bevy_kira_audio it takes a couple seconds for my "Play" button to display and then a couple more after clicking "Play" for the scene to render. When I switched to bevy_audio, everything much quicker, i.e. no delay between startup and "Play" button or after clicking "Play".

project code: https://github.com/shnewto/limbo_pass

wasm branches

  • wasm-rodio
  • wasm-kira

Some of this is definitely a candidate for being system specific, I'm on macOS Monterey 12.3.1. I'd be curious to know if this is or isn't the case for someone with a different setup.

Don't panic

If Kira gives an error, log it instead and drop the audio command. A game shouldn't quit, bexause it couldn't play a sound.

See e.g. #50

Unexpected `PlaybackState` behavior

There are 3 slightly different cases. The common part is that we're playing a short sound on a separate AudioChannel with play() method.

  • Waiting for the sound to end. Checking PlaybackState: it is permanently PlaybackState::Playing
  • Waiting for the sound to end, running stop() method. Checking PlaybackState: it is permanently PlaybackState::Playing
  • Not waiting for the sound to end, running stop() method while the sound is still playing. Checking PlaybackState: it is permanently PlaybackState::Stopping

In all cases my expectation for PlaybackState would be PlaybackState::Stopped.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.