tesselode / kira

Library for expressive game audio.
https://crates.io/crates/kira
Apache License 2.0
855 stars 43 forks source link

Add audio events #97

Open tobx opened 3 months ago

tobx commented 3 months ago

Is it possible to play a sound right after another sound ended playing (e.g. song ended, play next song)?

I just need an end event, but obviously other events might be useful too (start, stop, pause, loop, etc.).

tesselode commented 3 months ago

Do you have any thoughts on how such a feature should be designed? I've had some thoughts, but I'm curious to hear what other people think.

tobx commented 3 months ago

Do you have any thoughts on how such a feature should be designed? I've had some thoughts, but I'm curious to hear what other people think.

I think you have a way better understanding of how this all works, I do not have a lot of Rust experience, but for me a solution like in rodio would be fine: https://docs.rs/rodio/latest/rodio/struct.Sink.html#method.sleep_until_end

That would not work for "end of loop" events though, but I guess a simple mpsc::Receiver would be sufficient.

A little off-topic, but in the end I would prefer gapless playback, but I guess that is not the priority of a gaming audio library. But since Symphonia supports it already, it might not be too much work?

Roms1383 commented 3 months ago

Having audio events of some sort would be dope since it could allow e.g. granting a temporary track and dispose / re-attribute it once sounds are finished being played, or simply getting rid of StaticSoundHandle / StreamingSoundHandle when they are Stopped instead of dedicating a callback to regularly check.

tesselode commented 3 months ago

Having audio events of some sort would be dope since it could allow e.g. granting a temporary track and dispose / re-attribute it once sounds are finished being played, or simply getting rid of StaticSoundHandle / StreamingSoundHandle when they are Stopped instead of dedicating a callback to regularly check.

What do you mean by getting rid of a sound handle? Dropping it?

Roms1383 commented 3 months ago

Ok I must warn that my use-case is a bit niche: I use kira as an alternate audio engine for Cyberpunk 2077 (which uses AudioKinetics under the hood, and I can't be bothered to detour each and every of its methods buried deep down the binary, plus I don't think any modder will want to learn AudioKinetics to simply add a couple of sounds). Initially I just used it for my own mod, but lately more and more modders came to ask me to open-source my plugin so that they also can use it.

So, long story short, I conditionally detour calls to the native audio system and, when asked to play custom sounds, I redirect and play them with kira instead. This forces me to keep kira's sounds handle around in some static OnceCell<Mutex<HashMap<_, _>>>, but I'd sometimes like to get rid of them when they are finished (PlaybackState::Stopped), which I initially did by dedicating a thread to regularly check their state: it was very cumbersome, especially since I needed to properly park/unpark this thread based on current game state, so even if it was working fine I ended up removing it and instead recycle hashmap entries containing stopped sounds whenever a new sounds is requested for play.

Of course there are other situation where having audio events would allow pretty cool features (even better: audio events based callbacks). For example it could allow building dialogs by chaining sounds one after another whenever they are finished playing. Or whatever you can think that requires knowing the current state of play of any given sound, I'm pretty sure there's way more use cases than mine that I cannot think of right now.

Since this necessarily requires some overhead in kira, it could probably be gated behind an optional feature flag, but I think it would be a nice addition @tesselode.