tesselode / kira Goto Github PK
View Code? Open in Web Editor NEWLibrary for expressive game audio.
Home Page: https://crates.io/crates/kira
License: Apache License 2.0
Library for expressive game audio.
Home Page: https://crates.io/crates/kira
License: Apache License 2.0
Using StaticSoundData
when symphonia
is built with opt-level = 0
can cause long audio processing times of up to twelve seconds. In an application that plays sound effects rapidly (such as a game that makes a sound every time you shoot or move), this is enough to fill the command queue. Ideally, until symphonia
can be optimized, this limitation should be documented somewhere.
Currently, static and streaming SoundData::Handle
s have no unified API (e.g. if you are working with both types in the same context you must handle each as a seperate case.
It would be really nice if there was a seperate SoundHandle trait that both static and streaming sound handles implemented to that contained the methods they have in common.
(if something like this already exists, please point me towards it, I'm pretty new to Rust :))
Seeing this error in console on every quit (and it takes indeed 1 second for program to exit):
Kira failed to free up resources after 1000 milliseconds, giving up
Seems this is the bare minimum example that reproduces this issue for me:
let mut manager = AudioManager::new(AudioManagerSettings::default())?;
let music_track = manager.add_sub_track(SubTrackSettings::default())?;
Tested on macOS.
Edit: Realized that the issue seems to be related to the fact I keep the sub-track reference in the same object as audio manager:
pub struct Audio {
manager: AudioManager,
music_track: SubTrackHandle,
}
Not sure how I can workaround this? I do need a reference to this track handle for later use.
I believe the set_pitch
function is incorrectly named. It just changes the playback rate of the music.
Changing the pitch without affecting playback rate would involve techniques like phase vocoding (as far as I know) or using a library like Rubber Band: https://en.wikipedia.org/wiki/Audio_time_stretching_and_pitch_scaling#Phase_vocoder
https://breakfastquay.com/rubberband/
set_pitch
should probably be called something like set_playback_rate
.
The API currently doesn't have a feature to select an output device (it always uses the default one given by cpal).
Would it be possible to add an API that lets you query and choose output devices?
Hello! I would like to express my gratitude for this awesome crate. It's the best game sound framework for now. For me, as a musician, it's very comfortable to work with. But, unfortunately, there's a bug while audio is playing.
As you can see on the screenshot that I've attached:
there is insane clipping on the PH 3/4 channels. All the audio from the computer goes to the AN1/2 and on the PH 3/4 there is a wild electricity sound with +24 dB clipping. I've noticed it in my own project (a game made with Bevy engine) and decided to create completely new clean project "Hello world" using Kira audio only. And the bug is there too.
Besides the screenshot I'm attaching an audio with that sound, which I've recorded (DON'T PLAY IT LOUDLY):
https://github.com/tesselode/kira/assets/128966780/aa7753ba-e97c-4204-9b9b-36e9da46483b
I get the same sound regardless of different songs that I have played. The sound wave looks like this:
After that I've created Cpal basic project (from Cpal's examples folder) to see if the bug came from there. And it turned out, that there is a sound on the 3/4 channel, but it is merely a copy of original sound from the 1/2 channel.
I'll appreciate if you can do anything with it, thanks!
The minimal reproducing steps are simply dropping a AudioManager
.
PanicInfo { payload: Any { .. }, message: Some(called `Option::unwrap()` on a `None` value), location: Location { file: "~/.cargo/registry/src/github.com-1ecc6299db9ec823/kira-0.7.1/src/manager/backend/cpal/desktop/stream_manager/renderer_wrapper.rs", line: 40, col: 9 }, can_unwind: true }
Currently this issue is temporarily fixed by implementing the Drop trait for the oboe backend of cpal (host/oboe/mod.rs):
impl Drop for Stream {
fn drop(&mut self) {
match self {
Self::Input(stream) => {
stream.borrow_mut().stop();
stream.borrow_mut().close();
}
Self::Output(stream) => {
stream.borrow_mut().stop();
stream.borrow_mut().close();
}
}
}
}
Not sure if this is an issue of cpal.
Hello all,
I’m attempting to use this in a game (more similar to an emulator) where I’m receiving audio data in a u8 buffer. I tried looking around but it seems there’s no real way of creating a sound data object that I can just send off to play. I already know the num of channels and rate.
It could also be this library isn’t meant to be used this way. Any help would be appreciated :)
Currently, <MockBackend as Backend>::Error
is ()
so it cannot be converted to Box<dyn std::error::Error>
.
Using std::convert::Infallible
or a standalone type that implement std::error::Error
would be more convenient.
Would it be feasible to implement changes to the looping behaviour in StreamingSoundHandle
/StaticSoundHandle
?
The old (0.5) implementation had support for loading files directly from memory (from_ogg_reader
etc) instead of file paths. Could we have the same feature in the new version as well?
This would support things like loading sound files from archives, virtual filesystems or network.
I noticed that Clock::shared
is only updated in on_process_start
, which causes a delay up to a few milliseconds e.g. in ClockInfoProvider::when_to_start
.
I moved the update of Clock::shared
into Clock::update
and I didn't notice a performance impact. On my machine, running cargo bench
has a performance decrease of 3% for simple
and (interestingly) almost no impact for with on_start_processing callback
.
Do you think it's possible to move it there or maybe enable it with a feature? If you agree I'd be happy to make a PR.
Hi, and thanks for this great library!
I am experimenting with Kira and bevy, as well as building a super simple audio player for fun. I think it would be great to access a Frame
at a time, for example to have a game entity react to the sound or add visualization to audio. I see that there is get_frame_at_position, but this is not implemented for the Handle. Would this be reasonable to add or am I missing a way to make this work with the current state maybe?
After updating from 0.7.0
-> 0.8.1
I'm getting an error when trying to play StreamingSoundData
.
Here's the stack trace, let me know if anything else might be helpful.
thread '<unnamed>' panicked at 'did not get expected frame after seeking decoder', /vendor/kira/src/sound/streaming/sound/decode_scheduler.rs:159:22
0: 0x55f1096ae84a - std::backtrace_rs::backtrace::libunwind::trace::heb3166a6cb1fd02b
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
1: 0x55f1096ae84a - std::backtrace_rs::backtrace::trace_unsynchronized::h34837841e045a1d4
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
2: 0x55f1096ae84a - std::sys_common::backtrace::_print_fmt::h4348a4b63f328ee4
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/sys_common/backtrace.rs:65:5
3: 0x55f1096ae84a - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h1bad440d01eeeb29
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/sys_common/backtrace.rs:44:22
4: 0x55f1096d386e - core::fmt::write::hb5a073c651a6cb64
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/core/src/fmt/mod.rs:1232:17
5: 0x55f1096ab875 - std::io::Write::write_fmt::h97cc768331421fb2
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/io/mod.rs:1682:15
6: 0x55f1096ae615 - std::sys_common::backtrace::_print::h23bd93d6897965f3
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/sys_common/backtrace.rs:47:5
7: 0x55f1096ae615 - std::sys_common::backtrace::print::h4d41ae33ce7a824f
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/sys_common/backtrace.rs:34:9
8: 0x55f1096affcf - std::panicking::default_hook::{{closure}}::h8ab48635107c713a
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/panicking.rs:267:22
9: 0x55f1096afd0b - std::panicking::default_hook::h6305ca3c910e41d2
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/panicking.rs:286:9
10: 0x55f1096b06d9 - std::panicking::rust_panic_with_hook::ha8dfad8ee636a9a3
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/panicking.rs:688:13
11: 0x55f1096b0479 - std::panicking::begin_panic_handler::{{closure}}::h4fcf608bbbd27b26
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/panicking.rs:579:13
12: 0x55f1096aecfc - std::sys_common::backtrace::__rust_end_short_backtrace::h86f63ffb2338c5c8
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/sys_common/backtrace.rs:137:18
13: 0x55f1096b0182 - rust_begin_unwind
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/panicking.rs:575:5
14: 0x55f108d82353 - core::panicking::panic_fmt::ha12d43373dd0f588
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/core/src/panicking.rs:64:14
15: 0x55f1096d15d1 - core::panicking::panic_display::h17cae662562d6a06
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/core/src/panicking.rs:147:5
16: 0x55f1096d157b - core::panicking::panic_str::hfa275bfdfc298aa4
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/core/src/panicking.rs:131:5
17: 0x55f108d82316 - core::option::expect_failed::h09e72beb5cdbcf2e
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/core/src/option.rs:1924:5
18: 0x55f1092987cc - core::option::Option<T>::expect::h45a4a6c94b2112a8
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/core/src/option.rs:786:21
19: 0x55f1092987cc - kira::sound::streaming::sound::decode_scheduler::DecodeScheduler<Error>::frame_at_index::h1ffee1aa2b581f79
at /vendor/kira/src/sound/streaming/sound/decode_scheduler.rs:159:7
20: 0x55f109298fc5 - kira::sound::streaming::sound::decode_scheduler::DecodeScheduler<Error>::run::ha0b5650e36e80c0c
at /vendor/kira/src/sound/streaming/sound/decode_scheduler.rs:120:15
21: 0x55f10929971f - kira::sound::streaming::sound::decode_scheduler::DecodeScheduler<Error>::start::{{closure}}::h8d76de61f9a6d530
at /vendor/kira/src/sound/streaming/sound/decode_scheduler.rs:85:10
22: 0x55f109270e10 - std::sys_common::backtrace::__rust_begin_short_backtrace::ha54d63d75c2749dc
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/sys_common/backtrace.rs:121:18
23: 0x55f10926cd40 - std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}::h35a6626b5833273f
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/thread/mod.rs:558:17
24: 0x55f109443294 - <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::hfdabcee9c49c59f1
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/core/src/panic/unwind_safe.rs:271:9
25: 0x55f109443110 - std::panicking::try::do_call::hedb9f28a17b1b15a
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/panicking.rs:483:40
26: 0x55f10944321b - __rust_try
27: 0x55f109442f2c - std::panicking::try::hbb5be7c505a66fc5
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/panicking.rs:447:19
28: 0x55f1092d60b0 - std::panic::catch_unwind::h698223ec4512f974
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/panic.rs:140:14
29: 0x55f10926c640 - std::thread::Builder::spawn_unchecked_::{{closure}}::h9231232d909805a1
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/thread/mod.rs:557:30
30: 0x55f1092b83af - core::ops::function::FnOnce::call_once{{vtable.shim}}::hc087fc5fef99e45e
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/core/src/ops/function.rs:250:5
31: 0x55f1096b4d13 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h9646bd6a135081c9
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/alloc/src/boxed.rs:1988:9
32: 0x55f1096b4d13 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h180d98f11b902552
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/alloc/src/boxed.rs:1988:9
33: 0x55f1096b4d13 - std::sys::unix::thread::Thread::new::thread_start::h83489d4028ebb6e1
at /rustc/ef982929c0b653436a6ea6892a2a839fba7c8b57/library/std/src/sys/unix/thread.rs:108:17
34: 0x7fd40599e609 - start_thread
at /build/glibc-SzIz7B/glibc-2.31/nptl/pthread_create.c:477:8
35: 0x7fd40576c133 - clone
at /build/glibc-SzIz7B/glibc-2.31/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95
36: 0x0 - <unknown>
sorry if i'm missing something obvious.
i have a struct that implements Decoder
which i wrap into a StreamingSoundData
and send to AudioManager::play
.
when the stream ends i return an error from decode
, but kira continues to busy-wait poll the stream, burning cpu pretty hard.
i can't see a way to tell the audio manager to stop the handle, or to reply from the decoder that the stream has ended.
what should i do?
thanks
Hey there, I just wanted to open up the discussion as far as the possibility of making the AudioManager``Sync + Send
.
I thought the issue might be related to the audio backend and possibly unavoidable, but then I saw that the CpalBackend
is indeed Sync + Send
.
The actual issue from the Rust error message seems to be that dyn Sound
and dyn Modulator
aren't necessarily Sync
.
Would there be a way to add a feature flag maybe that additionally restricts Sound
and Modulator
to be Sync
maybe?
I tried playing this audio file as a StreamingSoundData
with a loop point of 7.0. Occasionally, this would work, but sometimes, it would come out as a scratchy mess:
Upon closer inspection, this seems to be a sped up version of the track. Sometimes this issue would correct itself at the loop point, but occasionally, it continues forever.
Thus far, I've only been able to reproduce this issue in debug builds (with optimized dependencies). Release builds seem to be unaffected.
it would be a nice feature if we could query the total length of the audio in a StreamingSound(Data/Handle)
I tried to look into making a MediaSource and piping interleaved PCM into it but... I dont know if that would work.
I tried using the Simple Sound Playback example in the readme with a .wav and .ogg file, but it panics on an internal array access. I then tried using the latest git commit (c2877eb) and tweaked the example based on the current changes, but the behaviour was the same.
The panic message: thread '<unnamed>' panicked at 'index out of bounds: the len is 1 but the index is 1', /home/xelivous/.cargo/git/checkouts/kira-a39b987b43e480e3/c2877eb/kira/src/manager/mod.rs:217:21
Line 217 in c2877eb
I'm running on Manjaro; I looked at basic issues pertaining to linux/arch on cpal's repo but none of them seem to apply, and i could run cpal's examples just fine on my system.
My best guess from comparing the examples code and the code in kira is that they use device.default_output_config()?
while kira uses device.supported_output_configs()?.next()
. The difference being that kira pulls in whatever is listed first, even if it's a very incapable interface that isn't the best suited interface. Debugging it a little, it seems that the interface returned is a single channel interface with a sample rate of 384000
...
If I change the following config selection chain:
Lines 202 to 207 in c2877eb
Into something like:
let config = device.default_output_config().ok().ok_or(AudioError::NoSupportedAudioConfig)?.config();
Then everything works without problems, although there might be a better way to send out the proper error other than the really dank ok().ok_or()
combo. And i'm not sure if you did it with supported_output_configs
for some particular reason that would be broken for other people when using default_output_config
.
The alternative solution is properly handling when an interface only has a single output frame/channel and mapping it to something like mono but idk if running something at a really meme sample rate has value.
I am writing a game engine that has to support some custom audio format that wouldn't make sense to include in the library, so I am trying to make my own types to implement SoundData
and Sound
traits.
It does seem possible to implement it, but I have to duplicate a lot of code from kira
: managing volume, panning, resampling audio... Ideally I would like to implement some trait that returns sample rate & decodes audio packets on demand, without copying half of kira into my impls.
One simple solution would be to use StaticSoundData
, but I need to use streaming for better loading latency.
From what I can see,
VolumeControlHandle:.set_volume doesn't need &mut because,
Producer::push doesn't need &mut since,
Producer::push_access doesn't need &mut since,
SharedVec::get_mut(), CachePadded::load nor CachePadded::store don't need &mut
I am trying to update bevy_kira_audio to Kira 0.6
One part of this is to migrate the asset loaders. The only viable option I currently see to load StaticSoundData is via from_cursor
. The problem is, that I cannot satisfy the static lifetime bound for the byte slice.
One option would be to expose from_media_source
. Then I can clone the bytes and pass Box::new(Cursor::new(owned_bytes))
as media source. This is the solution I am currently working with from my fork. Do you see any better approach?
When I play the sound using AudioManager::play
, the console prints the following message:
The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.
How should I play a sound on wasm? Is there an example?
In the new kira API, sequencers don't seem to exist. It would be useful to be able to define sequencers of some kind in order to define simple patterns, probably using clock ticks instead of beats (writing a metronome in the new API requires creating many clock instances).
I'm currently building a rhythm game, so I want to sync the game's clock to a soundtrack's playback position.
What's the idiomatic way to get the playback position of a sound instance?
Hi, I'm new to Rust and would need audio playback for my project. I can't compile your examples. Can you please help me? Thanks.
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> src/main.rs:15:19
|
15 | let mut manager = AudioManager::new(
| ^^^^^^^^^^^^^^^^^ expected 1 argument
16 | CpalBackend::new()?,
| -------------------
17 | AudioManagerSettings::default(),
| ------------------------------- supplied 2 arguments
|
note: associated function defined here
--> /Users/christian/.cargo/registry/src/github.com-1ecc6299db9ec823/kira-0.5.3/src/manager/mod.rs:143:9
|
143 | pub fn new(settings: AudioManagerSettings) -> Result<Self, SetupError> {
| ^^^
error[E0277]: the ?
operator can only be used in a function that returns Result
or Option
(or another type that implements FromResidual
)
--> src/main.rs:16:23
|
8 | / fn abc() {
9 | | extern crate kira;
10 | | extern crate kira_cpal;
11 | | extern crate kira_loaders;
... |
16 | | CpalBackend::new()?,
| | ^ cannot use the ?
operator in a function that returns ()
... |
19 | | Result::<(), Box>::Ok(())
20 | | }
| |_- this function should return Result
or Option
to accept ?
|
= help: the trait FromResidual<Result<Infallible, DeviceSetupError>>
is not implemented for ()
error[E0277]: the ?
operator can only be used in a function that returns Result
or Option
(or another type that implements FromResidual
)
--> src/main.rs:18:2
|
8 | / fn abc() {
9 | | extern crate kira;
10 | | extern crate kira_cpal;
11 | | extern crate kira_loaders;
... |
18 | | )?;
| | ^ cannot use the ?
operator in a function that returns ()
19 | | Result::<(), Box>::Ok(())
20 | | }
| |_- this function should return Result
or Option
to accept ?
|
= help: the trait FromResidual<Result<Infallible, SetupError>>
is not implemented for ()
error[E0308]: mismatched types
--> src/main.rs:19:1
|
19 | Result::<(), Box>::Ok(())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected ()
, found enum Result
|
= note: expected unit type ()
found enum Result<(), Box<dyn std::error::Error>>
help: consider using a semicolon here
|
19 | Result::<(), Box>::Ok(());
| +
help: try adding a return type
|
8 | fn abc() -> Result<(), Box> {
| +++++++++++++++++++++++++++++++++++++++++
Hi,
I've read through the book but it's not clear to me how I would have a single file for all my sounds, and just play specific portions of them.
Would I create a single StaticSoundData
to load the whole sound, and then somehow ask the manager
to play subportions of it? It looks like manager
cannot play a sub-section
of a sound?
Or would i create separate individual StaticSoundData
from my file, each using StaticSoundSettings
to define the beginning end of the chunk? It looks like StaticSoundSettings
supports start_position
but not end_position
.
The closest I can get to this functionality on my own is to either:
stop()
methodI feel like this is a common feature that kira would benefit from having built in. Would it be feasible to implement this?
I don't know if kira has this capability, but when I call set_playback_rate on my sound, I can speed up the sound, but the pitch change makes it sound strange. I want to be able to play the sound at 2x speed without changing the way the voice sounds (like speeding up youtube videos).
I'm an audio noob, so I can't express what I want in precise terminology, but I hope its clear what I'm after.
I am facing this error on Arch Linux (KDE Plasma 5 on Wayland). I did not know what when wrong, and I cannot reproduce when using symphonia-play
(the song still played as expected). Please let me know if you need any additional information.
Step to reproduce:
git clone [email protected]:tesselode/kira-examples.git
cd kira-examples
cargo run -p simple-sound-playback
Full error message:
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: BuildStreamError(BackendSpecific { err: BackendSpecificError { description: "ALSA function 'snd_pcm_hw_params' failed with error 'EIO: I/O error'" } })', /home/thang/.cargo/registry/src/index.crates.io-6f17d22bba15001f/kira-0.8.0/src/manager/backend/cpal/desktop/stream_manager.rs:69:59
stack backtrace:
0: rust_begin_unwind
at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:593:5
1: core::panicking::panic_fmt
at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/panicking.rs:67:14
2: core::result::unwrap_failed
at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/result.rs:1651:5
3: core::result::Result<T,E>::unwrap
at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/result.rs:1076:23
4: kira::manager::backend::cpal::desktop::stream_manager::StreamManager::start::{{closure}}
at /home/thang/.cargo/registry/src/index.crates.io-6f17d22bba15001f/kira-0.8.0/src/manager/backend/cpal/desktop/stream_manager.rs:69:4
Default for Tween being 10ms linear easing is quite weird, there should at least be some way to create a 0ms tween
Hey there,
first of all thanks for the great work. This library is core of so many playback libraries!
To my issue, I want to play a radio stream using Kira. The stream is remote and has no content-length as it is infinite. The issue I recognize is that Kira's SymphoniaDecoder::new function tries to determine sample_rate and num_frames at decoder creation and unfortunately it isn't able to determine the num_frames. I guess this is from Kira targeting game development whose would always have files on disk. Could you maybe consider to also allow playing remote files as well? I really like this library and would like to prevent using rodio for streaming and kira for local files (rodio doesn't support seeking or chaning positions).
Here is my example
use std::io::{Read, Seek, SeekFrom};
use std::thread::sleep;
use std::time::Duration;
use kira::manager::{backend::DefaultBackend, AudioManager, AudioManagerSettings};
use kira::sound::streaming::{StreamingSoundData, StreamingSoundSettings};
use reqwest::{Client, Url};
use stream_download::http::HttpStream;
use stream_download::source::SourceStream;
use stream_download::storage::memory::MemoryStorageProvider;
use stream_download::{Settings, StreamDownload};
use symphonia::core::io::MediaSource;
struct RemoteSource {
reader: StreamDownload<MemoryStorageProvider>,
content_length: Option<u64>,
}
impl RemoteSource {
pub async fn from_url(url: String) -> Result<Self, String> {
let parsed_url = url.parse::<Url>().map_err(|error| format!("Invalid url: {}", error))?;
let stream = HttpStream::<Client>::create(parsed_url)
.await
.map_err(|error| format!("Failed to create stream: {}", error))?;
let content_length = stream.content_length();
let reader = StreamDownload::from_stream(stream, MemoryStorageProvider::default(), Settings::default())
.await
.map_err(|error| format!("Failed to create download: {}", error))?;
Ok(RemoteSource { reader, content_length })
}
}
impl Read for RemoteSource {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.reader.read(buf)
}
}
impl Seek for RemoteSource {
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
self.reader.seek(pos)
}
}
impl MediaSource for RemoteSource {
fn is_seekable(&self) -> bool {
self.content_length.is_some()
}
fn byte_len(&self) -> Option<u64> {
self.content_length
}
}
const FILE: &'static str = "H:\\Data\\projects\\mupibox-rs\\admin_interface\\.storage\\audio\\0b7678f1-4121-4d38-be75-c26f86e2e30d-IsItReal.mp3";
#[tokio::main]
async fn main() {
let mut manager = AudioManager::<DefaultBackend>::new(AudioManagerSettings::default()).expect("manager to load");
let url = "https://streamtdy.ir-media-tec.com/live/mp3-128/web/play.mp3".to_string();
let sound = StreamingSoundData::from_media_source(
RemoteSource::from_url(url).await.expect("source to be loaded"),
StreamingSoundSettings::default(),
)
.expect("stream sound data to be created");
let mut handle = manager.play(sound).expect("failed to play");
sleep(Duration::from_secs(5));
}
With these dependencies
[dependencies]
kira = "0.8.5"
symphonia = "0.5.3"
reqwest = { version = "0.11.22", features = ["blocking"] }
stream-download = "0.3.0"
tokio = { version = "1.33.0", features = ["full"] }
rangemap = "1.4.0"
If not I can understand that as well :)
Have a nice day and best regards
fragsalat
self.spatial_scene.add_emitter(position, emitter_settings)
I am getting a ton of CommandQueue full errors. i have about 10 sounds of 20 seconds length playing.
Is there some kind of limit to the emitter?
ps: i am reusing the same StaticSoundData if that matters
Hello, I'm using kira to make a simple little podcast player with a terminal interface, and its been really nice to use so far :)
I am however experiencing some subtle but audible glitches when playing MP3 files on macOS (I have not tried any other OS). I've tried several different files and they all seem to have the same problem.
At first I thought it could have been something with the StreamingSound setup that made this happen, but I'm having the same issues using StaticSound.
I can reproduce it locally using the simple_sound_playback
with one of the files I have (seems any MP3 file would do).
Additionally, I tried playing the same file in the example symphonia-play
in the Symphonia repo, which did not exhibit the same issue.
Let me know if you want more information, or if I can help out in any way!
Effect::init
is called on the audio thread. It shouldn't be.
I am experiencing periodic (every few seconds) glitches in audio playback under OS X (13.0.1) on Apple Silicon.
#23 may be related, but I am using wired headphones on a M1 MacBook Pro 2020.
The following snippet under kira 0.7.1 reproduces the issue, as long as I have at least one other application playing audio. If nothing else is playing audio, audio playback seems fine!
let mut manager = AudioManager::<CpalBackend>::new(AudioManagerSettings::default()).unwrap();
let sound_data = StaticSoundData::from_file("audio.ogg", StaticSoundSettings::default()).unwrap();
manager.play(sound_data.clone()).unwrap();
loop {} // keep main thread alive
I found that loaded audio resources will not be released after it stops, here is a quick example:
use anyhow::Result;
use kira::{
manager::{backend::DefaultBackend, AudioManager, AudioManagerSettings},
sound::static_sound::{StaticSoundData, StaticSoundSettings},
tween::Tween,
};
fn main() {
play().unwrap();
}
fn play() -> Result<()> {
// Create an audio manager. This plays sounds and manages resources.
let mut manager = AudioManager::<DefaultBackend>::new(AudioManagerSettings::default())?;
let path = std::env::current_dir()
.unwrap()
.join("assets/audio/test.ogg");
let file = std::fs::File::open(path)?;
let sound_data = StaticSoundData::from_media_source(file, StaticSoundSettings::new())?;
let mut handle = manager.play(sound_data)?;
let mut i = 0;
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
i += 1;
if i == 10 {
handle.stop(Tween::default())?;
}
}
}
The music will play for 10 seconds and then stop, seeing that no memory usage drop in task manager.
I think it is just because a missing implement of removing it here:
kira/crates/kira/src/manager/backend/resources/sounds.rs
Lines 35 to 48 in 4c047c3
Stopped sound is moved to unused_sound_producer
but no next steps, while simply comment out line 40~45 will fix the problem.
Not sure if the problem exist in other backends or wasm.
Hello and high five for this crate, it indeed looks great!
I'm trying it today for the first time and followed the instructions on docs.rs and also from the book (very good initiative).
TBH my audio knowledge is inexistent, but luckily by following your instructions it doesn't look that difficult.
Just opening this issue here because there's some inconsistencies in the examples, e.g.
load
/ load_sound
where the docs points out to kira-loaders, but indeed doesn't look necessary anymore (AudioManager
's load_sound
seems the way to go).mixer
section, which is the one I'm the most interested into.Thanks :)
Currently having issues with commands seemingly getting stuck in the command queue because I'm seeing that it's getting full and crashing because of it. I'd like to be able to see how many commands are in queue at any point so that I can debug when/where the commands are getting stuck.
Is there a clean way to add this capability?
Hi! I stumbled upon kira while reading stuff on bevy, while trying to reasearch on the topic of audio engines for games that could lead to expressive uses of audio (most simple example I can think of: "In some action RPG, one of the instruments in the current fighting track represents a character. The more that character loses HPs, the more its associated instrument gets filtered and/or the narrower in the stereo field it becomes")
I had 2 questions re. kira:
This is a more natural representation than an f64 (e.g. a 1/3 note in 4/4 time has a 1/12 semantic duration), and does not accumulate error over time in subtle or frustrating ways.
For example, if I write something like this:
if let Ok(mut sound) = manager.play(sound_buf) {
sound.set_volume(0.01, Tween {
start_time: StartTime::Immediate,
duration: Duration::from_secs(0),
easing: Easing::Linear,
});
}
the volume doesn't get applied instantly, for a very short time the volume is still at 1.0
Hi there, I'm wanting to use Kira in Bevy Retro, but I need the ability to create a Sound
from raw bytes, instead of passing a file path. Are you open to me creating a PR for this?
Symphonia v0.5 has recently shipped with much improved support for MP3, as well as improvements for pretty much the entire rest of the codecs it supports. I see kira-loaders
currently uses v0.4; it would be nice to upgrade to v0.5 to get those improvements.
v0.5 is not semver compatible with v0.4.x, so Kira users will not get this upgrade simply by running cargo update
; this requires an explicit version bump in your Cargo.toml
.
As the title says, I am making an audio player using this, so it should be nice to have m4a support
This makes it hard to do things like Arc::try_unwrap(...)
on a StaticSoundData
. The guidelines say all types should implement Debug
(except for rare exceptions) but it looks like the ringbuf
dependency does not, which makes it hard to fix in kira
.
Is there any opinion between these options?
Debug
, formatting the obvious fields (and optionally providing something nice for things like consumer
)ringbuf
dependency (it is behind) and open an issue in their repo; wait for a fix and then auto-derive Debug
ringbuf
types and provide a generic Debug
implementation inside kira
This is really more like a question here. But I found having separate crates I need to have dependencies on core functionality a bit weird. Would it not be better instead of requiring users to have separate dependencies in their Cargo.toml - have the kira-cpal
and kira-loaders
exposed as features instead? Internally you still have multiple crates, they can still be disabled with default-features = false
, custom backend/loader still can be implemented by user, etc.
At least from my experience in Rust this seems to be a more common approach in libraries, but maybe there is a good reason it is the way it is?
There are some (admittedly rare) cases where making a Cursor out of sound data isn't practical, while implementing Read+Seek and a few helper methods is (my particular use case is rewriting the Minecraft sound system, where I use callbacks to access a Java BufferedInputStream from Rust and implement Read+Seek on it)
v0.7.1 compiles fine, but v0.7.2 does not:
dev/kira dc66cd9 cargo check -p kira --target wasm32-unknown-unknown
Compiling crossbeam-utils v0.8.15
Checking web-sys v0.3.61
Checking ringbuf v0.3.2
Checking cpal v0.14.2
Checking kira v0.7.1 (C:\Users\Johan\dev\kira\crates\kira)
Finished dev [unoptimized + debuginfo] target(s) in 1.55s
dev/kira dc66cd9 git co v0.7.2
Previous HEAD position was dc66cd9 version bump
HEAD is now at b2e8bca prepare 0.7.2 release
dev/kira b2e8bca cargo check -p kira --target wasm32-unknown-unknown
Updating crates.io index
Checking web-sys v0.3.61
Checking cpal v0.15.1
Checking kira v0.7.2 (C:\Users\Johan\dev\kira\crates\kira)
error[E0061]: this function takes 4 arguments but 3 arguments were supplied
--> crates\kira\src\manager\backend\cpal\wasm.rs:51:24
|
51 | let stream = device.build_output_stream(
| _________________________________^^^^^^^^^^^^^^^^^^^-
52 | | &config,
53 | | move |data: &mut [f32], _| {
54 | | renderer.on_start_processing();
... |
65 | | move |_| {},
66 | | )?;
| |_____________- an argument of type `Option<Duration>` is missing
|
note: associated function defined here
--> C:\Users\Johan\.cargo\registry\src\github.com-1ecc6299db9ec823\cpal-0.15.1\src\traits.rs:153:8
|
153 | fn build_output_stream<T, D, E>(
| ^^^^^^^^^^^^^^^^^^^
help: provide the argument
|
51 ~ let stream = device.build_output_stream(&config, move |data: &mut [f32], _| {
52 ~ renderer.on_start_processing();
53 ~ for frame in data.chunks_exact_mut(channels as usize) {
54 ~ let out = renderer.process();
55 ~ if channels == 1 {
56 ~ frame[0] = (out.left + out.right) / 2.0;
57 ~ } else {
58 ~ frame[0] = out.left;
59 ~ frame[1] = out.right;
60 ~ }
61 ~ }
62 ~ }, move |_| {}, /* Option<Duration> */)?;
|
For more information about this error, try `rustc --explain E0061`.
error: could not compile `kira` due to previous error
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.