tesselode / kira

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

Periodic dropouts/glitches on OS X when other apps are playing audio #38

Closed XMPPwocky closed 1 year ago

XMPPwocky commented 1 year ago

I am experiencing periodic (every few seconds) glitches in audio playback under OS X (13.0.1) on Apple Silicon.

https://github.com/tesselode/kira/issues/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
jakerr commented 1 year ago

I'm experiencing glitchy playback in macOS as well. Replacing the blip.ogg in the crates/examples/assets directory with a bit longer file and running cargo run --release -p simple_sound_playback I get quite a bit of crackle. I tried through my laptop speakers, monitor speakers, head phones and they all have the same issue. In my case I don't have any other audio playing and it's still reproducing.

This is on a M2, 2022 MacBook Air.

It seems to be quite reproducable with various files but the one I used, for reference, was a kick drum sample: kick.ogg.zip

jakerr commented 1 year ago

This might be related to this CpalBackend issue: https://github.com/RustAudio/cpal/issues/748

jakerr commented 1 year ago

I've narrowed this down to a line in stream_manager.rs

https://github.com/tesselode/kira/blob/82d9c3ed5584fe7f5df3c6d49407a022c3ba2819/crates/kira/src/manager/backend/cpal/desktop/stream_manager.rs#L99

Some how this call to default_device_and_config causes crackle in the audio stream. As others have mentioned it does appear more likely if there are other software using the audio device.

In terms of reproduction: If you increase the interval for checking the stream, and then put a log line around L99 mentioned above you can see for certain that the crackle happens right when that call occurs.

Once every five seconds for example:

const CHECK_STREAM_INTERVAL: Duration = Duration::from_millis(5000);

I added a bunch of other logging and this is occuring even with the result of the default_device_and_config causes no change to the manager. It's not the case that the stream is being started and stopped because of a detected change. The crackle happens just by calling this function.

I also tried moving the default_device_and_config call into a dedicated thread (since it's a free function this was easy) and delivering the results to the thread holding the streammanager via a channel but that does not appear to help.

tesselode commented 1 year ago

Fixed in 0.7.2.